143 lines
6.5 KiB
GDScript
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)
|