137 lines
4.9 KiB
GDScript3
137 lines
4.9 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Headless gameplay test: run with
|
||
|
|
# godot --headless -s res://tests/test_conquered_planet_clear.gd
|
||
|
|
# A planet's garrison was destroyed to take it, so it must not be standing
|
||
|
|
# there again the next time the player lands. Capture points already came
|
||
|
|
# back marked captured; the enemies came back alive, which read as the
|
||
|
|
# conquest having quietly been undone.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. an unconquered planet lays out its authored enemies, as before
|
||
|
|
# B. once every capture point is taken, re-landing places no enemies - and
|
||
|
|
# still places the capture points, marked captured
|
||
|
|
# C. a setup that authors enemies but NO capture points keeps them. Such a
|
||
|
|
# planet counts as vacuously conquered (nothing to capture), so keying
|
||
|
|
# only off the conquered flag would delete a garrison nobody has beaten
|
||
|
|
|
||
|
|
const PLANET_KEY: String = "test_conquered_planet_clear"
|
||
|
|
const OPEN_PLANET_KEY: String = "test_conquered_planet_clear_open"
|
||
|
|
|
||
|
|
var game_state: Node
|
||
|
|
var host_scene: PackedScene
|
||
|
|
var stage: int = 0
|
||
|
|
var elapsed: float = 0.0
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
game_state = root.get_node("GameState")
|
||
|
|
game_state.planet_capture.clear()
|
||
|
|
host_scene = load("res://PlanetSetupHost.tscn")
|
||
|
|
|
||
|
|
|
||
|
|
func _process(delta: float) -> bool:
|
||
|
|
elapsed += delta
|
||
|
|
if stage == 0:
|
||
|
|
# One frame of grace so the autoload is fully up, same as the other
|
||
|
|
# scene-driven tests.
|
||
|
|
if elapsed < 0.1:
|
||
|
|
return false
|
||
|
|
|
||
|
|
# --- A. unconquered: the garrison is there ---------------------------
|
||
|
|
game_state.planet_id = PLANET_KEY
|
||
|
|
game_state.planet_definition_id = "rocky"
|
||
|
|
var setup: Resource = _make_setup(2, 3)
|
||
|
|
var enemies: int = _apply_and_count_enemies(setup)
|
||
|
|
if enemies != 3:
|
||
|
|
return _fail("an unconquered planet placed %d of its 3 authored enemies" % enemies)
|
||
|
|
if game_state.is_planet_conquered(PLANET_KEY):
|
||
|
|
return _fail("a planet with 2 uncaptured points reported itself conquered")
|
||
|
|
print("unconquered planet: 3 enemies placed")
|
||
|
|
|
||
|
|
# --- B. conquered: the garrison stays destroyed ----------------------
|
||
|
|
game_state.mark_point_captured(PLANET_KEY, 0)
|
||
|
|
game_state.mark_point_captured(PLANET_KEY, 1)
|
||
|
|
if not game_state.is_planet_conquered(PLANET_KEY):
|
||
|
|
return _fail("capturing every point did not conquer the planet")
|
||
|
|
|
||
|
|
var host: Node = host_scene.instantiate()
|
||
|
|
root.add_child(host)
|
||
|
|
host.apply_setup(setup)
|
||
|
|
var remaining: int = _count_enemies(host)
|
||
|
|
var points: int = _count_capture_points(host)
|
||
|
|
host.free()
|
||
|
|
if remaining != 0:
|
||
|
|
return _fail("re-landing on a conquered planet placed %d enemies" % remaining)
|
||
|
|
if points != 2:
|
||
|
|
return _fail("a conquered planet placed %d of its 2 capture points - conquest should clear the garrison, not the map" % points)
|
||
|
|
print("conquered planet: 0 enemies, both capture points still placed")
|
||
|
|
|
||
|
|
# --- C. a setup with nothing to capture keeps its enemies ------------
|
||
|
|
game_state.planet_id = OPEN_PLANET_KEY
|
||
|
|
var open_setup: Resource = _make_setup(0, 2)
|
||
|
|
var open_enemies: int = _apply_and_count_enemies(open_setup)
|
||
|
|
if not game_state.is_planet_conquered(OPEN_PLANET_KEY):
|
||
|
|
return _fail("a setup with no capture points was expected to register as vacuously conquered, and did not - so this case no longer tests what it claims to")
|
||
|
|
if open_enemies != 2:
|
||
|
|
return _fail("a setup with no capture points lost %d of its 2 enemies to the conquest rule" \
|
||
|
|
% (2 - open_enemies))
|
||
|
|
print("setup with no capture points: both enemies kept, despite counting as conquered")
|
||
|
|
|
||
|
|
print("TEST_CONQUERED_PLANET_CLEAR: PASS")
|
||
|
|
quit(0)
|
||
|
|
return true
|
||
|
|
return false
|
||
|
|
|
||
|
|
|
||
|
|
func _make_setup(capture_count: int, enemy_count: int) -> Resource:
|
||
|
|
var setup: Resource = load("res://PlanetSetup.gd").new()
|
||
|
|
setup.setup_id = "in_memory"
|
||
|
|
setup.surface_profile_id = "rocky"
|
||
|
|
var points: PackedVector2Array = PackedVector2Array()
|
||
|
|
for i in range(capture_count):
|
||
|
|
points.append(Vector2(200.0 * float(i + 1), 0.0))
|
||
|
|
setup.capture_points = points
|
||
|
|
var spawn_script: Script = load("res://PlanetSetupSpawn.gd")
|
||
|
|
for i in range(enemy_count):
|
||
|
|
var spawn: Resource = spawn_script.new()
|
||
|
|
spawn.enemy_id = "chaser"
|
||
|
|
spawn.position = Vector2(0.0, 200.0 * float(i + 1))
|
||
|
|
setup.enemy_spawns.append(spawn)
|
||
|
|
return setup
|
||
|
|
|
||
|
|
|
||
|
|
func _apply_and_count_enemies(setup: Resource) -> int:
|
||
|
|
var host: Node = host_scene.instantiate()
|
||
|
|
root.add_child(host)
|
||
|
|
host.apply_setup(setup)
|
||
|
|
var count: int = _count_enemies(host)
|
||
|
|
host.free()
|
||
|
|
return count
|
||
|
|
|
||
|
|
|
||
|
|
# Counted by group rather than by script or node name: that is how everything
|
||
|
|
# else in the game finds enemies, so this cannot pass while the real hunters
|
||
|
|
# see something different.
|
||
|
|
func _count_enemies(host: Node) -> int:
|
||
|
|
var count: int = 0
|
||
|
|
for child in host.get_children():
|
||
|
|
if child.is_in_group("enemies"):
|
||
|
|
count += 1
|
||
|
|
return count
|
||
|
|
|
||
|
|
|
||
|
|
func _count_capture_points(host: Node) -> int:
|
||
|
|
var count: int = 0
|
||
|
|
for child in host.get_children():
|
||
|
|
if child.is_in_group("enemies"):
|
||
|
|
continue
|
||
|
|
if "point_index" in child:
|
||
|
|
count += 1
|
||
|
|
return count
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_CONQUERED_PLANET_CLEAR: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|