# herbal_dew_system.gd —— Metin2 40250 白高草药炼丹酿造与 6 色神圣露水系统 1:1 # 对照 40250 服务端 char_item.cpp, blend.txt, potion.quest 及 NPC 20018 Baek-Go class_name HerbalDewSystem extends RefCounted const NPC_BAEK_GO := 20018 const ITEM_EMPTY_BOTTLE := 70030 # 6 色神圣露水定义 (50821~50826) const DEW_TABLE: Dictionary = { 50821: { "name": "绿露水", "color": "green", "stat": "magic_defense", "stat_desc": "魔法防御力", "min_val": 30, "max_val": 70, "duration": 600.0, # 10 分钟 "water_vnum": 50721 }, 50822: { "name": "红露水", "color": "red", "stat": "critical_pct", "stat_desc": "致命一击几率", "min_val": 8, "max_val": 20, "duration": 600.0, "water_vnum": 50722 }, 50823: { "name": "蓝露水", "color": "blue", "stat": "att_grade", "stat_desc": "物理攻击力", "min_val": 50, "max_val": 120, "duration": 600.0, "water_vnum": 50723 }, 50824: { "name": "白露水", "color": "white", "stat": "def_grade", "stat_desc": "物理防御力", "min_val": 40, "max_val": 100, "duration": 600.0, "water_vnum": 50724 }, 50825: { "name": "粉露水", "color": "pink", "stat": "penetrate_pct", "stat_desc": "穿透一击几率", "min_val": 8, "max_val": 20, "duration": 600.0, "water_vnum": 50725 }, 50826: { "name": "黄露水", "color": "yellow", "stat": "att_speed", "stat_desc": "攻击速度", "min_val": 2, "max_val": 8, "duration": 600.0, "water_vnum": 50726 } } # 草药提炼对应表 (herb_vnum -> water_vnum) const HERB_TO_WATER: Dictionary = { 50701: 50721, # 桃花 -> Sim-Water 50702: 50722, # 风铃草 -> Dok-Water 50703: 50723, # 柿子花 -> Bo-Water 50704: 50724, # 高山石斛 -> Young-Water 50705: 50725, # 紫丁香 -> Zin-Water 50708: 50726 # 桑椹 -> Sam-Water } # 正在生效的露水增益: dew_vnum -> { name, stat, value, duration } var active_dews: Dictionary = {} # 1. 在白高处提取草药药水 (原料草药 -> 中间提取液) static func brew_water(inventory: Array, herb_vnum: int) -> Dictionary: if not HERB_TO_WATER.has(herb_vnum): return {"ok": false, "reason": "INVALID_HERB", "msg": "此草药无法用于提炼!"} var target_water: int = int(HERB_TO_WATER[herb_vnum]) # 消耗草药 var herb_slot := -1 for i in range(inventory.size()): var it = inventory[i] if it != null and int(it.get("vnum", 0)) == herb_vnum: herb_slot = i break if herb_slot == -1: return {"ok": false, "reason": "MISSING_HERB", "msg": "背包中缺少所需草药!"} inventory[herb_slot] = null # 寻找背包空位生成药水提取液 var empty_slot := -1 for i in range(inventory.size()): if inventory[i] == null: empty_slot = i break if empty_slot == -1: return {"ok": false, "reason": "INVENTORY_FULL", "msg": "背包已满!"} inventory[empty_slot] = {"vnum": target_water, "count": 1} return {"ok": true, "water_vnum": target_water, "slot": empty_slot} # 2. 在白高处合成露水 (药水提取液 + 空瓶 70030 -> 神圣露水) static func brew_dew(inventory: Array, dew_vnum: int, force_max_roll: bool = false) -> Dictionary: if not DEW_TABLE.has(dew_vnum): return {"ok": false, "reason": "INVALID_DEW"} var cfg: Dictionary = DEW_TABLE[dew_vnum] var req_water: int = int(cfg["water_vnum"]) var water_slot := -1 var bottle_slot := -1 for i in range(inventory.size()): var it = inventory[i] if it != null: var v: int = int(it.get("vnum", 0)) if v == req_water and water_slot == -1: water_slot = i elif v == ITEM_EMPTY_BOTTLE and bottle_slot == -1: bottle_slot = i if water_slot == -1: return {"ok": false, "reason": "MISSING_WATER", "msg": "缺少对应的草药提取水剂!"} if bottle_slot == -1: return {"ok": false, "reason": "MISSING_BOTTLE", "msg": "缺少用于盛装露水的空药瓶 (70030)!"} # 扣除水剂与空药瓶 inventory[water_slot] = null inventory[bottle_slot] = null # 抽取露水品质数值 (min_val ~ max_val) var min_v: int = int(cfg["min_val"]) var max_v: int = int(cfg["max_val"]) var roll_val: int = max_v if force_max_roll else randi_range(min_v, max_v) var dew_item: Dictionary = { "vnum": dew_vnum, "name": cfg["name"], "value": roll_val, "duration": float(cfg["duration"]) } # 存入背包 var stored_slot := -1 for i in range(inventory.size()): if inventory[i] == null: inventory[i] = dew_item stored_slot = i break return { "ok": true, "dew_vnum": dew_vnum, "name": cfg["name"], "value": roll_val, "slot": stored_slot, "stat_desc": cfg["stat_desc"], "msg": "成功酿造出【%s】!品质增幅:%s +%d!" % [cfg["name"], cfg["stat_desc"], roll_val] } # 3. 饮用露水获得增益 func drink_dew(item: Dictionary) -> Dictionary: var vnum: int = int(item.get("vnum", 0)) if not DEW_TABLE.has(vnum): return {"ok": false, "reason": "NOT_A_DEW"} var cfg: Dictionary = DEW_TABLE[vnum] var roll_val: int = int(item.get("value", cfg["min_val"])) active_dews[vnum] = { "name": cfg["name"], "stat": cfg["stat"], "value": roll_val, "duration": float(cfg["duration"]), "total_duration": float(cfg["duration"]) } return { "ok": true, "dew_vnum": vnum, "name": cfg["name"], "stat": cfg["stat"], "value": roll_val, "duration": float(cfg["duration"]) } # 逐帧更新倒计时 func update(dt: float) -> Array[int]: var expired: Array[int] = [] for vnum in active_dews.keys(): var data: Dictionary = active_dews[vnum] data["duration"] = maxf(0.0, float(data["duration"]) - dt) if float(data["duration"]) <= 0.0: expired.append(vnum) for vnum in expired: active_dews.erase(vnum) return expired # 查询某项属性在当前露水中的总加成 func get_stat_bonus(stat_name: String) -> int: var total := 0 for vnum in active_dews: var data: Dictionary = active_dews[vnum] if String(data.get("stat", "")) == stat_name: total += int(data.get("value", 0)) return total func has_dew(vnum: int) -> bool: return active_dews.has(vnum)