extends SceneTree # Forgejo #23 + #25: the mothership hangar presents vessels by type, tapping # an available type crews one, tapping a fleet type stores one, and contextual # world buttons each get their own touch berth. var game_state: Node var scene: Node var fleet: Node var controller: Node var stage: int = 0 var elapsed: float = 0.0 func _initialize() -> void: game_state = root.get_node("GameState") game_state.buildings.clear() game_state.extractors.clear() game_state.transporters.clear() game_state.stored_vessels.clear() game_state.rocks = 100 scene = load("res://Main.tscn").instantiate() root.add_child(scene) fleet = scene.get_node("Fleet") controller = scene.get_node("BuildController") func _process(delta: float) -> bool: elapsed += delta if stage == 0: scene.get_node("AsteroidField").set_process(false) scene.get_node("EnemySpawner").set_process(false) for a in get_nodes_in_group("asteroids"): if is_instance_valid(a): a.queue_free() fleet.spawn_ships(1, Vector2.ZERO) fleet.add_ship(GameState.VESSEL_SHIELD) game_state.stored_vessels = [GameState.VESSEL_INTERCEPTOR, GameState.VESSEL_SHIELD, GameState.VESSEL_TRANSPORTER] controller._on_hangar_pressed() elapsed = 0.0 stage = 1 return false if stage == 1: if elapsed < 0.2: return false # Available cards name the vessel and count what can be crewed. var available_label: Label = controller.hangar_available_labels[0] if "Interceptor" not in available_label.text or "1 available" not in available_label.text: _fail("available interceptor card says '%s'" % available_label.text) return true if controller._hangar_types().has(GameState.VESSEL_TRANSPORTER) \ or fleet.add_ship(GameState.VESSEL_TRANSPORTER): _fail("a logistics transporter was exposed as a fleet vessel") return true controller._on_hangar_crew_type(0) if fleet.ships.size() != 3 or game_state.stored_vessels.has(GameState.VESSEL_INTERCEPTOR): _fail("tapping an available interceptor did not crew it") return true controller._on_hangar_store_type(1) if fleet.ships.size() != 2 or not game_state.stored_vessels.has(GameState.VESSEL_SHIELD): _fail("tapping the shield fleet card did not store it") return true # The safety rule prevents an empty deployed fleet. controller._on_hangar_store_type(0) controller._on_hangar_store_type(0) if fleet.ships.size() != 1: _fail("hangar allowed the last deployed ship to be stored") return true # Context actions are compact until expanded. A mothership unfolds # research and hangar; transfer stays as a persistent shortcut beside # Build and is not duplicated in the foldout. var mothership: Node2D = load("res://Building.tscn").instantiate() mothership.set("building_type", GameState.BUILDING_MOTHERSHIP) mothership._ready() controller.current_building = mothership controller.context_actions_expanded = true controller.transfer_button.visible = controller._has_transfer_context() controller._layout_context_buttons() var buttons: Array = [controller.building_action_button, controller.hangar_button] for i in range(buttons.size() - 1): if buttons[i].offset_right > buttons[i + 1].offset_left: _fail("context buttons %d and %d overlap" % [i, i + 1]) return true controller._collapse_context_actions() if controller.building_action_button.visible or controller.hangar_button.visible: _fail("collapsing the context button left an action visible") return true if not controller.transfer_button.visible \ or controller.transfer_button.offset_top != controller.build_button.offset_top \ or controller.transfer_button.offset_left <= controller.build_button.offset_left: _fail("transfer shortcut is not beside Build") return true mothership.free() print("hangar crews and stores typed vessels; contextual actions expand and collapse") print("TEST_HANGAR_MANAGEMENT: PASS") quit(0) return true return false func _fail(message: String) -> void: print("TEST_HANGAR_MANAGEMENT: FAIL (%s)" % message) quit(1)