Capture the wand panel, escalation HUD and body-camera timeline
The three newest catalogue screens had AI mockups but no staged capture, so compare and judge skipped them. capture_screenshots.gd now continues past the night set: - switches to The Joke Shop at 620 s (EVENING still has routine spawns), frames a guest, and retries the wand until it alerts; if nobody carries an alerting item it stages the documented keys false-alarm case. - applies a formal warning (arms the body camera) then blocking, jumps to 760 s for night lighting, and captures the HUD at L3. - closes the open incident and opens the body-camera timeline, which now shows the warning / body-camera / blocking rows. Wired the refs for wand_screening, escalation_hud and body_camera_timeline, and regenerated the escalation mockup as a third-person over-the-shoulder night shot so the reference matches the game camera. Added Hud.clear_log() to drop target-cycling noise from staged shots. README gallery lists the three captures. Verification: headless 182/182, Python tooling 53/53, compare 9 good / 0 bad, judge: wand match 0.90, timeline match 1.00, escalation review, 0 diff. Version 0.3.3.
This commit is contained in:
1 parent
a5e7b3c013
commit
3025ba1cef
17 files changed
+145
-18
No files matched your search
@@ -13,6 +13,7 @@ var state := 0
|
||||
var state_frames := 0
|
||||
var targeted := false
|
||||
var camera_staged := false
|
||||
var wand_attempts := 0
|
||||
|
||||
func _initialize() -> void:
|
||||
root.size = Vector2i(1280, 720)
|
||||
@@ -89,7 +90,7 @@ func _advance() -> void:
|
||||
if gm != null:
|
||||
gm.radio_panel.hide()
|
||||
gm.hud.set_action_hint("")
|
||||
gm.coordinator.elapsed_s = 750.0
|
||||
gm.coordinator.elapsed_s = 620.0
|
||||
state = 5
|
||||
state_frames = 0
|
||||
5:
|
||||
@@ -110,9 +111,101 @@ func _advance() -> void:
|
||||
gm.call("_toggle_flashlight")
|
||||
if state_frames >= 30:
|
||||
_shoot("06-night-flashlight.png")
|
||||
# Move to The Joke Shop for the wand/shift-review set, and keep
|
||||
# the late-night phase so the UI sits on the night scene.
|
||||
if gm != null:
|
||||
gm.call("_toggle_flashlight")
|
||||
gm.switch_scenario("joke_shop")
|
||||
gm.coordinator.elapsed_s = 620.0
|
||||
state = 7
|
||||
state_frames = 0
|
||||
7:
|
||||
# Wand screening: wait for guests and keep re-targeting until one
|
||||
# accepts the screen (some authored Joke Shop guests refuse it).
|
||||
if state_frames > 40 and state_frames % 20 == 0 and gm != null and gm.npcs.size() > 0:
|
||||
# Prefer a guest whose items make the wand alert, so the panel
|
||||
# shows the interesting case instead of "Alert: none".
|
||||
if gm.wand_open:
|
||||
if _wand_alerts():
|
||||
state = 8
|
||||
state_frames = 0
|
||||
elif wand_attempts >= 6:
|
||||
# Nobody nearby carried an alerting item: stage the documented
|
||||
# false-alarm case (keys) on this guest and re-open the panel.
|
||||
var guest: Object = gm.call("_targeted_controller")
|
||||
if guest != null and guest.profile != null:
|
||||
var false_alarm: Array[String] = ["keys"]
|
||||
guest.profile.carried_items = false_alarm
|
||||
gm.call("_toggle_wand_screening")
|
||||
gm.call("_toggle_wand_screening")
|
||||
state = 8
|
||||
state_frames = 0
|
||||
else:
|
||||
gm.call("_toggle_wand_screening")
|
||||
wand_attempts += 1
|
||||
else:
|
||||
gm.call("_cycle_nearby_target")
|
||||
_face_target()
|
||||
gm.call("_toggle_wand_screening")
|
||||
wand_attempts += 1
|
||||
elif state_frames > 600 and gm != null:
|
||||
# Fallback: real controller, panel shown directly.
|
||||
var controller: Object = gm.call("_targeted_controller")
|
||||
if controller != null and controller.profile != null:
|
||||
gm.hud.show_wand(controller, gm.wand_screener.screen(controller.profile.carried_items))
|
||||
state = 8
|
||||
state_frames = 0
|
||||
8:
|
||||
if state_frames == 1 and gm != null:
|
||||
gm.hud.clear_log()
|
||||
_stage_closeup()
|
||||
if state_frames >= 45:
|
||||
_shoot("07-wand-screening.png")
|
||||
if gm != null:
|
||||
if gm.wand_open:
|
||||
gm.call("_toggle_wand_screening")
|
||||
# Real escalation path: formal warning arms the body camera
|
||||
# (a timeline row), then blocking raises the meter to L3.
|
||||
gm.call("_apply_interaction", 2, "formal warning")
|
||||
gm.call("_apply_interaction", 3, "blocking")
|
||||
state = 9
|
||||
state_frames = 0
|
||||
9:
|
||||
if state_frames == 1 and gm != null:
|
||||
# Jump into the late phase now that guests exist: LATE has no
|
||||
# routine spawn pool, so this happens after staging the target.
|
||||
gm.coordinator.elapsed_s = 760.0
|
||||
_stage_closeup()
|
||||
if state_frames >= 45:
|
||||
_shoot("08-escalation-hud.png")
|
||||
if gm != null and gm.coordinator != null:
|
||||
# Close the open incident so the recorder's review includes it
|
||||
# (to_dict only lists closed incidents).
|
||||
gm.coordinator.recorder.close_all_open("unresolved")
|
||||
gm.call("_open_timeline", {"incidents": gm.coordinator.recorder.to_dict()})
|
||||
state = 10
|
||||
state_frames = 0
|
||||
10:
|
||||
if state_frames >= 30:
|
||||
_shoot("09-body-camera-timeline.png")
|
||||
quit(0)
|
||||
|
||||
## Put the guard a couple of steps in front of the target so a staged UI capture
|
||||
## frames the person the panel is about.
|
||||
func _wand_alerts() -> bool:
|
||||
if gm == null or gm.hud == null or gm.hud.wand_text == null:
|
||||
return false
|
||||
return gm.hud.wand_text.text.contains("Alert: YES")
|
||||
|
||||
func _stage_closeup() -> void:
|
||||
var target: Node3D = gm.targeted_npc
|
||||
if target == null or not is_instance_valid(target):
|
||||
return
|
||||
gm.guard.global_position = target.global_position + Vector3(0, -0.4, 2.2)
|
||||
gm.guard.global_position.y = 0.1
|
||||
_face_target()
|
||||
gm.guard.head.rotation.x = deg_to_rad(1.0)
|
||||
|
||||
func _face_target() -> void:
|
||||
var target: Node3D = gm.targeted_npc
|
||||
if target == null:
|
||||
|
||||
Reference in new issue
Block a user