- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
138 lines
5.0 KiB
GDScript
138 lines
5.0 KiB
GDScript
# test_marriage_parity.gd —— 40250 结婚戒指与伴侣瞬移传送 1:1 纯净回归测试套件
|
|
extends SceneTree
|
|
|
|
const MarriageSystem = preload("res://marriage_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_parity (Direction 4: Marriage & Couple Warp 1:1) ===")
|
|
_test_marriage_qualifications_and_ring()
|
|
_test_love_points_growth()
|
|
_test_couple_warp_restrictions()
|
|
_test_successful_warp_and_cooldown()
|
|
_test_divorce()
|
|
_finish()
|
|
|
|
func _test_marriage_qualifications_and_ring() -> void:
|
|
print("\n--- Test 1: Marriage Prerequisites & Ring Inscription ---")
|
|
var ms := MarriageSystem.new()
|
|
var ring := {"vnum": 70301}
|
|
var non_ring := {"vnum": 10}
|
|
|
|
# Level 20 rejected (requires 25)
|
|
var res = ms.marry("Hero", "Alice", ring, 20)
|
|
_assert(res["ok"] == false and res["reason"] == "LEVEL_TOO_LOW", "Level < 25 rejected")
|
|
|
|
# Non wedding ring rejected
|
|
res = ms.marry("Hero", "Alice", non_ring, 30)
|
|
_assert(res["ok"] == false and res["reason"] == "NO_WEDDING_RING", "Non-wedding ring rejected")
|
|
|
|
# Valid marriage succeeds
|
|
res = ms.marry("Hero", "Alice", ring, 30)
|
|
_assert(res["ok"] == true, "Marriage ceremony succeeds")
|
|
_assert(ms.is_married == true, "Player is now married")
|
|
_assert(ms.spouse_name == "Alice", "Spouse name is Alice")
|
|
_assert(ring["inscribed_name"] == "Alice", "Ring inscribed with partner's name")
|
|
_assert(ms.love_points == 50, "Initial love points is 50%")
|
|
|
|
func _test_love_points_growth() -> void:
|
|
print("\n--- Test 2: Love Points Growth ---")
|
|
var ms := MarriageSystem.new()
|
|
var ring := {"vnum": 70301}
|
|
ms.marry("Hero", "Alice", ring, 30)
|
|
|
|
ms.add_love_points(30)
|
|
_assert(ms.love_points == 80, "Love points increased to 80%")
|
|
|
|
# Clamped to 100%
|
|
ms.add_love_points(50)
|
|
_assert(ms.love_points == 100, "Love points clamped at 100%")
|
|
|
|
func _test_couple_warp_restrictions() -> void:
|
|
print("\n--- Test 3: Couple Warp Restrictions ---")
|
|
var ms := MarriageSystem.new()
|
|
var spouse_loc := {"is_online": true, "map": "metin2_map_a1", "pos": Vector3(100, 0, 100)}
|
|
|
|
# Unmarried player rejected
|
|
var res = ms.warp_to_spouse(100, spouse_loc, false)
|
|
_assert(res["ok"] == false and res["reason"] == "NOT_MARRIED", "Unmarried player cannot warp")
|
|
|
|
# Marry
|
|
var ring := {"vnum": 70301}
|
|
ms.marry("Hero", "Alice", ring, 30)
|
|
|
|
# Dead player rejected
|
|
res = ms.warp_to_spouse(100, spouse_loc, true)
|
|
_assert(res["ok"] == false and res["reason"] == "PLAYER_DEAD", "Dead player cannot warp")
|
|
|
|
# Not enough SP (< 50)
|
|
res = ms.warp_to_spouse(30, spouse_loc, false)
|
|
_assert(res["ok"] == false and res["reason"] == "NOT_ENOUGH_SP", "Fails when SP < 50")
|
|
|
|
# Offline spouse rejected
|
|
res = ms.warp_to_spouse(100, {"is_online": false}, false)
|
|
_assert(res["ok"] == false and res["reason"] == "SPOUSE_OFFLINE", "Offline spouse rejected")
|
|
|
|
# Forbidden zone (Devil Tower F9) rejected
|
|
var forbidden_loc := {"is_online": true, "map": "deviltower_f9", "pos": Vector3(50, 0, 50)}
|
|
res = ms.warp_to_spouse(100, forbidden_loc, false)
|
|
_assert(res["ok"] == false and res["reason"] == "FORBIDDEN_ZONE", "Warp into Devil Tower F9 blocked")
|
|
|
|
func _test_successful_warp_and_cooldown() -> void:
|
|
print("\n--- Test 4: Successful Couple Warp & Cooldown ---")
|
|
var ms := MarriageSystem.new()
|
|
var ring := {"vnum": 70301}
|
|
ms.marry("Hero", "Alice", ring, 30)
|
|
|
|
var spouse_loc := {"is_online": true, "map": "metin2_map_b1", "pos": Vector3(250, 10, 320)}
|
|
var warped := [false]
|
|
ms.couple_warped.connect(func(m: String, p: Vector3): warped[0] = true)
|
|
|
|
var res = ms.warp_to_spouse(80, spouse_loc, false)
|
|
_assert(res["ok"] == true, "Warp request succeeded")
|
|
_assert(warped[0] == true, "couple_warped signal emitted")
|
|
_assert(res["sp_cost"] == 50, "50 SP consumed")
|
|
_assert(res["target_map"] == "metin2_map_b1", "Target map is metin2_map_b1")
|
|
_assert(res["target_pos"] == Vector3(250, 10, 320), "Target position accurately resolved")
|
|
_assert(ms.warp_cooldown == 180.0, "Warp entered 180s cooldown")
|
|
|
|
# Second warp immediately blocked by cooldown
|
|
res = ms.warp_to_spouse(80, spouse_loc, false)
|
|
_assert(res["ok"] == false and res["reason"] == "COOLDOWN_ACTIVE", "Second warp blocked by 180s cooldown")
|
|
|
|
# Fast forward 181 seconds
|
|
ms.update(181.0)
|
|
_assert(ms.warp_cooldown == 0.0, "Cooldown expired after 181s")
|
|
|
|
func _test_divorce() -> void:
|
|
print("\n--- Test 5: Divorce ---")
|
|
var ms := MarriageSystem.new()
|
|
var ring := {"vnum": 70301}
|
|
ms.marry("Hero", "Alice", ring, 30)
|
|
_assert(ms.is_married == true, "Married initially")
|
|
|
|
var res = ms.divorce()
|
|
_assert(res["ok"] == true, "Divorce completed")
|
|
_assert(ms.is_married == false, "No longer married")
|
|
_assert(ms.spouse_name.is_empty(), "Spouse name cleared")
|
|
_assert(ms.love_points == 0, "Love points reset to 0")
|
|
|
|
func _finish() -> void:
|
|
print("\n=== SUMMARY: %d passed, %d failed ===" % [_passed, _failed])
|
|
if _failed == 0:
|
|
print("ALL TESTS PASSED!\n")
|
|
quit(0)
|
|
else:
|
|
printerr("SOME TESTS FAILED!\n")
|
|
quit(1)
|