Files
mtgodot-poc/project/test_wedding_marriage_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

164 lines
5.9 KiB
GDScript

# test_wedding_marriage_parity.gd —— 40250 官方结婚典礼与夫妻同心婚戒系统 1:1 回归测试套件
extends SceneTree
const WeddingMarriageSystem = preload("res://wedding_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_wedding_marriage_parity (Direction 3: Wedding & Marriage 1:1) ===")
_test_wedding_ceremony_and_ring_issuance()
_test_wedding_ring_teleport()
_test_love_points_and_marriage_buffs()
_test_divorce_and_ring_clearing()
_test_serialization()
_finish()
func _test_wedding_ceremony_and_ring_issuance() -> void:
print("\n--- Test 1: Wedding Ceremony & Wedding Ring Issuance ---")
var sys := WeddingMarriageSystem.new()
_assert(not sys.is_married, "Initially unmarried")
var inv: Array = [
{"vnum": WeddingMarriageSystem.VNUM_ENGAGEMENT_RING, "name": "订婚戒指"}
]
# 1. Missing wedding dress
var res_no_dress = sys.conduct_wedding("月神姬", inv, "M")
_assert(res_no_dress["ok"] == false, "Wedding rejected without Tuxedo/Dress")
_assert(res_no_dress["reason"] == "NO_WEDDING_DRESS", "Reason is NO_WEDDING_DRESS")
# Add Tuxedo
inv.append({"vnum": WeddingMarriageSystem.VNUM_TUXEDO, "name": "新郎礼服"})
var wed_sig := {"fired": false, "spouse": ""}
sys.marriage_completed.connect(func(s: String):
wed_sig["fired"] = true
wed_sig["spouse"] = s
)
# 2. Successful wedding
var res_wed = sys.conduct_wedding("月神姬", inv, "M")
_assert(res_wed["ok"] == true, "Wedding ceremony succeeded")
_assert(sys.is_married == true, "is_married is true")
_assert(sys.spouse_name == "月神姬", "Spouse name is 月神姬")
_assert(inv[0]["vnum"] == WeddingMarriageSystem.VNUM_WEDDING_RING, "Slot 0 replaced with Wedding Ring (70302)")
_assert(wed_sig["fired"] == true, "marriage_completed signal emitted")
_assert(wed_sig["spouse"] == "月神姬", "Signal reported spouse name")
func _test_wedding_ring_teleport() -> void:
print("\n--- Test 2: Wedding Ring Spouse Teleport ---")
var sys := WeddingMarriageSystem.new()
sys.is_married = true
sys.spouse_name = "月神姬"
var warp_sig := {"fired": false, "map": "", "pos": Vector2.ZERO}
sys.spouse_warped.connect(func(m: String, p: Vector2):
warp_sig["fired"] = true
warp_sig["map"] = m
warp_sig["pos"] = p
)
# 1. Spouse is offline
var res_offline = sys.use_wedding_ring(false, "Desert", Vector2(100, 200), "Yongan")
_assert(res_offline["ok"] == false, "Warp rejected: spouse offline")
_assert(res_offline["reason"] == "SPOUSE_OFFLINE", "Reason is SPOUSE_OFFLINE")
# 2. Forbidden map (Arena)
var res_arena = sys.use_wedding_ring(true, "Arena", Vector2(100, 200), "Yongan")
_assert(res_arena["ok"] == false, "Warp rejected in Arena")
_assert(res_arena["reason"] == "FORBIDDEN_MAP", "Reason is FORBIDDEN_MAP")
# 3. Successful warp
var res_succ = sys.use_wedding_ring(true, "Desert", Vector2(450, 780), "Yongan")
_assert(res_succ["ok"] == true, "Warp succeeded")
_assert(warp_sig["fired"] == true, "spouse_warped signal emitted")
_assert(warp_sig["map"] == "Desert", "Target map is Desert")
_assert(warp_sig["pos"] == Vector2(450, 780), "Target pos matches spouse")
func _test_love_points_and_marriage_buffs() -> void:
print("\n--- Test 3: Love Points & Marriage Aura Buffs ---")
var sys := WeddingMarriageSystem.new()
sys.is_married = true
sys.love_points = 50
var love_sig := {"fired": false, "pts": 0}
sys.love_points_updated.connect(func(p: int):
love_sig["fired"] = true
love_sig["pts"] = p
)
sys.add_love_points(30) # 50 -> 80
_assert(sys.love_points == 80, "Love points increased to 80")
_assert(love_sig["fired"] == true, "love_points_updated signal emitted")
# Buff check when NOT near spouse
var buff_far = sys.calculate_marriage_buff(true, true, false)
_assert(buff_far.is_empty(), "No marriage buffs when distant from spouse")
# Buff check when near spouse: base (10 + 8) = 18% exp
# + Ring of Love (+20% exp) = 38%
# + Bracelet of Love (+10% crit)
var buff_near = sys.calculate_marriage_buff(true, true, true)
_assert(buff_near["couple_exp_bonus_pct"] == 38, "Couple exp bonus is 38% (18% + 20%)")
_assert(buff_near["crit_pct"] == 10, "Crit bonus is 10%")
func _test_divorce_and_ring_clearing() -> void:
print("\n--- Test 4: Divorce & Wedding Ring Clearing ---")
var sys := WeddingMarriageSystem.new()
sys.is_married = true
sys.spouse_name = "月神姬"
sys.love_points = 80
var inv: Array = [
{"vnum": WeddingMarriageSystem.VNUM_WEDDING_RING, "name": "结婚戒指"}
]
var div_sig := {"fired": false}
sys.divorced.connect(func():
div_sig["fired"] = true
)
var res_div = sys.divorce(inv)
_assert(res_div["ok"] == true, "Divorce succeeded")
_assert(sys.is_married == false, "is_married is now false")
_assert(sys.spouse_name.is_empty(), "Spouse name cleared")
_assert(sys.love_points == 0, "Love points cleared to 0")
_assert(inv[0] == null, "Wedding ring revoked and slot cleared")
_assert(div_sig["fired"] == true, "divorced signal emitted")
func _test_serialization() -> void:
print("\n--- Test 5: Serialization & Restoration ---")
var sys1 := WeddingMarriageSystem.new()
sys1.is_married = true
sys1.spouse_name = "雪月花"
sys1.love_points = 95
sys1.marry_timestamp = 1600000000
var data = sys1.serialize()
var sys2 := WeddingMarriageSystem.new()
sys2.deserialize(data)
_assert(sys2.is_married == true, "Restored is_married")
_assert(sys2.spouse_name == "雪月花", "Restored spouse name")
_assert(sys2.love_points == 95, "Restored love points")
_assert(sys2.marry_timestamp == 1600000000, "Restored marry timestamp")
func _finish() -> void:
print("\n=======================================================")
print("Wedding Marriage Parity Tests: %d Passed, %d Failed" % [_passed, _failed])
print("=======================================================\n")
if _failed > 0:
quit(1)
else:
quit(0)