Turn dev mode into sandbox menu

This commit is contained in:
Loïc Wisniewski 2026-09-03 20:05:33 +02:00
commit c325501999
19 changed files with 651 additions and 54 deletions

95
tests/test_dev_menu.gd Normal file
View file

@ -0,0 +1,95 @@
extends SceneTree
# The dev button is now a doorway rather than a one-off wave shortcut. This
# exercises the real Main scene so additions and removals prove they affect
# the live fleet, not only GameState bookkeeping.
const VESSEL_DEFINITIONS = preload("res://vessels/VesselDefinitions.gd")
var state: Node
var scene: Node
var fleet: Node
var dev_button: Control
var menu: Control
var stage: int = 0
var elapsed: float = 0.0
func _initialize() -> void:
state = root.get_node("GameState")
state.start_dev_game()
scene = load("res://world/Main.tscn").instantiate()
root.add_child(scene)
current_scene = scene
fleet = scene.get_node("Fleet")
dev_button = scene.get_node("UI/DevMenuButton")
menu = scene.get_node("UI/DevMenu")
func _process(delta: float) -> bool:
elapsed += delta
match stage:
0:
if elapsed < 0.2:
return false
if state.intro_active:
return _fail("the dev world opened inside the intro")
if fleet.ships.size() != GameState.STARTING_SHIP_COUNT:
return _fail("post-intro dev mode did not start with the normal fleet")
dev_button.button.pressed.emit()
if not menu.visible:
return _fail("the HUD dev button opened no menu")
menu.unlock_button.pressed.emit()
for skill in GameState.SKILL_TREE:
if not state.is_unlocked(String(skill.id)):
return _fail("unlock-all missed %s" % skill.id)
if state.max_fleet_size() != GameState.DEFAULT_FORMATION.size():
return _fail("unlock-all did not expose the complete fleet capacity")
for definition in VESSEL_DEFINITIONS.fleet():
menu.fleet_add_requested.emit(String(definition.definition_id))
for definition in VESSEL_DEFINITIONS.fleet():
if not fleet.has_vessel_type(String(definition.definition_id)):
return _fail("the menu could not add %s" % definition.display_name)
print("dev menu added every fleet-eligible vessel to the live fleet")
var before: int = fleet.ships.size()
menu.fleet_remove_requested.emit(GameState.VESSEL_GAS_BOMBER)
if fleet.ships.size() != before - 1:
return _fail("the dev menu did not remove a vessel")
menu.unlimited_button.pressed.emit()
if not state.dev_unlimited_resources:
return _fail("the unlimited-resources toggle did not turn on")
for resource_type in state.resource_types():
state.bank_inventory.withdraw(resource_type, GameState.DEV_UNLIMITED_AMOUNT)
state.research_points = 0
state._process(0.0)
for resource_type in state.resource_types():
if state.banked_resource(resource_type) != GameState.DEV_UNLIMITED_AMOUNT:
return _fail("unlimited mode did not replenish %s" % resource_type)
if state.research_points != GameState.DEV_UNLIMITED_AMOUNT:
return _fail("unlimited mode did not replenish research points")
print("skill unlock and unlimited resources operate on persistent GameState")
var wave_before: int = state.wave_number
menu.wave_button.pressed.emit()
if menu.visible:
return _fail("starting a wave left the dev menu over the action")
if state.wave_number != wave_before + 1 or not state.wave_pending:
return _fail("the dev menu did not retain the immediate wave tool")
state.reset_new_game()
if state.dev_mode or state.dev_unlimited_resources:
return _fail("dev cheats leaked into a normal new game")
print("TEST_DEV_MENU: PASS")
quit(0)
return true
return false
func _fail(message: String) -> bool:
print("TEST_DEV_MENU: FAIL (%s)" % message)
quit(1)
return true