_start_shift() now calls _refresh_freeze(), clearing the start-menu input lock and returning to captured mouse mode. The movement smoke asserts both and no longer captures the mouse itself. Headless 226/226 and smoke_movement pass in a clean worktree; only this game_manager hunk is staged, not the active realism edits.
120 lines
3.4 KiB
GDScript
120 lines
3.4 KiB
GDScript
extends SceneTree
|
|
## Movement smoke (windowed): walks the guard to the entrance to check step-up,
|
|
## measures precision-walk speed, and checks footstep/landing cues. The guard
|
|
## reads captured-mouse input, so run it windowed:
|
|
##
|
|
## godot --path . --script res://src/test/smoke_movement.gd
|
|
##
|
|
## Exit code 0 = pass, 1 = failure.
|
|
|
|
const MAX_FRAMES := 1600
|
|
var frame := 0
|
|
var gm: Node = null
|
|
var started := false
|
|
var step := 0
|
|
var step_frame := 0
|
|
var failures: Array[String] = []
|
|
var start_pos := Vector3.ZERO
|
|
var normal_distance := 0.0
|
|
var footsteps_before := 0
|
|
|
|
func _initialize() -> void:
|
|
root.size = Vector2i(1280, 720)
|
|
root.add_child(load("res://scenes/main.tscn").instantiate())
|
|
|
|
func _process(_delta: float) -> bool:
|
|
frame += 1
|
|
if gm == null:
|
|
gm = root.find_child("GameManager", true, false)
|
|
return false
|
|
if not started:
|
|
gm.call("_on_venue_selected", "hollywood_building")
|
|
_check(not gm.guard.input_locked, "venue selection releases the guard")
|
|
_check(Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED,
|
|
"venue selection recaptures the mouse")
|
|
started = true
|
|
return false
|
|
if frame > MAX_FRAMES:
|
|
_fail("timeout before the movement checks finished")
|
|
return true
|
|
step_frame += 1
|
|
match step:
|
|
0:
|
|
if step_frame < 20:
|
|
return false
|
|
_place_guard(8.5)
|
|
footsteps_before = gm.audio.footsteps
|
|
start_pos = gm.guard.global_position
|
|
Input.action_press("move_forward")
|
|
step = 1
|
|
step_frame = 0
|
|
1:
|
|
if step_frame >= 280:
|
|
Input.action_release("move_forward")
|
|
var moved := start_pos.distance_to(gm.guard.global_position)
|
|
_check(moved > 2.0, "guard walked toward the entrance (%.1f m)" % moved)
|
|
_check(gm.guard.global_position.y > 0.35,
|
|
"guard climbed the steps (y=%.2f)" % gm.guard.global_position.y)
|
|
_check(gm.guard.global_position.z < 4.2,
|
|
"guard reached the steps (z=%.1f)" % gm.guard.global_position.z)
|
|
_check(gm.audio.footsteps > footsteps_before,
|
|
"footsteps are emitted while walking")
|
|
step = 2
|
|
step_frame = 0
|
|
2:
|
|
if step_frame < 45:
|
|
return false
|
|
_place_guard(8.5)
|
|
normal_distance = 0.0
|
|
start_pos = gm.guard.global_position
|
|
Input.action_press("move_forward")
|
|
Input.action_press("walk_slow")
|
|
step = 3
|
|
step_frame = 0
|
|
3:
|
|
if step_frame >= 120:
|
|
Input.action_release("walk_slow")
|
|
Input.action_release("move_forward")
|
|
var moved := start_pos.distance_to(gm.guard.global_position)
|
|
_check(moved > 1.0 and moved < 4.6,
|
|
"precision walk covers less ground (%.1f m in 2 s)" % moved)
|
|
var chip = gm.hud.precision_label
|
|
_check(chip != null and chip.visible,
|
|
"precision walk shows its HUD chip")
|
|
step = 4
|
|
step_frame = 0
|
|
4:
|
|
if gm.audio.landings == 0:
|
|
gm.guard.global_position += Vector3(0, 1.2, 0)
|
|
if step_frame >= 90:
|
|
_check(gm.audio.landings > 0, "landing cue fires after a drop")
|
|
_finish()
|
|
return true
|
|
return false
|
|
|
|
func _place_guard(z: float) -> void:
|
|
gm.guard.global_position = Vector3(0, 0.1, z)
|
|
gm.guard.rotation.y = 0.0
|
|
gm.guard.velocity = Vector3.ZERO
|
|
|
|
func _check(condition: bool, message: String) -> void:
|
|
if condition:
|
|
print("ok: " + message)
|
|
else:
|
|
_fail(message)
|
|
|
|
func _fail(message: String) -> void:
|
|
failures.append(message)
|
|
_finish()
|
|
|
|
func _finish() -> void:
|
|
Input.action_release("move_forward")
|
|
Input.action_release("walk_slow")
|
|
if failures.is_empty():
|
|
print("SMOKE OK: movement feel (steps, precision walk, footsteps)")
|
|
quit(0)
|
|
else:
|
|
for message in failures:
|
|
printerr("SMOKE FAIL: " + message)
|
|
quit(1)
|