- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
174 lines
7.3 KiB
GDScript
174 lines
7.3 KiB
GDScript
# test_item_enchant_manager_parity.gd —— 40250 装备附魔洗炼与稀有词条重铸 1:1 回归测试套件
|
|
extends SceneTree
|
|
|
|
const ItemEnchantSystem = preload("res://item_enchant_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_item_enchant_manager_parity (Direction 3: Item Enchant & Rare Reforge 1:1) ===")
|
|
_test_scroll_and_item_compatibility()
|
|
_test_add_1_to_4_attributes()
|
|
_test_blessing_marble_5th_attribute()
|
|
_test_change_attributes()
|
|
_test_rare_6th_and_7th_attributes()
|
|
_finish()
|
|
|
|
func _test_scroll_and_item_compatibility() -> void:
|
|
print("\n--- Test 1: Scroll & Equipment Compatibility ---")
|
|
_assert(ItemEnchantSystem.is_enchant_scroll(71085), "71085 is enchant scroll")
|
|
_assert(ItemEnchantSystem.is_enchant_scroll(71084), "71084 is enchant scroll")
|
|
_assert(ItemEnchantSystem.is_enchant_scroll(70024), "70024 is enchant scroll")
|
|
_assert(ItemEnchantSystem.is_enchant_scroll(71151), "71151 is enchant scroll")
|
|
_assert(ItemEnchantSystem.is_enchant_scroll(71152), "71152 is enchant scroll")
|
|
_assert(not ItemEnchantSystem.is_enchant_scroll(27001), "Potion is not enchant scroll")
|
|
|
|
var sword := {"vnum": 10, "type": 1, "attrs": []}
|
|
var arrow := {"vnum": 8000, "type": 1, "attrs": []}
|
|
var locked_armor := {"vnum": 11299, "type": 2, "is_locked": true, "attrs": []}
|
|
|
|
_assert(ItemEnchantSystem.is_enchantable_item(sword), "Sword is enchantable")
|
|
_assert(not ItemEnchantSystem.is_enchantable_item(arrow), "Arrow (8000) cannot be enchanted")
|
|
_assert(not ItemEnchantSystem.is_enchantable_item(locked_armor), "Locked armor is protected from enchanting")
|
|
|
|
func _test_add_1_to_4_attributes() -> void:
|
|
print("\n--- Test 2: Add 1st~4th Attributes (71085) ---")
|
|
var sys := ItemEnchantSystem.new()
|
|
var inv: Array = [
|
|
{"vnum": ItemEnchantSystem.VNUM_ATTR_ADD, "name": "添加属性秘籍", "count": 10},
|
|
{"vnum": 10, "name": "巨剑+9", "type": 1, "attrs": []}
|
|
]
|
|
|
|
var sig_data := {"fired": false, "slot": -1, "success": false}
|
|
sys.enchant_applied.connect(func(slot: int, _svnum: int, succ: bool, _attrs: Array):
|
|
sig_data["fired"] = true
|
|
sig_data["slot"] = slot
|
|
sig_data["success"] = succ
|
|
)
|
|
|
|
# Add 1st attribute (force_success = true)
|
|
var res1 = sys.apply_scroll(0, 1, inv, true)
|
|
_assert(res1["ok"] == true and res1["success"] == true, "1st attribute added")
|
|
_assert(inv[1]["attrs"].size() == 1, "Sword has 1 attribute")
|
|
_assert(inv[0]["count"] == 9, "Scroll count decreased 10 -> 9")
|
|
_assert(sig_data["fired"] == true and sig_data["slot"] == 1, "enchant_applied signal emitted")
|
|
|
|
# Add 2nd, 3rd, 4th attributes
|
|
sys.apply_scroll(0, 1, inv, true)
|
|
sys.apply_scroll(0, 1, inv, true)
|
|
sys.apply_scroll(0, 1, inv, true)
|
|
_assert(inv[1]["attrs"].size() == 4, "Sword has 4 attributes")
|
|
_assert(inv[0]["count"] == 6, "Scroll count is now 6")
|
|
|
|
# 5th attempt with 71085 must be rejected
|
|
var res5 = sys.apply_scroll(0, 1, inv, true)
|
|
_assert(res5["ok"] == false and res5["reason"] == "MAX_BASE_ATTRS_REACHED", "5th attempt rejected by 71085")
|
|
_assert(inv[0]["count"] == 6, "Scroll count NOT consumed on failure")
|
|
|
|
func _test_blessing_marble_5th_attribute() -> void:
|
|
print("\n--- Test 3: Blessing Marble 5th Attribute (70024) ---")
|
|
var sys := ItemEnchantSystem.new()
|
|
var inv: Array = [
|
|
{"vnum": ItemEnchantSystem.VNUM_BLESSING_MARBLE, "name": "祝福宝珠", "count": 2},
|
|
{"vnum": 10, "name": "巨剑+9", "type": 1, "attrs": [{"type": 1, "name": "最大生命", "value": 2000}]} # only 1 attr
|
|
]
|
|
|
|
# Using on item with < 4 attrs must fail
|
|
var fail_res = sys.apply_scroll(0, 1, inv, true)
|
|
_assert(fail_res["ok"] == false and fail_res["reason"] == "NEED_4_ATTRS_FIRST", "Blessing marble requires 4 attrs first")
|
|
|
|
# Fill up to 4 attrs
|
|
inv[1]["attrs"] = [
|
|
{"type": 1, "name": "HP", "value": 2000},
|
|
{"type": 5, "name": "STR", "value": 12},
|
|
{"type": 15, "name": "Crit", "value": 10},
|
|
{"type": 16, "name": "Pen", "value": 10}
|
|
]
|
|
|
|
# Now use blessing marble
|
|
var res5 = sys.apply_scroll(0, 1, inv, true)
|
|
_assert(res5["ok"] == true and res5["success"] == true, "5th attribute added by Blessing Marble")
|
|
_assert(inv[1]["attrs"].size() == 5, "Item now has exactly 5 attributes")
|
|
_assert(inv[0]["count"] == 1, "Marble consumed (2 -> 1)")
|
|
|
|
# 6th attempt with blessing marble must be rejected
|
|
var res6 = sys.apply_scroll(0, 1, inv, true)
|
|
_assert(res6["ok"] == false and res6["reason"] == "ALREADY_HAS_5_ATTRS", "Blessing marble rejected when 5 attrs exist")
|
|
|
|
func _test_change_attributes() -> void:
|
|
print("\n--- Test 4: Change All Attributes (71084) ---")
|
|
var sys := ItemEnchantSystem.new()
|
|
var old_attrs: Array = [
|
|
{"type": 1, "name": "HP", "value": 500},
|
|
{"type": 2, "name": "SP", "value": 100},
|
|
{"type": 7, "name": "AtkSpeed", "value": 2}
|
|
]
|
|
var inv: Array = [
|
|
{"vnum": ItemEnchantSystem.VNUM_ATTR_CHANGE, "name": "属性改变秘籍", "count": 1},
|
|
{"vnum": 10, "name": "巨剑+9", "type": 1, "attrs": old_attrs.duplicate(true)}
|
|
]
|
|
|
|
var res = sys.apply_scroll(0, 1, inv)
|
|
_assert(res["ok"] == true and res["success"] == true, "Attributes rerolled")
|
|
_assert(inv[1]["attrs"].size() == 3, "Still has exactly 3 attributes")
|
|
_assert(inv[0] == null, "Single scroll consumed to null")
|
|
|
|
func _test_rare_6th_and_7th_attributes() -> void:
|
|
print("\n--- Test 5: 6th & 7th Rare Attributes (71151 / 71152) ---")
|
|
var sys := ItemEnchantSystem.new()
|
|
var inv: Array = [
|
|
{"vnum": ItemEnchantSystem.VNUM_RARE_ADD, "name": "稀有属性秘籍", "count": 3},
|
|
{"vnum": ItemEnchantSystem.VNUM_RARE_CHANGE, "name": "稀有属性改变", "count": 1},
|
|
{"vnum": 10, "name": "巨剑+9", "type": 1, "attrs": [{"type": 1, "name": "HP", "value": 2000}], "rare_attrs": []}
|
|
]
|
|
|
|
var rare_sig := {"fired": false, "rares": []}
|
|
sys.rare_enchant_applied.connect(func(_slot: int, _succ: bool, rares: Array):
|
|
rare_sig["fired"] = true
|
|
rare_sig["rares"] = rares
|
|
)
|
|
|
|
# Add 6th attribute (1st rare)
|
|
var r1 = sys.apply_scroll(0, 2, inv, true)
|
|
_assert(r1["ok"] == true and r1["success"] == true, "6th attribute (1st rare) added")
|
|
_assert(inv[2]["rare_attrs"].size() == 1, "1 rare attribute present")
|
|
_assert(inv[2]["attrs"].size() == 1, "Base attrs untouched")
|
|
_assert(rare_sig["fired"] == true, "rare_enchant_applied signal emitted")
|
|
|
|
# Add 7th attribute (2nd rare)
|
|
var r2 = sys.apply_scroll(0, 2, inv, true)
|
|
_assert(r2["ok"] == true and r2["success"] == true, "7th attribute (2nd rare) added")
|
|
_assert(inv[2]["rare_attrs"].size() == 2, "2 rare attributes present")
|
|
|
|
# 3rd rare must be rejected
|
|
var r3 = sys.apply_scroll(0, 2, inv, true)
|
|
_assert(r3["ok"] == false and r3["reason"] == "MAX_RARE_ATTRS", "3rd rare rejected")
|
|
|
|
# Change rare attributes (71152)
|
|
var rc = sys.apply_scroll(1, 2, inv)
|
|
_assert(rc["ok"] == true and rc["success"] == true, "Rare attributes rerolled")
|
|
_assert(inv[2]["rare_attrs"].size() == 2, "2 rare attributes preserved after reroll")
|
|
_assert(inv[2]["attrs"].size() == 1, "Base attrs remain intact")
|
|
_assert(inv[1] == null, "71152 scroll consumed")
|
|
|
|
func _finish() -> void:
|
|
print("\n==========================================")
|
|
print("Item Enchant Manager Parity Tests Finished:")
|
|
print("Passed: %d, Failed: %d" % [_passed, _failed])
|
|
print("==========================================")
|
|
if _failed > 0:
|
|
printerr("FAILED: Some tests did not pass.")
|
|
quit(1)
|
|
else:
|
|
print("SUCCESS: All Item Enchant Manager parity tests passed!")
|
|
quit(0)
|