- 桥梁与静态物体高度采样修复: - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
100 lines
3.9 KiB
GDScript
100 lines
3.9 KiB
GDScript
# test_private_shop_bundle_parity.gd —— 验证方向 4:束发包袱皮与个人私有商店摆摊 40250 1:1 对齐
|
|
extends SceneTree
|
|
|
|
const PrivateShopSystem = preload("res://private_shop_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_private_shop_bundle_parity (Direction 4: Private Shop Bundle 1:1) ===")
|
|
test_bundle_item_check()
|
|
test_prerequisites()
|
|
test_sign_validation()
|
|
test_item_stocking()
|
|
test_shop_build_and_stall_vnum()
|
|
|
|
print("\n=== SUMMARY: %d passed, %d failed ===" % [_passed, _failed])
|
|
if _failed > 0:
|
|
printerr("TEST FAILED!")
|
|
quit(1)
|
|
else:
|
|
print("ALL TESTS PASSED!")
|
|
quit(0)
|
|
|
|
func test_bundle_item_check() -> void:
|
|
print("\n--- Test 1: Bundle Item Vnum Check (50200) ---")
|
|
_assert(PrivateShopSystem.is_bundle(50200), "50200 is Bundle (ITEM_BUNDLE)")
|
|
_assert(not PrivateShopSystem.is_bundle(10), "Sword is not a bundle")
|
|
_assert(not PrivateShopSystem.is_bundle(27001), "Potion is not a bundle")
|
|
|
|
func test_prerequisites() -> void:
|
|
print("\n--- Test 2: Shop Opening Prerequisites (Battle, Mount, Death) ---")
|
|
# Fails when dead
|
|
var r_dead := PrivateShopSystem.can_open_private_shop(false, false, true)
|
|
_assert(not r_dead.ok and r_dead.code == "CANNOT_DEAD", "Rejected while dead")
|
|
|
|
# Fails when mounted
|
|
var r_mount := PrivateShopSystem.can_open_private_shop(false, true, false)
|
|
_assert(not r_mount.ok and r_mount.code == "CANNOT_MOUNTED", "Rejected while mounted")
|
|
|
|
# Fails when fighting
|
|
var r_fight := PrivateShopSystem.can_open_private_shop(true, false, false)
|
|
_assert(not r_fight.ok and r_fight.code == "CANNOT_FIGHTING", "Rejected while in battle")
|
|
|
|
# Succeeds when peaceful
|
|
var r_ok := PrivateShopSystem.can_open_private_shop(false, false, false)
|
|
_assert(r_ok.ok, "Can open shop when peaceful on foot")
|
|
|
|
func test_sign_validation() -> void:
|
|
print("\n--- Test 3: Shop Sign Text Validation ---")
|
|
var v_empty := PrivateShopSystem.validate_sign("")
|
|
_assert(not v_empty.ok and v_empty.code == "SIGN_EMPTY", "Empty sign rejected")
|
|
|
|
var long_sign := "这是一个超级无敌非常长长长长长长长长长长长长长长长长的名字" # > 25 chars
|
|
var v_long := PrivateShopSystem.validate_sign(long_sign)
|
|
_assert(not v_long.ok and v_long.code == "SIGN_TOO_LONG", "Sign > 25 chars rejected")
|
|
|
|
var v_valid := PrivateShopSystem.validate_sign("神装特价店")
|
|
_assert(v_valid.ok and v_valid.sign == "神装特价店", "Valid sign accepted")
|
|
|
|
func test_item_stocking() -> void:
|
|
print("\n--- Test 4: Staging Items with Price into Stock ---")
|
|
var stock := {}
|
|
var sword_item := {"cell": 0, "vnum": 10, "count": 1}
|
|
|
|
# Zero/negative price rejected
|
|
var r_zero := PrivateShopSystem.add_item_to_stock(stock, 0, sword_item, 0)
|
|
_assert(not r_zero.ok and r_zero.code == "INVALID_PRICE", "Zero price rejected")
|
|
|
|
# Valid add
|
|
var r_add := PrivateShopSystem.add_item_to_stock(stock, 0, sword_item, 5000)
|
|
_assert(r_add.ok and stock.has(0), "Item added to stock slot 0")
|
|
_assert(stock[0].price == 5000, "Price set to 5000 gold")
|
|
|
|
# Remove from stock
|
|
_assert(PrivateShopSystem.remove_item_from_stock(stock, 0), "Item removed from stock slot 0")
|
|
_assert(not stock.has(0), "Stock slot 0 is now empty")
|
|
|
|
func test_shop_build_and_stall_vnum() -> void:
|
|
print("\n--- Test 5: Shop Build & Stall Model (Vnum 30000) ---")
|
|
var stock := {
|
|
0: {"cell": 0, "vnum": 10, "count": 1, "price": 5000}
|
|
}
|
|
var stall_pos := Vector3(120, 0, 80)
|
|
|
|
var res_build := PrivateShopSystem.build_private_shop("平民杂货摊", stock, stall_pos)
|
|
_assert(res_build.ok and res_build.code == "SHOP_OPENED", "Shop opened successfully")
|
|
_assert(res_build.stall_vnum == PrivateShopSystem.VNUM_SHOP_HOST_STALL,
|
|
"Stall model is 30000 (SHOP_HOST)")
|
|
_assert(res_build.items_count == 1, "Staged item count is 1")
|
|
_assert(res_build.position == stall_pos, "Stall spawned at current position")
|