# test_mercenary_companion_parity.gd —— 40250 单人单机假人/陪练佣兵助战 1:1 回归测试套件 extends SceneTree const MercenaryCompanionSystem = preload("res://mercenary_companion_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_mercenary_companion_parity (Direction 2: Mercenary Companion 1:1) ===") _test_summon_and_stats() _test_buff_and_healing() _test_assist_combat_and_stances() _test_teleport_and_movement() _test_downed_and_revival() _finish() func _test_summon_and_stats() -> void: print("\n--- Test 1: Summoning & Level Scaling ---") var merc := MercenaryCompanionSystem.new() var summon_sig := {"fired": false, "type": 0, "name": ""} merc.mercenary_summoned.connect(func(t: int, n: String): summon_sig["fired"] = true summon_sig["type"] = t summon_sig["name"] = n ) # Level 50 Shaman var res = merc.summon_mercenary(MercenaryCompanionSystem.MercenaryType.SHAMAN_HEALER, Vector3(10, 0, 10), 50) _assert(res["ok"] == true, "Shaman summoned") _assert(summon_sig["fired"] == true and summon_sig["type"] == 1, "mercenary_summoned signal emitted") _assert(merc.is_active == true and merc.is_alive == true, "Merc is active and alive") _assert(merc.level == 50, "Mercenary level is 50") # Level 50 growth: 1 + 49 * 0.05 = 3.45x base_hp (8000 * 3.45 = 27600) _assert(merc.max_hp == int(8000 * 3.45), "HP properly scaled by level") # Dismiss var dis_sig := {"fired": false} merc.mercenary_dismissed.connect(func(): dis_sig["fired"] = true) var dis_res = merc.dismiss_mercenary() _assert(dis_res["ok"] == true, "Merc dismissed") _assert(dis_sig["fired"] == true, "mercenary_dismissed signal emitted") _assert(merc.is_active == false, "Merc is inactive") func _test_buff_and_healing() -> void: print("\n--- Test 2: Shaman Buffs & Smart Emergency Healing ---") var merc := MercenaryCompanionSystem.new() merc.summon_mercenary(MercenaryCompanionSystem.MercenaryType.SHAMAN_HEALER, Vector3.ZERO, 30) var buffs_received := [] merc.buff_applied_to_player.connect(func(bname: String, dur: float, val: float): buffs_received.append({"name": bname, "duration": dur, "value": val}) ) var heal_received := {"fired": false, "amount": 0} merc.heal_applied_to_player.connect(func(amt: int): heal_received["fired"] = true heal_received["amount"] = amt ) # Update when player is healthy (10000 / 10000) var up1 = merc.update_mercenary(0.1, Vector3.ZERO, 10000, 10000) _assert(buffs_received.size() == 2, "Shaman applied 2 buffs (Blessing & Dragon's Aid)") _assert(heal_received["fired"] == false, "No heal cast when player is healthy") # Player HP drops to 40% (4000 / 10000 < 60%) var up2 = merc.update_mercenary(0.1, Vector3.ZERO, 4000, 10000) _assert(up2["status"] == "cast_heal", "Shaman triggered emergency heal") _assert(heal_received["fired"] == true, "heal_applied_to_player signal fired") _assert(heal_received["amount"] == 3500, "Healed 35% of max HP (3500)") # Second hit while heal is on cooldown should not retrigger heal heal_received["fired"] = false var up3 = merc.update_mercenary(0.1, Vector3.ZERO, 3000, 10000) _assert(heal_received["fired"] == false, "Heal respects cooldown") func _test_assist_combat_and_stances() -> void: print("\n--- Test 3: Stances & Warrior Assist Combat ---") var merc := MercenaryCompanionSystem.new() merc.summon_mercenary(MercenaryCompanionSystem.MercenaryType.WARRIOR_TANK, Vector3.ZERO, 50) # Check stance change var st_res = merc.set_stance(MercenaryCompanionSystem.Stance.FOLLOW) _assert(st_res["ok"] == true and merc.current_stance == MercenaryCompanionSystem.Stance.FOLLOW, "Stance set to FOLLOW") # Change to ASSIST merc.set_stance(MercenaryCompanionSystem.Stance.ASSIST) _assert(merc.current_stance == MercenaryCompanionSystem.Stance.ASSIST, "Stance set to ASSIST") var atk_sig := {"fired": false, "tgt": "", "dmg": 0} merc.mercenary_attacked.connect(func(tgt: String, dmg: int): atk_sig["fired"] = true atk_sig["tgt"] = tgt atk_sig["dmg"] = dmg ) # Target at (1.5, 0, 0) within melee range merc.pos = Vector3.ZERO var act = merc.update_mercenary(0.1, Vector3.ZERO, 10000, 10000, "mob_101", Vector3(1.5, 0, 0)) _assert(act["status"] == "attacked_target", "Warrior attacked target") _assert(atk_sig["fired"] == true and atk_sig["tgt"] == "mob_101", "mercenary_attacked signal fired") _assert(atk_sig["dmg"] == merc.atk, "Damage matches warrior's ATK") func _test_teleport_and_movement() -> void: print("\n--- Test 4: Distance Teleport Catch-up ---") var merc := MercenaryCompanionSystem.new() merc.summon_mercenary(MercenaryCompanionSystem.MercenaryType.SHAMAN_HEALER, Vector3.ZERO, 10) # Place mercenary 30 meters away (> 25m TELEPORT_DISTANCE) merc.pos = Vector3(30, 0, 0) var tp_act = merc.update_mercenary(0.1, Vector3.ZERO, 5000, 5000) _assert(tp_act["status"] == "teleported_to_player", "Mercenary teleported back to player") _assert(merc.pos.distance_to(Vector3.ZERO) < 3.0, "Position is now close to player") func _test_downed_and_revival() -> void: print("\n--- Test 5: Downed State & Revival ---") var merc := MercenaryCompanionSystem.new() merc.summon_mercenary(MercenaryCompanionSystem.MercenaryType.WARRIOR_TANK, Vector3.ZERO, 10) var down_sig := {"fired": false} var rev_sig := {"fired": false} merc.mercenary_downed.connect(func(): down_sig["fired"] = true) merc.mercenary_revived.connect(func(): rev_sig["fired"] = true) # Take fatal damage var hit = merc.receive_damage(999999) _assert(hit["ok"] == true and hit["downed"] == true, "Mercenary downed") _assert(down_sig["fired"] == true, "mercenary_downed signal fired") _assert(merc.is_alive == false, "is_alive is false") # Instant revive var rev_res = merc.revive(true) _assert(rev_res["ok"] == true, "Instant revive succeeded") _assert(rev_sig["fired"] == true, "mercenary_revived signal fired") _assert(merc.is_alive == true and merc.current_hp == merc.max_hp, "HP restored to 100% on instant revive") func _finish() -> void: print("\n==========================================") print("Mercenary Companion Parity Tests Finished:") print("Passed: %d, Failed: %d" % [_passed, _failed]) print("==========================================") if _failed > 0: printerr("FAILED: Some tests did not pass.") quit(1) else: print("SUCCESS: All Mercenary Companion parity tests passed!") quit(0)