Oil painting of a blacksmith drawing a glowing blade from the forge at night, a recipe ledger open beside brass scales

The Well-Run Forge

A deep dive into Shroud of the Avatar's crafting: the station, the recipe book, what Ultima Online and twenty-five years of games since can teach them, and twenty-two concrete proposals.

SotA's crafting UI finished its move to UI Toolkit this month: the station window with its three panes, the recipe book, and the enchant and masterwork effect picker, all sharing one recipe card. Underneath sits one of the deeper crafting simulations in the genre. This document surveys what the rest of the genre learned about crafting interfaces, measures our window against it, and proposes twenty-two improvements, most of them zero-server-cost, each grounded in the actual classes that would carry them. Per-school balance is out of scope; each crafting tree gets its own deep dive later.

0 · Executive summary 1 · Where we are today 2 · Lessons: Ultima Online to modern 3 · The twenty-two proposals    Tier 1 · Quick wins (S1–S9)    Tier 2 · Core upgrades (S10–S17)    Tier 3 · Server-backed (S18–S21)    Tier 4 · Directional (S22)    Considered and rejected 4 · The composed window 5 · Sequencing 6 · Appendix
Section 0

Executive summary

Ultima Online shipped tactile, simulation-first crafting in 1997 and then spent twenty-five years retrofitting the interface. Publish 14 (2001) alone added the unified crafting gump, your exact success percentage shown before committing, backpack material pooling, Make Last and Make Number — and UO players are still asking for "Make Last Number" two decades later. The genre then built the modern canon on top: crafting straight from storage (GW2, ESO, WoW, New World), the recipe book as a progression artifact (FFXIV), one-click subcomponent crafting (GW2), and player order economies (UO's Bulk Order Deeds, ESO's writs, WoW Dragonflight's crafting orders). SotA inherited UO's put-the-ingredients-on-the-table simulation, and almost none of the retrofits.

The sharpest fact this review found: the client already knows nearly everything the UI refuses to say. All 3,283 recipes with every field load client-side at startup; the player's known-recipe set syncs once at login; the success-chance formula is byte-identical shared code, and the recipe cards already run it locally every frame. Yet the station window waits on a server round-trip per table change to print the same number, the recipe book hides percentages away from stations, search matches recipe names only, and the fresh UITK port dropped item tooltips from both crafting grids.

Measured against the canon, our gaps cluster in three places:

  1. Round-trips the client does not need — the summary waits on the server, the book hides the odds, discovery stays silent, all on data that is already client-resident.
  2. Repetition without memory — no Craft Again, no Make Max, no queue, quantity resets, no favorites, no record of what you have crafted; every batch beyond fifty is manual re-pressing.
  3. The recipe graph is invisible — search cannot see ingredients or results, nothing links "created by" to "used in", there is no materials breakdown, and materials are locked to the backpack (the lot-supply feature, in flight, is the first crack in that wall).

Twenty-two proposals follow. Seventeen are pure client work with zero new server traffic. Four need server support, each flagged with its cost. One is a directional design for the crafting-orders economy.

#ProposalTierSizeServerOne-line pitch
S1Grid tooltips return Shipped1Snoneitem tooltips on both crafting grids (UITK regression)
S2Rich recipe tooltips Shipped1Mnoneresult, ingredients, tier, school on hover
S3Craft Again + quantity memory Shipped1Snoneone click repeats the last craft at the last quantity
S4Make Max Shipped1Snonequantity jumps to the most your materials allow
S5Missing-ingredients readout Shipped1Snone"Missing for Longsword: 1 Sword Hilt" in the window
S6Sortable list + skill tint Shipped1Mnonesort by name, success, can-make, skill; relevance color
S7Favorite recipes Shipped1Snonestar recipes; Favorites entry in the category dropdown
S8Search ingredients and results Shipped1Mnone"iron ingot" finds recipes that use it or make it
S9Success % in the book Shipped1Snoneodds shown away from stations, with a qualifier
S10Local table resolution2Lnoneinstant recipe match; server validates only at craft
S11Batch queue Shipped2Lnonequeue crafts across recipes, visible, cancelable
S12Shopping-list drill-in2Lnonemulti-level materials breakdown + Craft This Next
S13Created-by / used-in links2Mnoneevery item answers "what makes it, what needs it"
S14Discovery feedback2Mnone"these items appear in 2 recipes you have not learned"
S15Can-make counts2Mnone"x12" on every recipe row, over backpack + lot pool
S16Station coherence pass2Mnonebook at every station; real per-station pane filters; polish
S17Bulk salvage2Mnonefiltered multi-item salvage honoring the lock contract
S18Per-character crafting state3Lnew collectionsynced favorites, Make-Last memory, loadouts
S19Crafting record display3Mread RPCtimes crafted + XP decay state, finally visible
S20Bank pull + leftovers return3XLopsthe lot-storage feature's next two rooms
S21Signature-free commodity crafts3Mrecipe flaglow-value crafts stack again
S22Crafting orders board4XLmajorNPC writs v1; the UO Bulk Order Deed heritage loop
Section 1

Where we are today

The crafting family finished its UI Toolkit conversion this month: the station window, the recipe book, and the enchant and masterwork effect picker. One recipe card renders in both the station list and the book; ingredient rows already tint three ways (carried, lot supply, short) with live "have/need" counts; the Only Craftable filter and the new craft-from-lot-storage toggle are in. Enchant, masterwork, socket, pattern, and brew need no buttons of their own: they are recipes — put the item and reagents on the table and Craft routes the action. This document builds on all of that rather than re-proposing any of it.

Blacksmithing Stationpin  ✕
Recipes
All Recipes ▾
Filter
☑ Only craftable  ☐ Use lot storage
Iron Ingot95%
Iron Ore25/25
Coal4/4
Longsword84%
Sword Hilt0/1
Sword Blade1/1
Binding Ropes2/2
Requires Blacksmithing 40
Sword Hilt91%
Iron Ingot6/6 (+2 lot)
Coal4/4
... 55 more cards, one fixed order
Crafting Inventory
Iron IngotIron IngotCoal
Capacity: 3 / 10
Equipped Tool: Blacksmith Hammer 198/200
Longsword
84% success chance
12% exceptional item chance
1+Craft
SalvageRepairRecipesTake All
Crafting Longsword...  Cancel
Your Inventory
Show: All Items ▾
Iron Ingot24
Coal61
Sword Blade1
Curved Blade2
Bone14
Bandage55
Station-relevant items sort to the top; unrelated items grey out

The machinery every proposal plugs into

One session loop owns crafting: interacting with a station creates a server-side provisional bag for the table, then a watcher hashes the table contents and asks the server what they make on every change; the answer drives the summary text, the craft gates, and the Salvage and Repair enables. Pressing Craft sends one craft request per batch item, re-gathering ingredients from the backpack between items. The recipe catalog, the player's known-recipe list, the skill bonuses, and the success-chance formula all live client-side already; the UI controller exposes a clean view-surface seam that every proposal below extends. None of them forks the shared client/server crafting logic, and none touches the server's craft transaction itself.

flowchart LR
  A["Use a station\nprovisional table bag"] --> B["Drop ingredients\nequip tool"]
  B --> C["Table watcher\nhash on every change"]
  C -->|"today: round trip per change"| D["(Server recipe\nresolution)"]
  D --> E["Summary: recipe name\nsuccess + exceptional %"]
  E --> F["Craft pressed"]
  F --> G["(Server craft transaction\nauthoritative, per batch item)"]
  G --> H["Progress bar\nresult + chat line"]
  H --> C
  style D stroke:#a33d2e,stroke-width:2px
  style E stroke:#a33d2e,stroke-width:2px
The two hard constraints. First: every table change currently waits on the server round-trip highlighted above, even though the full recipe database and the matching hash are client-resident; S10 removes it, and until then every information proposal tolerates one round-trip of staleness. Second: the UITK lists have no virtualization, and recipe cards re-bind whenever either item grid changes — anything computed per card must cache against the item signature, and search must debounce. The crafting simulation itself — the server-side roll, ingredient consumption, discovery rules — is untouched by everything in this document.
Section 2

Lessons: Ultima Online to modern

UO 1997 was SotA's diagnosis in miniature: a rich simulation — skill curves, material tiers, exceptional procs, maker's marks, a real player economy — behind a bare interface of tool-in-backpack menus, hidden odds, and materials destroyed on failure. Publish 14 (2001) changed no formulas and is remembered as the crafting update: one unified gump, your percentage chance shown before committing, backpack pooling ("no materials will need to be targeted"), Make Last, Make Number, and docked Repair and Smelt verbs. Bulk Order Deeds arrived in the same publish and gave crafting a reason to be opened daily. The salvage bag (2007) turned the most repetitive action in the game into one context-menu click. Imbuing (2009) converted the runic-tool slot machine into a spent budget with shown odds. Every step was interface-and-loop work on an unchanged simulation.

Oil painting of an open recipe book on a lectern, threads of golden light connecting its pages to shelves of reagents and materials
The recipe graph made visible: every ingredient knows what it becomes, every result knows what it needs. The client already holds this entire graph; proposals S8, S12 and S13 finally draw it.
1997
UO launch crafting
Deep simulation, blind interface: hidden odds, per-pile targeting, destroy-on-fail.
2001
UO Publish 14
The gump: shown success %, material pooling, Make Last / Make Number. Plus BODs. No formula changed.
2003
SWG
Schematic / tool / station split, experimentation, factories: batch crafting as a structure, practice mode.
2007–09
UO salvage bag, imbuing
Bulk verbs beat per-item verbs; every random lever grows a deterministic sibling.
2012
GW2
Craft from material storage, per-row can-make counts, "+" crafts the missing part, warm/cold discovery.
2013–14
FFXIV, ESO
The crafting log as progression; daily writs industrialize the loop; Teamcraft proves the shopping-list gap.
2021–22
New World, WoW DF
Settlement-storage crafting; crafting orders + the genre's best pre-commit quality forecast.

What each game contributes

Ultima Online: the template — the gump before the math, pool materials, show the number, give crafting a goal loop, bulk verbs, and ship the batch primitive completely (UO never did; "Make Last Number" is a twenty-year-old open request). Star Wars Galaxies: the closest kin to SotA's player-economy DNA — schematics as knowledge, experimentation as directed enhancement, factories as the proof that deep crafting and mass production can coexist, practice mode as the market-safe trainer. FFXIV: the crafting log with first-craft checkmarks makes breadth itself a goal; right-click a material to find its recipes; Teamcraft's existence is the strongest evidence that multi-level crafting lists belong in the client. WoW Dragonflight: the expected-quality bar is the gold standard of pre-commit transparency, and crafting orders solved "find me a crafter" after nineteen years. ESO: daily writs and an improvement dial that reaches 100% if you pay for it; the craft bag is the mechanic to copy and the paywall not to. GW2: the best crafting panel shipped — storage-fed counts, inline subcomponent crafting, discovery that tells you when you are warm. New World: storage-shed crafting with a spatial cost, and bulk salvage with the lock rail UO's salvage bag lacked.

Capability matrix

CapabilityUOSWGFFXIVWoWESOGW2NWSotA todaySotA proposed
Search by ingredient or result● S8
Recipe favorites / pinning● S7/S18
Can-make count per recipe◔ filter only● S15
Craft max / craft all● S4
Craft again / repeat last● 2001● S3
Batch queue across recipes● factories◔ addon● S11
Instant local recipe match○ round trip● S10
Multi-level materials breakdown◔ 3rd party◔ addon● S12
Craft from bank / storage◔ lot, in flight● S20
Success or quality forecast○ n/a◔ station only● S9/S10
Practice / trial craft○ rejected
Created-by / used-in links● S13
Discovery feedback◔ silent● S14
Per-recipe crafted count◔ hidden● S19
Bulk salvage with locks◔ bag◔ addon● S17
Crafting orders / writs● BODs● leves◔ S22

● native · ◔ partial or third-party · ○ absent. "SotA today" = the UITK crafting windows on the migration branch, 2026-07. WoW = Dragonflight and later.

Section 3

The twenty-two proposals

Mockup legend — the real ingredient tints: carried (enough in backpack) lot supply (reachable via lot chests) short (missing) success chance / selection stack counts

Tier 1 · Quick wins — client-only, zero new server traffic

S1 · Grid tooltips return

ShippedTier 1Size SServer: none

Shipped 28 July 2026, as part of a pass that restored hover info to every converted item list. Hovering an item on either crafting pane shows its tooltip again, and the Show Inventory Tooltips option governs it.

Hovering an item on the crafting table or the backpack pane shows the item tooltip again. The UITK grid shipped with no tooltip wiring at all, so both crafting panes lost hover info in the port. This is a straight regression fix, the cheapest trust repair on the list, and the hover surface that S2, S13 and S19 render into.

Seen in: every modern crafting UI; parity with SotA's own pre-port window.

Implementation notes

The inventory improvement program's S10 builds the shared UITK tooltip builder (hover via the project's reliable mouse events, short delay, tooltip keyed to the item and re-anchored across rebuilds, honors the Show Tooltips option). This item routes both crafting grids through the same builder, so the crafting window and the backpack tell one truth. Tooltip content assembly stays out of the quarter-second rebuild tick.

client Sserver noneperf hover-only costtests shared tooltip builder units

S2 · Rich recipe tooltips

ShippedTier 1Size MServer: none

Shipped 29 July 2026. Recipe rows and recipe book cards both hover the full readout now. The ingredient list is not limited to the eight rows a card can draw, so long recipes finally show everything they need.

Hovering a recipe row shows what matters: the result item, the full ingredient list with have/need counts, the recipe's tier and school, and the required skill. Today the hover shows the recipe's display name and nothing else — the rich tooltip path the old UI had is unreachable from the new list.

Seen in: WoW and FFXIV recipe tooltips; the baseline everywhere.

Implementation notes

Everything the tooltip needs is already computed for the card itself (the card model exposes ingredients, tints, counts, skill line, success chance). This item assembles that data into the S1 tooltip surface instead of the bare name string. One builder, reused by the recipe book's cards.

client Mserver noneperf hover-onlytests tooltip content builder units

S3 · Craft Again + quantity memory

ShippedTier 1Size SServer: none

Shipped 30 July 2026. The quantity you set is remembered for that recipe and comes back the next time you put it on the table, and an empty table now offers to make the last thing you made here again. The offer follows the station, so the forge does not offer you a shirt.

The quantity field remembers your last quantity per recipe, and after a craft finishes (or the table empties), the empty-table hint zone offers one inline button: "Craft again: Longsword x 5". One click re-gathers the same ingredients and re-validates normally. UO shipped Make Last in 2001; this is that, plus the quantity memory UO still lacks.

Seen in: UO Publish 14 Make Last; FFXIV Quick Synthesis repeat.

Implementation notes

Cache the last crafted recipe and quantity after a successful run; the button drives the existing auto-populate path (which already clears the table, gathers from backpack and optionally lot supply, and aborts cleanly on shortfall) followed by the normal validation. No new trust surface: the server still validates at craft time. Memory is client prefs in v1; S18 makes it follow the character.

client Sserver noneperf nonetests controller state units

S4 · Make Max

ShippedTier 1Size SServer: none

Shipped 30 July 2026. A Max button sits between the quantity stepper and Craft, and sets the count to the most your staged materials allow. It greys out when the count is already there, so an empty table says so instead of letting you press it. It also carries a tooltip the window never had: crafting several at once earns less experience for each item and gives no materials back when one fails.

A Max button beside the quantity stepper jumps the count to the most your materials can supply. The client already computes exactly this ceiling when it sizes a batch; the button just surfaces the number players currently discover by overshooting.

Seen in: UO Make Max, GW2 and ESO quantity controls, everywhere since.

Implementation notes

The batch-count computation already walks table + backpack + lot counts per ingredient archetype. Max sets the stepper to that value, clamped to the batch cap of fifty plus the refinement bonus; with S11, values beyond the cap become queued waves instead of being clamped. The button is disabled whenever the count already sits at the ceiling.

Built: the cap and the ceiling arithmetic moved into a pure values-in-values-out class so they could be tested at all — the fifty was an unnamed local inside a method that also walked containers, and nothing covered it. Three defects fell out. Two of the four hand-written copies of the ceiling expression were missing their floor, so a table holding nothing the recipe wanted wrote a literal zero into the quantity field and took that recipe's remembered quantity with it; a negative refining bonus could drive the cap below one and abandon the craft outright; and the obvious rewrite of the counting climb divides by zero on a real input. All four callers read one accessor now.

The press deliberately leaves the quantity memory alone. That memory holds what you asked for, and a Max value is whatever your pack happened to hold at the moment you pressed it — pressing Max to read the number should not overwrite the twenty you typed yesterday. Pressing Craft afterwards records it the ordinary way.

client Sserver noneperf cheaper than beforetests 14 units

S5 · Missing-ingredients readout

ShippedTier 1Size SServer: none

Shipped 30 July 2026. When double-clicking a recipe cannot fill the table, the window names what it could not find, on its own line under the summary and in the same red the short ingredients on the card use: "Missing for Longsword: 1 Sword Hilt, 2 Iron Ingot". The number is the gap rather than the requirement, so short one of three says two. The chat line carries the same sentence instead of the old generic one.

When double-click auto-populate cannot fill the table, the window says so in place: "Missing for Longsword: 1 Sword Hilt" appears in the summary block, with the short ingredients tinted red on the card. Today the attempt aborts with a chat line most players never see, and the table just stays unchanged.

Seen in: UO Publish 14 details pane; GW2 and ESO shortfall displays.

Implementation notes

The shortfall math already exists (per-ingredient found-vs-required contexts, the same data the card tints run on); this routes the failed auto-populate result into the summary text surface instead of chat. Reuses the lot-supply aggregate counts so the summary and the card can never disagree. One new localized string.

client Sserver noneperf nonetests summary composition units

S6 · Sortable recipe list + skill tint

ShippedTier 1Size MServer: none

Shipped 30 July 2026. A Sort dropdown sits beside the category one: Name, Success chance, Can make, Skill. Recipe names carry a colour now. Red is a recipe your skill cannot reach yet, orange is one that fails more often than it works, then yellow and green as the odds improve, and a dim grey once the craft cannot fail at all. Your choice of order is remembered. Can make counts what your materials actually cover, so the recipes you can produce most of come first. "Recently crafted" is listed but not selectable yet; it needs the per-recipe craft counts S19 brings.

A Sort dropdown joins the category dropdown: Name, Success chance, Can make, Skill. Recipe names tint by skill relevance — the convention WoW taught the whole genre — so a glance separates "still teaches me something" from "trivial". Recipes far below your skill dim toward the existing unreachable style.

Seen in: WoW's orange-to-grey recipe colors (vanilla, copied everywhere); FFXIV level-range tabs.

Implementation notes

Comparators are pure functions over data the card model already holds (name, computed chance, craftable count, required skill vs the player's). The sort choice persists with the window's other prefs. "Recently crafted" appears in the dropdown greyed out until S19 supplies the data. Sorting happens at row-list build time; no per-frame cost.

Built: the tint runs off the computed chance of success rather than the bare skill requirement. That chance already folds difficulty, your skill and your tool bonus into one number, and it tops out at 100%, which is exactly what trivial means. Most recipes declare no skill requirement at all, so a margin against the requirement alone would have put nearly the whole list in one colour and said nothing. An unmet requirement still wins over the chance, so the name and the required-skill line under it cannot end up saying different things.

Every order falls through to name and then to the row's original position, so rebuilding an unchanged list cannot shuffle equal rows around. That matters more than it sounds: the list rebuilds whenever either item grid changes. Name now sorts on the name printed on the card, where the old fixed order sorted on an internal one, so a few recipes sit in a different place than they used to.

Can make needed a real count, and a count means reading your bags once per recipe. It reuses the cache the "Only craftable" filter already fills, widened from a yes/no to a yes/no and a number out of that same single read, and the window only asks for it when that order is chosen. Tools and optional ingredients are left out of the arithmetic but still have to be present: one hammer covers a whole batch, and counting it as a limit would have pinned every recipe that wants a tool at "can make 1".

client Mserver noneperf sort at rebuild onlytests 71 units

S7 · Favorite recipes

ShippedTier 1Size SServer: none

Shipped 30 July 2026. Every recipe card leads with a star. Click it and the recipe goes gold and rises to the top of the list, whichever order you have the list in. A "Favorites" entry sits under All Recipes in the category dropdown, and the recipe book opens a Favorites chapter ahead of the schools, gathering your starred recipes from every craft onto their own pages. Stars follow the character, not the station, so one star shows up everywhere that recipe does.

A star on every recipe card. Starred recipes float to the top of the list, and a "Favorites" entry joins the existing category dropdown, exactly the way the inventory window treats Locked as a pseudo-category. The recipe book gets a Favorites chapter, first in the contents. Your six daily recipes stop hiding in a fifty-eight card scroll.

Seen in: WoW recipe favorites (addon-proven for years, then first-party); Terraria's favorite-and-protect pattern.

Implementation notes

Client prefs in v1 (per-machine), keyed alongside the existing per-station-type window persistence; S18 upgrades the store to the character. The star is part of the card header row, not a new column; the pseudo-category is one more entry in the dropdown's source list. Book chapter builds from the same set in the pure page model, which is already unit-tested.

Built: one set for every station and the book alike rather than a set per station type. A star is a statement about a recipe, not about a forge, and the book's chapter has to gather starred recipes from every craft at once, which a per-station store could not answer. It keys off the character name, so two characters on one machine do not inherit each other's stars.

The star is one glyph in two colours rather than a filled one and a hollow one. The filled star is the only one the game's fonts are known to carry, and an unstarred card showing a missing-glyph box would read worse than a dim star does.

Favourites float in every order, not just one. A star means keep this where I can reach it, and an order that dropped it back into the run would be answering a different question than the one asked. Inside the starred run the order you picked still applies.

Two rules the book needed. A starred recipe appears twice, once in the Favorites chapter and once in its own school, so the chapter's pages are deliberately left out of the jump-to-recipe map: otherwise learning a recipe would take you to the Favorites page instead of the recipe's real home. And the chapter stays out of a filtered book entirely, the same way the contents and the chapter pages already vanish under a search, because a filtered book is the list of matches and a favourites section would print half of them a second time.

Starring while the book is open repaints the star at once but does not restructure the book underneath you. Adding or removing the chapter shifts the page number of everything after it, and you would be thrown onto a different page by your own click. The chapter catches up the next time the book is opened, which is also when a star set at a crafting station arrives.

client Sserver noneperf nonetests 92 units

S8 · Search ingredients and results

ShippedTier 1Size MServer: none

Shipped 30 July 2026. The Filter box at a crafting station and the search in the recipe book both match a recipe's name, its ingredients and what it makes. Type "iron ingot" and you get the recipe that produces one and the recipes that consume one, with the smelting recipe at the top rather than buried. Three words narrow it: uses:coal for recipes that consume coal, makes:ingot for recipes that produce one, name:sword to search names only. Put a minus in front of a word to exclude it, quote a phrase to match it whole. Hover the box for the syntax.

The one Filter box learns to match what players actually think in: typing "iron ingot" finds every recipe that consumes iron ingots and the recipe that produces them, not just recipes with "iron ingot" in their name. The recipe book's search does the same.

Seen in: FFXIV's "Search Recipes Using This Material"; WoW's first-party profession search after fifteen years of addons proving the demand.

Implementation notes

One reverse index built when the recipe catalog loads (ingredient name and result name to recipe list, 3,283 recipes, trivial memory), shared verbatim by S12's breakdown and S13's links. The station filter and the book's debounced search both consult it after the name match. Classification (wildcard) ingredients index under each member name. Search stays debounced because the recipe pane rebuilds its rows per change. Token grammar coordinates with the inventory program's search tokens (uses:, makes:) so the two windows never learn different languages.

Built: widening what a typed word matches is not enough on its own. At a well stocked forge "iron ingot" now returns a hundred recipes that consume one, and the recipe that makes one would sit wherever the alphabet put it. Recipes matched on their own name float above the ones matched only through an ingredient, under your starred recipes and above whichever order you picked. Outside a search nothing moves.

The index builds a recipe at a time, the first time something asks about it, rather than all 3,283 when the catalog loads. Working out what a salvage recipe can produce means walking its whole loot table, and doing that for the entire catalog at startup would cost every player a slower load to serve a search most sessions never run.

A half-typed token is not a filter. "uses:" on the way to "uses:coal" is a real string that asks for nothing, and treating it as a live search emptied the recipe list and blanked the book between two keystrokes.

Words this search does not have are reported rather than guessed at. Type something like "type:reagent" and a line under the box tells you what it does know, instead of quietly searching for that text and finding nothing. Those spellings are being kept clear for the inventory window's own search, so the two boxes will not end up speaking different languages.

Known limit: a recipe that asks for "any ore" is indexed under that, so uses:copper will not find it. Search matches what the recipe card actually prints, and the card prints "Ore". Expanding those into every member belongs with the shopping-list work that has to group them anyway.

client Mserver noneperf index per recipe, on demandtests 36 units + wiring

S9 · Success % in the book

ShippedTier 1Size SServer: none

Shipped 30 July 2026. Every recipe card quotes your chance of success now, in the recipe book at home as readily as at a forge, and the recipe names carry the same red-through-grey relevance colour the station list has. Hover a card and the chance of an exceptional item sits under it. When you are not standing at that craft's table, both say so: "Chance shown for a standard station and your equipped tools." Plan a levelling run from your house.

Recipe-book cards show your success and exceptional chance wherever you are, with one honest qualifier: "Chance shown for a standard station." Today the same card computes and shows the number at a station and hides it everywhere else, so planning "what should I level next" means running to a forge.

Seen in: WoW's always-visible recipe difficulty; ESO's improvement percentages.

Implementation notes

The card presenter already runs the shared success formula with the player's skill and bonuses; the visibility gate is a modeled predicate that currently requires station flags. Widen it to fall back to the recipe's own school flags with a zero station-difficulty assumption, and add the qualifier line so numbers at an actual station (which add station difficulty and tool effects) reading slightly differently never looks like a bug.

Built: the odds follow the recipe's school rather than the station in front of you, which turned out to matter more than the "away from a station" case it was written for. The recipe book handed every card on a page the open station's craft, so reading the tailoring chapter while standing at a forge quoted your blacksmithing against tailoring recipes. That is fixed by the same change.

No new arithmetic was needed for "a standard station". A station adds its tier to your skill while its window is open, so away from one the existing formula already answers the standard-station number. The qualifier names your equipped tools as well, because the tool bonus is yours rather than the station's and is included in the number: read the book with no smith hammer equipped and the forge will show you a higher chance, and blaming that on the station alone would have been wrong.

The exceptional chance went on the hover rather than the card. The card is the same one the station list uses, and its rows are a fixed height a second line would overflow; and on the ingots, reagents and meals that are most of the book the number is a critical success rather than an exceptional item, which the hover has room to say and a bare second percentage did not.

Two smaller faults fixed on the way through: hovering a recipe at a printing press used to raise an error inside the tooltip, and a recipe authored with an out-of-range difficulty could reach past the end of the success table, which mattered more once the book started reading every craft rather than one station's list.

client Sserver noneperf same math, new contexttests 47 units

Tier 2 · Core upgrades

S10 · Local table resolution

Tier 2Size LServer: none (validation stays server-side)

The enabler. The instant your table contents change, the window says what they will make, your odds, and what is short — with zero latency, because the client resolves the recipe locally. The ingredient-hash function is shared client/server code and the full recipe cache is client-resident; the recipe cards prove the math every frame. One authoritative server validation remains, exactly where it matters: the moment you press Craft, Salvage, or Repair.

Seen in: every crafting UI in the genre; SotA is the outlier in asking the server per change.

The summary block, after S5 + S10 + S14 + S19
Longsword
84% success chance
12% exceptional item chance
Crafted 41 times. Producer XP is normal for this recipe.
Missing for Longsword: 1 Sword Hilt
These items appear in 2 recipes you have not learned.
All six lines local; the first four update the instant the table changes
Implementation notes

Replace the poll-and-round-trip cycle with local resolution: hash the table via the shared helper, look up the shared recipe cache, compose the same summary strings. Repair and salvage eligibility are not client-computable and explicitly stay server-side; their buttons enable from the single validation that runs when pressed, which also remains the authority for the craft itself (the server transaction is untouched, per the standing safety rule). Local-versus-server mismatches log for telemetry. Parity is provable in EditMode by replaying recorded server validation answers across the entire recipe database.

client Lserver noneperf removes a round-trip per table changetests resolver parity replay

S11 · Batch queue

Tier 2Size LServer: none

While a craft runs, the Craft button stays alive and enqueues: line up two hundred ingots, then forty bandages, and watch the queue work through them in the progress block, each line with its own cancel. Batches beyond the server's per-request cap become successive waves instead of manual re-presses. This is the answer to the community's loudest crafting ask — bulk refining an evening's gathering in one interaction.

Seen in: SWG factories (the structural ancestor); FFXIV Quick Synthesis; the addon queues WoW players ran for a decade.

Progress block while a queue runs
Crafting Iron Ingot 37 of 200   Cancel
Next: Iron Ingot x 150 (wave 2)  [x]
Next: Bandage x 40  [x]
Craft relabels Queue while running; queued lines cancel individually
Implementation notes

A client state machine sequencing the existing per-item craft requests and the existing between-item re-gather; the server batch cap and per-item validation are untouched, and gathering skips anything the inventory program's bulk-protection predicate shields. Checkpoints after every completed item; window close, station exit, tool break, and disconnect cancel cleanly at the next boundary (the close path already waits for the in-flight operation). The wishlist's "equal XP for bulk refining" half is a server balance question, handed to the per-tree dives; this item makes bulk fast, not cheaper. Ships with the free fix for the progress bar's wrong-color flash between batch items.

client Lserver noneperf no new traffic; same RPCs, sequencedtests queue state machine units

S12 · Shopping-list drill-in + Craft This Next

Tier 2Size LServer: none

The selected recipe card grows a "Full materials" expander that walks the whole tree: the Longsword needs a Sword Hilt you do not have; the hilt needs six ingots and coal you do. Each short subcomponent row carries a "Craft this next" button that loads that recipe onto the station and remembers the way back. The out-of-game spreadsheet dies.

Seen in: GW2's "+" subcomponent button (one level); FFXIV Teamcraft, a third-party empire that exists only because the game never shipped this.

Selected card, expanded
Longsword84%
Sword Hilt0/1
Sword Blade1/1
Binding Ropes2/2
[v] Full materials
Sword Hilt needs
Iron Ingot6/6
Coal4/4
Craft this next >
Implementation notes

Expansion walks the client's reverse index (result to producing recipes) plus each recipe's ingredient list; cycle-safe, depth-capped, wildcard ingredients grouped by classification. Where several recipes produce one item, prefer known, then craftable, then cheapest. Counts come from the same found-versus-required contexts the card tints use. "Craft this next" drives the S3 load path and pushes a one-deep return breadcrumb ("Return to Longsword" in the hint zone). Cross-station subcomponents display the required station name instead of the button. Expansion computes on demand (selection), never in the rebuild tick.

client Lserver noneperf on-select only; depth-cappedtests cycle-safe walk units

S13 · Created-by / used-in links

Tier 2Size MServer: none

Every item tooltip and book card gains two lines: "Created by: Smelt Iron Ingot" and "Used in 14 recipes" — clickable, paging the recipe book or selecting the recipe at a compatible station. The game becomes its own wiki, and the "what is this reagent even for" dead-item problem dies with it.

Seen in: Vintage Story's Survival Handbook (the genre gold standard); FFXIV's material search.

Implementation notes

Forward data is the recipe's ingredient list; reverse is S8's index plus the existing result-to-recipes lookup. Renders inside the S1/S2 tooltip surfaces and on book cards; the book's deep-link entry points (page to recipe, page to school) already exist and keep their signatures. Undiscovered recipes render as "??" so the graph never spoils discovery; large used-in sets group by classification and cap with "and N more". Reference only; zero economy surface.

client Mserver noneperf index lookups, hover/select onlytests index units share S8's

S14 · Discovery feedback

Tier 2Size MServer: none

When the items on your table partially match recipes you have not learned, one quiet summary line appears: "These items appear in 2 recipes you have not learned." Add or remove items and the count warms or cools. Discovery stops being an accident and becomes deduction — without naming anything, and without changing what is discoverable.

Seen in: GW2's Discovery tab ("[N] possible unknown recipes! Add more compatible ingredients!"), the one discovery UI players praise.

Implementation notes

Pure client counting: the catalog (with its discoverable flags), the known-recipe set, and every recipe's full ingredient-hash fan-out are local. A recipe counts as warm when the table's items are a subset of one of its ingredient sets. Hints stay coarse — a count, never a name, and recipes above a rarity threshold are excluded entirely — so rare discoverables do not become checklist items. The actual reveal still happens through the unchanged server learning flow on first craft.

client Mserver noneperf recompute on table change onlytests partial-match counter units

S15 · Can-make counts

Tier 2Size MServer: none

Every recipe row shows "x12": how many you can make right now from the selected material sources (backpack, plus lot supply when the toggle is on). Combined with the S6 sort, "what can I make with what I have" becomes a glance instead of a filter toggle and a scroll.

Seen in: GW2's Production tab, the affordance every crafter who has played it asks other games for.

Implementation notes

The Only Craftable filter already maintains a per-refresh craftability cache; this extends it from a boolean to a count (the division the batch-ceiling computation already performs). Cached per item-signature because cards re-bind whenever either grid changes; recomputed only when the signature moves. Shown as part of the card header, controlled by an option in the gear menu for players who want quieter cards.

client Mserver noneperf cache keyed to item signaturetests availability tests extend

S16 · Station coherence pass

Tier 2Size MServer: none

Three debts in one pass. The Recipes button ungates, so the recipe book opens from every station, not just blacksmith, tailor, and carpentry. The backpack pane's per-station relevance filter becomes real — the smelter highlights ore and flux instead of guessing — today it is stubbed for most station types. And the polish items land: the progress bar stops flashing the wrong result color between batch items, and salvage and repair durations respect skill.

Seen in: baseline coherence expectations; New World and ESO per-station material filtering.

Implementation notes

The book gate shares a predicate with Salvage/Repair today; splitting them is button wiring. Salvage and Repair stay gated where the actions are server-legal (eligibility remains server-authoritative). The relevance filter's per-school material categories get authored once, as data, not code branches. Salvage/repair timing that changes actual durations extends the shared timing helpers, never forks them.

client Mserver noneperf nonetests station conversion tests extend

S17 · Bulk salvage

Tier 2Size MServer: none

Select a pile of loot on the backpack pane (or filter: "all Common weapons in this bag"), press Salvage once, and the run works through it visibly, wave by wave, with a cancel — and with everything you have locked automatically excluded, so good gear is never one misclick from becoming scrap.

Seen in: UO's Salvage Bag (the verb is "salvage a selection"); New World's bulk salvage with rarity filters and locks, the safety rail UO's version lacked.

Implementation notes

Client automation of the existing load-table, validate, salvage cycle: candidates load in waves under the table cap (the server already accepts salvage batches up to one hundred), each wave validates server-side, per-item rejections skip gracefully. Every candidate must pass the inventory program's bulk-protection predicate (locked, quest, no-trade, packaged) before it ever touches the table. Yield preview is an estimate and labeled as one. Shares S11's queue executor. No new server surface, no new mutation path.

client Mserver noneperf sequenced existing RPCstests selection filter + wave planner units

Tier 3 · Server-backed

Each of these lands with its data-migration ledger row, its shared-code mirror sync, and a tester task, one server change per commit.

S18 · Per-character crafting state

Tier 3Size Lnew collection

Your starred recipes, your per-station Craft Again memory, and named loadouts ("Tuesday batch: 200 ingots, 40 bandages") follow your character across machines and sessions. The station finally remembers you.

Seen in: WoW's synced favorites; SWG's manufacturing schematics (the saved-intent half, without the factory).

Implementation notes

This item creates the missing home. The known-recipes store is account-scoped by design, so nothing per-character can persist today; a new per-character collection (favorites, last-craft-by-station keyed by the existing station identity, loadouts) loads alongside the recipe book at login, with optimistic client updates mirroring the established pattern and debounced writes. S3 and S7 upgrade from machine-local prefs automatically. Ledger row: collection creation, index spec, rollback is a drop.

client Mserver Mdb new collection + ledger rowtests serialization + merge units

S19 · Crafting record display

Tier 3Size Mread RPC

Cards and the pre-craft summary show "Crafted 41 times. Producer XP is reduced for this recipe." The game already tracks per-recipe success counts and decays crafting XP against them; players just cannot see either, which is why the decay reads as a bug on the forums instead of a system.

Seen in: visible craft XP is the EQ2/FFXIV baseline; the decay-transparency half is rarer and better.

Implementation notes

The one missing input is the server-side per-recipe success count. A bulk read at login (next to the recipe-book fetch) exposes it, which also unlocks the "Recently crafted" sort in S6 and away-from-station display with S9. The XP formula mirrors into the shared helpers so the client predicts the actual award. No schema change; the new read rides the regenerated RPC table and the usual pre-deploy checks.

client Sserver Sdb none (read-only)tests XP mirror parity units

S20 · Bank pull + leftovers return

Tier 3Size XLops

The craft-from-lot-storage feature's next two rooms, in its own documented order: at stations on your lot, the "Use lot storage" toggle grows into a Materials selector that can also reach your bank; and when the window closes, pulled-but-unused materials flow back where they came from instead of flooding your backpack.

Seen in: WoW's reagent bank, GW2's material storage, New World's storage shed — the modern canon's number-one feature, adapted to SotA's lot-and-bank shape.

Implementation notes

These are the in-flight lot-supply feature's explicit v1 non-goals, picked up as its v2. Bank contents are not client-resident, so a scoped query op follows the feature's advisory-counts pattern; transfers stay client-orchestrated over existing move operations — the rejected idea of one server-side gather op stays rejected, because concentrating item movement in a single new op is exactly the duplication surface the standing safety rule exists to prevent. Leftover return rides origin tags on pulled stacks, unwound through the same move path at close. Sequenced strictly after the base feature's remaining hardening; heaviest safety-review item in this document.

client Lserver Mdb none expected; ops reviewtests conservation + planner integration

S21 · Signature-free commodity crafts

Tier 3Size Mrecipe flag

Arrows, bandages, and other low-value bulk crafts stop carrying an individual crafter signature, so they finally stack — ending the inventory sprawl that punishes exactly the players who craft the most. Masterworked, enchanted, and showpiece items keep their maker's mark; commodity output stops pretending to be one.

Seen in: commodities stack in every genre economy; the maker's mark stays where UO put it, on the exceptional work.

Implementation notes

A data-driven flag on the recipe asset, exported through the standard recipe data pipeline, consumed at the existing signature-application site — a minimal, reviewable diff, not a craft-path restructure. Which recipes qualify is per-tree input; this ships the mechanism and a conservative first list. Forward-only: existing signed stacks never merge with new unsigned ones, which gets a behavioral note in the migrations ledger for support. Anything enhanced or branded stays signed, always.

client Sserver S + data passdb behavioral ledger notetests flag consumption units

Tier 4 · Directional

Oil painting of a dawn workshop: a row of finished swords cooling in sequence while a craftswoman reads a wax-sealed order ledger
The orders morning: queued work finished overnight, commissions checked against the ledger. Every long-lived crafting economy eventually builds this loop; UO got there in 2001.

S22 · Crafting orders board

Tier 4Size XLmajor

A rotating order board at crafting halls: "The garrison wants 20 Iron Longswords. Reward: gold, rare fuel, a bounty voucher." Crafters get a reason to open the station beyond self-supply, low-tier goods get a demand signal, and designers get a safe channel for crafter-only rewards. This is the highest-return retention retrofit in crafting history — UO's Bulk Order Deeds required zero changes to the crafting math — and the one big loop SotA never inherited. Presented as a direction to react to, not a spec.

Seen in: UO Bulk Order Deeds (2001), ESO daily writs + Master Writs, EQ2's untimed Work Orders and timed Rush Orders, WoW Dragonflight's order board.

Implementation notes

V1 sketch: NPC orders generated from the recipe catalog (creation recipes only), untimed and timed variants side by side so the loop is never reflex-gated, turn-in verified by the crafter signature (the one place the signature is a pure asset), rewards through existing grant paths, never a new mutation path. Needs new server collections for board state, per-character progress in S18's record, an economy review, and deliberately conservative initial rewards with telemetry. Player-to-player commissions are v2, only if the NPC loop proves out. Per-school reward tables belong to the per-tree dives.

client Lserver XLdb new collections + ledger rowseconomy review board first

Considered and rejected

Section 4

The composed window

Composition rules that keep twenty-two features from becoming twenty-two widgets: the Filter box is the query surface (S8 extends its matching; no second box appears); one options surface (a gear in the chrome) hosts every preference tail; tooltips and the summary block absorb every pure-information feature (S2, S5, S9, S10, S13, S14, S19); the queue lives inside the existing progress block (S11); the shopping list is a drill-in of the selected card (S12), never a fourth pane; favorites are a star on the card plus a category entry (S7). Net new widgets across the whole catalog: three — the Sort dropdown, the Max button, and the options gear.

Blacksmithing Station⚙  pin  ✕
Recipes
Favorites ▾Sort: Can make ▾
hilt
Materials: Backpack + lot ▾
☑ Only craftable
Sword Hiltx12 91%
Iron Ingot6/6
Coal4/4
Longswordx3 84%
Sword Hilt0/1
Sword Blade1/1
Binding Ropes2/2
[v] Full materials
Sword Hilt needs Iron Ingot 6/6, Coal 4/4
Craft this next >
Iron Ingotx8 95%
Iron Ore25/25
Coal4/4 (+2 lot)
favorites first, then by can-make count
Crafting Inventory
Iron IngotIron IngotCoal
Capacity: 3 / 10  ·  Blacksmith Hammer 198/200
Longsword
84% success chance  12% exceptional
Crafted 41 times. Producer XP is normal for this recipe.
Missing for Longsword: 1 Sword Hilt
These items appear in 2 recipes you have not learned.
5+MaxCraft
SalvageRepairRecipesTake All
Crafting Longsword 2 of 5  Cancel
Next: Sword Hilt x 2  [x]
Your Inventory
Show: Blacksmithing ▾
Iron Ingot24
Coal61
Sword Blade1
Bandage55
Iron Ingot
Crafting material
Weight 1.0Value 15
Created by: Smelt Iron Ingot
Used in 14 recipes
Empty-table hint zone adds: Craft again: Longsword x 5

Zone anatomy

chrome        title + options gear (the ONE options surface) + pin + close
left pane     query row (category + sort) / filter row (THE query surface)
              source row (materials selector + only-craftable)
              card roster: favorites first, drill-in lives on the selected card
center pane   station vignette / table grid (empty state hosts Craft Again)
              capacity + equipped tool
              summary: recipe, odds, record, shortfall, discovery
              stepper + Max + Craft / Salvage Repair Recipes | Take All
              progress block: bar + queue lines (swaps with the controls)
right pane    Show dropdown (station-aware) / backpack grid, tooltips on

The recipe book, evolved in place

Recipe Book
oak
Contents
Favorites6
Alchemy31
Blacksmithing58
Carpentry44
Oak Bow78%
Oak Timber12
Bowstring1
Chance shown for a standard station
Used in 2 recipes
page 12 of 31

Same book, four upgrades: search that sees ingredients and results (S8), a Favorites chapter first in the contents (S7), success chances away from stations with their qualifier (S9), and reference links that page the book (S13). Cards stay draggable for teaching and vendor listing.

Section 5

Sequencing

PhaseShipsServerDepends onWhy this order
1S1, S3, S4, S5, S7, S9 + free fixesnonepatch-note-sized wins; the tooltip regression first
2S2, S6, S8, S13, S15noneone shared reverse index serves S8, S12, S13query power and list identity
3S10, then S11, S12, S14noneS10 is the enabler; S12 needs S8the resolver core; queue and breakdown stand on instant resolution
4S16, S17noneS17 needs the bulk-protection contract + S11's executorwider surfaces, bulk safety
5S18, S19, S21, S20, S22collection, RPC, flag, ops, majorS7 → S18; lot-supply feature → S20; S18 → S22one server change per commit, ledger row in the same commit; S22 last, after economy review
flowchart TD
  P1["Phase 1: S1 S3 S4 S5 S7 S9"] --> P2["Phase 2: S2 S6 S8 S13 S15"]
  RIDX["Reverse recipe index"] --> S8x["S8"] & S12x["S12"] & S13x["S13"]
  S10x["S10 local resolver"] --> S11x["S11 queue"] & S14x["S14 discovery"] & S15x["S15 counts"]
  S8x --> S12x
  S11x --> S17x["S17 bulk salvage"]
  S7x["S7 favorites"] --> S18x["S18 per-character state"]
  LOT["Lot-supply feature (in flight)"] --> S20x["S20 bank pull"]
  S18x --> S22x["S22 orders board"]
  S12x -.-> S22x
Section 6

Appendix

A1 · Zero-RPC proof

Every display datum in the seventeen client-only proposals is already client-resident: the full recipe catalog with ingredients, results, tiers, difficulties, schools, discoverability and fuel flags (loaded once at startup); the known-recipe set with teachability (synced at login); every skill level and crafting bonus stat (local character state); the success, exceptional, and recovery formulas (shared code, the server's own math); recursive backpack ingredient counts plus the lot-supply advisory counts; the result-to-recipes reverse lookup; and the ingredient-hash function that names any hypothetical table's recipe. Only actions transact. The one genuinely server-side display datum in this document is S19's crafted-count, which is why S19 sits in Tier 3.

A2 · Constraints honored

Shared crafting logic extended, never forked; the server craft transaction untouched by every item here; no new item-mutation paths anywhere (S17 and S20 sequence existing operations); every bulk action calls the inventory program's bulk-protection predicate; per-card computeds cache against item signatures because cards re-bind on any grid change; search debounces; the one recipe card keeps rendering identically in station and book; new reads ride a regenerated RPC table; every database change lands with its migrations-ledger row in the same commit; and every player-visible sample string in this document follows the plain-voice rules.

A3 · Test surface

Pure-logic targets for the EditMode suite: the S10 resolver (parity replay of recorded server validation answers across the full recipe database), the S11 queue state machine, S12's cycle-safe graph walk, S8's matcher and index, S6's comparators, and S14's partial-match counter. The recipe card and book page models already established the pattern, and the existing thirty-plus crafting test files stay green throughout.

A4 · Sources

UO: UOGuide (Publish 14, Bulk Order Deeds, runic tools, Salvage Bag, imbuing), the official UO wiki, and the long-running "Make Last Number" forum request. FFXIV: crafting log, Trial Synthesis (7.4), the Endwalker HQ-material removal, Teamcraft. WoW: the Dragonflight professions overhaul, The War Within's Concentration, Warband-bank crafting orders, and the fifteen-year addon canon. ESO: craft bag, trait research, writs. GW2: crafting, Material Storage, and the Discovery panel. New World: settlement storage, gear-score bands, bulk salvage. EQ2: tradeskill events, Work and Rush Orders. Valheim (the CraftFromContainers mod as a shipped spec) and Enshrouded's Magic Chest. SWG: schematics, experimentation, factories, practice mode. Vintage Story: the Survival Handbook.

Written against the unity-6.5 branch, 2026-07-26. Per-school deep dives (blacksmithing, tailoring, alchemy, cooking, agriculture and the rest) follow separately. Comments and votes below reach the team directly.

Feedback

General comments

No account needed. Every proposal above also has its own Discussion box for talking about that one alone; this thread is for the plan as a whole. Comments are plain text, held to basic decency, and may be trimmed.