Alerts: wire room_too_large, no_stockpile_accepts, bill_blocked
Three alert signals had no UI subscribers — gameplay failures vanished silently. Now all three feed AlertsLog via translator handlers that forward to the generic alert_added sink. - EventBus: new no_stockpile_accepts(item_type, tile) and bill_blocked(recipe_label, reason, focus_tile) signals. - HaulingProvider: per-item-type 30s cooldown; emits when find_best_for scan finishes with viable items but no destinations. - CraftingProvider: per-(workbench, reason) 60s cooldown; emits at the skill_too_low and missing_ingredient continue sites. no_workbench reason declared for future use but not emitted (the iteration shape has no natural site for it). - AlertsLog: connect + disconnect for all three signals using the same has_signal-guarded pattern; translator handlers convert to localized alert_added(severity, text, focus_tile). - AlertsLog catch-up: room_too_large emits during World init, before this CanvasLayer mounts. _catch_up_room_too_large() in _ready scans World.rooms for rooms > ROOM_AUTOROOF_CAP and replays them, so the pre-built cabin's 24-tile-too-large warning lands in the log on every boot. Hauling/bill signals fire at runtime so they need no catch-up. Verified runtime: cabin warning shows up in AlertsLog with severity 'warn' and focus_tile (45, 24) — the cabin top-left. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
335ccf52b2
commit
708080a022
4 changed files with 115 additions and 0 deletions
|
|
@ -12,12 +12,22 @@ class_name CraftingProvider extends WorkProvider
|
|||
## search is global (no per-bench radius restriction — Phase 17 polish item per
|
||||
## docs/architecture.md "Ingredient acquisition radius").
|
||||
##
|
||||
## When a bill cannot proceed it emits EventBus.bill_blocked once per
|
||||
## (workbench × reason) per BILL_BLOCKED_COOLDOWN_TICKS (60 in-game seconds).
|
||||
##
|
||||
## Workbench and Pawn are intentionally duck-typed (no class_name reference) to match
|
||||
## WorkProvider convention and avoid init-order issues. Only Item.Quality and
|
||||
## QualityCalc are referenced by class_name (in job_runner.gd, not here).
|
||||
##
|
||||
## See docs/architecture.md "CraftingProvider" and docs/design.md "Bills".
|
||||
|
||||
## Rate-limit for bill_blocked alerts: one emit per (workbench × reason) per
|
||||
## 60 in-game seconds (20 Hz × 60 s = 1200 ticks).
|
||||
const BILL_BLOCKED_COOLDOWN_TICKS: int = 1200
|
||||
|
||||
## Per-(workbench_id|reason) cooldown map: String → tick at which next emit is allowed.
|
||||
var _bill_blocked_cooldown: Dictionary = {}
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
category = &"crafting"
|
||||
|
|
@ -53,11 +63,13 @@ func find_best_for(pawn) -> Job:
|
|||
|
||||
# Skill threshold check — pawn must meet the bill's minimum.
|
||||
if pawn.get_skill(b.recipe.required_skill) < b.recipe.skill_threshold:
|
||||
_emit_bill_blocked(b.recipe.label, &"skill_too_low", wb)
|
||||
continue
|
||||
|
||||
# Confirm a qualifying ingredient exists on the floor.
|
||||
var src = _find_ingredient_item(b.recipe.ingredient_type)
|
||||
if src == null:
|
||||
_emit_bill_blocked(b.recipe.label, &"missing_ingredient", wb)
|
||||
continue
|
||||
|
||||
# Score: total Manhattan travel distance pawn → ingredient → workbench.
|
||||
|
|
@ -103,3 +115,14 @@ func _find_ingredient_item(item_type: StringName):
|
|||
## Manhattan distance between two Vector2i tile coordinates.
|
||||
func _manhattan(a: Vector2i, b: Vector2i) -> int:
|
||||
return abs(a.x - b.x) + abs(a.y - b.y)
|
||||
|
||||
|
||||
## Emits EventBus.bill_blocked for the given workbench and reason, rate-limited
|
||||
## to once per (workbench × reason) per BILL_BLOCKED_COOLDOWN_TICKS.
|
||||
func _emit_bill_blocked(recipe_label: String, reason: StringName, wb) -> void:
|
||||
var key: String = "%s|%s" % [wb.get_instance_id(), reason]
|
||||
if _bill_blocked_cooldown.get(key, 0) > Sim.tick:
|
||||
return
|
||||
_bill_blocked_cooldown[key] = Sim.tick + BILL_BLOCKED_COOLDOWN_TICKS
|
||||
var focus: Vector2i = wb.get("tile") if wb.get("tile") != null else Vector2i(-1, -1)
|
||||
EventBus.bill_blocked.emit(recipe_label, reason, focus)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue