Bug-triage patch — fix torch builds, idle-pawn traps, floor render order

Three playtest-reported bugs fixed out-of-phase before Phase 18:

* Furniture build-queue gap: Torch / Bed / Crate / Workbench / CremationPyre
  were missing World.register_build_site(self) in _ready, so newly-painted
  designations never entered ConstructionProvider's iteration. The seeded
  cabin pre-built everything via _spawn_complete_* helpers, masking the gap
  until a player painted a fresh furniture designation.

* Wall-trap regression for bystanders + walk-through pawns: Wall._complete
  now dislodges any pawn on the tile via new Pathfinder.find_nearest_walkable
  BFS helper; Pawn._advance_walk re-checks next tile walkability before
  stepping, aborts walk + cancels job + lets Decision reroute. Phase 6's
  adjacent-stand fix only protected the BUILDING pawn.

* Floor / Pawn Y-sort ambiguity: Floor was anchored at tile-center
  (same Y as Pawn), so Y-sort tiebreak fell to scene-tree order and
  Floor (spawned later) drew over Pawn. Moved Floor origin to top-of-tile
  so Floor.y < Pawn.y under Y-sort; _draw rect offsets compensate.

All three verified via MCP runtime: torch built end-to-end, all 3 pawns
working on different jobs with no idle traps, pawn renders over floor.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
megaproxy 2026-05-15 13:58:15 +01:00
parent d41778a483
commit 922f269a6c
9 changed files with 97 additions and 14 deletions

View file

@ -51,6 +51,33 @@ func is_walkable(cell: Vector2i) -> bool:
return _astar.is_in_boundsv(cell) and not _astar.is_point_solid(cell)
## BFS outward from `cell` for the nearest walkable tile. Used to dislodge a
## pawn trapped on a tile that just became impassable (e.g. another pawn built
## a wall on top of them). Returns `cell` itself if no walkable tile is found
## within `max_radius` (BFS-ring distance).
func find_nearest_walkable(cell: Vector2i, max_radius: int = 8) -> Vector2i:
if is_walkable(cell):
return cell
var visited := {cell: true}
var frontier: Array[Vector2i] = [cell]
var offsets: Array[Vector2i] = [
Vector2i(0, -1), Vector2i(1, 0), Vector2i(0, 1), Vector2i(-1, 0),
]
for _ring in max_radius:
var next: Array[Vector2i] = []
for c in frontier:
for off in offsets:
var n: Vector2i = c + off
if visited.has(n):
continue
visited[n] = true
if is_walkable(n):
return n
next.append(n)
frontier = next
return cell
## Returns the path from `from` to `to` as tile-coordinate steps.
## The returned array EXCLUDES `from` and INCLUDES `to`.
## Returns an empty Array[Vector2i] when: