extends SceneTree var failures: Array[String] = [] func _initialize() -> void: call_deferred("_run") func _run() -> void: var main_scene: Node = load("res://main.tscn").instantiate() root.add_child(main_scene) await process_frame for _frame in 12: await physics_frame var simulation_manager: Node = main_scene.get_node("SimulationManager") simulation_manager.set_process(false) var combat_view: Node = main_scene.get_node("CombatPresentation") var player := main_scene.get_node("Player") as Node3D var controller := main_scene.get_node("Player/PlayerCombatController") await process_frame await process_frame _check( combat_view.hostiles.size() >= 1, "Authored wolves should spawn as hostile visuals in the loaded world" ) var hostiles: Array = simulation_manager.get_living_hostile_combatants() _check(not hostiles.is_empty(), "The simulation should own at least one living hostile") if hostiles.is_empty(): main_scene.queue_free() _finish() return var wolf: CombatantStateRecord = hostiles[0] _check( combat_view.hostiles.has(wolf.get_combatant_id()), "The hostile visual should bind to the authoritative combatant record" ) _check( ( wolf.get_kind() == SimulationIds.COMBATANT_KIND_WOLF and wolf.is_hostile() and wolf.get_faction_id() == SimulationIds.FACTION_TRIBE ), "Spawned wolves should be hostile tribe-affiliated combatants" ) var wolf_visual: Node3D = combat_view.hostiles[wolf.get_combatant_id()] var sword_definition := SimulationItems.get_weapon(SimulationIds.ITEM_SWORD) _check( is_equal_approx(controller.attack_range, sword_definition.reach), "Player targeting and simulation authority should share the sword definition reach" ) player.global_position = wolf_visual.global_position + Vector3(-2.0, 0.0, 0.0) player.look_at(wolf_visual.global_position, Vector3.UP) player.rotation.x = 0.0 simulation_manager.update_player_combatant(player.global_position) var wolf_health: float = wolf.get_health() controller.call("_perform_attack") _check( wolf.get_health() < wolf_health, "A player sword strike should damage the hostile wolf through the simulation" ) var hit_tween: Tween = wolf_visual.get("_flash_tween") as Tween wolf.set_position(wolf.get_position() + Vector3(0.1, 0.0, 0.0)) _check( wolf_visual.get("_flash_tween") == hit_tween, "An injured hostile should not replay its hit flash for a position-only state update" ) var struck := 0 for _attempt in 6: if not wolf.is_alive(): break controller.call("_advance_timers", sword_definition.attack_cooldown) simulation_manager.advance_player_combat_time(sword_definition.attack_cooldown) controller.call("_perform_attack") struck += 1 await process_frame _check(not wolf.is_alive(), "Repeated sword strikes should kill the hostile wolf") await process_frame await process_frame _check( not combat_view.hostiles.has(wolf.get_combatant_id()), "Killing a hostile should remove its presentation visual" ) _check( _has_event(simulation_manager, SimulationIds.EVENT_COMBATANT_KILLED), "The player's kill should be recorded as a combatant_killed fact" ) var tribe: FactionStateRecord = simulation_manager.get_faction(SimulationIds.FACTION_TRIBE) _check( ( simulation_manager.get_village_defender_count() >= 0 and tribe != null and ( simulation_manager.get_tribe_war_plan() in [ SimulationIds.WAR_PLAN_NONE, SimulationIds.WAR_PLAN_PLANNED, SimulationIds.WAR_PLAN_RAIDING, SimulationIds.WAR_PLAN_ABORTED, ] ) ), "The runtime should expose village defense and the tribe war plan" ) if failures.is_empty(): print("[TEST] Jajce combat presentation passed: wolves -> sword -> kill -> cleanup") quit(0) return for failure in failures: push_error("[TEST] " + failure) quit(1) func _has_event(manager: Node, event_type: StringName) -> bool: for event in manager.economic_events: if StringName(event.data["event_type"]) == event_type: return true return false func _check(condition: bool, message: String) -> void: if not condition: failures.append(message) func _finish() -> void: if failures.is_empty(): print("[TEST] Jajce combat presentation passed: wolves -> sword -> kill -> cleanup") quit(0) return for failure in failures: push_error("[TEST] " + failure) quit(1)