# hair_dye_system.gd —— Metin2 40250 官方发型染色与漂白重塑系统 1:1 # 对照 40250 服务端 char_item.cpp:3540-3580 class_name HairDyeSystem extends RefCounted signal hair_dyed(color_id: int, color_name: String) signal hair_bleached() # 40250 官方染发道具 Vnum const VNUM_BLEACH := 70201 # 漂白水 (重置发色为 0, 清空冷却) const VNUM_WHITE_DYE := 70202 # 染发剂(白) -> color 1 const VNUM_BLONDE_DYE := 70203 # 染发剂(金) -> color 2 const VNUM_RED_DYE := 70204 # 染发剂(红) -> color 3 const VNUM_BROWN_DYE := 70205 # 染发剂(棕) -> color 4 const VNUM_BLACK_DYE := 70206 # 染发剂(黑) -> color 5 # 颜色映射字典 const HAIR_COLORS: Dictionary = { 0: "原色黑发(Default)", 1: "雪原纯白(White)", 2: "璀璨金黄(Blonde)", 3: "烈火赤红(Red)", 4: "深栗浅棕(Brown)", 5: "曜石纯黑(Black)" } var current_hair_color: int = 0 var current_hair_style_id: int = 0 # 0 为基础原生发型,>= 1001 为时装发型 var last_dye_level: int = 0 # 记录上次染发时的角色等级 # 获取颜色名称 static func get_color_name(color_id: int) -> String: return HAIR_COLORS.get(color_id, "未知发色") # 执行染发或漂白 (40250 char_item.cpp:3540-3580) func dye_hair(inventory: Array, slot_index: int, player_level: int) -> Dictionary: if slot_index < 0 or slot_index >= inventory.size() or inventory[slot_index] == null: return {"ok": false, "reason": "INVALID_SLOT"} var item: Dictionary = inventory[slot_index] var item_vnum := int(item.get("vnum", 0)) if item_vnum < VNUM_BLEACH or item_vnum > VNUM_BLACK_DYE: return {"ok": false, "reason": "NOT_A_HAIR_DYE", "msg": "此物品不是染发剂或漂白水!"} # 40250 官方规则:独立时装发型 (PART_HAIR >= 1001) 无法进行普通染色 if current_hair_style_id >= 1001: return {"ok": false, "reason": "CANNOT_DYE_COSTUME_HAIR", "msg": "当前穿戴的特殊时装发型无法进行原生发色染色!"} # 40250 官方冷却规则: # last_dye_level == 0 || last_dye_level + 3 <= GetLevel() || item->GetVnum() == 70201 var is_bleach: bool = (item_vnum == VNUM_BLEACH) if not is_bleach and last_dye_level > 0 and (last_dye_level + 3 > player_level): var req_lv := last_dye_level + 3 return { "ok": false, "reason": "LEVEL_COOLDOWN_ACTIVE", "req_level": req_lv, "msg": "染发药水药效尚未散去!角色需达到 %d 级方可再次染色(漂白水除外)。" % req_lv } # 消耗 1 瓶染发剂 var cnt := int(item.get("count", 1)) if cnt > 1: item["count"] = cnt - 1 else: inventory[slot_index] = null if is_bleach: # 漂白水重置发色为 0,并清空染色等级限制 current_hair_color = 0 last_dye_level = 0 hair_bleached.emit() return { "ok": true, "is_bleach": true, "hair_color": 0, "color_name": get_color_name(0), "msg": "使用漂白水褪色成功!发色已恢复经典天然原色。" } else: current_hair_color = item_vnum - VNUM_BLEACH last_dye_level = player_level hair_dyed.emit(current_hair_color, get_color_name(current_hair_color)) return { "ok": true, "is_bleach": false, "hair_color": current_hair_color, "color_name": get_color_name(current_hair_color), "last_dye_level": last_dye_level, "msg": "染发成功!角色秀发已焕新为【%s】。" % get_color_name(current_hair_color) } # 序列化 func serialize() -> Dictionary: return { "current_hair_color": current_hair_color, "current_hair_style_id": current_hair_style_id, "last_dye_level": last_dye_level } # 反序列化 func deserialize(data: Dictionary) -> void: current_hair_color = int(data.get("current_hair_color", 0)) current_hair_style_id = int(data.get("current_hair_style_id", 0)) last_dye_level = int(data.get("last_dye_level", 0))