diff --git a/boss/BossEncounter.gd b/boss/BossEncounter.gd index 65b3ef7..485da54 100644 --- a/boss/BossEncounter.gd +++ b/boss/BossEncounter.gd @@ -14,7 +14,6 @@ extends Node2D const REVEAL_SECONDS: float = 1.15 const REVEAL_SHAKE: float = 28.0 -const APPROACH_STANDOFF: float = 850.0 var reveal_started: bool = false var reveal_left: float = 0.0 @@ -47,22 +46,11 @@ func _ready() -> void: _set_combat_ui_visible(false) indicator.visible = true indicator_label.visible = true - game_state.encounter_locks_movement = true - # The encounter introduces itself in the world: the fleet is drawn toward - # the signal until the Warden reaches the edge of view, then control is - # returned after the roar. No dialog or separate scene hides the approach. - _begin_approach.call_deferred() + # The signal is a destination, not an autopilot order. The player keeps + # control while approaching it; only the short reveal below takes the wheel. _refresh_status() -func _begin_approach() -> void: - # PlanetSurfaceController composes this encounter before it spawns the - # restored fleet. Waiting one call guarantees there are ships for the - # scripted move to steer. - if not reveal_started and not fleet.ships.is_empty(): - fleet.move_to(boss.global_position + Vector2(0.0, APPROACH_STANDOFF)) - - func _exit_tree() -> void: if game_state != null: game_state.encounter_locks_movement = false @@ -95,6 +83,7 @@ func begin_reveal() -> void: return reveal_started = true reveal_left = REVEAL_SECONDS + game_state.encounter_locks_movement = true fleet.stop() indicator.visible = false indicator_label.visible = false diff --git a/tests/_boss_approach_preview.gd b/tests/_boss_approach_preview.gd index 4da1768..ada33f0 100644 --- a/tests/_boss_approach_preview.gd +++ b/tests/_boss_approach_preview.gd @@ -21,5 +21,5 @@ func _ready() -> void: var surface: Node = load("res://surface/PlanetSurface.tscn").instantiate() add_child(surface) surface.get_node("FadeOverlay/FadeRect").visible = false - # Four screenshot frames are nowhere near enough for the automatic - # approach to cover 950 world units, so the signal remains off-screen. + # Four screenshot frames leave the fleet at its landing point, so the + # signal remains off-screen until the player chooses to follow it. diff --git a/tests/test_boss_planet.gd b/tests/test_boss_planet.gd index 9280466..2e052b7 100644 --- a/tests/test_boss_planet.gd +++ b/tests/test_boss_planet.gd @@ -8,7 +8,7 @@ extends SceneTree # scripted profile is excluded from the map editor # B. landing composes BossEncounter instead of a PlanetSetup and does not # mark the world conquered for free -# C. the off-screen approach locks movement and reveals with its own cue +# C. the off-screen approach remains controllable and reveals with its own cue # D. waves are larger, expelled outward, varied, and golden only 1/3 times # E. killing the marked hatchling sends a visible return to the boss and # opens an attackable tentacle eye @@ -119,14 +119,16 @@ func _process(delta: float) -> bool: return _fail("boss combat UI is visible before the boss enters view") if not encounter.indicator.visible or not encounter.indicator_label.visible: return _fail("the off-screen boss has no directional border indicator") - if not state.encounter_locks_movement or boss.combat_active: - return _fail("the approach did not take temporary control or already started combat") - # Put the camera where the automatic approach eventually carries it; - # the encounter itself must detect the boss crossing into view. + if state.encounter_locks_movement or boss.combat_active: + return _fail("the off-screen approach locked player movement or already started combat") + # Put the camera where the player can carry the fleet; the encounter + # itself must detect the boss crossing into view. surface.get_node("Camera2D").global_position = boss.global_position + Vector2(0.0, 1000.0) encounter._process(0.0) if not encounter.reveal_started: return _fail("bringing the boss into view did not trigger its reveal") + if not state.encounter_locks_movement: + return _fail("the reveal did not briefly lock movement for the cinematic") if not encounter.health_bar.visible or encounter.indicator.visible: return _fail("the reveal did not exchange the indicator for the health UI") var scream_heard: bool = false