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

124 lines
5.3 KiB
GDScript

# test_soul_stone_grandmaster_parity.gd —— Metin2 40250 灵魂石领悟宗师绝技 1:1 测试套件
extends SceneTree
const SoulStoneGrandmasterSystem = preload("res://soul_stone_grandmaster_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_soul_stone_grandmaster_parity (Direction 1: Soul Stone Grandmaster 1:1) ===")
test_eligibility_and_alignment_cost()
test_successful_training_and_p_tier()
test_failure_alignment_penalty()
test_cooldown_and_exorcism()
test_serialization()
print("\n=======================================================")
print("Soul Stone Grandmaster Tests: %d Passed, %d Failed" % [_passed, _failed])
print("=======================================================")
if _failed > 0:
quit(1)
else:
quit(0)
func test_eligibility_and_alignment_cost() -> void:
print("\n--- Test 1: Eligibility & Alignment Calculations (40250 1:1) ---")
var system = SoulStoneGrandmasterSystem.new()
# 检查 G 阶资格: 30(G1) ~ 39(G10) 允许,其他拒绝
_assert(system.can_train_skill(20) == false, "M-tier skill (Lv 20) not eligible for soul stone")
_assert(system.can_train_skill(30) == true, "G1 (Lv 30) eligible")
_assert(system.can_train_skill(39) == true, "G10 (Lv 39) eligible")
_assert(system.can_train_skill(40) == false, "P-tier (Lv 40) already maxed")
# 善恶值消耗计算: need_alignment = 1000 + 500 * (level - 30)
# 正善恶值玩家
_assert(system.get_required_alignment(30, 5000) == 1000, "G1 costs 1000 alignment")
_assert(system.get_required_alignment(31, 5000) == 1500, "G2 costs 1500 alignment")
_assert(system.get_required_alignment(39, 5000) == 5500, "G10 costs 5500 alignment")
# 负善恶值 (邪恶阵营) 翻倍惩罚 (40250 quest: need_alignment = need_alignment * 2)
_assert(system.get_required_alignment(30, -2000) == 2000, "G1 costs 2000 alignment for evil player")
_assert(system.get_required_alignment(39, -500) == 11000, "G10 costs 11000 alignment for evil player")
func test_successful_training_and_p_tier() -> void:
print("\n--- Test 2: Successful Training & Reaching P (40250 1:1) ---")
var system = SoulStoneGrandmasterSystem.new()
var inv: Array = [
{"vnum": 50513, "count": 2} # 灵魂石 x2
]
# 1. 成功从 G1 (30) 升到 G2 (31)
var res = system.train_grandmaster_skill(inv, 0, 1, "三重斩", 30, 8000, false, true)
_assert(res["ok"] == true and res["success"] == true, "Training succeeded")
_assert(res["new_level"] == 31, "Skill level promoted to 31 (G2)")
_assert(res["alignment_cost"] == 1000, "Deducted 1000 alignment")
_assert(res["new_alignment"] == 7000, "New alignment is 7000 (8000 - 1000)")
_assert(inv[0]["count"] == 1, "Consumed 1 Soul Stone")
# 清除冷却用于测试
system.use_exorcism_scroll()
# 2. 成功从 G10 (39) 登峰造极突破至 P 阶 (40)
res = system.train_grandmaster_skill(inv, 0, 1, "三重斩", 39, 10000, false, true)
_assert(res["ok"] == true and res["success"] == true, "Promoted to P tier")
_assert(res["new_level"] == 40, "Level reached 40")
_assert(res["is_perfect_master"] == true, "Reached Perfect Master!")
_assert(res["tier_text"] == "P 阶 (Perfect Master)", "Tier text is Perfect Master")
func test_failure_alignment_penalty() -> void:
print("\n--- Test 3: Failure & Alignment Penalty (40250 1:1) ---")
var system = SoulStoneGrandmasterSystem.new()
var inv: Array = [{"vnum": 50513, "count": 1}]
# 强制失败 (roll = 90 > 30)
var res = system.train_grandmaster_skill(inv, 0, 2, "旋风斩", 30, 5000, false, false, 90)
_assert(res["ok"] == true and res["success"] == false, "Training failed")
_assert(res["new_level"] == 30, "Skill level unchanged at 30")
_assert(res["alignment_cost"] >= 330 and res["alignment_cost"] <= 500, "Deducted 1/3 to 1/2 penalty")
_assert(res["new_alignment"] < 5000, "Alignment penalised")
_assert(inv[0] == null, "Soul stone shattered and removed")
func test_cooldown_and_exorcism() -> void:
print("\n--- Test 4: Cooldown & Exorcism Scroll (40250 1:1) ---")
var system = SoulStoneGrandmasterSystem.new()
var inv: Array = [{"vnum": 50513, "count": 2}]
system.train_grandmaster_skill(inv, 0, 1, "三重斩", 30, 8000, false, true)
_assert(system.training_cooldown_left > 0.0, "Cooldown active after training")
# 冷却期间再次参悟 -> 拦截
var res = system.train_grandmaster_skill(inv, 0, 1, "三重斩", 31, 7000, false, true)
_assert(res["ok"] == false, "Rejected during cooldown")
_assert(res["reason"] == "COOLDOWN_ACTIVE", "Reason is COOLDOWN_ACTIVE")
# 使用驱魔卷轴 (71001) 清除心境冷却
system.use_exorcism_scroll()
_assert(system.training_cooldown_left == 0.0, "Cooldown cleared by exorcism scroll")
# 再次参悟 -> 成功
res = system.train_grandmaster_skill(inv, 0, 1, "三重斩", 31, 7000, false, true)
_assert(res["ok"] == true, "Trained successfully after exorcism")
func test_serialization() -> void:
print("\n--- Test 5: Serialization & Restoration ---")
var system = SoulStoneGrandmasterSystem.new()
system.training_cooldown_left = 15000.0
var data = system.serialize()
var restored = SoulStoneGrandmasterSystem.new()
restored.deserialize(data)
_assert(restored.training_cooldown_left == 15000.0, "Restored cooldown")