- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
149 lines
5.1 KiB
GDScript
149 lines
5.1 KiB
GDScript
# test_endless_spire_dungeon_parity.gd —— 40250 无尽天关爬塔挑战 1:1 回归测试套件
|
|
extends SceneTree
|
|
|
|
const EndlessSpireDungeonSystem = preload("res://endless_spire_dungeon_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_endless_spire_dungeon_parity (Direction 1: Endless Spire Dungeon 1:1) ===")
|
|
_test_start_and_normal_floors()
|
|
_test_milestone_boss_and_checkpoint()
|
|
_test_resume_from_checkpoint()
|
|
_test_full_clear_floor_50()
|
|
_test_timeout_defeat()
|
|
_finish()
|
|
|
|
func _test_start_and_normal_floors() -> void:
|
|
print("\n--- Test 1: Starting Floor 1 & Clearing Mobs ---")
|
|
var spire := EndlessSpireDungeonSystem.new()
|
|
|
|
var start_sig := {"fired": false, "floor": 0, "is_boss": true}
|
|
spire.floor_started.connect(func(f: int, is_b: bool, _c: int):
|
|
start_sig["fired"] = true
|
|
start_sig["floor"] = f
|
|
start_sig["is_boss"] = is_b
|
|
)
|
|
|
|
var res = spire.start_trial(false)
|
|
_assert(res["ok"] == true and spire.current_floor == 1, "Trial started at Floor 1")
|
|
_assert(start_sig["fired"] == true and start_sig["floor"] == 1 and start_sig["is_boss"] == false, "floor_started signal emitted for regular floor")
|
|
_assert(spire.active_mobs.size() == 6, "Floor 1 has 6 mobs (4 + (1%5)*2 = 6)")
|
|
|
|
# Kill all mobs on floor 1
|
|
var m_ids = spire.active_mobs.keys().duplicate()
|
|
for mid in m_ids:
|
|
spire.kill_mob(mid)
|
|
|
|
# Transitioned to floor 2
|
|
_assert(spire.current_floor == 2, "Transitioned to Floor 2")
|
|
_assert(spire.total_points == 10, "Points earned 10 (1 * 10)")
|
|
|
|
func _test_milestone_boss_and_checkpoint() -> void:
|
|
print("\n--- Test 2: Floor 5 Milestone Boss & Checkpoint Save ---")
|
|
var spire := EndlessSpireDungeonSystem.new()
|
|
spire.start_trial(false)
|
|
|
|
var cp_sig := {"fired": false, "cp": 0}
|
|
spire.checkpoint_saved.connect(func(cp: int):
|
|
cp_sig["fired"] = true
|
|
cp_sig["cp"] = cp
|
|
)
|
|
|
|
# Advance to floor 5
|
|
while spire.current_floor < 5:
|
|
var ids = spire.active_mobs.keys().duplicate()
|
|
for mid in ids:
|
|
spire.kill_mob(mid)
|
|
|
|
_assert(spire.current_floor == 5, "Reached Floor 5 (Milestone Boss)")
|
|
_assert(spire.active_mobs.size() == 1, "Floor 5 has 1 boss")
|
|
var boss_id = spire.active_mobs.keys()[0]
|
|
_assert(spire.active_mobs[boss_id]["vnum"] == 691, "Boss is Orc Chief (691)")
|
|
|
|
# Kill Floor 5 Boss
|
|
spire.kill_mob(boss_id)
|
|
_assert(spire.current_floor == 6, "Advanced to Floor 6")
|
|
_assert(cp_sig["fired"] == true and cp_sig["cp"] == 6, "checkpoint_saved signal fired with Floor 6")
|
|
_assert(spire.highest_checkpoint == 6, "highest_checkpoint is 6")
|
|
|
|
func _test_resume_from_checkpoint() -> void:
|
|
print("\n--- Test 3: Exit & Resume from Checkpoint ---")
|
|
var spire := EndlessSpireDungeonSystem.new()
|
|
spire.start_trial(false)
|
|
|
|
# Progress to checkpoint 6
|
|
while spire.current_floor < 6:
|
|
var ids = spire.active_mobs.keys().duplicate()
|
|
for mid in ids:
|
|
spire.kill_mob(mid)
|
|
|
|
# Exit trial
|
|
spire.exit_trial()
|
|
_assert(spire.is_in_trial == false, "Exited trial")
|
|
|
|
# Resume from checkpoint
|
|
var resume_res = spire.start_trial(true)
|
|
_assert(resume_res["ok"] == true, "Resumed trial")
|
|
_assert(spire.current_floor == 6, "Resumed directly at Floor 6")
|
|
|
|
func _test_full_clear_floor_50() -> void:
|
|
print("\n--- Test 4: Floor 50 Final Boss & Spire Mastery ---")
|
|
var spire := EndlessSpireDungeonSystem.new()
|
|
spire.highest_checkpoint = 50
|
|
spire.start_trial(true)
|
|
|
|
var mastery_sig := {"fired": false, "floor": 0}
|
|
spire.spire_trial_completed.connect(func(f: int, _p: int):
|
|
mastery_sig["fired"] = true
|
|
mastery_sig["floor"] = f
|
|
)
|
|
|
|
_assert(spire.current_floor == 50, "At final Floor 50")
|
|
var boss_id = spire.active_mobs.keys()[0]
|
|
_assert(spire.active_mobs[boss_id]["vnum"] == 8027, "Final boss is Chaos Overlord (8027)")
|
|
|
|
# Kill final boss
|
|
var finish_res = spire.kill_mob(boss_id)
|
|
_assert(finish_res["ok"] == true and finish_res["trial_completed"] == true, "Trial fully completed")
|
|
_assert(spire.is_in_trial == false, "Trial marked as finished")
|
|
_assert(mastery_sig["fired"] == true and mastery_sig["floor"] == 50, "spire_trial_completed emitted")
|
|
|
|
func _test_timeout_defeat() -> void:
|
|
print("\n--- Test 5: Timeout Defeat ---")
|
|
var spire := EndlessSpireDungeonSystem.new()
|
|
spire.start_trial(false)
|
|
|
|
var fail_sig := {"fired": false, "floor": 0}
|
|
spire.spire_trial_failed.connect(func(f: int, _r: String):
|
|
fail_sig["fired"] = true
|
|
fail_sig["floor"] = f
|
|
)
|
|
|
|
# Advance time past 120s limit
|
|
var tick = spire.update(125.0)
|
|
_assert(tick["status"] == "failed" and tick["reason"] == "TIME_EXPIRED", "Failed on timeout")
|
|
_assert(fail_sig["fired"] == true and fail_sig["floor"] == 1, "spire_trial_failed emitted")
|
|
_assert(spire.is_in_trial == false, "Trial ended")
|
|
|
|
func _finish() -> void:
|
|
print("\n==========================================")
|
|
print("Endless Spire Dungeon Parity Tests Finished:")
|
|
print("Passed: %d, Failed: %d" % [_passed, _failed])
|
|
print("==========================================")
|
|
if _failed > 0:
|
|
printerr("FAILED: Some tests did not pass.")
|
|
quit(1)
|
|
else:
|
|
print("SUCCESS: All Endless Spire Dungeon parity tests passed!")
|
|
quit(0)
|