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
|
|
@ -11,11 +11,22 @@ class_name HaulingProvider extends WorkProvider
|
|||
## higher-priority destination has space — enabling the "items flow upward"
|
||||
## priority cascade described in design.md.
|
||||
##
|
||||
## When an item needs hauling but no stockpile accepts it, the provider emits
|
||||
## EventBus.no_stockpile_accepts once per item_type per ALERT_COOLDOWN_TICKS
|
||||
## ticks (30 in-game seconds at 20 Hz).
|
||||
##
|
||||
## Pawn is intentionally duck-typed (no class_name reference) to match the
|
||||
## WorkProvider convention and avoid init-order issues.
|
||||
##
|
||||
## See docs/architecture.md "HaulingProvider".
|
||||
|
||||
## Rate-limit for no_stockpile_accepts alerts: one emit per item_type per
|
||||
## 30 in-game seconds (20 Hz × 30 s = 600 ticks).
|
||||
const ALERT_COOLDOWN_TICKS: int = 600
|
||||
|
||||
## Per-item-type cooldown map: StringName → tick at which the next emit is allowed.
|
||||
var _alert_cooldown: Dictionary = {}
|
||||
|
||||
|
||||
func _init() -> void:
|
||||
category = &"haul"
|
||||
|
|
@ -41,6 +52,11 @@ func find_best_for(pawn) -> Job:
|
|||
var best_dist: int = 999999
|
||||
var best_is_corpse: bool = false
|
||||
|
||||
# Tracks the first item_type that needed hauling but had no valid destination.
|
||||
# Used to emit no_stockpile_accepts once per cooldown window.
|
||||
var first_orphan_type: StringName = &""
|
||||
var first_orphan_tile: Vector2i = Vector2i(-1, -1)
|
||||
|
||||
# ── regular items ─────────────────────────────────────────────────────────
|
||||
for item in World.items_needing_haul.keys():
|
||||
# Skip items another pawn is already carrying.
|
||||
|
|
@ -50,6 +66,10 @@ func find_best_for(pawn) -> Job:
|
|||
# Find the best destination for this item type + priority.
|
||||
var dest = _find_best_destination_for(item)
|
||||
if dest == null:
|
||||
# Item needs hauling but no stockpile accepts it — record first occurrence.
|
||||
if first_orphan_type == &"":
|
||||
first_orphan_type = item.item_type
|
||||
first_orphan_tile = item.tile
|
||||
continue
|
||||
|
||||
var drop: Vector2i = dest.find_drop_position(item)
|
||||
|
|
@ -72,6 +92,12 @@ func find_best_for(pawn) -> Job:
|
|||
best_drop_cell = drop
|
||||
best_is_corpse = false
|
||||
|
||||
# Emit alert for the first orphaned item_type, rate-limited per type.
|
||||
if first_orphan_type != &"":
|
||||
if _alert_cooldown.get(first_orphan_type, 0) <= Sim.tick:
|
||||
EventBus.no_stockpile_accepts.emit(first_orphan_type, first_orphan_tile)
|
||||
_alert_cooldown[first_orphan_type] = Sim.tick + ALERT_COOLDOWN_TICKS
|
||||
|
||||
# ── Phase 14: corpses ─────────────────────────────────────────────────────
|
||||
# Corpses route to GraveSlot StorageDestinations exactly like items, but
|
||||
# use PICKUP_CORPSE / DEPOSIT_CORPSE toils (since Corpse is not an Item).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue