extends SceneTree # Headless gameplay test: run with # godot --headless -s res://tests/test_enemy_composition.gd # Verifies: # 1. an Enemy resolves its stats/hull/color from EnemyDefinitions, not # hardcoded fields # 2. an enemy instantiated under a node that is NOT a sibling of Fleet # still finds the fleet and pursues it (the old `../Fleet` path would # break here - this is exactly the planet-surface hazard #44 exists # to close before #45/#46 land) var main_scene: Node var fleet: Node var nested_host: Node2D var enemy: Node var elapsed: float = 0.0 var stage: int = 0 func _initialize() -> void: var chaser_def: Resource = EnemyDefinitions.get_definition("chaser") if chaser_def.enemy_id != "chaser" or chaser_def.max_hp != 3: return _fail("EnemyDefinitions did not resolve the chaser definition") main_scene = load("res://world/Main.tscn").instantiate() root.add_child(main_scene) fleet = main_scene.get_node("Fleet") main_scene.get_node("EnemySpawner").set_process(false) # Deliberately NOT a sibling of Fleet - two levels deep under an # unrelated node, the way a planet surface's SurfaceFeatures parents # things. nested_host = Node2D.new() nested_host.name = "NestedHost" main_scene.add_child(nested_host) var inner: Node2D = Node2D.new() inner.name = "Inner" nested_host.add_child(inner) enemy = load("res://enemies/Enemy.tscn").instantiate() enemy.position = fleet.get_centroid() + Vector2(600, 0) inner.add_child(enemy) func _process(delta: float) -> bool: elapsed += delta match stage: 0: if elapsed < 0.1: return false if enemy.definition == null or enemy.definition.enemy_id != "chaser": return _fail("enemy did not resolve its definition on _ready") if enemy.hp != enemy.definition.max_hp: return _fail("enemy hp did not come from the definition") if not enemy.has_capability("pursuit"): return _fail("chaser did not compose a pursuit component") elapsed = 0.0 stage = 1 return false 1: # Give the pursuit component a few physics ticks to close distance. if elapsed < 1.0: return false var distance: float = enemy.position.distance_to(fleet.get_centroid()) print("distance_after_1s=%.1f (started at 600)" % distance) if distance >= 550.0: return _fail("enemy under a non-sibling host never approached the fleet") print("TEST_ENEMY_COMPOSITION: PASS") quit(0) return true return false func _fail(message: String) -> bool: print("TEST_ENEMY_COMPOSITION: FAIL (%s)" % message) quit(1) return true