- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
117 lines
4.7 KiB
GDScript
117 lines
4.7 KiB
GDScript
# test_polymorph_parity.gd —— 40250 变身球与变身术技能 1:1 纯净回归测试套件
|
|
extends SceneTree
|
|
|
|
const PolymorphSystem = preload("res://polymorph_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_polymorph_parity (Direction 2: Polymorph System 1:1) ===")
|
|
_test_marble_item_and_prerequisites()
|
|
_test_duration_and_skill_scaling()
|
|
_test_transformation_stat_boost()
|
|
_test_combat_and_action_restrictions()
|
|
_test_termination_and_death()
|
|
_finish()
|
|
|
|
func _test_marble_item_and_prerequisites() -> void:
|
|
print("\n--- Test 1: Marble Item & Transformation Prerequisites ---")
|
|
var ps := PolymorphSystem.new()
|
|
var marble := {"vnum": 70104, "mob_vnum": 101} # Wild Boar
|
|
var non_marble := {"vnum": 10, "mob_vnum": 101}
|
|
|
|
# Non marble rejected
|
|
var res = ps.use_polymorph_marble(non_marble, false, false)
|
|
_assert(res["ok"] == false and res["reason"] == "NOT_A_MARBLE", "Non-marble item rejected")
|
|
|
|
# Dead player rejected
|
|
res = ps.use_polymorph_marble(marble, true, false)
|
|
_assert(res["ok"] == false and res["reason"] == "PLAYER_DEAD", "Dead player cannot transform")
|
|
|
|
# Mounted player rejected
|
|
res = ps.use_polymorph_marble(marble, false, true)
|
|
_assert(res["ok"] == false and res["reason"] == "PLAYER_MOUNTED", "Mounted player cannot transform")
|
|
|
|
# Peaceful on foot succeeds
|
|
res = ps.use_polymorph_marble(marble, false, false)
|
|
_assert(res["ok"] == true, "Transformation succeeds on foot while alive")
|
|
_assert(ps.is_polymorphed == true, "Player is now in polymorphed state")
|
|
_assert(ps.current_mob_vnum == 101, "Current mob vnum is 101 (Wild Boar)")
|
|
|
|
func _test_duration_and_skill_scaling() -> void:
|
|
print("\n--- Test 2: Duration Scaling with Skill Level (1~P) ---")
|
|
# Level 1: 620s (~10 min)
|
|
_assert(PolymorphSystem.get_duration_by_skill(1) == 620.0, "Skill Lv1: 620s")
|
|
# Level 20 (M1): 1200s (20 min)
|
|
_assert(PolymorphSystem.get_duration_by_skill(20) == 1200.0, "Skill M1 (Lv20): 1200s (20 min)")
|
|
# Level 30 (G1): 1500s (25 min)
|
|
_assert(PolymorphSystem.get_duration_by_skill(30) == 1500.0, "Skill G1 (Lv30): 1500s (25 min)")
|
|
# Level 40 (P): 2100s (35 min)
|
|
_assert(PolymorphSystem.get_duration_by_skill(40) == 2100.0, "Skill P (Lv40): 2100s (35 min)")
|
|
|
|
func _test_transformation_stat_boost() -> void:
|
|
print("\n--- Test 3: Monster Attributes & Skill Scaling Boost ---")
|
|
var ps := PolymorphSystem.new()
|
|
ps.poly_skill_level = 40 # P grade (multiplier 1.0 + 40*0.025 = 2.0x)
|
|
|
|
var tiger_marble := {"vnum": 70104, "mob_vnum": 114} # White Tiger (base atk: 85)
|
|
var res = ps.use_polymorph_marble(tiger_marble, false, false)
|
|
_assert(res["ok"] == true, "White tiger transformation succeeds")
|
|
_assert(ps.bonus_atk == 170, "P-Grade Tiger ATK is doubled: 85 * 2.0 = 170")
|
|
_assert(ps.bonus_def == 40, "Tiger DEF is 40")
|
|
_assert(ps.bonus_speed == 140, "Tiger movement speed is 140")
|
|
|
|
func _test_combat_and_action_restrictions() -> void:
|
|
print("\n--- Test 4: Action Restrictions (Skills, Mount, Weapon) ---")
|
|
var ps := PolymorphSystem.new()
|
|
var marble := {"vnum": 70104, "mob_vnum": 110} # Bear
|
|
ps.use_polymorph_marble(marble, false, false)
|
|
|
|
# Active skills blocked
|
|
_assert(ps.can_use_skill(1) == false, "Warrior skill 1 (Three-way Cut) blocked")
|
|
_assert(ps.can_use_skill(2) == false, "Warrior skill 2 (Sword Spin) blocked")
|
|
_assert(ps.can_use_skill(129) == true, "Polymorph skill 129 permitted")
|
|
|
|
# Weapon change blocked
|
|
_assert(ps.can_change_weapon() == false, "Weapon swapping blocked while transformed")
|
|
|
|
# Mounting blocked
|
|
_assert(ps.can_mount() == false, "Mounting horse blocked while transformed")
|
|
|
|
func _test_termination_and_death() -> void:
|
|
print("\n--- Test 5: Revert on Countdown Expiry & Death ---")
|
|
var ps := PolymorphSystem.new()
|
|
var marble := {"vnum": 70104, "mob_vnum": 101}
|
|
ps.use_polymorph_marble(marble, false, false)
|
|
_assert(ps.is_polymorphed == true, "Polymorphed initially")
|
|
|
|
# Fast forward time to expire
|
|
ps.update(ps.remaining_time + 1.0)
|
|
_assert(ps.is_polymorphed == false, "Polymorph ended after countdown expired")
|
|
_assert(ps.bonus_atk == 0, "Bonus ATK cleared")
|
|
_assert(ps.can_use_skill(1) == true, "Skills unlocked again after polymorph ends")
|
|
|
|
# Re-transform and test death
|
|
ps.use_polymorph_marble(marble, false, false)
|
|
_assert(ps.is_polymorphed == true, "Re-transformed")
|
|
ps.on_player_death()
|
|
_assert(ps.is_polymorphed == false, "Polymorph immediately cancelled on player death")
|
|
|
|
func _finish() -> void:
|
|
print("\n=== SUMMARY: %d passed, %d failed ===" % [_passed, _failed])
|
|
if _failed == 0:
|
|
print("ALL TESTS PASSED!\n")
|
|
quit(0)
|
|
else:
|
|
printerr("SOME TESTS FAILED!\n")
|
|
quit(1)
|