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