Build distinct Joke Shop and TV Studio venues
Full build / Import + headless tests (push) Successful in 40s
Full build / Full desktop build + optional release (push) Successful in 4m57s

Add the alley walls, warm lantern, shutters, dumpster, AC clutter and door
step for the Joke Shop. Build the studio stone facade, bulb canopy, glossy
black car, stanchions and barriers. Rebuild only the world container when the
venue changes, so the guard and UI survive; add per-venue navigation checks.
Capture gallery shots 12/13, update the concept mapping and docs. Headless
231/231, Python 87/87, screenshot gate 13 good/0 bad. The vision-judge retry is
tracked separately because the API key is invalid.
This commit is contained in:
zwitschi committed 2026-11-01 19:09:47 +01:00
1 parent 4cca2af2dd
commit 8b0845bcce
25 files changed
+347 -87

No files matched your search

+25 -1
View File
@@ -32,6 +32,9 @@ const SettingsPanel := preload("res://src/game/ui/settings_panel.gd")
const EventTimeline := preload("res://src/game/ui/event_timeline.gd")
var world_builder: WorldBuilder = null
## Dedicated container for the procedural world, so switching venues can rebuild
## the geometry without touching the guard, UI, or other scene-root children.
var world_root: Node3D = null
var door := DoorState.new()
var flashlight_on := false
var body_camera_on := false
@@ -135,8 +138,11 @@ func _ready() -> void:
scene_root = Node3D.new()
scene_root.name = "SceneRoot"
add_child(scene_root)
world_root = Node3D.new()
world_root.name = "World"
scene_root.add_child(world_root)
world_builder = WorldBuilder.new(scene_root)
world_builder = WorldBuilder.new(world_root, active_scenario_id)
world_builder.build()
_ensure_lighting()
@@ -235,9 +241,26 @@ func _build_scenario(id: String) -> VenueScenario:
func switch_scenario(id: String) -> void:
active_scenario_id = id
selected_scenario = _build_scenario(id)
_rebuild_world_for_venue(id)
if coordinator:
restart_shift()
## Rebuild the procedural venue in place. The guard/UI stay under `SceneRoot`;
## only the `World` container is replaced, so navigation, props, lights and the
## venue-specific dressing match the selected scenario.
func _rebuild_world_for_venue(id: String) -> void:
if world_root == null:
return
for child in world_root.get_children():
child.free()
world_builder = WorldBuilder.new(world_root, id)
world_builder.build()
if guard != null:
guard.global_position = world_builder.spec.get("guard_spawn", Vector3(0, 0.1, -2.0))
guard.rotation.y = PI
if world_builder != null:
world_builder.set_door_locked(door.locked)
func restart_shift() -> void:
if shift_review_panel:
shift_review_panel.hide()
@@ -301,6 +324,7 @@ func _on_venue_selected(scenario_id: String) -> void:
active_scenario_id = scenario_id
_venue_index = maxi(0, VENUE_ORDER.find(scenario_id))
selected_scenario = _build_scenario(scenario_id)
_rebuild_world_for_venue(scenario_id)
if hud:
hud.set_wand_icon(false)
_reset_shift_state()