# portable_service_system.gd —— Metin2 40250 随身便民道具与即时服务系统 1:1 # 对照 40250 服务端 char_item.cpp, cmd_general.cpp, Items 70005, 70006, 70007 class_name PortableServiceSystem extends RefCounted signal service_opened(service_type: String) signal portable_item_consumed(vnum: int, remaining: int) const ITEM_PORTABLE_SAFEBOX := 70005 # 随身仓库卷轴 const ITEM_PORTABLE_BLACKSMITH := 70006 # 随身铁匠手稿 const ITEM_PORTABLE_GENERAL_STORE := 70007 # 随身杂货铺契约 # 随身杂货铺基础货架商品列表 (大红、大蓝、加速药水、回城卷轴) const PORTABLE_STORE_GOODS: Array = [ {"vnum": 27003, "name": "红药水(大)", "price": 3200, "count": 200}, {"vnum": 27006, "name": "蓝药水(大)", "price": 4800, "count": 200}, {"vnum": 27102, "name": "绿药水(大)", "price": 10000, "count": 10}, {"vnum": 22000, "name": "回城卷轴", "price": 2000, "count": 1} ] var active_service: String = "" # "safebox", "blacksmith", "store", or "" # 使用随身仓库 (70005) func use_portable_safebox(slot_idx: int, inventory: Array) -> Dictionary: var consume_res := _consume_portable_item(slot_idx, inventory, ITEM_PORTABLE_SAFEBOX) if not consume_res["ok"]: return consume_res active_service = "safebox" service_opened.emit("safebox") return { "ok": true, "service": "safebox", "remaining_scrolls": consume_res["remaining"], "msg": "使用了【随身仓库卷轴】,已建立与城市货郎的远程仓库连接!" } # 使用随身铁匠 (70006) func use_portable_blacksmith(slot_idx: int, inventory: Array) -> Dictionary: var consume_res := _consume_portable_item(slot_idx, inventory, ITEM_PORTABLE_BLACKSMITH) if not consume_res["ok"]: return consume_res active_service = "blacksmith" service_opened.emit("blacksmith") return { "ok": true, "service": "blacksmith", "remaining_scrolls": consume_res["remaining"], "msg": "展开了【随身铁匠手稿】,便携精炼锻造炉已点燃!随时可强化装备!" } # 使用随身杂货铺 (70007) func use_portable_store(slot_idx: int, inventory: Array) -> Dictionary: var consume_res := _consume_portable_item(slot_idx, inventory, ITEM_PORTABLE_GENERAL_STORE) if not consume_res["ok"]: return consume_res active_service = "store" service_opened.emit("store") return { "ok": true, "service": "store", "goods": PORTABLE_STORE_GOODS.duplicate(true), "remaining_scrolls": consume_res["remaining"], "msg": "出示了【随身杂货铺契约】,随身货郎已赶来!随时可补给药水或出售垃圾!" } # 从随身杂货铺购买商品 func buy_goods_from_portable_store( goods_idx: int, player_data: Dictionary, inventory: Array ) -> Dictionary: if active_service != "store": return {"ok": false, "reason": "STORE_NOT_OPEN", "msg": "随身杂货铺尚未开启!"} if goods_idx < 0 or goods_idx >= PORTABLE_STORE_GOODS.size(): return {"ok": false, "reason": "INVALID_GOODS", "msg": "商品不存在!"} var goods: Dictionary = PORTABLE_STORE_GOODS[goods_idx] var price: int = int(goods["price"]) var current_gold: int = int(player_data.get("gold", 0)) if current_gold < price: return { "ok": false, "reason": "INSUFFICIENT_YANG", "price": price, "current_gold": current_gold, "msg": "金币不足,无法购买!" } # 寻找背包空位 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": "背包已满,无法容纳所购商品!"} # 扣费并放入物品 player_data["gold"] = current_gold - price inventory[empty_slot] = { "vnum": goods["vnum"], "name": goods["name"], "count": goods.get("count", 1) } return { "ok": true, "item": inventory[empty_slot], "slot": empty_slot, "remaining_gold": player_data["gold"], "msg": "成功购买【%s】!" % goods["name"] } # 关闭随身服务窗口 func close_service() -> void: active_service = "" # 内部通用道具消耗处理 func _consume_portable_item(slot_idx: int, inventory: Array, expected_vnum: int) -> Dictionary: if slot_idx < 0 or slot_idx >= inventory.size(): return {"ok": false, "reason": "INVALID_SLOT"} var item = inventory[slot_idx] if item == null or int(item.get("vnum", 0)) != expected_vnum: return {"ok": false, "reason": "ITEM_MISMATCH", "msg": "该格子上不是对应的随身卷轴!"} var cnt: int = int(item.get("count", 1)) var remaining: int = cnt - 1 if remaining <= 0: inventory[slot_idx] = null else: item["count"] = remaining portable_item_consumed.emit(expected_vnum, remaining) return {"ok": true, "remaining": remaining}