- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
137 lines
5.2 KiB
GDScript
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)
|