# test_auto_combat_bot_parity.gd —— 40250 自动战斗猎杀挂机助手 1:1 回归测试套件 extends SceneTree const AutoCombatBotSystem = preload("res://auto_combat_bot_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_auto_combat_bot_parity (Direction 2: Auto Combat Bot 1:1) ===") _test_bot_toggle() _test_auto_potion() _test_auto_target_and_combat() _test_auto_looting() _finish() func _test_bot_toggle() -> void: print("\n--- Test 1: Bot Toggle State ---") var bot := AutoCombatBotSystem.new() var toggle_sig := {"fired": false, "enabled": false} bot.bot_toggled.connect(func(en: bool): toggle_sig["fired"] = true toggle_sig["enabled"] = en ) var res1 = bot.toggle_bot(true) _assert(res1["enabled"] == true and bot.is_enabled == true, "Bot enabled") _assert(toggle_sig["fired"] == true and toggle_sig["enabled"] == true, "bot_toggled emitted true") bot.toggle_bot(false) _assert(bot.is_enabled == false, "Bot disabled") func _test_auto_potion() -> void: print("\n--- Test 2: Smart Auto Potion (HP/SP Threshold) ---") var bot := AutoCombatBotSystem.new() bot.toggle_bot(true) var player := { "hp": 400, "max_hp": 1000, # 40% < 50% threshold "sp": 800, "max_sp": 1000, # 80% > 40% threshold (no SP potion) "pos": Vector3.ZERO } var inv: Array = [ {"vnum": 27003, "name": "红色药水(特大)", "count": 2}, {"vnum": 27006, "name": "蓝色药水(特大)", "count": 2} ] var pot_events := [] bot.potion_used.connect(func(v: int, pt: String): pot_events.append({"vnum": v, "type": pt}) ) # Update tick should trigger HP potion only bot.update_bot(0.1, player, inv, [], []) _assert(player["hp"] == 1000, "HP restored (capped at max 1000)") _assert(inv[0]["count"] == 1, "Red potion consumed (2 -> 1)") _assert(pot_events.size() == 1 and pot_events[0]["type"] == "hp", "potion_used emitted for HP") # Now drop SP to 20% (< 40%) and reset potion cooldown bot.potion_cooldown = 0.0 player["sp"] = 200 bot.update_bot(0.1, player, inv, [], []) _assert(player["sp"] == 1000, "SP restored to max 1000") _assert(inv[1]["count"] == 1, "Blue potion consumed (2 -> 1)") _assert(pot_events.size() == 2 and pot_events[1]["type"] == "sp", "potion_used emitted for SP") func _test_auto_target_and_combat() -> void: print("\n--- Test 3: Auto Target, Move & Skill/Attack Execution ---") var bot := AutoCombatBotSystem.new() bot.toggle_bot(true) bot.assigned_skills = [1] # Assign Triple Slash var player := { "atk": 500, "hp": 1000, "max_hp": 1000, "sp": 1000, "max_sp": 1000, "pos": Vector3.ZERO } var mob := { "id": "mob_99", "hp": 2000, "alive": true, "pos": Vector3(8.0, 0.0, 0.0) # 8m away (> 3.0m attack range) } var lock_sig := {"fired": false, "id": ""} bot.target_locked.connect(func(tid: String): lock_sig["fired"] = true lock_sig["id"] = tid ) # 1. Step: Locks target and moves closer var step1 = bot.update_bot(0.5, player, [], [mob], []) _assert(lock_sig["fired"] == true and lock_sig["id"] == "mob_99", "target_locked emitted") _assert(step1["status"] == "moving_to_target", "Bot moving toward target") _assert(player["pos"].x > 0.0, "Player moved along X axis") # Move player close (2.0m <= 3.0m attack range) player["pos"] = Vector3(6.5, 0.0, 0.0) # 1.5m distance var sk_sig := {"fired": false} bot.auto_skill_fired.connect(func(_sk: int, _t: String): sk_sig["fired"] = true) # 2. Step: Fires skill (Triple Slash, 2.0x dmg = 1000) var step2 = bot.update_bot(0.1, player, [], [mob], []) _assert(step2["status"] == "skill_attack", "Executed skill attack") _assert(step2["damage"] == 1000, "Dealt 1000 skill damage (500 * 2)") _assert(mob["hp"] == 1000, "Mob HP reduced 2000 -> 1000") _assert(sk_sig["fired"] == true, "auto_skill_fired emitted") # 3. Step: Skill is now on cooldown, performs basic attack (500 dmg) var step3 = bot.update_bot(0.1, player, [], [mob], []) _assert(step3["status"] == "basic_attack", "Executed basic attack on cooldown") _assert(mob["hp"] == 500, "Mob HP reduced 1000 -> 500") func _test_auto_looting() -> void: print("\n--- Test 4: Auto Looting Within 8.0m ---") var bot := AutoCombatBotSystem.new() bot.toggle_bot(true) var player := { "hp": 1000, "max_hp": 1000, "sp": 1000, "max_sp": 1000, "pos": Vector3.ZERO } var inv: Array = [null, null] var drops: Array = [ {"id": 1, "vnum": 71003, "name": "祝福卷轴", "count": 1, "pos": Vector3(3.0, 0.0, 0.0), "looted": false}, {"id": 2, "vnum": 50513, "name": "灵魂之石", "count": 1, "pos": Vector3(20.0, 0.0, 0.0), "looted": false} # > 8m ] var loot_sig := {"fired": false, "name": ""} bot.auto_loot_collected.connect(func(n: String, _s: int): loot_sig["fired"] = true loot_sig["name"] = n ) bot.update_bot(0.1, player, inv, [], drops) _assert(drops[0]["looted"] == true, "Drop 1 (3m) was looted") _assert(drops[1]["looted"] == false, "Drop 2 (20m) out of range, not looted") _assert(inv[0]["vnum"] == 71003, "Blessing Scroll placed into slot 0") _assert(loot_sig["fired"] == true and loot_sig["name"] == "祝福卷轴", "auto_loot_collected emitted") func _finish() -> void: print("\n==========================================") print("Auto Combat Bot 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 Auto Combat Bot parity tests passed!") quit(0)