# mining_refinery_smelt_system.gd —— Metin2 40250 矿石采掘熔炼与首饰宝石镶嵌提纯炉系统 1:1 # 对照 40250 服务端 mining.cpp, char_item.cpp, item_manager.cpp class_name MiningRefinerySmeltSystem extends RefCounted signal ore_smelted(success: bool, gem_vnum: int, gem_name: String) signal jewelry_socket_opened(slot: int, socket_index: int) signal gem_embedded(slot: int, gem_name: String, stat_boost: float) const SMELT_ORE_COUNT := 100 # 熔炼需 100 颗原石 const SMELT_COST_GOLD := 10000 # 熔炼消耗 10,000 金币 const MAX_JEWELRY_SOCKETS := 3 # 首饰最多开 3 个孔 # 原石与精炼宝石对照表 const SMELT_TABLE: Dictionary = { 50621: {"name": "钻石原石", "gem_vnum": 50634, "gem_name": "纯净钻石", "is_diamond": true}, 50623: {"name": "乌木原石", "gem_vnum": 50636, "gem_name": "乌木精炼石", "is_diamond": false}, 50626: {"name": "黄金原石", "gem_vnum": 50639, "gem_name": "黄金精炼石", "is_diamond": false}, 50628: {"name": "白金原石", "gem_vnum": 50641, "gem_name": "白金精炼石", "is_diamond": false}, 50630: {"name": "天之泪原石", "gem_vnum": 50643, "gem_name": "天之泪精炼石", "is_diamond": false} } # 熔炼原石生成首饰宝石 func smelt_ore(ore_slot: int, stone_slot: int, inventory: Array, player_data: Dictionary, is_guild_alchemist: bool = false, force_success: bool = false) -> Dictionary: if ore_slot < 0 or ore_slot >= inventory.size() or inventory[ore_slot] == null: return {"ok": false, "reason": "INVALID_ORE_SLOT"} if stone_slot < 0 or stone_slot >= inventory.size() or inventory[stone_slot] == null: return {"ok": false, "reason": "INVALID_STONE_SLOT"} var ore_item = inventory[ore_slot] var stone_item = inventory[stone_slot] var ore_vnum = int(ore_item.get("vnum", 0)) if not SMELT_TABLE.has(ore_vnum): return {"ok": false, "reason": "NOT_AN_ORE", "msg": "该物品不是可熔炼的原矿石!"} var ore_count = int(ore_item.get("count", 1)) if ore_count < SMELT_ORE_COUNT: return {"ok": false, "reason": "NOT_ENOUGH_ORE", "msg": "原矿数量不足!需要 100 颗,当前仅有 %d 颗。" % ore_count} var gold = int(player_data.get("gold", 0)) if gold < SMELT_COST_GOLD: return {"ok": false, "reason": "NOT_ENOUGH_GOLD", "msg": "熔炼所需金币不足!需要 10,000 金币。"} # 消耗材料与金币 player_data["gold"] = gold - SMELT_COST_GOLD if ore_count > SMELT_ORE_COUNT: ore_item["count"] = ore_count - SMELT_ORE_COUNT else: inventory[ore_slot] = null var stone_cnt = int(stone_item.get("count", 1)) if stone_cnt > 1: stone_item["count"] = stone_cnt - 1 else: inventory[stone_slot] = null # 成功率计算 (普通提纯炉 60%,公会炼金炉 70%) var rate = 70 if is_guild_alchemist else 60 var roll = randi_range(1, 100) var is_succ = force_success or (roll <= rate) var target_gem = SMELT_TABLE[ore_vnum] var gem_vnum = target_gem["gem_vnum"] var gem_name = target_gem["gem_name"] if is_succ: # 入包精炼宝石 _add_gem_to_inventory(gem_vnum, gem_name, inventory) ore_smelted.emit(true, gem_vnum, gem_name) return { "ok": true, "success": true, "gem_vnum": gem_vnum, "gem_name": gem_name, "msg": "提纯炉烈焰喷涌!成功熔炼出高纯度【%s】!" % gem_name } else: ore_smelted.emit(false, gem_vnum, gem_name) return { "ok": true, "success": false, "msg": "熔炼失败!火候不纯,矿石与灵石化为了灰烬。" } # 使用纯净钻石 (50634) 为首饰打孔 func open_jewelry_socket(diamond_slot: int, target_slot: int, inventory: Array, force_success: bool = false) -> Dictionary: if diamond_slot < 0 or diamond_slot >= inventory.size() or inventory[diamond_slot] == null: return {"ok": false, "reason": "INVALID_DIAMOND_SLOT"} if target_slot < 0 or target_slot >= inventory.size() or inventory[target_slot] == null: return {"ok": false, "reason": "INVALID_TARGET_SLOT"} var d_item = inventory[diamond_slot] var target = inventory[target_slot] if int(d_item.get("vnum", 0)) != 50634: return {"ok": false, "reason": "NOT_A_DIAMOND", "msg": "打孔需要使用【纯净钻石】(50634)!"} if not target.has("jewelry_sockets"): target["jewelry_sockets"] = [] var sockets: Array = target["jewelry_sockets"] if sockets.size() >= MAX_JEWELRY_SOCKETS: return {"ok": false, "reason": "MAX_SOCKETS_REACHED", "msg": "该首饰已开辟 3 个宝石孔位,达到上限!"} # 消耗 1 颗钻石 var cnt = int(d_item.get("count", 1)) if cnt > 1: d_item["count"] = cnt - 1 else: inventory[diamond_slot] = null # 阶梯成功率: 第 1 孔 100%,第 2 孔 80%,第 3 孔 60% var rates = [100, 80, 60] var rate = rates[sockets.size()] var roll = randi_range(1, 100) var is_succ = force_success or (roll <= rate) if not is_succ: return {"ok": true, "success": false, "msg": "打孔失败!钻石碎裂,未能开辟新孔位。"} sockets.append(null) # 开辟一个空孔位 jewelry_socket_opened.emit(target_slot, sockets.size()) return { "ok": true, "success": true, "socket_index": sockets.size(), "total_sockets": sockets.size(), "msg": "打孔成功!首饰开辟了第 %d 个宝石镶嵌孔位!" % sockets.size() } # 将精炼宝石镶入首饰已开孔位 func embed_gem_into_socket(gem_slot: int, target_slot: int, inventory: Array) -> Dictionary: if gem_slot < 0 or gem_slot >= inventory.size() or inventory[gem_slot] == null: return {"ok": false, "reason": "INVALID_GEM_SLOT"} if target_slot < 0 or target_slot >= inventory.size() or inventory[target_slot] == null: return {"ok": false, "reason": "INVALID_TARGET_SLOT"} var gem_item = inventory[gem_slot] var target = inventory[target_slot] if not target.has("jewelry_sockets") or target["jewelry_sockets"].is_empty(): return {"ok": false, "reason": "NO_SOCKETS", "msg": "该首饰尚未开孔!请先使用纯净钻石打孔。"} var sockets: Array = target["jewelry_sockets"] var empty_idx = -1 for i in range(sockets.size()): if sockets[i] == null: empty_idx = i break if empty_idx == -1: return {"ok": false, "reason": "ALL_SOCKETS_OCCUPIED", "msg": "所有宝石孔位已镶满!"} var gem_vnum = int(gem_item.get("vnum", 0)) var gem_name = gem_item.get("name", "宝石") # 消耗 1 颗宝石 var cnt = int(gem_item.get("count", 1)) if cnt > 1: gem_item["count"] = cnt - 1 else: inventory[gem_slot] = null # 镶入孔位 (每颗宝石提供 +10% 首饰属性增强) sockets[empty_idx] = { "vnum": gem_vnum, "name": gem_name, "stat_boost": 0.10 } gem_embedded.emit(target_slot, gem_name, 0.10) return { "ok": true, "socket_idx": empty_idx, "gem_name": gem_name, "stat_boost": 0.10, "msg": "【%s】完美嵌入第 %d 孔!激活 +10%% 首饰属性加成!" % [gem_name, empty_idx + 1] } func _add_gem_to_inventory(vnum: int, iname: String, inventory: Array) -> void: for i in range(inventory.size()): if inventory[i] != null and int(inventory[i].get("vnum", 0)) == vnum: inventory[i]["count"] = int(inventory[i].get("count", 1)) + 1 return for i in range(inventory.size()): if inventory[i] == null: inventory[i] = {"vnum": vnum, "name": iname, "count": 1} return