160 lines
7.1 KiB
GDScript3
160 lines
7.1 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Headless test: run with
|
||
|
|
# godot --headless -s res://tests/test_outpost_crewing.gd
|
||
|
|
# Forgejo #104 (#97f): "When an outpost is configured to have a given amount
|
||
|
|
# of ship, the game should transfer, whenever available, ships from the
|
||
|
|
# mothership to the outpost to always fullfill the outpost conditions if
|
||
|
|
# possible."
|
||
|
|
#
|
||
|
|
# Vessels come from the HANGAR and never from the fleet: the fleet is what
|
||
|
|
# the player is flying, and taking a vessel out of it to crew a building
|
||
|
|
# would be the game undoing the player's own arrangement.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. an order with nothing in the hangar waits. It does not conjure a
|
||
|
|
# vessel, and it does not take one out of the fleet
|
||
|
|
# B. a matching vessel in the hangar is dispatched, travels, and joins the
|
||
|
|
# crew on arrival
|
||
|
|
# C. it dispatches exactly the shortfall - what is already in the air
|
||
|
|
# counts, or the whole hangar leaves to fill one berth
|
||
|
|
# D. lowering the order releases the surplus back to the hangar
|
||
|
|
# E. an outpost levelled while a vessel is inbound does not destroy it:
|
||
|
|
# the vessel lands in the hangar instead
|
||
|
|
|
||
|
|
var game_state: Node
|
||
|
|
var outpost_id: int = 0
|
||
|
|
var second_id: int = 0
|
||
|
|
var stage: int = 0
|
||
|
|
var elapsed: float = 0.0
|
||
|
|
var fleet_before: int = 0
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
# GameState is an autoload: a bare GameState.<instance member> does not
|
||
|
|
# compile in a SceneTree script, so the node is fetched by name instead.
|
||
|
|
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.vessel_deliveries.clear()
|
||
|
|
game_state.reset_progression()
|
||
|
|
game_state.reset_waves()
|
||
|
|
game_state.unlocked.append("forward_bases")
|
||
|
|
game_state.add_building(GameState.BUILDING_MOTHERSHIP, Vector2.ZERO)
|
||
|
|
outpost_id = game_state.add_building(GameState.BUILDING_OUTPOST, Vector2(1200.0, 0.0))
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_OUTPOST_CREWING: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|
||
|
|
|
||
|
|
|
||
|
|
# Runs the autoload's own clock without waiting out the real seconds: this
|
||
|
|
# test is about the dispatcher, not about how long a vessel takes to fly.
|
||
|
|
func _simulate(seconds: float) -> void:
|
||
|
|
var step: float = 1.0 / 60.0
|
||
|
|
var ticks: int = int(seconds / step)
|
||
|
|
for i in range(ticks):
|
||
|
|
game_state._advance_vessel_deliveries(step)
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
|
||
|
|
|
||
|
|
func _process(_delta: float) -> bool:
|
||
|
|
# --- A. an order nobody can fill waits ------------------------------
|
||
|
|
game_state.set_garrison_desired(outpost_id, GameState.VESSEL_INTERCEPTOR, 2)
|
||
|
|
if game_state.garrison_desired_total(outpost_id) != 2:
|
||
|
|
return _fail("the order did not take")
|
||
|
|
_simulate(20.0)
|
||
|
|
if not game_state.garrison_crew(outpost_id).is_empty():
|
||
|
|
return _fail("an outpost crewed itself out of an empty hangar")
|
||
|
|
if not game_state.vessel_deliveries.is_empty():
|
||
|
|
return _fail("something was dispatched with nothing in the hangar")
|
||
|
|
if game_state.garrison_desired_total(outpost_id) != 2:
|
||
|
|
return _fail("the unfillable order was dropped instead of waiting")
|
||
|
|
print("an order of 2 with an empty hangar waits, and stays an order")
|
||
|
|
|
||
|
|
# --- B. a hull in the hangar is sent ---------------------------------
|
||
|
|
game_state.stored_vessels.append(GameState.VESSEL_INTERCEPTOR)
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
if game_state.vessel_deliveries.size() != 1:
|
||
|
|
return _fail("a vessel in the hangar produced %d deliveries" \
|
||
|
|
% game_state.vessel_deliveries.size())
|
||
|
|
if not game_state.stored_vessels.is_empty():
|
||
|
|
return _fail("the vessel was dispatched and is still in the hangar too")
|
||
|
|
var delivery: Dictionary = game_state.vessel_deliveries[0]
|
||
|
|
if int(delivery.get("to_outpost", 0)) != outpost_id:
|
||
|
|
return _fail("the delivery is not bound for the outpost")
|
||
|
|
if float(delivery.progress) >= 1.0:
|
||
|
|
return _fail("the vessel teleported - it should have to fly there")
|
||
|
|
_simulate(30.0)
|
||
|
|
if game_state.garrison_crew_of(outpost_id, GameState.VESSEL_INTERCEPTOR) != 1:
|
||
|
|
return _fail("the vessel never arrived (crew=%s)" \
|
||
|
|
% str(game_state.garrison_crew(outpost_id)))
|
||
|
|
print("one hull in the hangar flies out and joins the crew")
|
||
|
|
|
||
|
|
# --- C. exactly the shortfall ---------------------------------------
|
||
|
|
for i in range(6):
|
||
|
|
game_state.stored_vessels.append(GameState.VESSEL_INTERCEPTOR)
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
if game_state.vessel_deliveries.size() != 1:
|
||
|
|
return _fail("one empty berth dispatched %d vessels" \
|
||
|
|
% game_state.vessel_deliveries.size())
|
||
|
|
# A second call before the first lands must not send another.
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
if game_state.vessel_deliveries.size() != 1:
|
||
|
|
return _fail("the dispatcher sent a second vessel for a berth already in the air")
|
||
|
|
if game_state.stored_vessels.size() != 5:
|
||
|
|
return _fail("the hangar holds %d, expected 5 left" % game_state.stored_vessels.size())
|
||
|
|
_simulate(30.0)
|
||
|
|
if game_state.garrison_crew(outpost_id).size() != 2:
|
||
|
|
return _fail("the outpost holds %d of its 2 berths" \
|
||
|
|
% game_state.garrison_crew(outpost_id).size())
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
if not game_state.vessel_deliveries.is_empty():
|
||
|
|
return _fail("a full outpost is still being sent vessels")
|
||
|
|
print("2 berths, 6 spare hulls: it sent exactly 1 and then stopped")
|
||
|
|
|
||
|
|
# --- D. lowering the order releases the surplus ----------------------
|
||
|
|
var hangar_before: int = game_state.stored_vessels.size()
|
||
|
|
game_state.set_garrison_desired(outpost_id, GameState.VESSEL_INTERCEPTOR, 1)
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
if game_state.garrison_crew(outpost_id).size() != 1:
|
||
|
|
return _fail("lowering the order to 1 left %d aboard" \
|
||
|
|
% game_state.garrison_crew(outpost_id).size())
|
||
|
|
_simulate(30.0)
|
||
|
|
if game_state.stored_vessels.size() != hangar_before + 1:
|
||
|
|
return _fail("the released vessel did not come home (hangar %d -> %d)" \
|
||
|
|
% [hangar_before, game_state.stored_vessels.size()])
|
||
|
|
print("lowering the order flies the surplus back to the hangar")
|
||
|
|
|
||
|
|
# --- E. a destination that stops existing ---------------------------
|
||
|
|
second_id = game_state.add_building(GameState.BUILDING_OUTPOST, Vector2(-1400.0, 0.0))
|
||
|
|
game_state.set_garrison_desired(second_id, GameState.VESSEL_INTERCEPTOR, 1)
|
||
|
|
game_state._advance_garrison_dispatch()
|
||
|
|
if game_state.garrison_inbound(second_id) != 1:
|
||
|
|
return _fail("nothing was dispatched to the second outpost")
|
||
|
|
hangar_before = game_state.stored_vessels.size()
|
||
|
|
if not game_state.destroy_building(second_id):
|
||
|
|
return _fail("the second outpost could not be destroyed")
|
||
|
|
_simulate(30.0)
|
||
|
|
if game_state.stored_vessels.size() != hangar_before + 1:
|
||
|
|
return _fail("a vessel inbound to a destroyed outpost was lost")
|
||
|
|
print("a vessel whose outpost was levelled under it lands back in the hangar")
|
||
|
|
|
||
|
|
# --- A (again). the fleet is never raided ---------------------------
|
||
|
|
game_state.stored_vessels.clear()
|
||
|
|
game_state.set_garrison_desired(outpost_id, GameState.VESSEL_INTERCEPTOR, 3)
|
||
|
|
fleet_before = game_state.surviving_ship_count
|
||
|
|
_simulate(20.0)
|
||
|
|
if game_state.surviving_ship_count != fleet_before:
|
||
|
|
return _fail("the dispatcher took a vessel out of the fleet")
|
||
|
|
if game_state.garrison_crew(outpost_id).size() != 1:
|
||
|
|
return _fail("the outpost gained a vessel from nowhere")
|
||
|
|
print("with an empty hangar it takes nothing from the fleet")
|
||
|
|
|
||
|
|
print("TEST_OUTPOST_CREWING: PASS")
|
||
|
|
quit(0)
|
||
|
|
return true
|