spaceship/tests/test_shield_vessel.gd

181 lines
5.7 KiB
GDScript3
Raw Normal View History

extends SceneTree
# Headless gameplay test: run with
# godot --headless -s res://tests/test_shield_vessel.gd
# Forgejo #5: the shield vessel's shield absorbs a hit that would destroy any
# other ship, and is then down until it cycles back up.
#
# The shield is PERSONAL - it protects the vessel carrying it and nothing
# else. Ships have no health in this game: contact with an enemy or an
# asteroid destroys them outright, so "absorbs a hit" means surviving the
# collision that would otherwise have killed it.
#
# Verifies:
# 1. an ordinary interceptor still dies to a rock (so the shield result
# below means something)
# 2. a shield vessel survives the same rock, and the rock is destroyed
# 3. its shield is then DOWN - a second rock while it is cycling kills it,
# or the shield would be permanent invulnerability
# 4. the shield comes back on its own after the recharge time
# 5. researched capacity lets it take more than one hit
# 6. the recharge upgrade actually shortens the wait
var game_state: Node
var scene: Node
var fleet: Node
var interceptor: Node
var shield_ship: Node
var stage: int = 0
var elapsed: float = 0.0
func _initialize() -> void:
game_state = root.get_node("GameState")
game_state.buildings.clear()
game_state.extractors.clear()
game_state.transporters.clear()
game_state.vessels_owed.clear()
game_state.reset_progression()
game_state.rocks = 2000
scene = load("res://Main.tscn").instantiate()
root.add_child(scene)
fleet = scene.get_node("Fleet")
func _rock_onto(ship: Node) -> void:
var rock: Area2D = load("res://Asteroid.tscn").instantiate()
rock.velocity = Vector2.ZERO
rock.global_position = ship.global_position
scene.add_child(rock)
func _process(delta: float) -> bool:
elapsed += delta
match stage:
0:
scene.get_node("AsteroidField").set_process(false)
scene.get_node("EnemySpawner").set_process(false)
for a in get_nodes_in_group("asteroids"):
if is_instance_valid(a):
a.queue_free()
fleet.spawn_ships(1, Vector2.ZERO)
interceptor = fleet.ships[0]
# Well clear of the interceptor, or one rock hits both.
fleet.add_ship(GameState.VESSEL_SHIELD)
shield_ship = fleet.ships[1]
shield_ship.position = Vector2(2000.0, 0.0)
elapsed = 0.0
stage = 1
return false
1:
if elapsed < 0.2:
return false
if not shield_ship.has_shield():
print("TEST_SHIELD_VESSEL: FAIL (a fresh shield vessel has no shield)")
quit(1)
return true
# --- 1. the control: an interceptor dies --------------------
_rock_onto(interceptor)
elapsed = 0.0
stage = 2
return false
2:
if elapsed < 0.4:
return false
if is_instance_valid(interceptor):
print("TEST_SHIELD_VESSEL: FAIL (an ordinary interceptor survived a rock - the test proves nothing)")
quit(1)
return true
print("control: interceptor destroyed by a rock")
# --- 2. the shield vessel survives it -----------------------
_rock_onto(shield_ship)
elapsed = 0.0
stage = 3
return false
3:
if elapsed < 0.4:
return false
if not is_instance_valid(shield_ship):
print("TEST_SHIELD_VESSEL: FAIL (the shield did not absorb the hit)")
quit(1)
return true
if shield_ship.has_shield():
print("TEST_SHIELD_VESSEL: FAIL (shield still up after taking a hit - it never goes down)")
quit(1)
return true
print("shield vessel survived, shield now down")
# --- 3. defenceless while it cycles -------------------------
_rock_onto(shield_ship)
elapsed = 0.0
stage = 4
return false
4:
if elapsed < 0.4:
return false
if is_instance_valid(shield_ship):
print("TEST_SHIELD_VESSEL: FAIL (survived a second hit with the shield down - it is just invulnerable)")
quit(1)
return true
print("second hit while cycling destroyed it, as it should")
# --- 4 + 5. recharge, and researched capacity ---------------
game_state.vessel_levels["shd_hits"] = 1
fleet.add_ship(GameState.VESSEL_SHIELD)
shield_ship = fleet.ships[fleet.ships.size() - 1]
shield_ship.position = Vector2(-2000.0, 0.0)
elapsed = 0.0
stage = 5
return false
5:
if elapsed < 0.2:
return false
if shield_ship.shield_charges != game_state.shield_max_charges():
print("TEST_SHIELD_VESSEL: FAIL (researched capacity %d, vessel has %d)" % [
game_state.shield_max_charges(), shield_ship.shield_charges
])
quit(1)
return true
print("with Layered Emitters researched: %d charges" % shield_ship.shield_charges)
_rock_onto(shield_ship)
elapsed = 0.0
stage = 6
return false
6:
if elapsed < 0.4:
return false
if not is_instance_valid(shield_ship) or not shield_ship.has_shield():
print("TEST_SHIELD_VESSEL: FAIL (a two-charge shield did not survive one hit with a charge left)")
quit(1)
return true
print("two-charge shield took a hit and is still up (%d left)" % shield_ship.shield_charges)
# --- 6. the recharge upgrade shortens the wait --------------
var slow: float = game_state.shield_recharge_time()
game_state.vessel_levels["shd_recharge"] = 2
var fast: float = game_state.shield_recharge_time()
print("recharge %.1fs -> %.1fs with Fast Cycling" % [slow, fast])
if fast >= slow:
print("TEST_SHIELD_VESSEL: FAIL (the recharge upgrade did not shorten the wait)")
quit(1)
return true
# --- 4. it really does come back ----------------------------
shield_ship.shield_charges = 0
shield_ship.shield_recharge_left = 0.15
elapsed = 0.0
stage = 7
return false
7:
if elapsed < 0.6:
return false
if not shield_ship.has_shield():
print("TEST_SHIELD_VESSEL: FAIL (the shield never cycled back up)")
quit(1)
return true
print("shield cycled back up on its own")
print("TEST_SHIELD_VESSEL: PASS")
quit(0)
return true
return false