134 lines
4.3 KiB
GDScript3
134 lines
4.3 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Headless gameplay test: run with
|
||
|
|
# godot --headless -s res://tests/test_building_collateral.gd
|
||
|
|
# Forgejo #165: a gas bomb and a vessel flying fast enough both damage a
|
||
|
|
# structure. The blast used to stop politely at anything the player owned,
|
||
|
|
# which made a bomb dropped on a besieged mothership a free way to sweep the
|
||
|
|
# attackers off it.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. a bomb landing on a structure damages it
|
||
|
|
# B. a bomb landing clear of it does not - the radius is the radius, and
|
||
|
|
# this is a weapon that has to be aimed
|
||
|
|
# C. a vessel resting against a structure does NOT damage it. The fleet
|
||
|
|
# sits on its own mothership constantly to bank ore; if that hurt, the
|
||
|
|
# game's own economy loop would grind its buildings down
|
||
|
|
# D. a vessel arriving fast does
|
||
|
|
|
||
|
|
var game_state: Node
|
||
|
|
var main: Node
|
||
|
|
var fleet: Node
|
||
|
|
var building_id: int = 0
|
||
|
|
var stage: int = 0
|
||
|
|
var elapsed: float = 0.0
|
||
|
|
var hp_before: int = 0
|
||
|
|
const BUILDING_AT := Vector2(1200.0, 0.0)
|
||
|
|
|
||
|
|
|
||
|
|
func _initialize() -> void:
|
||
|
|
game_state = root.get_node("GameState")
|
||
|
|
game_state.buildings.clear()
|
||
|
|
game_state.extractors.clear()
|
||
|
|
game_state.reset_progression()
|
||
|
|
main = load("res://world/Main.tscn").instantiate()
|
||
|
|
root.add_child(main)
|
||
|
|
current_scene = main
|
||
|
|
fleet = main.get_node("Fleet")
|
||
|
|
|
||
|
|
|
||
|
|
func _hp() -> int:
|
||
|
|
return int(game_state.find_building(building_id).get("hp", 0))
|
||
|
|
|
||
|
|
|
||
|
|
func _detonate_at(at: Vector2) -> void:
|
||
|
|
var bomb: Node2D = load("res://vfx/GasBombEffect.gd").new()
|
||
|
|
main.add_child(bomb)
|
||
|
|
bomb.target = at
|
||
|
|
bomb.damage = 6
|
||
|
|
bomb._explode()
|
||
|
|
bomb.queue_free()
|
||
|
|
|
||
|
|
|
||
|
|
func _process(delta: float) -> bool:
|
||
|
|
elapsed += delta
|
||
|
|
match stage:
|
||
|
|
0:
|
||
|
|
if elapsed < 0.4:
|
||
|
|
return false
|
||
|
|
main.get_node("EnemySpawner").set_process(false)
|
||
|
|
main.get_node("AsteroidField").set_process(false)
|
||
|
|
for hazard in get_nodes_in_group("asteroids") + get_nodes_in_group("enemies"):
|
||
|
|
if is_instance_valid(hazard):
|
||
|
|
hazard.queue_free()
|
||
|
|
main.get_node("BuildingField").place(GameState.BUILDING_MOTHERSHIP, BUILDING_AT)
|
||
|
|
building_id = int(game_state.buildings[0].id)
|
||
|
|
if _hp() <= 0:
|
||
|
|
return _fail("the structure has no hit points to lose")
|
||
|
|
stage = 1
|
||
|
|
elapsed = 0.0
|
||
|
|
return false
|
||
|
|
1:
|
||
|
|
if elapsed < 0.2:
|
||
|
|
return false
|
||
|
|
# --- B. a bomb well clear of it does nothing ------------------
|
||
|
|
hp_before = _hp()
|
||
|
|
_detonate_at(BUILDING_AT + Vector2(900.0, 0.0))
|
||
|
|
if _hp() != hp_before:
|
||
|
|
return _fail("a bomb 900 away still damaged the structure")
|
||
|
|
print("a bomb clear of the structure leaves it alone")
|
||
|
|
|
||
|
|
# --- A. a bomb on top of it does --------------------------------
|
||
|
|
_detonate_at(BUILDING_AT)
|
||
|
|
if _hp() >= hp_before:
|
||
|
|
return _fail("a bomb landing on the structure did not damage it (hp %d)" % _hp())
|
||
|
|
print("a bomb on the structure took it from %d to %d" % [hp_before, _hp()])
|
||
|
|
|
||
|
|
# --- C. resting against it is free ------------------------------
|
||
|
|
hp_before = _hp()
|
||
|
|
fleet.spawn_ships(1, BUILDING_AT, PackedStringArray([GameState.VESSEL_INTERCEPTOR]))
|
||
|
|
for ship in fleet.ships:
|
||
|
|
ship.global_position = BUILDING_AT
|
||
|
|
ship.velocity = Vector2.ZERO
|
||
|
|
stage = 2
|
||
|
|
elapsed = 0.0
|
||
|
|
return false
|
||
|
|
2:
|
||
|
|
# Long enough for several strike ticks to have passed.
|
||
|
|
if elapsed < 2.0:
|
||
|
|
return false
|
||
|
|
for ship in fleet.ships:
|
||
|
|
ship.velocity = Vector2.ZERO
|
||
|
|
if _hp() != hp_before:
|
||
|
|
return _fail("a vessel resting on the structure damaged it (%d -> %d) - the fleet docks here to bank ore" \
|
||
|
|
% [hp_before, _hp()])
|
||
|
|
print("a vessel parked on the structure for %.1fs did nothing to it" % elapsed)
|
||
|
|
|
||
|
|
# --- D. arriving fast does --------------------------------------
|
||
|
|
hp_before = _hp()
|
||
|
|
for ship in fleet.ships:
|
||
|
|
# Placed clear and sent IN, because the impact is detected on
|
||
|
|
# entry - a ship spawned already overlapping never enters.
|
||
|
|
ship.global_position = BUILDING_AT - Vector2(400.0, 0.0)
|
||
|
|
ship.velocity = Vector2(900.0, 0.0)
|
||
|
|
ship.set_move_target(BUILDING_AT + Vector2(600.0, 0.0))
|
||
|
|
stage = 3
|
||
|
|
elapsed = 0.0
|
||
|
|
return false
|
||
|
|
3:
|
||
|
|
if elapsed < 1.2:
|
||
|
|
return false
|
||
|
|
if _hp() >= hp_before:
|
||
|
|
return _fail("a vessel arriving at 900 did not damage the structure")
|
||
|
|
print("a vessel arriving fast took it from %d to %d" % [hp_before, _hp()])
|
||
|
|
|
||
|
|
print("TEST_BUILDING_COLLATERAL: PASS")
|
||
|
|
quit(0)
|
||
|
|
return true
|
||
|
|
return false
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_BUILDING_COLLATERAL: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|