Turn dev mode into sandbox menu
This commit is contained in:
parent
68985316e5
commit
c325501999
19 changed files with 651 additions and 54 deletions
28
tests/_dev_menu_preview.gd
Normal file
28
tests/_dev_menu_preview.gd
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
extends Node2D
|
||||
|
||||
# Visual-only phone preview for the editor sandbox panel. It builds only the
|
||||
# fleet and the menu; loading Main also schedules infinite-world population,
|
||||
# which is wasted behind this opaque panel and painfully slow in softpipe.
|
||||
#
|
||||
# bash tests/screenshot.sh res://tests/_dev_menu_preview.tscn /tmp/dev_menu.png 4 720x1280
|
||||
|
||||
const FLEET = preload("res://vessels/Fleet.gd")
|
||||
const DEV_MENU = preload("res://ui/menus/DevMenu.tscn")
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
GameState.start_dev_game()
|
||||
GameState.dev_unlock_all_skills()
|
||||
var fleet: Node = FLEET.new()
|
||||
add_child(fleet)
|
||||
fleet.spawn_ships(4, Vector2.ZERO, PackedStringArray([
|
||||
GameState.VESSEL_INTERCEPTOR,
|
||||
GameState.VESSEL_SHIELD,
|
||||
GameState.VESSEL_GAS_BOMBER,
|
||||
GameState.VESSEL_LASER,
|
||||
]))
|
||||
var layer := CanvasLayer.new()
|
||||
add_child(layer)
|
||||
var menu: Control = DEV_MENU.instantiate()
|
||||
layer.add_child(menu)
|
||||
menu.open_for(fleet)
|
||||
1
tests/_dev_menu_preview.gd.uid
Normal file
1
tests/_dev_menu_preview.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://bxsf8yo6lyhf8
|
||||
6
tests/_dev_menu_preview.tscn
Normal file
6
tests/_dev_menu_preview.tscn
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
[gd_scene load_steps=2 format=3]
|
||||
|
||||
[ext_resource type="Script" path="res://tests/_dev_menu_preview.gd" id="1"]
|
||||
|
||||
[node name="DevMenuPreview" type="Node2D"]
|
||||
script = ExtResource("1")
|
||||
95
tests/test_dev_menu.gd
Normal file
95
tests/test_dev_menu.gd
Normal 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
|
||||
1
tests/test_dev_menu.gd.uid
Normal file
1
tests/test_dev_menu.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://dws3sq74nik4v
|
||||
|
|
@ -73,6 +73,8 @@ func _process(delta: float) -> bool:
|
|||
game_state.start_dev_game()
|
||||
if not game_state.dev_mode:
|
||||
return _fail("start_dev_game() did not set dev_mode")
|
||||
if game_state.intro_active:
|
||||
return _fail("dev mode still starts at the prologue instead of after it")
|
||||
for resource_type in game_state.resource_types():
|
||||
var banked: int = game_state.banked_resource(resource_type)
|
||||
if banked != GameState.DEV_RESOURCE_AMOUNT:
|
||||
|
|
@ -116,6 +118,8 @@ func _process(delta: float) -> bool:
|
|||
game_state.reset_new_game()
|
||||
if game_state.dev_mode:
|
||||
return _fail("starting a normal game after a dev one left dev_mode set")
|
||||
if game_state.dev_unlimited_resources:
|
||||
return _fail("starting a normal game kept unlimited resources enabled")
|
||||
if game_state.rocks != 0 or game_state.research_points != 0:
|
||||
return _fail("starting a normal game after a dev one kept the dev stock")
|
||||
print("starting a normal game afterwards clears dev mode entirely")
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ extends SceneTree
|
|||
|
||||
const MENUS: Array[String] = [
|
||||
"BuildMenu", "CraftMenu", "LabMenu", "TransferMenu", "HangarMenu",
|
||||
"FormationMenu", "SkillMenu", "PlanningMenu", "GarrisonMenu",
|
||||
"FormationMenu", "SkillMenu", "PlanningMenu", "GarrisonMenu", "DevMenu",
|
||||
]
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -434,7 +434,7 @@ func _process(delta: float) -> bool:
|
|||
if elapsed < 0.3:
|
||||
return false
|
||||
# #140: the objective lives behind a button next to the map's,
|
||||
# not on the HUD - it used to sit on top of the wave button.
|
||||
# not on the HUD - it used to sit on top of the dev button.
|
||||
if panel.visible:
|
||||
return _fail("the objective panel is open before anyone pressed anything")
|
||||
if not quest_button.visible:
|
||||
|
|
@ -442,9 +442,9 @@ func _process(delta: float) -> bool:
|
|||
var map_button: Control = scene.get_node("UI/MapButton")
|
||||
if quest_button.get_rect().intersects(map_button.get_rect()):
|
||||
return _fail("the quest button is drawn on top of the map button")
|
||||
var wave_button: Control = scene.get_node("UI/DevWaveButton")
|
||||
if quest_button.get_rect().intersects(wave_button.get_rect()):
|
||||
return _fail("the quest button is drawn on top of the wave button")
|
||||
var dev_button: Control = scene.get_node("UI/DevMenuButton")
|
||||
if quest_button.get_rect().intersects(dev_button.get_rect()):
|
||||
return _fail("the quest button is drawn on top of the dev button")
|
||||
if absf(quest_button.get_rect().get_center().y - map_button.get_rect().get_center().y) > 1.0:
|
||||
return _fail("the quest button does not sit beside the map button")
|
||||
panel.open()
|
||||
|
|
@ -458,7 +458,7 @@ func _process(delta: float) -> bool:
|
|||
return _fail("the panel does not show the objective")
|
||||
if panel.progress != Vector2i(0, 5):
|
||||
return _fail("the panel reads %s, expected 0 of 5" % panel.progress)
|
||||
print("quest button beside the map, clear of the wave button; panel: \"%s\" - %s (%d/%d)" \
|
||||
print("quest button beside the map, clear of the dev button; panel: \"%s\" - %s (%d/%d)" \
|
||||
% [panel.quest_label.text, panel.objective_label.text,
|
||||
panel.progress.x, panel.progress.y])
|
||||
panel.close()
|
||||
|
|
|
|||
|
|
@ -224,20 +224,24 @@ func _process(delta: float) -> bool:
|
|||
return _fail("killing the whole wave did not bring the quiet back")
|
||||
print("the wave died and the quiet came back")
|
||||
|
||||
# --- G. the dev button ---------------------------------------
|
||||
var dev_button: Control = scene.get_node("UI/DevWaveButton")
|
||||
# --- G. the dev menu keeps the immediate wave tool -----------
|
||||
var dev_button: Control = scene.get_node("UI/DevMenuButton")
|
||||
var dev_menu: Control = scene.get_node("UI/DevMenu")
|
||||
game_state.dev_mode = false
|
||||
dev_button._process(0.0)
|
||||
if dev_button.visible:
|
||||
return _fail("the dev wave button is offered in a normal game")
|
||||
return _fail("the dev menu button is offered in a normal game")
|
||||
game_state.dev_mode = true
|
||||
dev_button._process(0.0)
|
||||
if not dev_button.visible:
|
||||
return _fail("the dev wave button is hidden in dev mode")
|
||||
var number_before: int = game_state.wave_number
|
||||
return _fail("the dev menu button is hidden in dev mode")
|
||||
dev_button.button.pressed.emit()
|
||||
if not dev_menu.visible:
|
||||
return _fail("the dev button did not open the dev menu")
|
||||
var number_before: int = game_state.wave_number
|
||||
dev_menu.wave_button.pressed.emit()
|
||||
if game_state.wave_phase != GameState.WAVE_PHASE_ACTIVE:
|
||||
return _fail("the button left the wave in \"%s\"" % game_state.wave_phase)
|
||||
return _fail("the menu's wave tool left the wave in \"%s\"" % game_state.wave_phase)
|
||||
if not game_state.wave_pending:
|
||||
return _fail("the button turned the wave active without owing it to anyone")
|
||||
if game_state.wave_number != number_before + 1:
|
||||
|
|
@ -249,7 +253,7 @@ func _process(delta: float) -> bool:
|
|||
spawner._process(0.0)
|
||||
if _enemy_count() <= 0:
|
||||
return _fail("the forced wave produced no enemies")
|
||||
print("dev button: wave %d on the board at once, %d enemies" \
|
||||
print("dev menu: wave %d on the board at once, %d enemies" \
|
||||
% [game_state.wave_number, _enemy_count()])
|
||||
game_state.dev_mode = false
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue