140 lines
4.9 KiB
GDScript3
140 lines
4.9 KiB
GDScript3
|
|
extends SceneTree
|
||
|
|
|
||
|
|
# Headless gameplay test: run with
|
||
|
|
# godot --headless -s res://tests/test_pickup_feedback.gd
|
||
|
|
# Forgejo #79: collecting used to be silent - a rock vanished and a number in
|
||
|
|
# the corner of the screen changed. Which number, and by how much, was left
|
||
|
|
# for the player to notice. A "+N" in the resource's own colour now rises
|
||
|
|
# where the pickup happened.
|
||
|
|
#
|
||
|
|
# Covers:
|
||
|
|
# A. collecting ore raises a marker at the pickup point, carrying the right
|
||
|
|
# resource and amount
|
||
|
|
# B. it is built from the resource catalog's own glyph, so a material added
|
||
|
|
# later cannot end up with one mark in the HUD and another in the world
|
||
|
|
# C. it clears itself up rather than accumulating one node per pickup
|
||
|
|
# D. a pickup that is REFUSED - a full hold - raises nothing, so the marker
|
||
|
|
# never claims something the player did not get
|
||
|
|
|
||
|
|
var game_state: Node
|
||
|
|
var main: Node
|
||
|
|
var fleet: 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.reset_progression()
|
||
|
|
main = load("res://Main.tscn").instantiate()
|
||
|
|
root.add_child(main)
|
||
|
|
current_scene = main
|
||
|
|
fleet = main.get_node("Fleet")
|
||
|
|
|
||
|
|
|
||
|
|
const PICKUP_VFX = preload("res://ResourcePickupVFX.gd")
|
||
|
|
|
||
|
|
|
||
|
|
func _markers() -> Array:
|
||
|
|
var found: Array = []
|
||
|
|
for node in root.get_children():
|
||
|
|
if node.get_script() == PICKUP_VFX:
|
||
|
|
found.append(node)
|
||
|
|
return found
|
||
|
|
|
||
|
|
|
||
|
|
func _drop_rock_on_fleet() -> Node2D:
|
||
|
|
var rock: Node2D = load("res://Rock.tscn").instantiate()
|
||
|
|
rock.build_shape(7)
|
||
|
|
rock.position = fleet.ships[0].global_position
|
||
|
|
main.add_child(rock)
|
||
|
|
return rock
|
||
|
|
|
||
|
|
|
||
|
|
func _process(delta: float) -> bool:
|
||
|
|
elapsed += delta
|
||
|
|
match stage:
|
||
|
|
0:
|
||
|
|
if elapsed < 0.3:
|
||
|
|
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("rocks"):
|
||
|
|
if is_instance_valid(hazard):
|
||
|
|
hazard.free()
|
||
|
|
fleet.spawn_ships(1, Vector2.ZERO, PackedStringArray([GameState.VESSEL_INTERCEPTOR]))
|
||
|
|
game_state.fleet_inventory.set_amount(GameState.RESOURCE_ORE, 0)
|
||
|
|
if not _markers().is_empty():
|
||
|
|
return _fail("a pickup marker existed before anything was collected")
|
||
|
|
_drop_rock_on_fleet()
|
||
|
|
stage = 1
|
||
|
|
elapsed = 0.0
|
||
|
|
return false
|
||
|
|
1:
|
||
|
|
if elapsed < 0.4:
|
||
|
|
return false
|
||
|
|
# --- A. one marker, right resource, right amount --------------
|
||
|
|
var markers: Array = _markers()
|
||
|
|
if markers.size() != 1:
|
||
|
|
return _fail("collecting one rock raised %d markers" % markers.size())
|
||
|
|
var marker: Node2D = markers[0]
|
||
|
|
if game_state.fleet_resource(GameState.RESOURCE_ORE) <= 0:
|
||
|
|
return _fail("the rock was not actually collected, so the marker is reporting a pickup that did not happen")
|
||
|
|
if marker.global_position.distance_to(fleet.ships[0].global_position) > 120.0:
|
||
|
|
return _fail("the marker appeared %.0f away from where the pickup happened" \
|
||
|
|
% marker.global_position.distance_to(fleet.ships[0].global_position))
|
||
|
|
|
||
|
|
# --- B. built from the catalog's own glyph --------------------
|
||
|
|
var definitions: Script = load("res://ResourceDefinitions.gd")
|
||
|
|
var ore: Resource = definitions.get_definition(GameState.RESOURCE_ORE)
|
||
|
|
if not marker.colour.is_equal_approx(ore.color):
|
||
|
|
return _fail("the marker is %s, but ore is %s" % [marker.colour, ore.color])
|
||
|
|
var glyph_scripts: Array = []
|
||
|
|
for child in marker.get_children():
|
||
|
|
glyph_scripts.append(child.get_script())
|
||
|
|
var probe: Node = ore.glyph_scene.instantiate()
|
||
|
|
var expected: Script = probe.get_script()
|
||
|
|
probe.free()
|
||
|
|
if expected not in glyph_scripts:
|
||
|
|
return _fail("the marker does not use the ore glyph the resource catalog defines")
|
||
|
|
print("collecting ore raised one marker at the pickup point, in ore's own colour and glyph")
|
||
|
|
stage = 2
|
||
|
|
elapsed = 0.0
|
||
|
|
return false
|
||
|
|
2:
|
||
|
|
# --- C. it cleans itself up -----------------------------------
|
||
|
|
if elapsed < 1.5:
|
||
|
|
return false
|
||
|
|
if not _markers().is_empty():
|
||
|
|
return _fail("%d marker(s) still on screen 1.5s later - they accumulate" % _markers().size())
|
||
|
|
print("marker cleared itself up")
|
||
|
|
|
||
|
|
# --- D. a refused pickup says nothing -------------------------
|
||
|
|
# Hold filled to capacity, so collect_cargo takes nothing.
|
||
|
|
var capacity: int = game_state.fleet_inventory.total_capacity
|
||
|
|
if capacity < 0:
|
||
|
|
return _fail("the fleet hold has no capacity limit, so a refused pickup cannot be staged")
|
||
|
|
game_state.fleet_inventory.set_amount(GameState.RESOURCE_ORE, capacity)
|
||
|
|
_drop_rock_on_fleet()
|
||
|
|
stage = 3
|
||
|
|
elapsed = 0.0
|
||
|
|
return false
|
||
|
|
3:
|
||
|
|
if elapsed < 0.4:
|
||
|
|
return false
|
||
|
|
if not _markers().is_empty():
|
||
|
|
return _fail("a full hold refused the rock but a marker claimed it was collected")
|
||
|
|
print("a pickup refused by a full hold raises no marker")
|
||
|
|
|
||
|
|
print("TEST_PICKUP_FEEDBACK: PASS")
|
||
|
|
quit(0)
|
||
|
|
return true
|
||
|
|
return false
|
||
|
|
|
||
|
|
|
||
|
|
func _fail(message: String) -> bool:
|
||
|
|
print("TEST_PICKUP_FEEDBACK: FAIL (%s)" % message)
|
||
|
|
quit(1)
|
||
|
|
return true
|