Files
aetherbound-guild/runtime/tests/p10_1/motion_runtime_test.gd
T

143 lines
6.5 KiB
GDScript

extends SceneTree
const Controller = preload("res://p10_1/runtime_controller.gd")
const Fixture = preload("res://tests/p10_1/runtime_fixture.gd")
const VIEWPORT := Vector2i(844, 390)
var failures: Array[String] = []
var experience
func _initialize() -> void:
call_deferred("run_test")
func run_test() -> void:
root.content_scale_mode = Window.CONTENT_SCALE_MODE_CANVAS_ITEMS
root.content_scale_aspect = Window.CONTENT_SCALE_ASPECT_EXPAND
root.content_scale_size = VIEWPORT
root.size = VIEWPORT
experience = Controller.new()
experience.persistence_enabled = false
experience.battle_auto_advance = false
experience.size = Vector2(VIEWPORT)
experience.configure_entry(Fixture.prepared_snapshot(2))
root.add_child(experience)
await settle_frames()
experience.choose_region_plan("follow_tide")
experience.region_battle_paused = true
var paused_clock := float(experience.region_motion_clock)
await settle_frames()
expect(is_equal_approx(experience.region_motion_clock, paused_clock), "battle pause also freezes presentation time")
var authority_before := var_to_str(experience.region_battle_snapshot)
advance_to(1)
await settle_frames()
var enemies: Array[Node] = experience.find_children("P101BattleEnemy_*", "TextureRect", true, false)
var total_enemies: int = experience.region_market.state.current_run.pending_encounter.enemy_ids.size()
expect(not enemies.is_empty() and enemies.size() < total_enemies, "first wave enters before later enemies")
var front_id := String(experience.region_actor_order[0])
var rear_id := String(experience.region_actor_order[-1])
var front := battle_actor(front_id)
var rear := battle_actor(rear_id)
var first_enemy := battle_actor(experience.region_motion.front_visible_enemy())
expect(front != null and rear != null and first_enemy != null, "opposing lines render from authoritative wave and Company order")
if front != null and rear != null and first_enemy != null:
expect(front.position.x > rear.position.x, "front Recruit is closest to the enemy")
var ally_base := Vector2(front.get_meta("base_position"))
var enemy_base := Vector2(first_enemy.get_meta("base_position"))
expect(enemy_base.x > ally_base.x and enemy_base.x - (ally_base.x + front.size.x) < 58.0, "opposing line destinations meet near the battlefield center")
expect(first_enemy.position.x > enemy_base.x, "first wave visibly enters from the right")
advance_to(10)
await settle_frames()
expect(experience.find_child("P101HealingDenialTether", true, false) != null, "healing denial is attached to the battlefield target")
advance_to(18)
await settle_frames()
expect(experience.find_child("P101IndexedMudMarker", true, false) != null, "indexed mud persists on its disclosed battlefield position")
var pulled_id := String(experience.region_recent_events.filter(func(event): return event.kind == "pull_committed")[0].target_id)
var pulled := battle_actor(pulled_id)
if pulled != null:
var start_x := pulled.position.x
experience.region_motion_clock += 0.29
experience._animate_region_battle_actors()
expect(absf(pulled.position.x - start_x) > 8.0, "pull visibly interpolates between old and new line slots")
advance_to(20)
await settle_frames()
var attack_event: Dictionary = experience.region_recent_events.filter(func(event): return event.kind == "allied_basic")[-1]
var attacker := battle_actor(String(attack_event.actor_id))
expect(experience.find_child("P101MotionProjectile_*", true, false) != null, "allied contact creates a traveling strike or projectile")
if attacker != null:
var attack_base := Vector2(attacker.get_meta("base_position"))
experience.region_motion_clock += 0.30
experience._animate_region_battle_actors()
expect(String(attacker.get_meta("motion_state", "")) == "attack" and attacker.position.x > attack_base.x + 8.0, "attack reaches a distinct contact pose")
advance_to(24)
await settle_frames()
expect(experience.find_child("P101MotionDamage_*", true, false) != null, "enemy contact creates an actor-bound damage value")
expect(experience.find_child("P101MotionImpact_*", true, false) != null, "enemy contact creates a local impact effect")
var tide_actor_id := String(experience.region_actor_order[0])
advance_to(50)
await settle_frames()
var tide_actor := battle_actor(tide_actor_id)
if tide_actor != null:
var tide_start_x := tide_actor.position.x
experience.region_motion_clock += 0.36
experience._animate_region_battle_actors()
var tide_mid_x := tide_actor.position.x
experience.region_motion_clock += 0.40
experience._animate_region_battle_actors()
var tide_end_x := tide_actor.position.x
var first_leg := tide_mid_x - tide_start_x
var second_leg := tide_end_x - tide_mid_x
expect(absf(first_leg) > 2.0 and absf(second_leg) > 2.0 and signf(first_leg) == signf(second_leg), "Company follows the tide with continuous directional displacement")
advance_to(experience.region_battle_terminal_tick)
await settle_frames()
experience.region_motion_clock += 0.95
experience._animate_region_battle_actors()
for recruit_id in experience.region_actor_order:
var actor := battle_actor(String(recruit_id))
if actor != null and int(experience.region_display_hp.get(recruit_id, 1)) > 0:
expect(String(actor.get_meta("motion_state", "")) == "victory", "surviving Recruit enters a distinct victory rest")
for enemy_id in experience.region_motion.visible_enemy_ids:
var enemy := battle_actor(String(enemy_id))
if enemy != null:
expect(String(enemy.get_meta("motion_state", "")) == "death" and enemy.modulate.a < 0.25, "terminal enemy remains in the death state")
expect(var_to_str(experience.region_battle_snapshot) == authority_before, "presentation consumes but never mutates battle authority")
experience.queue_free()
await settle_frames(45)
if failures.is_empty():
print("ABG_P10_1_MOTION_RUNTIME_OK waves=staged formation=front_contact attack=contact projectile=true pull=eased tide=eased damage=actor_bound denial=tether mud=indexed victory=rest enemy=death authority_mutations=0")
quit(0)
else:
for failure in failures:
push_error(failure)
quit(1)
func advance_to(target_tick: int) -> void:
var delta: int = target_tick - int(experience.region_battle_tick)
if delta > 0:
experience.advance_region_battle_ticks(delta)
func battle_actor(actor_id: String) -> TextureRect:
return experience.battle_actors.get(actor_id) as TextureRect
func settle_frames(count := 5) -> void:
for _index in count:
await process_frame
func expect(condition: bool, message: String) -> void:
if not condition:
failures.append("P10.1 motion runtime: %s" % message)