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

170 lines
5.9 KiB
GDScript

# test_flame_dungeon_razador_parity.gd —— 40250 红龙烈焰神殿与拉扎多尔试炼 1:1 回归测试套件
extends SceneTree
const FlameDungeonRazadorSystem = preload("res://flame_dungeon_razador_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_flame_dungeon_razador_parity (Direction 2: Flame Dungeon Razador 1:1) ===")
_test_entry_and_ticket_consumption()
_test_stage_advancement_and_altars()
_test_razador_boss_slay_and_rewards()
_test_timeout_failure()
_test_serialization()
_finish()
func _test_entry_and_ticket_consumption() -> void:
print("\n--- Test 1: Flame Dungeon Entry & Ticket Consumption ---")
var sys := FlameDungeonRazadorSystem.new()
var inv: Array = [
{"vnum": FlameDungeonRazadorSystem.VNUM_TICKET_71095, "name": "通行证", "count": 2}
]
# 1. Level too low (< 100)
var res_low = sys.enter_dungeon(95, inv)
_assert(res_low["ok"] == false, "Entry rejected: level 95 < 100")
_assert(res_low["reason"] == "LEVEL_TOO_LOW", "Reason is LEVEL_TOO_LOW")
var enter_sig := {"fired": false, "dur": 0.0}
sys.dungeon_entered.connect(func(d: float):
enter_sig["fired"] = true
enter_sig["dur"] = d
)
# 2. Valid entry at Lv 100
var res_succ = sys.enter_dungeon(100, inv)
_assert(res_succ["ok"] == true, "Entered Flame Dungeon successfully")
_assert(sys.is_active == true, "Dungeon is active")
_assert(sys.current_stage == 1, "Initial stage is 1")
_assert(inv[0]["count"] == 1, "Ticket count decremented 2 -> 1")
_assert(enter_sig["fired"] == true, "dungeon_entered signal emitted")
_assert(enter_sig["dur"] == 2700.0, "Time limit is 2700.0s (45 minutes)")
func _test_stage_advancement_and_altars() -> void:
print("\n--- Test 2: Stage Advancement & Altar Lighting ---")
var sys := FlameDungeonRazadorSystem.new()
var inv: Array = [{"vnum": FlameDungeonRazadorSystem.VNUM_TICKET_71130, "name": "烈焰通行证", "count": 1}]
sys.enter_dungeon(105, inv)
# Advance stages 1 -> 2 -> 3 -> 4 -> 5
for i in range(4):
sys.advance_stage()
_assert(sys.current_stage == 5, "Reached Stage 5 (Fire Altars)")
var altar_sig := {"fired": false, "lit": 0}
sys.altar_lit.connect(func(l: int, _t: int):
altar_sig["fired"] = true
altar_sig["lit"] = l
)
# Light 4 altars
for i in range(4):
var res_altar = sys.light_fire_altar()
_assert(res_altar["stage_cleared"] == false, "Stage not yet cleared with < 5 altars")
_assert(sys.altars_lit_count == 4, "4 altars lit")
# Light 5th altar -> auto clears stage 5 and enters stage 6
var res_5th = sys.light_fire_altar()
_assert(res_5th["stage_cleared"] == true, "5th altar lit: stage cleared")
_assert(sys.current_stage == 6, "Automatically advanced to Stage 6")
var boss_sig := {"fired": false, "vnum": 0}
sys.razador_spawned.connect(func(v: int):
boss_sig["fired"] = true
boss_sig["vnum"] = v
)
# Advance stage 6 -> 7 (Boss Chamber)
var res_boss_room = sys.advance_stage()
_assert(res_boss_room["current_stage"] == 7, "Entered Stage 7 (Razador)")
_assert(sys.razador_alive == true, "Razador is alive")
_assert(boss_sig["fired"] == true, "razador_spawned signal emitted")
_assert(boss_sig["vnum"] == 6091, "Razador mob vnum is 6091")
func _test_razador_boss_slay_and_rewards() -> void:
print("\n--- Test 3: Razador Boss Slay & Rewards ---")
var sys := FlameDungeonRazadorSystem.new()
var inv: Array = [
{"vnum": FlameDungeonRazadorSystem.VNUM_TICKET_71095, "name": "通行证", "count": 1},
null, null, null
]
sys.enter_dungeon(105, inv)
sys.current_stage = 7
sys.razador_alive = true
var comp_sig := {"fired": false}
sys.dungeon_completed.connect(func():
comp_sig["fired"] = true
)
# Slay Razador
var res_slay = sys.slay_razador(inv)
_assert(res_slay["ok"] == true, "Razador slain")
_assert(sys.is_active == false, "Dungeon completed and inactive")
_assert(comp_sig["fired"] == true, "dungeon_completed signal emitted")
# Verify Razador's Chest received
var chest_found := false
for it in inv:
if it != null and int(it.get("vnum", 0)) == FlameDungeonRazadorSystem.VNUM_RAZADOR_CHEST:
chest_found = true
break
_assert(chest_found == true, "Razador's Chest (50186) found in inventory")
func _test_timeout_failure() -> void:
print("\n--- Test 4: Dungeon Timeout Failure ---")
var sys := FlameDungeonRazadorSystem.new()
var inv: Array = [{"vnum": FlameDungeonRazadorSystem.VNUM_TICKET_71095, "name": "通行证", "count": 1}]
sys.enter_dungeon(100, inv)
var fail_sig := {"fired": false, "reason": ""}
sys.dungeon_failed.connect(func(r: String):
fail_sig["fired"] = true
fail_sig["reason"] = r
)
# Advance 2700s
sys.update(2700.0)
_assert(sys.is_active == false, "Dungeon inactive on timeout")
_assert(fail_sig["fired"] == true, "dungeon_failed signal emitted")
_assert(fail_sig["reason"] == "TIMEOUT", "Reported TIMEOUT")
func _test_serialization() -> void:
print("\n--- Test 5: Serialization & Restoration ---")
var sys1 := FlameDungeonRazadorSystem.new()
var inv: Array = [{"vnum": FlameDungeonRazadorSystem.VNUM_TICKET_71095, "name": "通行证", "count": 1}]
sys1.enter_dungeon(100, inv)
sys1.current_stage = 5
sys1.altars_lit_count = 3
sys1.update(600.0) # 2100s left
var data = sys1.serialize()
var sys2 := FlameDungeonRazadorSystem.new()
sys2.deserialize(data)
_assert(sys2.is_active == true, "Restored is_active")
_assert(sys2.current_stage == 5, "Restored current stage 5")
_assert(sys2.altars_lit_count == 3, "Restored altars lit count 3")
_assert(is_equal_approx(sys2.time_remaining, 2100.0), "Restored time remaining 2100s")
func _finish() -> void:
print("\n=======================================================")
print("Flame Dungeon Razador Parity Tests: %d Passed, %d Failed" % [_passed, _failed])
print("=======================================================\n")
if _failed > 0:
quit(1)
else:
quit(0)