spaceship/tests/test_planet_garrison.gd

143 lines
5.5 KiB
GDScript3
Raw Permalink Normal View History

extends SceneTree
# Headless gameplay test: run with
# godot --headless -s res://tests/test_planet_garrison.gd
# Forgejo #211: taking a planet is killing what defends it. The capture
# points this replaced - stand in a ring, wait out a timer, once per ring -
# are gone, so what has to be proven is that the FIGHT reaches the conquest
# state, through the enemies' own deaths rather than through a bookkeeping
# call a test makes on their behalf.
#
# test_conquered_planet_clear.gd covers the counting rules around landing and
# re-landing. This one covers the wiring: a real Enemy, destroyed the way
# anything destroys one, moves the planet toward being held.
#
# Covers:
# A. an authored garrison registers itself when the surface is composed
# B. killing one defender is progress, not conquest
# C. killing the last one conquers the planet, exactly once, and the
# research award rides along with the signal
# D. an enemy that dies after the planet has already fallen changes nothing
# Resolved via load() inside _initialize(), NOT a top-level `const ...
# preload(...)`. A top-level preload in a script-mode ENTRY point (-s
# this_file.gd) evaluates during this file's own early compilation, which can
# happen before autoloads are registered - and these scripts reference
# GameState in function bodies, which GDScript resolves at compile time.
var PLANET_SETUP_SCRIPT: Script
var SPAWN_SCRIPT: Script
var game_state: Node
var host: Node
var planet_id: String = "test_garrison_planet"
var conquered_count: int = 0
var conquered_points: int = -1
var stage: int = 0
var elapsed: float = 0.0
func _initialize() -> void:
PLANET_SETUP_SCRIPT = load("res://surface/PlanetSetup.gd")
SPAWN_SCRIPT = load("res://surface/PlanetSetupSpawn.gd")
game_state = root.get_node("GameState")
game_state.planet_capture.clear()
game_state.planet_id = planet_id
game_state.planet_definition_id = "rocky"
game_state.planet_conquered.connect(func(_id, points):
conquered_count += 1
conquered_points = points)
var setup: Resource = PLANET_SETUP_SCRIPT.new()
setup.setup_id = "test_garrison"
setup.surface_profile_id = "rocky"
# Worth something, so the award travelling with the signal is checked on a
# planet that actually pays.
setup.research_point_reward = 3
for i in range(3):
var spawn: Resource = SPAWN_SCRIPT.new()
spawn.enemy_id = "chaser"
spawn.position = Vector2(0.0, 300.0 * float(i + 1))
setup.enemy_spawns.append(spawn)
host = load("res://surface/PlanetSetupHost.tscn").instantiate()
root.add_child(host)
host.apply_setup(setup)
func _defenders() -> Array:
var out: Array = []
for child in host.get_children():
if is_instance_valid(child) and child.is_in_group("enemies") \
and not child.is_queued_for_deletion():
out.append(child)
return out
func _process(delta: float) -> bool:
elapsed += delta
if elapsed < 0.2:
return false
match stage:
0:
# --- A. the garrison registered itself -----------------------
var defenders: Array = _defenders()
if defenders.size() != 3:
return _fail("the surface placed %d defenders for 3 authored" % defenders.size())
if game_state.garrison_total(planet_id) != 3 \
or game_state.garrison_remaining(planet_id) != 3:
return _fail("a 3-strong garrison registered as %d of %d" % [
game_state.garrison_remaining(planet_id),
game_state.garrison_total(planet_id)])
print("3 defenders placed, and the planet knows it")
# --- B. one down is not conquest -----------------------------
var points_before: int = game_state.research_points
defenders[0].take_damage(defenders[0].hp)
if game_state.garrison_remaining(planet_id) != 2:
return _fail("one kill left %d of the garrison standing, expected 2" \
% game_state.garrison_remaining(planet_id))
if game_state.is_planet_conquered(planet_id):
return _fail("the planet fell to the first kill")
if game_state.research_points != points_before:
return _fail("an unfinished conquest paid out")
print("one defender down: 2 left, planet still theirs")
# --- C. the last one takes it --------------------------------
defenders[1].take_damage(defenders[1].hp)
defenders[2].take_damage(defenders[2].hp)
if not game_state.is_planet_conquered(planet_id):
return _fail("the whole garrison is dead and the planet is not ours")
if conquered_count != 1:
return _fail("planet_conquered fired %d times, expected once" % conquered_count)
if conquered_points != 3:
return _fail("the conquest reported %d research points, expected the authored 3" \
% conquered_points)
if game_state.research_points != points_before + 3:
return _fail("the reported award was not the one banked")
print("last defender down: planet taken, 3 research points paid once")
elapsed = 0.0
stage = 1
return false
1:
# --- D. a straggler after the fact changes nothing -----------
# A shot already in flight, or a bomb still blooming, can kill
# something a frame after the planet has fallen.
var points_after: int = game_state.research_points
game_state.mark_garrison_enemy_destroyed(planet_id)
if conquered_count != 1:
return _fail("a kill after conquest fired planet_conquered again")
if game_state.research_points != points_after:
return _fail("a kill after conquest paid the reward a second time")
print("a late kill is absorbed: no second conquest, no second payment")
print("TEST_PLANET_GARRISON: PASS")
quit(0)
return true
return false
func _fail(message: String) -> bool:
print("TEST_PLANET_GARRISON: FAIL (%s)" % message)
quit(1)
return true