Files
mtgodot-poc/project/equipment_inspect_system.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

135 lines
4.0 KiB
GDScript

# equipment_inspect_system.gd —— 40250 装备透视检视与 GM 监察系统 1:1
# 严格对照:
# Client/Eternexus/root/uiequipmentdialog.py (EquipmentDialog)
# ClientVS22/source/UserInterface/PythonPlayer.cpp
# metin2/src/server/game/src/cmd_gm.cpp (do_view_equip)
extends RefCounted
# 官方装备槽位常量定义 (1:1 ClientVS22/source/UserInterface/GameType.h)
const WEAR_BODY := 0 # 铠甲
const WEAR_HEAD := 1 # 头盔
const WEAR_FOOTS := 2 # 鞋子
const WEAR_WRIST := 3 # 手镯
const WEAR_WEAPON := 4 # 武器
const WEAR_NECK := 5 # 项链
const WEAR_EAR := 6 # 耳环
const WEAR_SHIELD := 10 # 盾牌
const WEAR_COSTUME_BODY := 19 # 时装身体
const WEAR_COSTUME_HAIR := 20 # 时装发型
const WEAR_COSTUME_WEAPON := 21 # 时装武器
const SLOT_NAMES := {
WEAR_BODY: "铠甲",
WEAR_HEAD: "头盔",
WEAR_FOOTS: "鞋子",
WEAR_WRIST: "手镯",
WEAR_WEAPON: "武器",
WEAR_NECK: "项链",
WEAR_EAR: "耳环",
WEAR_SHIELD: "盾牌",
WEAR_COSTUME_BODY: "时装身体",
WEAR_COSTUME_HAIR: "时装发型",
WEAR_COSTUME_WEAPON: "时装武器",
}
# 窗口状态
var is_open: bool = false
var inspected_vid: int = 0
var inspected_name: String = ""
var equipment_slots: Dictionary = {} # slot_idx -> item_data Dictionary
func _init() -> void:
is_open = false
inspected_vid = 0
inspected_name = ""
equipment_slots.clear()
# 1. 打开检视窗口 (1:1 EquipmentDialog.Open)
# caller_is_gm: GM 可强制穿透隐私限制
func open_dialog(
target_vid: int,
target_name: String,
target_equip_dict: Dictionary,
allow_inspect: bool = true,
caller_is_gm: bool = false
) -> Dictionary:
var res := { "success": false, "error_code": "OK", "message": "" }
if not allow_inspect and not caller_is_gm:
res["error_code"] = "INSPECT_FORBIDDEN"
res["message"] = "目标玩家设置了隐私保护,禁止查看装备。"
return res
inspected_vid = target_vid
inspected_name = target_name
equipment_slots.clear()
# 载入目标玩家装备数据
for slot_key in target_equip_dict:
var slot_idx: int = int(slot_key)
var it: Dictionary = target_equip_dict[slot_key]
equipment_slots[slot_idx] = _normalize_item_data(it)
is_open = true
res["success"] = true
res["message"] = "成功载入 %s 的装备信息。" % target_name
return res
# 2. 关闭检视窗口 (EquipmentDialog.Close)
func close_dialog() -> void:
is_open = false
inspected_vid = 0
inspected_name = ""
equipment_slots.clear()
# 3. 规范化装备项数据 (确保含有 3 宝石孔与 7 词条结构)
func _normalize_item_data(it: Dictionary) -> Dictionary:
var item_copy := it.duplicate(true)
var sockets: Array = item_copy.get("sockets", [0, 0, 0])
while sockets.size() < 3:
sockets.append(0)
item_copy["sockets"] = sockets
var attrs: Array = item_copy.get("attributes", [])
item_copy["attributes"] = attrs
return item_copy
# 4. 获取指定槽位装备
func get_slot_item(slot_idx: int) -> Dictionary:
if not is_open:
return {}
return equipment_slots.get(slot_idx, {})
# 5. 悬停生成 Tooltip 详情 (1:1 EquipmentDialog.OverInItem)
func build_slot_tooltip(slot_idx: int) -> String:
if not is_open:
return ""
if not equipment_slots.has(slot_idx):
var slot_name: String = SLOT_NAMES.get(slot_idx, "未知槽位")
return "[%s] 未佩戴装备" % slot_name
var it: Dictionary = equipment_slots[slot_idx]
var lines: Array = []
var title_name: String = it.get("name", "Unknown Item")
var vnum: int = it.get("vnum", 0)
lines.append("=== %s (Vnum: %d) ===" % [title_name, vnum])
lines.append("部位: %s" % SLOT_NAMES.get(slot_idx, "特殊部位"))
# 宝石孔位
var sockets: Array = it.get("sockets", [])
for i in range(sockets.size()):
var s: int = sockets[i]
if s > 0:
lines.append("孔位 %d: 镶嵌宝石 [Vnum %d]" % [i + 1, s])
elif s == 1:
lines.append("孔位 %d: 空孔" % [i + 1])
# 附加属性 (1~7 词条)
var attrs: Array = it.get("attributes", [])
for a in attrs:
lines.append("附加属性: 属性 %d +%d" % [a.get("type", 0), a.get("value", 0)])
return ("\n").join(lines)