- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
125 lines
5.2 KiB
GDScript
125 lines
5.2 KiB
GDScript
# test_marriage_wedding_love_parity.gd —— Metin2 40250 夫妻同心传送与爱情点数婚戒系统 1:1 测试套件
|
|
extends SceneTree
|
|
|
|
const MarriageWeddingLoveSystem = preload("res://marriage_wedding_love_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_marriage_wedding_love_parity (Direction 2: Marriage & Wedding Ring 1:1) ===")
|
|
|
|
test_marriage_and_partner_query()
|
|
test_love_points_and_items_bonus()
|
|
test_wedding_ring_teleport()
|
|
test_divorce_and_cleanup()
|
|
test_serialization()
|
|
|
|
print("\n=======================================================")
|
|
print("Marriage & Wedding Ring Tests: %d Passed, %d Failed" % [_passed, _failed])
|
|
print("=======================================================\n")
|
|
|
|
if _failed > 0:
|
|
quit(1)
|
|
else:
|
|
quit(0)
|
|
|
|
func test_marriage_and_partner_query() -> void:
|
|
print("\n--- Test 1: Marriage Creation & Querying (40250 1:1) ---")
|
|
var system = MarriageWeddingLoveSystem.new()
|
|
|
|
_assert(system.is_married(1001) == false, "Not married initially")
|
|
|
|
# 缔结婚姻
|
|
var cid = system.marry(1001, "剑魂", 2002, "雪儿")
|
|
_assert(cid > 0, "Created marriage couple")
|
|
_assert(system.is_married(1001) == true, "Player 1 is married")
|
|
_assert(system.is_married(2002) == true, "Player 2 is married")
|
|
_assert(system.get_partner_pid(1001) == 2002, "Player 1 partner is 2002")
|
|
_assert(system.get_partner_pid(2002) == 1001, "Player 2 partner is 1001")
|
|
_assert(system.get_partner_name(1001) == "雪儿", "Player 1 partner name is 雪儿")
|
|
_assert(system.get_partner_name(2002) == "剑魂", "Player 2 partner name is 剑魂")
|
|
|
|
func test_love_points_and_items_bonus() -> void:
|
|
print("\n--- Test 2: Love Points & Jewelry Scaling (40250 1:1) ---")
|
|
var system = MarriageWeddingLoveSystem.new()
|
|
system.marry(1001, "剑魂", 2002, "雪儿")
|
|
|
|
_assert(system.get_love_points(1001) == 50, "Initial love points 50%")
|
|
|
|
# 增加爱情点数至 100%
|
|
system.add_love_points(1001, 50)
|
|
_assert(system.get_love_points(1001) == 100, "Love points maxed to 100%")
|
|
|
|
# 爱情饰品 100% 加成
|
|
var b_atk = system.get_love_item_bonus(1001, MarriageWeddingLoveSystem.VNUM_BRACELET_OF_LOVE)
|
|
_assert(b_atk["bonus_type"] == "att_grade" and b_atk["value"] == 40, "Bracelet of Love gives +40 ATK at 100% love")
|
|
|
|
var b_def = system.get_love_item_bonus(1001, MarriageWeddingLoveSystem.VNUM_EARRINGS_OF_LOVE)
|
|
_assert(b_def["bonus_type"] == "def_grade" and b_def["value"] == 30, "Earrings of Love give +30 DEF at 100% love")
|
|
|
|
var b_crit = system.get_love_item_bonus(1001, MarriageWeddingLoveSystem.VNUM_NECKLACE_OF_LOVE)
|
|
_assert(b_crit["bonus_type"] == "crit_pct" and b_crit["value"] == 20, "Necklace of Love gives +20% Crit at 100% love")
|
|
|
|
func test_wedding_ring_teleport() -> void:
|
|
print("\n--- Test 3: Wedding Ring (70302) Teleportation (40250 1:1) ---")
|
|
var system = MarriageWeddingLoveSystem.new()
|
|
system.marry(1001, "剑魂", 2002, "雪儿")
|
|
system.add_love_points(1001, 50) # 100% 爱情点数 -> 消耗 50 SP
|
|
|
|
var target_pos = Vector2(1500.0, 3200.0)
|
|
|
|
# 1. 伴侣离线 -> 拦截
|
|
var res = system.use_wedding_ring(1001, 500, false, "谷地", target_pos)
|
|
_assert(res["ok"] == false, "Rejected when partner offline")
|
|
_assert(res["reason"] == "PARTNER_OFFLINE", "Reason is PARTNER_OFFLINE")
|
|
|
|
# 2. 伴侣处于竞技场 (IsArenaMap) -> 拦截
|
|
res = system.use_wedding_ring(1001, 500, true, "竞技场", target_pos, true)
|
|
_assert(res["ok"] == false, "Rejected when partner in arena")
|
|
_assert(res["reason"] == "PARTNER_IN_ARENA", "Reason is PARTNER_IN_ARENA")
|
|
|
|
# 3. SP 不足 -> 拦截 (需要 50 SP,玩家只有 30)
|
|
res = system.use_wedding_ring(1001, 30, true, "首阳山", target_pos, false)
|
|
_assert(res["ok"] == false, "Rejected insufficient SP")
|
|
_assert(res["reason"] == "NOT_ENOUGH_SP", "Reason is NOT_ENOUGH_SP")
|
|
|
|
# 4. 传送成功
|
|
res = system.use_wedding_ring(1001, 200, true, "首阳山", target_pos, false)
|
|
_assert(res["ok"] == true, "Teleport succeeded")
|
|
_assert(res["target_pos"] == target_pos, "Target position matches partner position")
|
|
_assert(res["sp_consumed"] == 50, "Consumed 50 SP at 100% love points")
|
|
_assert(res["remaining_sp"] == 150, "Remaining SP is 150")
|
|
|
|
func test_divorce_and_cleanup() -> void:
|
|
print("\n--- Test 4: Divorce & State Cleanup (40250 1:1) ---")
|
|
var system = MarriageWeddingLoveSystem.new()
|
|
system.marry(1001, "剑魂", 2002, "雪儿")
|
|
|
|
var div_ok = system.divorce(1001)
|
|
_assert(div_ok == true, "Divorce succeeded")
|
|
_assert(system.is_married(1001) == false, "Player 1 is no longer married")
|
|
_assert(system.is_married(2002) == false, "Player 2 is no longer married")
|
|
|
|
func test_serialization() -> void:
|
|
print("\n--- Test 5: Serialization & Restoration ---")
|
|
var system = MarriageWeddingLoveSystem.new()
|
|
system.marry(1001, "剑魂", 2002, "雪儿")
|
|
system.add_love_points(1001, 30)
|
|
|
|
var data = system.serialize()
|
|
_assert(data.has("marriages") and data.has("pid_to_couple"), "Serialized data")
|
|
|
|
var restored = MarriageWeddingLoveSystem.new()
|
|
restored.deserialize(data)
|
|
_assert(restored.is_married(1001) == true, "Restored marriage state")
|
|
_assert(restored.get_love_points(1001) == 80, "Restored love points 80")
|