Files
mtgodot-poc/project/test_jewelry_socket_parity.gd
T
shenandshen 66d217b313 feat(client): 完成40250客户端核心功能1:1对齐与桥梁高度采样修复
- 桥梁与静态物体高度采样修复:
  - 严格对齐 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 客户端对拍缺陷发现与修复工程指南
2026-09-19 08:51:25 -07:00

131 lines
5.3 KiB
GDScript

# test_jewelry_socket_parity.gd —— 40250 首饰打孔与精炼宝石镶嵌 1:1 纯净回归测试套件
extends SceneTree
const JewelrySocketSystem = preload("res://jewelry_socket_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_jewelry_socket_parity (Direction 3: Jewelry Sockets 1:1) ===")
_test_accessory_validation_and_diamond()
_test_socket_drilling_progression()
_test_refined_gem_insertion_and_bonuses()
_test_endurance_decay_and_expiration()
_finish()
func _test_accessory_validation_and_diamond() -> void:
print("\n--- Test 1: Accessory Validation & Diamond Check ---")
var sword := {"vnum": 10} # Weapon
var armor := {"vnum": 11200} # Armor
var ebony_earrings := {"vnum": 17109} # Earrings (17xxx)
var diamond := {"vnum": 50621} # Refined Diamond
var fake_stone := {"vnum": 28030} # Metin stone
# Non-accessory rejected
_assert(JewelrySocketSystem.is_accessory(sword) == false, "Sword is not an accessory")
_assert(JewelrySocketSystem.is_accessory(armor) == false, "Armor is not an accessory")
_assert(JewelrySocketSystem.is_accessory(ebony_earrings) == true, "Ebony Earrings is an accessory")
var res = JewelrySocketSystem.drill_socket(sword, diamond)
_assert(res["ok"] == false and res["reason"] == "NOT_ACCESSORY", "Cannot drill sockets on weapons")
# Non diamond rejected
res = JewelrySocketSystem.drill_socket(ebony_earrings, fake_stone)
_assert(res["ok"] == false and res["reason"] == "NOT_DIAMOND", "Cannot drill without refined diamond (50621)")
func _test_socket_drilling_progression() -> void:
print("\n--- Test 2: Socket Drilling Progression (1~3 Sockets) ---")
var necklace := {"vnum": 16109, "socket_count": 0}
var diamond := {"vnum": 50621}
# Drill 1st socket
var res = JewelrySocketSystem.drill_socket(necklace, diamond, true)
_assert(res["ok"] == true and res["socket_count"] == 1, "1st socket drilled successfully")
# Drill 2nd socket
res = JewelrySocketSystem.drill_socket(necklace, diamond, true)
_assert(res["ok"] == true and res["socket_count"] == 2, "2nd socket drilled successfully")
# Drill 3rd socket
res = JewelrySocketSystem.drill_socket(necklace, diamond, true)
_assert(res["ok"] == true and res["socket_count"] == 3, "3rd socket drilled successfully")
# 4th socket attempt rejected (MAX_SOCKETS = 3)
res = JewelrySocketSystem.drill_socket(necklace, diamond, true)
_assert(res["ok"] == false and res["reason"] == "SOCKETS_FULL", "Cannot drill more than 3 sockets")
func _test_refined_gem_insertion_and_bonuses() -> void:
print("\n--- Test 3: Refined Gem Insertion & Tiered Bonuses ---")
var bracelet := {
"vnum": 14109, # White Gold Bracelet (14xxx)
"socket_count": 3,
"sockets": [0, 0, 0],
"gem_times": [0.0, 0.0, 0.0]
}
var white_gold_gem := {"vnum": 50630} # White Gold (50630)
var wrong_gem := {"vnum": 50628} # Ebony (50628)
# Mismatched gem rejected when required
var res = JewelrySocketSystem.insert_gem(bracelet, wrong_gem, 50630)
_assert(res["ok"] == false and res["reason"] == "GEM_MISMATCH", "Mismatched gem rejected")
# Insert 1st gem (+10%)
res = JewelrySocketSystem.insert_gem(bracelet, white_gold_gem, 50630)
_assert(res["ok"] == true and res["slot"] == 0, "1st gem inserted into socket 0")
_assert(is_equal_approx(float(res["total_bonus_pct"]), 0.10), "1st gem bonus: +10%")
# Insert 2nd gem (+10%, total +20%)
res = JewelrySocketSystem.insert_gem(bracelet, white_gold_gem, 50630)
_assert(res["ok"] == true and res["slot"] == 1, "2nd gem inserted into socket 1")
_assert(is_equal_approx(float(res["total_bonus_pct"]), 0.20), "2nd gem bonus: total +20%")
# Insert 3rd gem (+20%, total +40%)
res = JewelrySocketSystem.insert_gem(bracelet, white_gold_gem, 50630)
_assert(res["ok"] == true and res["slot"] == 2, "3rd gem inserted into socket 2")
_assert(is_equal_approx(float(res["total_bonus_pct"]), 0.40), "3rd gem bonus: total +40%")
# Full sockets reject further insertion
res = JewelrySocketSystem.insert_gem(bracelet, white_gold_gem, 50630)
_assert(res["ok"] == false and res["reason"] == "NO_EMPTY_SOCKET", "Cannot insert into full sockets")
func _test_endurance_decay_and_expiration() -> void:
print("\n--- Test 4: Endurance Decay & Gem Expiration ---")
var item := {
"vnum": 17109,
"socket_count": 1,
"sockets": [50628, 0, 0],
"gem_times": [10.0, 0.0, 0.0] # 10 seconds remaining
}
_assert(JewelrySocketSystem.count_active_gems(item) == 1, "Initially 1 active gem")
# Decay by 5 seconds
var res = JewelrySocketSystem.update_gem_endurance(item, 5.0)
_assert(res["active_gems"] == 1, "Still 1 active gem after 5s decay")
_assert(res["expired"].is_empty(), "No gems expired yet")
# Decay by another 6 seconds -> should expire
res = JewelrySocketSystem.update_gem_endurance(item, 6.0)
_assert(res["active_gems"] == 0, "0 active gems after expiration")
_assert(res["expired"] == [50628], "Gem 50628 expired and recorded")
_assert(item["sockets"][0] == 0, "Socket 0 cleared and available for re-insertion")
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)