From eef7b5c362b3142bcbe90708186b9d8043b319b5 Mon Sep 17 00:00:00 2001 From: Codex Date: Wed, 7 Oct 2026 16:20:14 +0200 Subject: [PATCH] Wire Hebat Allah dive into the main game --- .../vertical_slice/vertical_slice_root.gd | 12 ++--- .../run_vertical_slice_foundation.gd | 49 +++++++++++++++++-- 2 files changed, 52 insertions(+), 9 deletions(-) diff --git a/game/composition/vertical_slice/vertical_slice_root.gd b/game/composition/vertical_slice/vertical_slice_root.gd index 2c2c4e8..3e95cfe 100644 --- a/game/composition/vertical_slice/vertical_slice_root.gd +++ b/game/composition/vertical_slice/vertical_slice_root.gd @@ -51,8 +51,8 @@ const ConfirmationDialogScreen = preload( const RebindResult = preload("res://game/application/input/rebind_result.gd") const MAIN_MENU_SCENE = preload("res://game/presentation/main_menu/main_menu_screen.tscn") -const VEHICLE_TEST_WORLD_SCENE_PATH := ( - "res://game/composition/vertical_slice/vehicle_test_world.tscn" +const DIVE_WORLD_SCENE_PATH := ( + "res://game/composition/vertical_slice/sunlit_shallows_world.tscn" ) const COCKPIT_HUD_SCENE = preload("res://game/presentation/cockpit/cockpit_hud.tscn") const SONAR_DISPLAY_SCENE = preload( @@ -66,7 +66,7 @@ const CONFIRMATION_SCENE = preload( "res://game/presentation/confirmation/confirmation_dialog.tscn" ) -const DIVE_SESSION_ID := &"vertical_slice_vehicle_test" +const DIVE_SESSION_ID := &"sunlit_shallows_dive" const CONFIRM_ABANDON := &"abandon_dive" const CONFIRM_MAIN_MENU := &"return_main_menu" const CONFIRM_QUIT := &"quit_game" @@ -105,7 +105,7 @@ func _ready() -> void: _show_main_menu() -func _start_vehicle_test() -> void: +func _start_dive() -> void: var rules = DiveRulesResolver.new().resolve( DiveDifficultyProfile.standard(), DiveUpgradeEffects.new(), @@ -117,7 +117,7 @@ func _start_vehicle_test() -> void: if not session.is_ready(): return - var world_scene := load(VEHICLE_TEST_WORLD_SCENE_PATH) as PackedScene + var world_scene := load(DIVE_WORLD_SCENE_PATH) as PackedScene if world_scene == null: return var world := world_scene.instantiate() as Node3D @@ -457,7 +457,7 @@ func _show_main_menu() -> void: _replace_active_world(null) var screen := MAIN_MENU_SCENE.instantiate() as MainMenuScreen _replace_active_screen(screen) - screen.new_game_requested.connect(_start_vehicle_test) + screen.new_game_requested.connect(_start_dive) screen.quit_requested.connect(_quit_game) diff --git a/tests/integration/run_vertical_slice_foundation.gd b/tests/integration/run_vertical_slice_foundation.gd index f537333..5f4da00 100644 --- a/tests/integration/run_vertical_slice_foundation.gd +++ b/tests/integration/run_vertical_slice_foundation.gd @@ -29,8 +29,14 @@ const ControlsSettingsScreen = preload( const ProductionInputAdapter = preload( "res://game/infrastructure/input/production_input_adapter.gd" ) +const SunlitShallowsEnvironment = preload( + "res://game/world/sites/sunlit_shallows_environment.gd" +) +const WreckActor = preload("res://game/world/wrecks/wreck_actor.gd") +const SonarService = preload("res://game/application/sonar/sonar_service.gd") +const SonarMaterial = preload("res://game/domain/sonar/sonar_material.gd") -const TEST_COUNT := 94 +const TEST_COUNT := 99 var _failures: Array[String] = [] @@ -120,7 +126,32 @@ func _test_vehicle_slice(composition: VerticalSliceRoot) -> void: var hud := composition.active_screen() as CockpitHud var sonar_service = composition.sonar_service() var sonar_display = composition.sonar_display() - _expect(composition.active_world() != null, "vehicle test world is assembled") + var active_world := composition.active_world() + var site: SunlitShallowsEnvironment = null + var wreck: WreckActor = null + var floor_body: StaticBody3D = null + if active_world != null: + site = active_world.get_node_or_null("Environment") as SunlitShallowsEnvironment + if site != null: + wreck = site.get_node_or_null("HebatAllahWreck") as WreckActor + floor_body = site.get_node_or_null("FlatFloor") as StaticBody3D + _expect(active_world != null and active_world.name == "SunlitShallowsWorld", "new game loads sunlit shallows world") + _expect(site != null, "sunlit environment is active") + _expect( + floor_body != null and floor_body.get_node_or_null("Collision") is CollisionShape3D, + "active dive has a physical seabed" + ) + _expect( + wreck != null and wreck.get_node_or_null("Collision") is CollisionShape3D, + "active dive contains the collidable Hebat Allah wreck" + ) + _expect( + actor != null + and wreck != null + and (wreck.global_position - actor.global_position).dot(-actor.global_basis.z) > 0.0 + and actor.global_position.distance_to(wreck.global_position) < SonarService.MAXIMUM_RANGE_M, + "wreck starts ahead of the submarine within sonar range" + ) _expect(actor != null, "production submarine actor is assembled") _expect(camera != null, "cockpit camera is attached to the submarine") _expect(instruments != null, "physical cockpit instruments are assembled") @@ -222,7 +253,11 @@ func _test_vehicle_slice(composition: VerticalSliceRoot) -> void: var first_scan = sonar_service.current_scan() _expect(first_scan != null, "manual sonar command publishes a typed scan") _expect(first_scan.samples.observed_count() > 1000, "reference acquisition captures dense bathymetry") - _expect(first_scan.contacts.size() >= 1, "metal calibration target becomes a distinct contact") + var has_wreck_contact := false + for contact in first_scan.contacts: + if contact.material == SonarMaterial.Value.METAL: + has_wreck_contact = true + _expect(has_wreck_contact, "manual sonar sees the metal wreck in the active world") _expect("RELEVÉ EN COURS" in sonar_display.status_text(), "sonar display reports progressive reveal") _expect(not sonar_display.idle_prompt_visible(), "sonar data replaces the idle instruction") for frame in 18: @@ -243,12 +278,20 @@ func _test_vehicle_slice(composition: VerticalSliceRoot) -> void: _expect(not sonar_display.is_expanded(), "expanded sonar returns to cockpit view") var start_position: Vector3 = actor.global_position + var start_wreck_distance: float = ( + actor.global_position.distance_to(wreck.global_position) if wreck != null else INF + ) var starting_battery: float = composition.latest_update().snapshot.battery.remaining_kwh Input.action_press(ProductionInputAdapter.ACTION_FORWARD) for frame in 35: await physics_frame Input.action_release(ProductionInputAdapter.ACTION_FORWARD) _expect(actor.global_position.distance_to(start_position) > 0.1, "keyboard propulsion moves the submarine") + _expect( + wreck != null + and actor.global_position.distance_to(wreck.global_position) < start_wreck_distance - 0.1, + "forward propulsion closes the distance to the wreck" + ) _expect(actor.velocity.length() > 0.1, "propulsion builds inertial velocity") _expect( composition.latest_update().snapshot.battery.remaining_kwh < starting_battery, -- 2.56.0