- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
167 lines
5.8 KiB
GDScript
167 lines
5.8 KiB
GDScript
# test_treasure_box_key_parity.gd —— Metin2 40250 金银宝箱与钥匙解锁系统 1:1 测试套件
|
|
extends SceneTree
|
|
|
|
const TreasureBoxKeySystem = preload("res://treasure_box_key_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_treasure_box_key_parity (Direction 2: Treasure Boxes & Keys 1:1) ===")
|
|
|
|
test_silver_box_and_key()
|
|
test_gold_box_and_key()
|
|
test_mismatch_and_rejections()
|
|
test_plus_boxes()
|
|
test_history_and_serialization()
|
|
|
|
print("\n=======================================================")
|
|
print("Treasure Box & Key Tests: %d Passed, %d Failed" % [_passed, _failed])
|
|
print("=======================================================\n")
|
|
|
|
if _failed > 0:
|
|
quit(1)
|
|
else:
|
|
quit(0)
|
|
|
|
func test_silver_box_and_key() -> void:
|
|
print("\n--- Test 1: Silver Key Unlocks Silver Box (40250 1:1) ---")
|
|
var system = TreasureBoxKeySystem.new()
|
|
|
|
var unlocked_signals := []
|
|
system.box_unlocked.connect(func(box, key, reward):
|
|
unlocked_signals.append({"box": box, "key": key, "reward": reward})
|
|
)
|
|
|
|
var inv: Array = [
|
|
{"vnum": 50008, "count": 2}, # 银钥匙 x2 (slot 0)
|
|
{"vnum": 50006, "count": 1} # 银宝箱 x1 (slot 1)
|
|
]
|
|
|
|
_assert(system.can_unlock(50008, 50006) == true, "Silver key matches silver box")
|
|
|
|
# 开启宝箱,强制掉落索引 0 (技能书 50300)
|
|
var res = system.unlock_box_with_key(inv, 0, 1, 0)
|
|
_assert(res["ok"] == true, "Unlocked silver box successfully")
|
|
_assert(inv[0] != null and inv[0]["count"] == 1, "Key count decremented from 2 to 1")
|
|
# 原宝箱槽位已被新发放的奖励技能书复用填充
|
|
_assert(res["reward"]["vnum"] == 50300, "Rewarded skill book (50300)")
|
|
var has_box = false
|
|
for it in inv:
|
|
if it != null and it.get("vnum", 0) == 50006:
|
|
has_box = true
|
|
_assert(has_box == false, "Silver box was consumed and no longer in inventory")
|
|
_assert(unlocked_signals.size() == 1, "box_unlocked signal fired")
|
|
_assert(unlocked_signals[0]["box"] == 50006, "Signal reports silver box")
|
|
|
|
func test_gold_box_and_key() -> void:
|
|
print("\n--- Test 2: Gold Key Unlocks Gold Box (40250 1:1) ---")
|
|
var system = TreasureBoxKeySystem.new()
|
|
|
|
var inv: Array = [
|
|
{"vnum": 50009, "count": 1}, # 金钥匙 (slot 0)
|
|
{"vnum": 50007, "count": 1} # 金宝箱 (slot 1)
|
|
]
|
|
|
|
_assert(system.can_unlock(50009, 50007) == true, "Gold key matches gold box")
|
|
|
|
# 开启金宝箱,强制掉落索引 0 (祝福卷轴 25040)
|
|
var res = system.unlock_box_with_key(inv, 0, 1, 0)
|
|
_assert(res["ok"] == true, "Unlocked gold box successfully")
|
|
var has_gold_key = false
|
|
var has_gold_box = false
|
|
for it in inv:
|
|
if it != null:
|
|
if it.get("vnum", 0) == 50009:
|
|
has_gold_key = true
|
|
if it.get("vnum", 0) == 50007:
|
|
has_gold_box = true
|
|
_assert(has_gold_key == false, "Gold key consumed")
|
|
_assert(has_gold_box == false, "Gold box consumed")
|
|
_assert(res["reward"]["vnum"] == 25040, "Rewarded Blessing Scroll (25040)")
|
|
|
|
func test_mismatch_and_rejections() -> void:
|
|
print("\n--- Test 3: Key Mismatch & Invalid Targets (40250 1:1) ---")
|
|
var system = TreasureBoxKeySystem.new()
|
|
|
|
var fail_signals := []
|
|
system.unlock_failed.connect(func(reason):
|
|
fail_signals.append(reason)
|
|
)
|
|
|
|
var inv: Array = [
|
|
{"vnum": 50008, "count": 1}, # 银钥匙 (slot 0)
|
|
{"vnum": 50007, "count": 1}, # 金宝箱 (slot 1)
|
|
{"vnum": 27987, "count": 1} # 珍珠蚌 (slot 2, 非宝箱)
|
|
]
|
|
|
|
# 1. 银钥匙对金宝箱 -> 拒绝
|
|
_assert(system.can_unlock(50008, 50007) == false, "Silver key cannot unlock gold box")
|
|
var res = system.unlock_box_with_key(inv, 0, 1)
|
|
_assert(res["ok"] == false, "Rejected mismatch")
|
|
_assert(res["reason"] == "KEY_MISMATCH", "Reason is KEY_MISMATCH")
|
|
_assert(inv[0]["count"] == 1, "Key not consumed")
|
|
_assert(inv[1]["count"] == 1, "Box not consumed")
|
|
|
|
# 2. 钥匙拖拽至非宝箱物品 -> 拒绝
|
|
res = system.unlock_box_with_key(inv, 0, 2)
|
|
_assert(res["ok"] == false, "Rejected non-box target")
|
|
_assert(res["reason"] == "NOT_A_TREASURE_BOX", "Reason is NOT_A_TREASURE_BOX")
|
|
|
|
# 3. 非钥匙道具拖拽 -> 拒绝
|
|
res = system.unlock_box_with_key(inv, 2, 1)
|
|
_assert(res["ok"] == false, "Rejected non-key item")
|
|
_assert(res["reason"] == "NOT_A_KEY", "Reason is NOT_A_KEY")
|
|
|
|
_assert(fail_signals.size() == 3, "All 3 failure signals emitted")
|
|
|
|
func test_plus_boxes() -> void:
|
|
print("\n--- Test 4: Silver+ and Gold+ Boxes (40250 1:1) ---")
|
|
var system = TreasureBoxKeySystem.new()
|
|
|
|
var inv: Array = [
|
|
{"vnum": 50014, "count": 1}, # 银钥匙+
|
|
{"vnum": 50012, "count": 1}, # 银宝箱+
|
|
{"vnum": 50015, "count": 1}, # 金钥匙+
|
|
{"vnum": 50013, "count": 1} # 金宝箱+
|
|
]
|
|
|
|
# 银钥匙+ 开 银宝箱+
|
|
var res = system.unlock_box_with_key(inv, 0, 1, 0)
|
|
_assert(res["ok"] == true, "Unlocked Silver Box+")
|
|
_assert(res["reward"]["count"] == 2, "Silver+ gave 2 skill books")
|
|
|
|
# 金钥匙+ 开 金宝箱+
|
|
res = system.unlock_box_with_key(inv, 2, 3, 0)
|
|
_assert(res["ok"] == true, "Unlocked Gold Box+")
|
|
_assert(res["reward"]["vnum"] == 25040 and res["reward"]["count"] == 2, "Gold+ gave 2 Blessing Scrolls")
|
|
|
|
func test_history_and_serialization() -> void:
|
|
print("\n--- Test 5: History Tracking & Serialization ---")
|
|
var system = TreasureBoxKeySystem.new()
|
|
var inv: Array = [
|
|
{"vnum": 50008, "count": 1},
|
|
{"vnum": 50006, "count": 1}
|
|
]
|
|
system.unlock_box_with_key(inv, 0, 1, 0)
|
|
|
|
var history = system.get_open_history()
|
|
_assert(history.size() == 1, "Recorded 1 unlock history")
|
|
_assert(history[0]["box_vnum"] == 50006, "History records box 50006")
|
|
|
|
var data = system.serialize()
|
|
var restored = TreasureBoxKeySystem.new()
|
|
restored.deserialize(data)
|
|
_assert(restored.get_open_history().size() == 1, "Restored 1 history item")
|
|
|
|
system.clear_history()
|
|
_assert(system.get_open_history().is_empty(), "Cleared history")
|