# test_mob_combat_reaction_parity.gd —— 验证方向 2:怪物主动仇恨视野、追击脱战与连击击退硬直 40250 1:1 对齐 extends SceneTree const MobCombatReactionSystem = preload("res://mob_combat_reaction_system.gd") var _passed := 0 var _failed := 0 func _assert(cond: bool, msg: String) -> void: if cond: _passed += 1 print(" [PASS] %s" % msg) else: _failed += 1 printerr(" [FAIL] %s" % msg) func _init() -> void: print("\n=== Running test_mob_combat_reaction_parity (Direction 2: Mob Aggro & Knockback 1:1) ===") test_aggro_radius_detection() test_leash_distance_and_reset() test_combo_reaction_steps() test_knockback_direction_vector() print("\n=== SUMMARY: %d passed, %d failed ===" % [_passed, _failed]) if _failed > 0: printerr("TEST FAILED!") quit(1) else: print("ALL TESTS PASSED!") quit(0) func test_aggro_radius_detection() -> void: print("\n--- Test 1: Aggro Radius (18m) Detection ---") var mob_pos := Vector3(0, 0, 0) var player_in_range := Vector3(10, 0, 10) # distance = ~14.14m <= 18m var player_out_range := Vector3(20, 0, 20) # distance = ~28.28m > 18m # Active aggressive mob _assert(MobCombatReactionSystem.check_aggro(mob_pos, player_in_range, true, 18.0), "Aggressive mob detects player within 18m") _assert(not MobCombatReactionSystem.check_aggro(mob_pos, player_out_range, true, 18.0), "Aggressive mob ignores player outside 18m") # Passive mob ignores player even close _assert(not MobCombatReactionSystem.check_aggro(mob_pos, player_in_range, false, 18.0), "Passive mob does not aggro even when close") func test_leash_distance_and_reset() -> void: print("\n--- Test 2: Leash Distance (40m) & Full HP Reset ---") var spawn_pos := Vector3(100, 0, 100) var mob_chasing := Vector3(120, 0, 120) # distance = 28.28m <= 40m var mob_leashed := Vector3(150, 0, 150) # distance = 70.71m > 40m _assert(not MobCombatReactionSystem.check_leash_exceeded(mob_chasing, spawn_pos, 40.0), "Mob within 40m remains in chase") _assert(MobCombatReactionSystem.check_leash_exceeded(mob_leashed, spawn_pos, 40.0), "Mob exceeding 40m triggers leash exceeded") # Leash reset var damaged_mob := {"hp": 200, "max_hp": 2000, "target_vid": 1, "state": MobCombatReactionSystem.MobAIState.CHASE} var reset_res := MobCombatReactionSystem.perform_leash_reset(damaged_mob, spawn_pos) _assert(reset_res.leashed, "Leash reset executed") _assert(damaged_mob.hp == 2000, "HP fully restored to 2000") _assert(damaged_mob.target_vid == 0, "Target cleared") _assert(damaged_mob.state == MobCombatReactionSystem.MobAIState.RETREAT, "State set to RETREAT") func test_combo_reaction_steps() -> void: print("\n--- Test 3: 40250 Combo Step Reactions (1-2 Damage vs 3-4 Knockdown) ---") var mob_pos := Vector3(0, 0, 0) # Step 1: Hit 1 -> normal damage stun var hit1 := MobCombatReactionSystem.calculate_combo_reaction(1, mob_pos, 0.0) _assert(hit1.reaction_type == "DAMAGE_STUN" and not hit1.is_knockback, "Combo 1 is DAMAGE_STUN (no knockback)") _assert(hit1.anim == "damage", "Plays damage animation") # Step 2: Hit 2 -> normal damage stun var hit2 := MobCombatReactionSystem.calculate_combo_reaction(2, mob_pos, 0.0) _assert(hit2.reaction_type == "DAMAGE_STUN" and not hit2.is_knockback, "Combo 2 is DAMAGE_STUN") # Step 3: Hit 3 -> heavy knockback & knockdown var hit3 := MobCombatReactionSystem.calculate_combo_reaction(3, mob_pos, 0.0) _assert(hit3.reaction_type == "KNOCKBACK_FLYING" and hit3.is_knockback, "Combo 3 triggers KNOCKBACK_FLYING") _assert(hit3.anim == "knockdown" and hit3.standup_anim == "standup", "Triggers knockdown and standup") # Step 4: Hit 4 -> heavy knockback & knockdown var hit4 := MobCombatReactionSystem.calculate_combo_reaction(4, mob_pos, 0.0) _assert(hit4.reaction_type == "KNOCKBACK_FLYING" and hit4.is_knockback, "Combo 4 triggers KNOCKBACK_FLYING") func test_knockback_direction_vector() -> void: print("\n--- Test 4: Knockback Push Vector Along Attack Heading ---") var mob_pos := Vector3(10, 0, 10) # Attack heading = 0 radians (North / +Z) var hit_north := MobCombatReactionSystem.calculate_combo_reaction(3, mob_pos, 0.0) var offset_z: float = hit_north.push_offset.z _assert(is_equal_approx(offset_z, 1.5), "Knockback pushed 1.5m along attack heading") _assert(is_equal_approx(hit_north.target_pos.z, 11.5), "Target position updated to 11.5m")