- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
123 lines
5.5 KiB
GDScript
123 lines
5.5 KiB
GDScript
# test_dragon_soul_parity.gd —— 40250 龙神炼金石系统 1:1 纯净回归测试套件
|
|
extends SceneTree
|
|
|
|
const DragonSoulSystem = preload("res://dragon_soul_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_dragon_soul_parity (Direction 1: Dragon Soul Alchemy 1:1) ===")
|
|
_test_stone_creation_and_attributes()
|
|
_test_grade_and_clarity_refinement()
|
|
_test_deck_equipping_and_switching()
|
|
_test_active_bonuses_and_duration_decay()
|
|
_finish()
|
|
|
|
func _test_stone_creation_and_attributes() -> void:
|
|
print("\n--- Test 1: Stone Creation & 40250 Attribute Scaling ---")
|
|
# Diamond: Rough, Matt, +0
|
|
var diamond := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.DIAMOND, 0, 0, 0)
|
|
var attrs: Dictionary = diamond["attributes"]
|
|
_assert(attrs["int_bonus"] == 5, "Diamond +0 int_bonus is 5")
|
|
_assert(attrs["magic_defense"] == 2, "Diamond +0 magic_defense is 2")
|
|
|
|
# Ruby: Legendary (Grade 4), Excellent (Clarity 4), +6 Refine
|
|
var ruby := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY, 4, 4, 6)
|
|
attrs = ruby["attributes"]
|
|
# str_bonus: 5 + (4*3) + (4*2) + 6 = 31
|
|
_assert(attrs["str_bonus"] == 31, "Legendary Ruby STR bonus is 31")
|
|
# att_grade: 20 + (4*15) + (4*10) + (6*5) = 20 + 60 + 40 + 30 = 150
|
|
_assert(attrs["att_grade"] == 150, "Legendary Ruby Attack Power bonus is 150")
|
|
|
|
# Jade: Max HP
|
|
var jade := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.JADE, 4, 0, 0)
|
|
_assert(jade["attributes"]["max_hp"] == 1300, "Legendary Jade Max HP is 1300")
|
|
|
|
func _test_grade_and_clarity_refinement() -> void:
|
|
print("\n--- Test 2: Grade & Clarity Refinement ---")
|
|
var r1 := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY, DragonSoulSystem.Grade.ROUGH, 0)
|
|
var r2 := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY, DragonSoulSystem.Grade.ROUGH, 0)
|
|
var d1 := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.DIAMOND, DragonSoulSystem.Grade.ROUGH, 0)
|
|
|
|
# Mismatched type rejected
|
|
var res = DragonSoulSystem.refine_grade(r1, d1)
|
|
_assert(res["ok"] == false and res["reason"] == "MISMATCHED_STONES", "Cannot fuse Ruby with Diamond")
|
|
|
|
# Grade refine success
|
|
res = DragonSoulSystem.refine_grade(r1, r2, true)
|
|
_assert(res["ok"] == true and res["success"] == true, "Ruby successfully upgraded to Cut grade")
|
|
_assert(res["stone"]["grade"] == DragonSoulSystem.Grade.CUT, "New stone grade is Cut (1)")
|
|
|
|
# Clarity refine success
|
|
var c1 := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY, DragonSoulSystem.Grade.CUT, DragonSoulSystem.Clarity.MATT)
|
|
var c2 := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY, DragonSoulSystem.Grade.CUT, DragonSoulSystem.Clarity.MATT)
|
|
res = DragonSoulSystem.refine_clarity(c1, c2, true)
|
|
_assert(res["ok"] == true and res["success"] == true, "Ruby clarity successfully upgraded to Clear")
|
|
_assert(res["stone"]["clarity"] == DragonSoulSystem.Clarity.CLEAR, "New stone clarity is Clear (1)")
|
|
|
|
func _test_deck_equipping_and_switching() -> void:
|
|
print("\n--- Test 3: Sky Deck & Earth Deck Equipping ---")
|
|
var dss := DragonSoulSystem.new()
|
|
var diamond := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.DIAMOND)
|
|
var ruby := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY)
|
|
|
|
# Equip in Sky Deck (0)
|
|
var res = dss.equip_stone(DragonSoulSystem.DECK_SKY, diamond)
|
|
_assert(res["ok"] == true and res["slot"] == 0, "Diamond equipped into Sky Deck slot 0")
|
|
_assert(dss.decks[DragonSoulSystem.DECK_SKY][0] != null, "Sky Deck slot 0 is filled")
|
|
|
|
res = dss.equip_stone(DragonSoulSystem.DECK_SKY, ruby)
|
|
_assert(res["ok"] == true and res["slot"] == 1, "Ruby equipped into Sky Deck slot 1")
|
|
|
|
# Unequip from Sky Deck
|
|
res = dss.unequip_stone(DragonSoulSystem.DECK_SKY, 0)
|
|
_assert(res["ok"] == true, "Diamond unequipped")
|
|
_assert(dss.decks[DragonSoulSystem.DECK_SKY][0] == null, "Sky Deck slot 0 is now empty")
|
|
|
|
func _test_active_bonuses_and_duration_decay() -> void:
|
|
print("\n--- Test 4: Active Deck Stat Injection & Duration Decay ---")
|
|
var dss := DragonSoulSystem.new()
|
|
var ruby := DragonSoulSystem.create_dragon_stone(DragonSoulSystem.DragonStoneType.RUBY, 4, 4, 6, 10.0) # 10s duration
|
|
dss.equip_stone(DragonSoulSystem.DECK_SKY, ruby)
|
|
|
|
# Initially inactive: 0 bonuses
|
|
var bonuses = dss.get_active_bonuses()
|
|
_assert(bonuses.is_empty(), "No bonuses when deck is inactive")
|
|
|
|
# Toggle Sky Deck on
|
|
var active = dss.toggle_deck(DragonSoulSystem.DECK_SKY)
|
|
_assert(active == true and dss.active_deck == DragonSoulSystem.DECK_SKY, "Sky Deck activated")
|
|
|
|
bonuses = dss.get_active_bonuses()
|
|
_assert(bonuses["str_bonus"] == 31, "Active deck injects +31 STR bonus")
|
|
_assert(bonuses["att_grade"] == 150, "Active deck injects +150 Attack Power")
|
|
|
|
# Update 5s -> still active
|
|
var expired = dss.update(5.0)
|
|
_assert(expired.is_empty(), "No stones expired after 5s")
|
|
_assert(dss.decks[DragonSoulSystem.DECK_SKY][1]["duration"] == 5.0, "5s duration remaining")
|
|
|
|
# Update 6s -> expires
|
|
expired = dss.update(6.0)
|
|
_assert(expired.size() == 1, "1 stone expired after duration reached 0")
|
|
bonuses = dss.get_active_bonuses()
|
|
_assert(bonuses.is_empty(), "Expired stones no longer provide stat bonuses")
|
|
|
|
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)
|