# consumable_system.gd —— 高级消耗品与瞬移定位系统(40250 官方 1:1 对齐) # 对齐源码: # - 40250 char_item.cpp:3950-4050 (AFFECT_AUTO_HP/SP_RECOVERY, 日月神水开关) # - 40250 char_item.cpp:7326-7390 (AutoRecoveryItemProcess, 自动补充与容量耗尽) # - 40250 affect.h:95-96 (AFFECT_AUTO_HP_RECOVERY = 534, AFFECT_AUTO_SP_RECOVERY = 535) # - 40250 char_item.cpp 龙神药水 (71027~71030: 攻/防/血/魔法比率加成, 30 分钟) # - 40250 char_item.cpp 卷轴 (22001 回城卷轴, 22010 地标传送卷轴) class_name ConsumableSystem extends RefCounted # 日月神水 Vnum 范围(40250 官方标准) const VNUM_SUN_ELIXIR_S := 72723 # 太阳神水 (小) - 1,000,000 HP const VNUM_SUN_ELIXIR_M := 72724 # 太阳神水 (中) - 3,000,000 HP const VNUM_SUN_ELIXIR_L := 72725 # 太阳神水 (大) - 5,000,000 HP const VNUM_SUN_ELIXIR_EX := 72726 # 太阳神水 (特别) - 10,000,000 HP const VNUM_MOON_ELIXIR_S := 72727 # 月亮神水 (小) - 100,000 SP const VNUM_MOON_ELIXIR_M := 72728 # 月亮神水 (中) - 300,000 SP const VNUM_MOON_ELIXIR_L := 72729 # 月亮神水 (大) - 500,000 SP const VNUM_MOON_ELIXIR_EX := 72730 # 月亮神水 (特别) - 1,000,000 SP # 龙神药水 Vnum const VNUM_DRAGON_GOD_ATTACK := 71027 # 龙神攻击 (+15% 伤害) const VNUM_DRAGON_GOD_DEFENSE := 71028 # 龙神防御 (+15% 防御) const VNUM_DRAGON_GOD_LIFE := 71029 # 龙神生命 (+20% HP) const VNUM_DRAGON_GOD_MANA := 71030 # 龙神法力 (+20% SP) # 卷轴 Vnum const VNUM_TOWN_SCROLL := 22001 # 瞬间回城卷轴 const VNUM_RETURN_SCROLL := 22010 # 地标记忆/传送卷轴 # 40250 Affect 编号 const AFFECT_AUTO_HP_RECOVERY := 534 const AFFECT_AUTO_SP_RECOVERY := 535 const DRAGON_GOD_DURATION := 1800.0 # 30 分钟持续时间 # 神水默认容量表 (Vnum -> 容量) const ELIXIR_CAPACITIES := { 72723: 1000000, 72724: 3000000, 72725: 5000000, 72726: 10000000, 72727: 100000, 72728: 300000, 72729: 500000, 72730: 1000000, } ## 检查是否为日月神水 static func is_elixir(vnum: int) -> bool: return (vnum >= 72723 and vnum <= 72730) ## 检查是否为生命神水(太阳神水) static func is_hp_elixir(vnum: int) -> bool: return (vnum >= 72723 and vnum <= 72726) ## 检查是否为法力神水(月亮神水) static func is_sp_elixir(vnum: int) -> bool: return (vnum >= 72727 and vnum <= 72730) ## 检查是否为龙神特药 static func is_dragon_god_potion(vnum: int) -> bool: return vnum in [VNUM_DRAGON_GOD_ATTACK, VNUM_DRAGON_GOD_DEFENSE, VNUM_DRAGON_GOD_LIFE, VNUM_DRAGON_GOD_MANA] ## 初始化神水数据(若插槽容量未设定) static func init_elixir_if_needed(item_data: Dictionary) -> void: var vnum := int(item_data.get("vnum", 0)) var sockets: Array = item_data.get("sockets", [0, 0, 0]).duplicate() while sockets.size() < 3: sockets.append(0) # socket[0]: 0=未激活, 1=激活 # socket[1]: 已使用量 # socket[2]: 总容量 if int(sockets[2]) <= 0: sockets[2] = ELIXIR_CAPACITIES.get(vnum, 1000000) sockets[0] = 0 sockets[1] = 0 item_data["sockets"] = sockets ## 切换神水激活状态 (40250 char_item.cpp:3950) static func toggle_elixir(item_data: Dictionary) -> Dictionary: init_elixir_if_needed(item_data) var sockets: Array = item_data["sockets"] var cur_active := (int(sockets[0]) != 0) var new_active := not cur_active sockets[0] = 1 if new_active else 0 item_data["sockets"] = sockets var is_hp := is_hp_elixir(int(item_data.get("vnum", 0))) var kind := "生命" if is_hp else "法力" var msg := ("已激活%s神水自充能!" % kind) if new_active else ("已关闭%s神水自充能。" % kind) return { "ok": true, "active": new_active, "affect_type": AFFECT_AUTO_HP_RECOVERY if is_hp else AFFECT_AUTO_SP_RECOVERY, "msg": msg, } ## 自充能 Tick 处理 (40250 char_item.cpp:7326 AutoRecoveryItemProcess) ## 返回消耗与恢复量,若耗尽返回 exhausted=true static func process_elixir_recovery(item_data: Dictionary, cur_val: int, max_val: int) -> Dictionary: init_elixir_if_needed(item_data) var sockets: Array = item_data["sockets"] if int(sockets[0]) == 0: return {"recovered": 0, "exhausted": false} # 未激活 var used := int(sockets[1]) var cap := int(sockets[2]) var avail := maxi(0, cap - used) if avail <= 0: return {"recovered": 0, "exhausted": true} var deficit := maxi(0, max_val - cur_val) if deficit <= 0: return {"recovered": 0, "exhausted": false} var heal: int = mini(deficit, avail) sockets[1] = used + heal item_data["sockets"] = sockets var is_depleted := (int(sockets[1]) >= cap) return { "recovered": heal, "exhausted": is_depleted, "remaining": maxi(0, cap - int(sockets[1])), "capacity": cap, } ## 使用龙神特药 (40250 char_item.cpp) ## 返回 Buff 增益配置 static func use_dragon_god_potion(vnum: int) -> Dictionary: match vnum: VNUM_DRAGON_GOD_ATTACK: return { "ok": true, "vnum": vnum, "name": "龙神攻击", "duration": DRAGON_GOD_DURATION, "bonus_type": "POINT_ATT_BONUS", "bonus_value": 15, "msg": "使用了龙神攻击,攻击力提升 15%,持续 30 分钟!" } VNUM_DRAGON_GOD_DEFENSE: return { "ok": true, "vnum": vnum, "name": "龙神防御", "duration": DRAGON_GOD_DURATION, "bonus_type": "POINT_DEF_BONUS", "bonus_value": 15, "msg": "使用了龙神防御,防御力提升 15%,持续 30 分钟!" } VNUM_DRAGON_GOD_LIFE: return { "ok": true, "vnum": vnum, "name": "龙神生命", "duration": DRAGON_GOD_DURATION, "bonus_type": "POINT_MAX_HP_PCT", "bonus_value": 20, "msg": "使用了龙神生命,最大生命值提升 20%,持续 30 分钟!" } VNUM_DRAGON_GOD_MANA: return { "ok": true, "vnum": vnum, "name": "龙神法力", "duration": DRAGON_GOD_DURATION, "bonus_type": "POINT_MAX_SP_PCT", "bonus_value": 20, "msg": "使用了龙神法力,最大法力值提升 20%,持续 30 分钟!" } return {"ok": false, "msg": "未知的龙神药水"} ## 使用回城卷轴 / 地标卷轴 (40250 char_item.cpp) static func use_warp_scroll(vnum: int, item_data: Dictionary, cur_x: float, cur_y: float, cur_map_id := 1) -> Dictionary: if vnum == VNUM_TOWN_SCROLL: return { "ok": true, "action": "TOWN_WARP", "consumed": true, "msg": "使用了回城卷轴,即将传送回城!" } elif vnum == VNUM_RETURN_SCROLL: var sockets: Array = item_data.get("sockets", [0, 0, 0]).duplicate() while sockets.size() < 3: sockets.append(0) # 若未记录坐标(socket[0] == 0),则记录当前位置,不消耗卷轴! if int(sockets[0]) == 0 and int(sockets[1]) == 0: sockets[0] = int(cur_x) sockets[1] = int(cur_y) sockets[2] = cur_map_id item_data["sockets"] = sockets return { "ok": true, "action": "RECORDED", "consumed": false, "coords": Vector2(cur_x, cur_y), "map_id": cur_map_id, "msg": "成功将当前坐标 (%d, %d) 记录到地标卷轴!" % [int(cur_x), int(cur_y)] } else: # 已记录坐标:传送至记录位置并消耗卷轴 var target_x := int(sockets[0]) var target_y := int(sockets[1]) var target_map := int(sockets[2]) return { "ok": true, "action": "WARP_TO_COORDS", "consumed": true, "target_x": target_x, "target_y": target_y, "target_map": target_map, "msg": "使用了地标卷轴,正在传送至 (%d, %d)!" % [target_x, target_y] } return {"ok": false, "msg": "未知的传送卷轴"}