- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
147 lines
6.4 KiB
GDScript
147 lines
6.4 KiB
GDScript
# test_empire_kingdom_parity.gd —— 40250 三圣帝国归属与领地国运系统 1:1 回归测试套件
|
|
extends SceneTree
|
|
|
|
const EmpireKingdomSystem = preload("res://empire_kingdom_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_empire_kingdom_parity (Direction 4: Empire Kingdom & Territory 1:1) ===")
|
|
_test_empire_selection_and_blessings()
|
|
_test_territory_hostility_checks()
|
|
_test_tincture_of_empires_transfer()
|
|
_test_serialization()
|
|
_finish()
|
|
|
|
func _test_empire_selection_and_blessings() -> void:
|
|
print("\n--- Test 1: Empire Selection & Daily Blessing Prayer ---")
|
|
var sys := EmpireKingdomSystem.new()
|
|
_assert(sys.current_empire == EmpireKingdomSystem.EMPIRE_NONE, "Initially unaligned")
|
|
|
|
var sel_sig := {"fired": false, "id": 0, "name": ""}
|
|
sys.empire_selected.connect(func(i: int, n: String):
|
|
sel_sig["fired"] = true
|
|
sel_sig["id"] = i
|
|
sel_sig["name"] = n
|
|
)
|
|
|
|
# Select Shinsoo (Red Empire 1)
|
|
var sel_res = sys.select_empire(EmpireKingdomSystem.EMPIRE_SHINSOO)
|
|
_assert(sel_res["ok"] == true, "Selected Shinsoo")
|
|
_assert(sys.current_empire == EmpireKingdomSystem.EMPIRE_SHINSOO, "Current empire is Shinsoo")
|
|
_assert(sel_sig["fired"] == true, "empire_selected signal emitted")
|
|
_assert(sel_sig["name"] == "慎修帝国", "Name is 慎修帝国")
|
|
|
|
# Activate Daily Prayer
|
|
var player_stats := {"gold_bonus_pct": 0, "shop_discount_pct": 0}
|
|
var pray_res = sys.activate_empire_prayer(player_stats)
|
|
_assert(pray_res["ok"] == true, "Prayer activated")
|
|
_assert(sys.is_blessing_active == true, "Blessing flag is active")
|
|
_assert(player_stats["gold_bonus_pct"] == 10, "Shinsoo gold bonus +10% applied")
|
|
_assert(player_stats["shop_discount_pct"] == 5, "Shinsoo shop discount +5% applied")
|
|
|
|
# Advance time 86400s -> expiry
|
|
sys.update(86400.0, player_stats)
|
|
_assert(sys.is_blessing_active == false, "Blessing expired after 24h")
|
|
_assert(player_stats["gold_bonus_pct"] == 0, "Gold bonus cleanly deducted")
|
|
_assert(player_stats["shop_discount_pct"] == 0, "Shop discount cleanly deducted")
|
|
|
|
func _test_territory_hostility_checks() -> void:
|
|
print("\n--- Test 2: Territory Hostility & Intruder Checks ---")
|
|
var sys := EmpireKingdomSystem.new()
|
|
sys.select_empire(EmpireKingdomSystem.EMPIRE_SHINSOO)
|
|
|
|
# 1. Home territory (Yongan / Jayang)
|
|
var home_check = sys.check_territory("Yongan")
|
|
_assert(home_check["is_home"] == true, "Yongan is Shinsoo homeland")
|
|
_assert(home_check["is_hostile"] == false, "Homeland is not hostile")
|
|
_assert(home_check["relation"] == "homeland", "Relation is homeland")
|
|
|
|
# 2. Hostile enemy territory (Pyungmoo - Jinno homeland)
|
|
var enemy_check = sys.check_territory("Pyungmoo")
|
|
_assert(enemy_check["is_home"] == false, "Pyungmoo is not homeland")
|
|
_assert(enemy_check["is_hostile"] == true, "Pyungmoo is hostile foreign territory")
|
|
_assert(enemy_check["relation"] == "hostile_invasion", "Relation is hostile invasion")
|
|
|
|
# 3. Neutral territory (Desert)
|
|
var neutral_check = sys.check_territory("Desert")
|
|
_assert(neutral_check["is_home"] == false, "Desert is not homeland")
|
|
_assert(neutral_check["is_hostile"] == false, "Desert is not hostile")
|
|
_assert(neutral_check["relation"] == "neutral", "Relation is neutral territory")
|
|
|
|
func _test_tincture_of_empires_transfer() -> void:
|
|
print("\n--- Test 3: Tincture of Empires (71054) Nation Transfer ---")
|
|
var sys := EmpireKingdomSystem.new()
|
|
sys.select_empire(EmpireKingdomSystem.EMPIRE_SHINSOO)
|
|
var player_stats := {"gold_bonus_pct": 0, "shop_discount_pct": 0, "attack_bonus": 0, "monster_damage_pct": 0}
|
|
sys.activate_empire_prayer(player_stats)
|
|
|
|
var inv: Array = [
|
|
{"vnum": EmpireKingdomSystem.VNUM_TINCTURE_OF_EMPIRES, "name": "转国卷轴", "count": 1}
|
|
]
|
|
|
|
# 1. Transfer while in a guild -> rejected (40250 rule)
|
|
var res_guild = sys.change_empire(EmpireKingdomSystem.EMPIRE_JINNO, 0, inv, player_stats, true)
|
|
_assert(res_guild["ok"] == false, "Rejected: player is in a guild")
|
|
_assert(res_guild["reason"] == "MUST_LEAVE_GUILD", "Reason is MUST_LEAVE_GUILD")
|
|
|
|
# 2. Transfer to same empire -> rejected
|
|
var res_same = sys.change_empire(EmpireKingdomSystem.EMPIRE_SHINSOO, 0, inv, player_stats, false)
|
|
_assert(res_same["ok"] == false, "Rejected: cannot transfer to same empire")
|
|
_assert(res_same["reason"] == "CANNOT_CHANGE_TO_SAME_EMPIRE", "Reason is CANNOT_CHANGE_TO_SAME_EMPIRE")
|
|
|
|
# 3. Successful transfer to Jinno (Blue Empire 3)
|
|
var change_sig := {"fired": false, "old": 0, "new": 0}
|
|
sys.empire_changed.connect(func(o: int, n: int):
|
|
change_sig["fired"] = true
|
|
change_sig["old"] = o
|
|
change_sig["new"] = n
|
|
)
|
|
|
|
var res_succ = sys.change_empire(EmpireKingdomSystem.EMPIRE_JINNO, 0, inv, player_stats, false)
|
|
_assert(res_succ["ok"] == true, "Transferred to Jinno successfully")
|
|
_assert(sys.current_empire == EmpireKingdomSystem.EMPIRE_JINNO, "Current empire updated to Jinno")
|
|
_assert(inv[0] == null, "Tincture scroll consumed")
|
|
_assert(change_sig["fired"] == true, "empire_changed signal emitted")
|
|
_assert(change_sig["old"] == 1 and change_sig["new"] == 3, "Signal reported 1 -> 3")
|
|
_assert(player_stats["gold_bonus_pct"] == 0, "Previous Shinsoo blessing removed upon transfer")
|
|
|
|
# Activate Jinno Prayer
|
|
sys.activate_empire_prayer(player_stats)
|
|
_assert(player_stats["attack_bonus"] == 50, "Jinno attack bonus +50 applied")
|
|
_assert(player_stats["monster_damage_pct"] == 5, "Jinno monster damage +5% applied")
|
|
|
|
func _test_serialization() -> void:
|
|
print("\n--- Test 4: Serialization & Restoration ---")
|
|
var sys1 := EmpireKingdomSystem.new()
|
|
sys1.select_empire(EmpireKingdomSystem.EMPIRE_CHUNJO) # Yellow
|
|
var dummy_stats := {}
|
|
sys1.activate_empire_prayer(dummy_stats)
|
|
|
|
var data = sys1.serialize()
|
|
_assert(data["current_empire"] == EmpireKingdomSystem.EMPIRE_CHUNJO, "Serialized empire is Chunjo")
|
|
_assert(data["is_blessing_active"] == true, "Serialized blessing is active")
|
|
|
|
var sys2 := EmpireKingdomSystem.new()
|
|
sys2.deserialize(data)
|
|
_assert(sys2.current_empire == EmpireKingdomSystem.EMPIRE_CHUNJO, "Restored empire is Chunjo")
|
|
_assert(sys2.is_blessing_active == true, "Restored blessing active state")
|
|
|
|
func _finish() -> void:
|
|
print("\n=======================================================")
|
|
print("Empire Kingdom Parity Tests: %d Passed, %d Failed" % [_passed, _failed])
|
|
print("=======================================================\n")
|
|
if _failed > 0:
|
|
quit(1)
|
|
else:
|
|
quit(0)
|