Files
mtgodot-poc/project/test_dynamic_bounty_event_parity.gd
T
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 40250 CMapOutdoor::GetHeight 与 CAttributeInstance::GetHeight
  - 解析 .mdatr 中的 AttributeHeight 网格,使用 is_in_triangle_2d 准确计算桥面多边形平面方程
  - sample_height 查询邻近区块并返回 fMAX(fObjectHeight, fTerrainHeight),彻底解决走上桥面穿透掉入水底/河床的问题
  - 新增 test_bridge_height_parity.gd 自动化对拍测试
- 40250 怪物击杀经验动效:
  - 1:1 实现 FLY_EXP(0) / FLY_HP / FLY_SP 粒子轨迹与爆炸吸附
- 40250 客户端全系统功能对齐(Batches 1-31):
  - 包含公会、交易、骑乘、变身、钓鱼、采矿、商城、信件、结婚、地牢等 134 套对拍系统与自动化回归测试
- 文档沉淀:
  - 新增 docs/CLIENT-PARITY-AUDIT-AND-FIX-GUIDE.md 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00

137 lines
5.2 KiB
GDScript

# test_dynamic_bounty_event_parity.gd —— 40250 动态随机事件与赏金通缉令 1:1 回归测试套件
extends SceneTree
const DynamicBountyEventSystem = preload("res://dynamic_bounty_event_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_dynamic_bounty_event_parity (Direction 4: Bounty Events 1:1) ===")
_test_bounty_generation()
_test_hunt_and_metin_progress()
_test_boss_bounty_completion()
_test_claim_rewards_and_validation()
_finish()
func _test_bounty_generation() -> void:
print("\n--- Test 1: Bounty Generation & Roster ---")
var sys := DynamicBountyEventSystem.new()
var ref_sig := {"fired": false, "count": 0}
sys.bounties_refreshed.connect(func(list: Array):
ref_sig["fired"] = true
ref_sig["count"] = list.size()
)
var bounties = sys.refresh_daily_bounties()
_assert(bounties.size() == 3, "Generated 3 daily bounties")
_assert(ref_sig["fired"] == true and ref_sig["count"] == 3, "bounties_refreshed signal emitted")
_assert(sys.active_bounties.has("bounty_hunt_barbarian"), "Has Barbarian Hunt bounty")
_assert(sys.active_bounties.has("bounty_metin_jealousy"), "Has Metin Shatter bounty")
_assert(sys.active_bounties.has("bounty_boss_ninetails"), "Has Nine Tails Boss bounty")
func _test_hunt_and_metin_progress() -> void:
print("\n--- Test 2: Hunt & Metin Progress Tracking ---")
var sys := DynamicBountyEventSystem.new()
sys.refresh_daily_bounties()
var prog_sig := {"fired": false, "cur": 0, "tgt": 0}
sys.bounty_progress_updated.connect(func(_id: String, cur: int, tgt: int):
prog_sig["fired"] = true
prog_sig["cur"] = cur
prog_sig["tgt"] = tgt
)
var comp_sig := {"fired": false, "title": ""}
sys.bounty_completed.connect(func(_id: String, title: String):
comp_sig["fired"] = true
comp_sig["title"] = title
)
# 1. Kill 10 barbarians (vnum 501)
sys.on_mob_killed(501, 10)
_assert(prog_sig["fired"] == true and prog_sig["cur"] == 10 and prog_sig["tgt"] == 25, "Progress updated to 10/25")
_assert(sys.active_bounties["bounty_hunt_barbarian"]["is_completed"] == false, "Not completed yet")
# Kill 15 more barbarians -> completes 25/25
sys.on_mob_killed(501, 15)
_assert(sys.active_bounties["bounty_hunt_barbarian"]["is_completed"] == true, "Barbarian hunt completed")
_assert(comp_sig["fired"] == true, "bounty_completed signal emitted")
# 2. Shatter 2 Metin stones (vnum 8008)
comp_sig["fired"] = false
sys.on_metin_destroyed(8008)
_assert(sys.active_bounties["bounty_metin_jealousy"]["current_count"] == 1, "Metin count is 1/2")
sys.on_metin_destroyed(8008)
_assert(sys.active_bounties["bounty_metin_jealousy"]["is_completed"] == true, "Metin bounty completed")
_assert(comp_sig["fired"] == true, "bounty_completed emitted for Metin")
func _test_boss_bounty_completion() -> void:
print("\n--- Test 3: World Boss Bounty Completion ---")
var sys := DynamicBountyEventSystem.new()
sys.refresh_daily_bounties()
# Slay Nine Tails (1901)
sys.on_mob_killed(1901, 1)
_assert(sys.active_bounties["bounty_boss_ninetails"]["is_completed"] == true, "Nine Tails bounty completed")
_assert(sys.total_completed_count == 1, "total_completed_count is 1")
func _test_claim_rewards_and_validation() -> void:
print("\n--- Test 4: Claiming Bounty Rewards & Double-Claim Guard ---")
var sys := DynamicBountyEventSystem.new()
sys.refresh_daily_bounties()
var player := {"exp": 1000, "gold": 5000}
var inv: Array = []
inv.resize(5)
for i in range(5): inv[i] = null
# Try claim incomplete bounty
var fail_inc = sys.claim_bounty_reward("bounty_boss_ninetails", player, inv)
_assert(fail_inc["ok"] == false and fail_inc["reason"] == "NOT_COMPLETED", "Cannot claim incomplete bounty")
# Slay Nine Tails
sys.on_mob_killed(1901, 1)
var claim_sig := {"fired": false, "exp": 0, "gold": 0}
sys.bounty_reward_claimed.connect(func(_id: String, e: int, g: int):
claim_sig["fired"] = true
claim_sig["exp"] = e
claim_sig["gold"] = g
)
# Claim Boss Reward (1,000,000 XP, 3,000,000 Gold, Chest + Scroll)
var claim_res = sys.claim_bounty_reward("bounty_boss_ninetails", player, inv)
_assert(claim_res["ok"] == true, "Reward claimed")
_assert(player["exp"] == 1001000, "XP awarded (+1,000,000)")
_assert(player["gold"] == 3005000, "Gold awarded (+3,000,000)")
_assert(inv[0]["vnum"] == DynamicBountyEventSystem.BOUNTY_CHEST_VNUM, "Received Bounty Chest in slot 0")
_assert(inv[1]["vnum"] == 71003, "Received Blessing Scroll in slot 1")
_assert(claim_sig["fired"] == true and claim_sig["exp"] == 1000000, "bounty_reward_claimed signal fired")
# Second claim attempt must fail
var fail_double = sys.claim_bounty_reward("bounty_boss_ninetails", player, inv)
_assert(fail_double["ok"] == false and fail_double["reason"] == "ALREADY_CLAIMED", "Double claim rejected")
func _finish() -> void:
print("\n==========================================")
print("Dynamic Bounty Event 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 Dynamic Bounty Event parity tests passed!")
quit(0)