# test_horse_combat_parity.gd —— 40250 战马骑乘战斗与马术技能 1:1 纯净回归测试套件 extends SceneTree const HorseCombatSystem = preload("res://horse_combat_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_horse_combat_parity (Direction 3: Mounted Combat & Horse Skills 1:1) ===") _test_mounted_state_and_basic_attack() _test_horse_skills_137_to_140() _test_cooldowns_and_sp_validation() _test_stamina_and_feeding() _finish() func _test_mounted_state_and_basic_attack() -> void: print("\n--- Test 1: Mounted State & 5.0m Attack Sweep Range ---") var hcs := HorseCombatSystem.new() var targets: Array = [ {"id": 1, "distance": 2.5}, # In range {"id": 2, "distance": 4.8}, # In range (<= 5.0m) {"id": 3, "distance": 5.2} # Out of range (> 5.0m) ] # 1. Not riding var r1 = hcs.perform_mounted_basic_attack(500, targets) _assert(r1["ok"] == false and r1["reason"] == "NOT_RIDING", "Attack blocked when not riding") # 2. Beginner horse (Tier 1) cannot fight hcs.set_mounted_state(true, HorseCombatSystem.HORSE_TIER_BEGINNER) var r2 = hcs.perform_mounted_basic_attack(500, targets) _assert(r2["ok"] == false and r2["reason"] == "HORSE_TIER_TOO_LOW", "Attack blocked on beginner horse") # 3. Combat horse (Tier 2) can fight hcs.set_mounted_state(true, HorseCombatSystem.HORSE_TIER_COMBAT) var attack_data := {"fired": false, "targets": 0, "dmg": 0} hcs.horse_attack_performed.connect(func(cnt: int, dmg: int): attack_data["fired"] = true attack_data["targets"] = cnt attack_data["dmg"] = dmg ) var r3 = hcs.perform_mounted_basic_attack(500, targets) _assert(r3["ok"] == true, "Attack succeeds on combat horse") _assert(r3["attack_range"] == 5.0, "Mounted attack range is 5.0m") _assert(r3["hit_count"] == 2, "Hit 2 targets within 5.0m (2.5m and 4.8m)") _assert(r3["damage_per_hit"] == 600, "1.2x damage multiplier (500 * 1.2 = 600)") _assert(r3["total_damage"] == 1200, "Total damage is 1200 for 2 targets") _assert(attack_data["fired"] == true and attack_data["targets"] == 2, "horse_attack_performed signal fired") func _test_horse_skills_137_to_140() -> void: print("\n--- Test 2: 4 Military Horse Skills (137-140) ---") var hcs := HorseCombatSystem.new() # Combat horse (Tier 2) cannot use skills hcs.set_mounted_state(true, HorseCombatSystem.HORSE_TIER_COMBAT) var r1 = hcs.use_horse_skill(137, 100, 1000) _assert(r1["ok"] == false and r1["reason"] == "REQUIRES_MILITARY_HORSE", "Skills blocked on tier 2 horse") # Switch to Military Horse (Tier 3) hcs.set_mounted_state(true, HorseCombatSystem.HORSE_TIER_MILITARY) var skill_signal := {"fired": false, "id": 0, "name": ""} hcs.horse_skill_used.connect(func(sid: int, sname: String, _sp: int): skill_signal["fired"] = true skill_signal["id"] = sid skill_signal["name"] = sname ) # 1. Skill 137: 战马砍击 (Horse Slash) var s137 = hcs.use_horse_skill(137, 100, 1000) _assert(s137["ok"] == true, "Skill 137 used successfully") _assert(s137["damage"] == 2500, "Skill 137 deals 250% damage (2500)") _assert(s137["effect"] == "KNOCKBACK", "Skill 137 inflicts KNOCKBACK") _assert(skill_signal["fired"] == true and skill_signal["id"] == 137, "horse_skill_used signal fired for 137") # 2. Skill 138: 战马突刺 (Horse Charge) var s138 = hcs.use_horse_skill(138, 100, 1000) _assert(s138["ok"] == true, "Skill 138 used successfully") _assert(s138["damage"] == 2000, "Skill 138 deals 200% damage (2000)") _assert(s138["effect"] == "STUMBLE", "Skill 138 inflicts STUMBLE") # 3. Skill 139: 战马震击 (Horse Stomp) var s139 = hcs.use_horse_skill(139, 100, 1000) _assert(s139["ok"] == true, "Skill 139 used successfully") _assert(s139["damage"] == 3000, "Skill 139 deals 300% damage (3000)") _assert(s139["effect"] == "AOE_STUN", "Skill 139 inflicts AOE_STUN") # 4. Skill 140: 破浪击 (Power Wave) var s140 = hcs.use_horse_skill(140, 100, 1000) _assert(s140["ok"] == true, "Skill 140 used successfully") _assert(s140["damage"] == 2200, "Skill 140 deals 220% damage (2200)") _assert(s140["range"] == 12.0, "Skill 140 has 12.0m ranged reach") func _test_cooldowns_and_sp_validation() -> void: print("\n--- Test 3: Skill Cooldowns & SP Verification ---") var hcs := HorseCombatSystem.new() hcs.set_mounted_state(true, HorseCombatSystem.HORSE_TIER_MILITARY) # Cast 137 hcs.use_horse_skill(137, 100, 1000) # Cast again immediately -> on cooldown var cd_res = hcs.use_horse_skill(137, 100, 1000) _assert(cd_res["ok"] == false and cd_res["reason"] == "SKILL_ON_COOLDOWN", "Skill 137 is on cooldown") # Update 10s -> still on cooldown hcs.update(10.0) _assert(hcs.skill_cooldowns[137] == 5.0, "5.0s remaining cooldown on 137") # Update 6s -> ready hcs.update(6.0) _assert(hcs.skill_cooldowns[137] == 0.0, "Cooldown expired") # Try with insufficient SP (< 30) var low_sp_res = hcs.use_horse_skill(137, 20, 1000) _assert(low_sp_res["ok"] == false and low_sp_res["reason"] == "INSUFFICIENT_SP", "Skill blocked with low SP") func _test_stamina_and_feeding() -> void: print("\n--- Test 4: Horse Stamina & Feeding (Carrot / Ginseng) ---") var hcs := HorseCombatSystem.new() hcs.set_mounted_state(true, HorseCombatSystem.HORSE_TIER_MILITARY) # Drain stamina manually to test exhaustion hcs.horse_stamina = 2.0 var ex_res = hcs.use_horse_skill(137, 100, 1000) _assert(ex_res["ok"] == false and ex_res["reason"] == "HORSE_EXHAUSTED", "Skill blocked when stamina < 5") # Feed invalid food var r_bad = hcs.feed_horse(99999) _assert(r_bad["ok"] == false and r_bad["reason"] == "WRONG_FOOD", "Invalid food rejected") # Feed Carrot (50054) -> +40 stamina (2 + 40 = 42) var r_carrot = hcs.feed_horse(50054) _assert(r_carrot["ok"] == true, "Fed carrot successfully") _assert(hcs.horse_stamina == 42.0, "Stamina increased by 40 to 42.0") # Feed Ginseng (50058) -> +80 stamina (42 + 80 = 122 -> capped at 100.0) var r_ginseng = hcs.feed_horse(50058) _assert(r_ginseng["ok"] == true, "Fed ginseng successfully") _assert(hcs.horse_stamina == 100.0, "Stamina capped at 100.0") func _finish() -> void: print("\n==========================================") print("Horse Combat Parity Test Results: %d Passed, %d Failed" % [_passed, _failed]) print("==========================================") if _failed > 0: quit(1) else: quit(0)