- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
111 lines
4.1 KiB
GDScript
111 lines
4.1 KiB
GDScript
# test_monster_card_parity.gd —— 40250 怪物图鉴与百科系统 1:1 纯净回归测试套件
|
|
extends SceneTree
|
|
|
|
const MonsterCardSystem = preload("res://monster_card_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_monster_card_parity (Direction 4: Monster Card Bestiary 1:1) ===")
|
|
_test_card_registration_and_discovery()
|
|
_test_zone_completion_and_permanent_bonuses()
|
|
_test_multiple_zone_bonuses_stacking()
|
|
_finish()
|
|
|
|
func _test_card_registration_and_discovery() -> void:
|
|
print("\n--- Test 1: Card Registration & Bestiary Entry Discovery ---")
|
|
var mcs := MonsterCardSystem.new()
|
|
|
|
# 1. Invalid card vnum
|
|
var r_bad = mcs.register_card(99999)
|
|
_assert(r_bad["ok"] == false and r_bad["reason"] == "INVALID_CARD", "Invalid card vnum rejected")
|
|
|
|
# 2. Query undiscovered monster 101 (野狼)
|
|
var undiscovered = mcs.get_monster_entry(101)
|
|
_assert(undiscovered["is_unlocked"] == false, "Entry 101 initially locked")
|
|
_assert(undiscovered["name"] == "???", "Name is hidden as '???'")
|
|
|
|
# 3. Register Card 70201 (野狼卡片)
|
|
var card_signal := {"fired": false, "vnum": 0, "name": ""}
|
|
mcs.card_collected.connect(func(v: int, n: String, _c: int):
|
|
card_signal["fired"] = true
|
|
card_signal["vnum"] = v
|
|
card_signal["name"] = n
|
|
)
|
|
|
|
var r_reg = mcs.register_card(70201)
|
|
_assert(r_reg["ok"] == true, "Card 70201 registered successfully")
|
|
_assert(card_signal["fired"] == true and card_signal["vnum"] == 101, "card_collected signal fired for 101")
|
|
_assert(mcs.collected_cards[101] == 1, "Collected 1 Wolf card")
|
|
|
|
# 4. Query discovered monster 101
|
|
var discovered = mcs.get_monster_entry(101)
|
|
_assert(discovered["is_unlocked"] == true, "Entry 101 is now unlocked")
|
|
_assert(discovered["name"] == "野狼", "Name revealed as '野狼'")
|
|
_assert(discovered["level"] == 1, "Level revealed as 1")
|
|
_assert(discovered["drops"].size() >= 2, "Drops revealed")
|
|
|
|
func _test_zone_completion_and_permanent_bonuses() -> void:
|
|
print("\n--- Test 2: Zone Completion & Passive Stat Activation ---")
|
|
var mcs := MonsterCardSystem.new()
|
|
|
|
var zone_signal := {"fired": false, "zname": "", "bonus": {}}
|
|
mcs.zone_completed.connect(func(zn: String, b: Dictionary):
|
|
zone_signal["fired"] = true
|
|
zone_signal["zname"] = zn
|
|
zone_signal["bonus"] = b
|
|
)
|
|
|
|
# Register Wolf (101) -> Village has 2 monsters, not complete yet
|
|
mcs.register_card(70201)
|
|
_assert(zone_signal["fired"] == false, "Village not complete with only 1/2 monsters")
|
|
_assert(mcs.get_active_collection_bonuses().is_empty(), "No bonuses active yet")
|
|
|
|
# Register White Oath (391, card 70202) -> Completes Village!
|
|
var r2 = mcs.register_card(70202)
|
|
_assert(r2["zone_completed"] == true, "Village zone completed")
|
|
_assert(zone_signal["fired"] == true and zone_signal["zname"] == "新手原野", "zone_completed signal fired")
|
|
_assert(zone_signal["bonus"]["max_hp"] == 300, "Village grants +300 Max HP")
|
|
|
|
var bonuses = mcs.get_active_collection_bonuses()
|
|
_assert(bonuses["max_hp"] == 300, "Active collection bonuses contain +300 Max HP")
|
|
|
|
func _test_multiple_zone_bonuses_stacking() -> void:
|
|
print("\n--- Test 3: Multi-Zone Stacking (Village + Desert + Catacomb) ---")
|
|
var mcs := MonsterCardSystem.new()
|
|
|
|
# Complete Village (+300 HP)
|
|
mcs.register_card(70201)
|
|
mcs.register_card(70202)
|
|
|
|
# Complete Desert (+3% Monster Dmg)
|
|
mcs.register_card(70203) # 2108 沙漠强盗
|
|
mcs.register_card(70204) # 2191 巨型沙漠龟
|
|
|
|
# Complete Catacomb (+50 DEF)
|
|
mcs.register_card(70205) # 2597 塔耳塔洛斯
|
|
mcs.register_card(70206) # 2598 冥王阿兹瑞尔
|
|
|
|
var all_bonuses = mcs.get_active_collection_bonuses()
|
|
_assert(all_bonuses["max_hp"] == 300, "Max HP +300 stacked")
|
|
_assert(all_bonuses["monster_dmg_pct"] == 3, "Monster Dmg +3% stacked")
|
|
_assert(all_bonuses["def"] == 50, "DEF +50 stacked")
|
|
|
|
func _finish() -> void:
|
|
print("\n==========================================")
|
|
print("Monster Card Parity Test Results: %d Passed, %d Failed" % [_passed, _failed])
|
|
print("==========================================")
|
|
if _failed > 0:
|
|
quit(1)
|
|
else:
|
|
quit(0)
|