Workbench bill editor — tap a workbench, see/edit bills

Tap-to-select chain extended to workbenches (pawn always wins on shared
tile). Mutually exclusive with pawn selection via EventBus —
selecting one clears the other.

New WorkbenchPanel (scenes/ui/workbench_panel.gd, ~432 LOC, layer 18,
right-anchored 360 px) mirrors PawnDetailPanel shape. Bill rows expose
recipe name, mode (FOREVER / COUNT / UNTIL_N), target count, completed
progress, pause, and remove. Add-bill popup filters RecipeCatalog.all()
by accepted_skill so a Hearth only offers cooking recipes.

Supporting plumbing:
- EventBus.workbench_selected / workbench_deselected signals.
- Workbench.remove_bill() — interrupts mid-craft cleanly via
  on_craft_interrupted() before erasing.
- RecipeCatalog.all() static enumerator + Recipe.display_name() helper.
- World.workbench_at_tile() lookup.
- i18n keys ui.bill.* and ui.workbench.* in strings.gd.

Closes the deferred Phase 17 "Bill UI for workbenches" item. Player-
built workbenches are now functionally configurable; before this
landed, only world.gd-hardcoded bills worked.
This commit is contained in:
megaproxy 2026-05-16 00:29:46 +01:00
parent e5f3693ad9
commit bdd435202d
9 changed files with 551 additions and 10 deletions

View file

@ -55,6 +55,8 @@ signal load_finished(slot: StringName, ok: bool, real_seconds_away: int) ## Emit
# Phase 17 — Touch UX completion.
signal pawn_selected(pawn) ## Emitted when Selection picks a pawn — opens PawnDetailPanel.
signal pawn_deselected ## Emitted when Selection clears — closes PawnDetailPanel.
signal workbench_selected(workbench)
signal workbench_deselected
signal pawn_priority_changed(pawn, category: StringName, level: int) ## Emitted when priority matrix updates a cell.
signal alert_added(severity: StringName, text: String, focus_tile: Vector2i) ## Emitted by gameplay subsystems to surface a player notice. severity = info | warn | danger.
signal request_wolf_spawn(count: int) ## Phase 15 EventCatalog → WolfSpawner. Decouples threat-event effects from spawner.

View file

@ -196,6 +196,18 @@ const TABLE: Dictionary = {
&"tool.workbench_cremation_pyre": "Cremation Pyre",
&"tool.stockpile_general": "Stockpile",
&"tool.graveyard": "Graveyard",
&"ui.bill.mode_forever": "Forever",
&"ui.bill.mode_count": "Do X times",
&"ui.bill.mode_until_n": "Do until X",
&"ui.bill.target": "Target",
&"ui.bill.until_count": "Until count",
&"ui.bill.completed": "Done",
&"ui.bill.pause": "Pause",
&"ui.bill.remove": "Remove",
&"ui.bill.add_button": "Add bill",
&"ui.bill.no_bills_hint": "No bills. Add one to start crafting.",
&"ui.workbench.current_bill": "Current",
&"ui.workbench.idle": "Idle",
}

View file

@ -124,6 +124,15 @@ func pawn_at_tile(tile: Vector2i) -> Pawn:
return null
## Returns the Workbench occupying `tile`, or null if none. Used by Selection
## to route taps on a workbench to the bill-editor panel.
func workbench_at_tile(tile: Vector2i):
for w in workbenches:
if w.tile == tile:
return w
return null
func clear_pawns() -> void:
# For save-load / new-game flow in Phase 16.
pawns.clear()