# wardrobe_transmog_system.gd —— Metin2 40250 装备外观幻化重塑与试衣间系统 1:1 # 对照 40250 服务端 item_transmutation.cpp, char_item.cpp class_name WardrobeTransmogSystem extends RefCounted signal item_transmuted(target_slot: int, target_name: String, new_look_vnum: int, new_look_name: String) signal transmutation_reverted(target_slot: int, item_name: String) const VNUM_TRANSMOG_SCROLL := 72301 # 幻化秘籍 const VNUM_REVERT_SCROLL := 72302 # 幻化还原秘籍 const TRANSMOG_COST_GOLD := 10000000 # 1000 万金币 # 装备大类 const TYPE_WEAPON := 1 const TYPE_ARMOR := 2 const TYPE_COSTUME := 28 # 试衣间预览外观效果 (不消耗物品) func preview_transmog(target_item: Dictionary, skin_item: Dictionary) -> Dictionary: var val = _validate_compatibility(target_item, skin_item) if not val["ok"]: return val return { "ok": true, "base_vnum": target_item.get("vnum", 0), "base_name": target_item.get("name", "神装"), "preview_vnum": skin_item.get("vnum", 0), "preview_name": skin_item.get("name", "幻化外观"), "msg": "试衣间预览生成完毕!" } # 执行幻化外观重塑 func apply_transmutation(scroll_slot: int, target_slot: int, skin_slot: int, inventory: Array, player_data: Dictionary) -> Dictionary: if scroll_slot < 0 or scroll_slot >= inventory.size() or inventory[scroll_slot] == null: return {"ok": false, "reason": "INVALID_SCROLL_SLOT"} if target_slot < 0 or target_slot >= inventory.size() or inventory[target_slot] == null: return {"ok": false, "reason": "INVALID_TARGET_SLOT"} if skin_slot < 0 or skin_slot >= inventory.size() or inventory[skin_slot] == null: return {"ok": false, "reason": "INVALID_SKIN_SLOT"} if target_slot == skin_slot: return {"ok": false, "reason": "SAME_SLOT", "msg": "目标装备与外观装备不能为同一格子!"} var scroll = inventory[scroll_slot] if int(scroll.get("vnum", 0)) != VNUM_TRANSMOG_SCROLL: return {"ok": false, "reason": "NOT_A_TRANSMOG_SCROLL", "msg": "需要使用【幻化秘籍】(72301)!"} var target = inventory[target_slot] var skin = inventory[skin_slot] var comp_check = _validate_compatibility(target, skin) if not comp_check["ok"]: return comp_check var gold = int(player_data.get("gold", 0)) if gold < TRANSMOG_COST_GOLD: return {"ok": false, "reason": "NOT_ENOUGH_GOLD", "msg": "幻化所需金币不足!需要 10,000,000 金币。"} # 扣除金币与卷轴 player_data["gold"] = gold - TRANSMOG_COST_GOLD var sc_cnt = int(scroll.get("count", 1)) if sc_cnt > 1: scroll["count"] = sc_cnt - 1 else: inventory[scroll_slot] = null # 消耗外观材料装备 var skin_vnum = int(skin.get("vnum", 0)) var skin_name = skin.get("name", "外观") var sk_cnt = int(skin.get("count", 1)) if sk_cnt > 1: skin["count"] = sk_cnt - 1 else: inventory[skin_slot] = null # 赋予目标装备幻化外观 (所有基础属性、强化与灵石 100% 保留) target["transmog_vnum"] = skin_vnum target["transmog_name"] = skin_name var tname: String = target.get("name", "装备") item_transmuted.emit(target_slot, tname, skin_vnum, skin_name) return { "ok": true, "target_slot": target_slot, "target_name": tname, "transmog_vnum": skin_vnum, "transmog_name": skin_name, "msg": "幻化成功!【%s】披上了【%s】的华丽外观!" % [tname, skin_name] } # 还原装备原生外观 func revert_transmutation(scroll_slot: int, target_slot: int, inventory: Array) -> Dictionary: if scroll_slot < 0 or scroll_slot >= inventory.size() or inventory[scroll_slot] == null: return {"ok": false, "reason": "INVALID_SCROLL_SLOT"} if target_slot < 0 or target_slot >= inventory.size() or inventory[target_slot] == null: return {"ok": false, "reason": "INVALID_TARGET_SLOT"} var scroll = inventory[scroll_slot] if int(scroll.get("vnum", 0)) != VNUM_REVERT_SCROLL: return {"ok": false, "reason": "NOT_A_REVERT_SCROLL", "msg": "需要使用【幻化还原秘籍】(72302)!"} var target = inventory[target_slot] if not target.has("transmog_vnum") or int(target.get("transmog_vnum", 0)) == 0: return {"ok": false, "reason": "NOT_TRANSMUTED", "msg": "该装备未曾幻化,无需还原!"} # 消耗还原卷轴 var cnt = int(scroll.get("count", 1)) if cnt > 1: scroll["count"] = cnt - 1 else: inventory[scroll_slot] = null target.erase("transmog_vnum") target.erase("transmog_name") var tname: String = target.get("name", "装备") transmutation_reverted.emit(target_slot, tname) return { "ok": true, "target_slot": target_slot, "item_name": tname, "msg": "幻化已抹除!【%s】恢复为原生经典外观。" % tname } # 校验外观类型兼容性 func _validate_compatibility(target: Dictionary, skin: Dictionary) -> Dictionary: if target.is_empty() or skin.is_empty(): return {"ok": false, "reason": "EMPTY_DATA"} var t_type = int(target.get("type", 1)) var s_type = int(skin.get("type", 1)) # 武器只能幻化武器或时装武器外观;防具只能幻化防具或时装衣服 if t_type == TYPE_WEAPON: if s_type != TYPE_WEAPON and s_type != TYPE_COSTUME: return {"ok": false, "reason": "TYPE_MISMATCH", "msg": "武器只能幻化武器或时装外观!"} elif t_type == TYPE_ARMOR: if s_type != TYPE_ARMOR and s_type != TYPE_COSTUME: return {"ok": false, "reason": "TYPE_MISMATCH", "msg": "防具衣服只能幻化衣服防具外观!"} else: return {"ok": false, "reason": "UNSUPPORTED_TYPE", "msg": "该装备部位暂不支持幻化外观。"} return {"ok": true}