Complete lab, quest, garrison, and energy tickets
This commit is contained in:
parent
d413d1da9f
commit
0f7edff15a
20 changed files with 238 additions and 45 deletions
|
|
@ -1,7 +1,7 @@
|
|||
extends Node2D
|
||||
|
||||
# Preview, not a test - the ship lab at the real 720x1280 viewport, with a
|
||||
# vessel selected and its upgrades listed.
|
||||
# vessel selected, its upgrades listed, and active research in progress.
|
||||
#
|
||||
# bash tests/screenshot.sh res://tests/_lab_menu_preview.tscn /tmp/lab.png 25 720x1280
|
||||
|
||||
|
|
@ -13,10 +13,21 @@ func _ready() -> void:
|
|||
GameState.bank_inventory.set_amount(GameState.RESOURCE_ORE, 310)
|
||||
GameState.fleet_inventory.set_amount(GameState.RESOURCE_ORE, 47)
|
||||
GameState.research_points = 4
|
||||
GameState.build_time_scale = 1.0
|
||||
var lab_id: int = GameState.add_building(GameState.BUILDING_SHIP_LAB,
|
||||
Vector2.ZERO)
|
||||
GameState.queue_lab_research(lab_id, "int_rate")
|
||||
GameState.deposit_resource_to_building(lab_id, GameState.RESOURCE_ORE,
|
||||
GameState.upgrade_cost("int_rate"))
|
||||
GameState.call("_advance_lab_research", GameState.lab_research_time() * 0.42)
|
||||
# Freeze the model so a slow software-rendered capture cannot finish the
|
||||
# research before it takes the frame this preview exists to show.
|
||||
GameState.set_process(false)
|
||||
var main: Node = load("res://world/Main.tscn").instantiate()
|
||||
add_child(main)
|
||||
main.get_node("EnemySpawner").set_process(false)
|
||||
main.get_node("AsteroidField").set_process(false)
|
||||
var build: Node = main.get_node("BuildController")
|
||||
build.lab_menu.visible = true
|
||||
build.lab_building_id = lab_id
|
||||
build.lab_menu.open_for(lab_id)
|
||||
build._refresh_lab()
|
||||
|
|
|
|||
1
tests/test_dialog_releases_joysticks.gd.uid
Normal file
1
tests/test_dialog_releases_joysticks.gd.uid
Normal file
|
|
@ -0,0 +1 @@
|
|||
uid://qgrnenhp5sqh
|
||||
|
|
@ -53,6 +53,8 @@ func _initialize() -> void:
|
|||
var logistics: Resource = game_state.building_logistics_profile(game_state.find_building(burner_id))
|
||||
conversion_rate = logistics.conversion_rate
|
||||
conversion_yield = logistics.conversion_yield
|
||||
if not is_equal_approx(conversion_rate, 0.2):
|
||||
_fail("burner conversion rate is %.2f/s, expected the reduced 0.20/s" % conversion_rate)
|
||||
|
||||
|
||||
func _process(delta: float) -> bool:
|
||||
|
|
@ -72,13 +74,13 @@ func _process(delta: float) -> bool:
|
|||
print("energy is generic: in resource_types(), own definition, own colour %s" % energy_color)
|
||||
|
||||
# --- B. produces energy from local gas at the configured rate -
|
||||
if elapsed < 2.5:
|
||||
if elapsed < 5.5:
|
||||
return false
|
||||
var gas_left: int = game_state.building_resource(burner_id, GameState.RESOURCE_GAS)
|
||||
var energy_made: int = game_state.building_resource(burner_id, GameState.RESOURCE_ENERGY)
|
||||
var gas_burned: int = 20 - gas_left
|
||||
if gas_burned < 2:
|
||||
return _fail("burner only burned %d gas in 2.5s at rate %.1f/s" % [gas_burned, conversion_rate])
|
||||
if gas_burned < 1:
|
||||
return _fail("burner burned no gas in 5.5s at rate %.2f/s" % conversion_rate)
|
||||
if energy_made != gas_burned * conversion_yield:
|
||||
return _fail("burner made %d energy for %d gas burned, expected %dx" % [
|
||||
energy_made, gas_burned, conversion_yield
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ func _process(delta: float) -> bool:
|
|||
return false
|
||||
1:
|
||||
# --- B. running, it converts ----------------------------------
|
||||
if elapsed < 1.5:
|
||||
if elapsed < 5.5:
|
||||
return false
|
||||
if _stock(GameState.RESOURCE_ENERGY) <= 0:
|
||||
return _fail("a running burner made no energy in %.1fs" % elapsed)
|
||||
|
|
@ -119,7 +119,7 @@ func _process(delta: float) -> bool:
|
|||
elapsed = 0.0
|
||||
return false
|
||||
3:
|
||||
if elapsed < 1.5:
|
||||
if elapsed < 5.5:
|
||||
return false
|
||||
if _stock(GameState.RESOURCE_ENERGY) <= energy_at_pause:
|
||||
return _fail("a resumed burner made no further energy")
|
||||
|
|
|
|||
|
|
@ -21,6 +21,8 @@ extends SceneTree
|
|||
# E. it goes back to patrolling once the enemy is gone
|
||||
# F. losing a garrison vessel frees the berth, so it gets crewed again
|
||||
# G. enemies fight back - a garrison vessel is a target like any other
|
||||
# H. #186 - with no hostile nearby, the same weapon-target contract lets a
|
||||
# garrison shoot asteroids for ore
|
||||
|
||||
var game_state: Node
|
||||
var main: Node
|
||||
|
|
@ -30,6 +32,7 @@ var outpost_id: int = 0
|
|||
var guard: Node2D
|
||||
var component: Node
|
||||
var enemy: Node2D
|
||||
var asteroid: Node2D
|
||||
var stage: int = 0
|
||||
var elapsed: float = 0.0
|
||||
var orbit_min: float = INF
|
||||
|
|
@ -231,14 +234,40 @@ func _process(delta: float) -> bool:
|
|||
return _fail("the garrison is still fighting an enemy that is gone")
|
||||
print("stood down and went back to its patrol")
|
||||
|
||||
# --- H. asteroids are valid lower-priority targets -----------
|
||||
asteroid = load("res://world/Asteroid.tscn").instantiate()
|
||||
asteroid.position = Vector2(300.0, 0.0)
|
||||
asteroid.velocity = Vector2.ZERO
|
||||
main.add_child(asteroid)
|
||||
asteroid.hp = 100000
|
||||
dummy_hp_before = asteroid.hp
|
||||
elapsed = 0.0
|
||||
stage = 6
|
||||
return false
|
||||
6:
|
||||
if elapsed < 2.5:
|
||||
return false
|
||||
if not component.is_engaging():
|
||||
return _fail("an asteroid beside the outpost was not engaged")
|
||||
if asteroid.hp >= dummy_hp_before:
|
||||
return _fail("the garrison engaged an asteroid but never shot it")
|
||||
print("garrison shot a nearby asteroid through the shared target contract")
|
||||
asteroid.queue_free()
|
||||
elapsed = 0.0
|
||||
stage = 7
|
||||
return false
|
||||
7:
|
||||
if elapsed < 0.5:
|
||||
return false
|
||||
|
||||
# --- F. a lost vessel frees its berth ------------------------
|
||||
if game_state.garrison_crew(outpost_id).size() != 1:
|
||||
return _fail("the crew is not 1 before the kill")
|
||||
guard.take_damage(1)
|
||||
elapsed = 0.0
|
||||
stage = 6
|
||||
stage = 8
|
||||
return false
|
||||
6:
|
||||
8:
|
||||
if elapsed < 0.3:
|
||||
return false
|
||||
if not game_state.garrison_crew(outpost_id).is_empty():
|
||||
|
|
|
|||
|
|
@ -133,6 +133,23 @@ func _catalogue_cases() -> bool:
|
|||
return _fail("the quest after the mothership is %s, not exploration" % after.id)
|
||||
print("the mothership answers with distance, and exploration follows it")
|
||||
|
||||
# #185: the final wide search has a propulsion lesson immediately before
|
||||
# it. The goal uses the stable vessel id while the player-facing copy uses
|
||||
# the renamed Energy Propulser name.
|
||||
var trail: Dictionary = QUESTS.by_id("trail")
|
||||
var trail_at: int = QUESTS.CHAIN.find(trail)
|
||||
if trail_at <= 0:
|
||||
return _fail("the Chart 150 quest is missing or opens the chain")
|
||||
var before_trail: Dictionary = QUESTS.at(trail_at - 1)
|
||||
if String(before_trail.id) != "propulser" \
|
||||
or String(before_trail.goal.kind) != QUESTS.GOAL_FLEET_VESSEL \
|
||||
or String(before_trail.goal.vessel) != GameState.VESSEL_DISTORDER:
|
||||
return _fail("Chart 150 is preceded by %s, not the Energy Propulser vessel quest" \
|
||||
% before_trail.get("id", "nothing"))
|
||||
if not "Energy Propulser" in String(before_trail.objective):
|
||||
return _fail("the propulsion quest does not name the Energy Propulser to the player")
|
||||
print("the Energy Propulser vessel quest leads directly into Chart 150")
|
||||
|
||||
# --- R. #145: every structure quest can actually be finished ---------
|
||||
# The extractor quest could not be. Extractors are placed onto a planet
|
||||
# from space and live in their own array, not in `buildings`, so the
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ var scene: Node
|
|||
var fleet: Node
|
||||
var field: Node
|
||||
var controller: Node
|
||||
var lab_id: int = 0
|
||||
var crafter_id: int = 0
|
||||
var stage: int = 0
|
||||
var elapsed: float = 0.0
|
||||
|
|
@ -83,6 +84,7 @@ func _process(delta: float) -> bool:
|
|||
game_state.unlocked = ["shipyards", "vessel_science", "coordination", "wing", "squadron"]
|
||||
game_state.research_points = 10
|
||||
field.place(GameState.BUILDING_SHIP_LAB, Vector2(-700.0, 0.0))
|
||||
lab_id = int(game_state.buildings[-1].id)
|
||||
field.place(GameState.BUILDING_SHIP_CRAFTER, Vector2(700.0, 0.0))
|
||||
crafter_id = int(game_state.buildings[-1].id)
|
||||
elapsed = 0.0
|
||||
|
|
@ -130,6 +132,29 @@ func _process(delta: float) -> bool:
|
|||
return true
|
||||
print("lab cards are vessel-specific and selectable")
|
||||
|
||||
# #184: a queued research uses the bar as its changing value. The
|
||||
# status names the state but never repeats it as a percentage.
|
||||
var lab_progress: ProgressBar = controller.get_node(
|
||||
"../UI/LabMenu/ResearchProgress")
|
||||
var lab_status: Label = controller.get_node("../UI/LabMenu/StatusLabel")
|
||||
controller.lab_building_id = lab_id
|
||||
if not game_state.queue_lab_research(lab_id, "int_rate"):
|
||||
return _fail("could not queue research for the progress-bar check")
|
||||
controller.call("_refresh_lab")
|
||||
if not lab_progress.visible or lab_progress.show_percentage:
|
||||
return _fail("pending research did not show a percentage-free progress bar")
|
||||
if "%" in lab_status.text:
|
||||
return _fail("pending research still prints a percentage: '%s'" % lab_status.text)
|
||||
game_state.deposit_resource_to_building(lab_id, GameState.RESOURCE_ORE,
|
||||
game_state.upgrade_cost("int_rate"))
|
||||
game_state.call("_advance_lab_research", game_state.lab_research_time() * 0.25)
|
||||
controller.call("_refresh_lab")
|
||||
if lab_progress.value < 0.2 or lab_progress.value > 0.3 \
|
||||
or lab_status.text != "Researching":
|
||||
return _fail("research bar did not track active work (value %.2f, status '%s')" \
|
||||
% [lab_progress.value, lab_status.text])
|
||||
print("pending lab research is shown by a live progress bar, without percentage text")
|
||||
|
||||
# --- 3. buying raises the level and charges ------------------
|
||||
var before_rocks: int = game_state.rocks
|
||||
var first_cost: int = game_state.upgrade_cost("int_damage")
|
||||
|
|
@ -225,3 +250,9 @@ func _process(delta: float) -> bool:
|
|||
quit(0)
|
||||
return true
|
||||
return false
|
||||
|
||||
|
||||
func _fail(message: String) -> bool:
|
||||
print("TEST_SHIP_LAB: FAIL (%s)" % message)
|
||||
quit(1)
|
||||
return true
|
||||
|
|
|
|||
Loading…
Reference in a new issue