# fishing_mining_system.gd —— 钓鱼与采矿休闲生活系统(40250 官方 1:1 对齐) # 对齐源码: # - 40250 server/game/src/fishing.cpp:180-360 (钓竿、鱼饵、钓鱼状态机、开鱼与蚌壳珍珠) # - 40250 server/game/src/mining.cpp:50-180 (矿镐、矿脉 NPC、采矿倒计时与原石产出) class_name FishingMiningSystem extends RefCounted # 核心道具 Vnum 常量 const VNUM_ROD_BASE := 27400 # 钓竿 +0 const VNUM_BAIT_EARTHWORM := 27800 # 鱼饵 (蚯蚓) const VNUM_BAIT_PASTE := 27801 # 鱼饵 (面团) const VNUM_FISHBONE := 27990 # 鱼骨 const VNUM_CLAM := 27987 # 蚌壳 const VNUM_STONE_PIECE := 27991 # 碎石片 const VNUM_WHITE_PEARL := 27992 # 白珍珠 const VNUM_BLUE_PEARL := 27993 # 蓝珍珠 const VNUM_BLOOD_PEARL := 27994 # 血红珍珠 const VNUM_PICKAXE_BASE := 29101 # 矿镐 +0 # 经典鱼类列表 const FISH_TABLE := [ {"vnum": 27802, "name": "金鲫鱼"}, {"vnum": 27803, "name": "鲤鱼"}, {"vnum": 27804, "name": "鲑鱼"}, {"vnum": 27805, "name": "鳟鱼"}, {"vnum": 27806, "name": "鲶鱼"}, ] # 矿脉 NPC 与对应原石产出表 (40250 mining.cpp) const VEIN_TABLE := { 20047: {"name": "钻石矿脉", "ore_vnum": 50601, "ore_name": "钻石原石"}, 20048: {"name": "琥珀矿脉", "ore_vnum": 50602, "ore_name": "琥珀原石"}, 20049: {"name": "化石木", "ore_vnum": 50603, "ore_name": "化石原石"}, 20050: {"name": "铜矿脉", "ore_vnum": 50604, "ore_name": "铜原石"}, 20051: {"name": "银矿脉", "ore_vnum": 50605, "ore_name": "银原石"}, 20052: {"name": "金矿脉", "ore_vnum": 50606, "ore_name": "金原石"}, 20053: {"name": "玉矿脉", "ore_vnum": 50607, "ore_name": "玉原石"}, 20054: {"name": "黑檀木", "ore_vnum": 50608, "ore_name": "黑檀原石"}, 20055: {"name": "珍珠矿脉", "ore_vnum": 50609, "ore_name": "珍珠原石"}, 20056: {"name": "白金矿脉", "ore_vnum": 50610, "ore_name": "白金原石"}, 20057: {"name": "水晶矿脉", "ore_vnum": 50611, "ore_name": "水晶原石"}, 20058: {"name": "紫晶矿脉", "ore_vnum": 50612, "ore_name": "紫晶原石"}, 20059: {"name": "天堂泪矿脉", "ore_vnum": 50613, "ore_name": "天堂泪原石"}, } # --- 钓鱼系统 --- ## 检查物品是否为钓竿 static func is_fishing_rod(vnum: int) -> bool: return vnum >= 27400 and vnum <= 27590 ## 检查物品是否为鱼饵 static func is_bait(vnum: int) -> bool: return vnum == VNUM_BAIT_EARTHWORM or vnum == VNUM_BAIT_PASTE ## 检查是否为鲜鱼 static func is_live_fish(vnum: int) -> bool: return vnum >= 27802 and vnum <= 27832 ## 检查是否为蚌壳 static func is_clam(vnum: int) -> bool: return vnum == VNUM_CLAM ## 钓鱼判定 (40250 fishing.cpp:210) ## has_bait: 是否已挂饵; rod_level: 钓竿等级 (0..9) static func perform_fishing(has_bait: bool, rod_level := 0, force_success := false) -> Dictionary: if not has_bait: return {"ok": false, "code": "NO_BAIT", "msg": "钓钩上没有鱼饵,无法钓鱼!"} # 40250 基础钓鱼成功率:40% + 钓竿等级 * 3% var base_rate := 40 + rod_level * 3 var roll := 0 if force_success else (randi() % 100 + 1) if not force_success and roll > base_rate: return { "ok": false, "code": "FISH_ESCAPED", "consumed_bait": true, "msg": "鱼饵被咬走了,但鱼溜掉了!" } # 成功钓上鲜鱼 var fish_idx := randi() % FISH_TABLE.size() var fish: Dictionary = FISH_TABLE[fish_idx] return { "ok": true, "code": "SUCCESS", "consumed_bait": true, "fish_vnum": fish["vnum"], "fish_name": fish["name"], "msg": "钓上了一条活蹦乱跳的【%s】!" % fish["name"] } ## 打开鲜鱼 (40250 fishing.cpp:330) ## 鲜鱼开出:死鱼 (50%)、鱼骨 27990 (30%)、蚌壳 27987 (10%)、滑落逃脱 (10%) static func open_live_fish(fish_vnum: int) -> Dictionary: var roll := randi() % 100 if roll < 50: # 获得死鱼(死鱼 Vnum = 活鱼 + 31) var dead_vnum := fish_vnum + 31 return { "ok": true, "code": "DEAD_FISH", "result_vnum": dead_vnum, "msg": "得到了一条死鱼,可以在篝火上烤熟食用。" } elif roll < 80: # 获得鱼骨 (精炼核心材料) return { "ok": true, "code": "FISHBONE", "result_vnum": VNUM_FISHBONE, "msg": "剖开鲜鱼,在鱼肚里找到了一根坚硬的【鱼骨】!" } elif roll < 90: # 获得珍贵蚌壳 return { "ok": true, "code": "CLAM", "result_vnum": VNUM_CLAM, "msg": "不可思议!在鱼肚里发现了一个紧闭的【蚌壳】!" } else: return { "ok": false, "code": "ESCAPED", "msg": "鲜鱼一摆尾巴跳进水里溜走了!" } ## 打开蚌壳 (40250 fishing.cpp 蚌壳产出珍珠算法) ## 碎石 (50%)、白珍珠 27992 (25%)、蓝珍珠 27993 (15%)、血红珍珠 27994 (10%) static func open_clam(force_pearl_type := 0) -> Dictionary: if force_pearl_type > 0: var pname := "白珍珠" if force_pearl_type == VNUM_WHITE_PEARL else ("蓝珍珠" if force_pearl_type == VNUM_BLUE_PEARL else "血红珍珠") return { "ok": true, "code": "PEARL", "result_vnum": force_pearl_type, "msg": "蚌壳里散发着璀璨光芒,开出了珍稀的【%s】!" % pname } var roll := randi() % 100 if roll < 50: return { "ok": true, "code": "STONE", "result_vnum": VNUM_STONE_PIECE, "msg": "蚌壳里只有一块无用的碎石片。" } elif roll < 75: return { "ok": true, "code": "PEARL", "result_vnum": VNUM_WHITE_PEARL, "msg": "蚌壳里开出了一颗温润光泽的【白珍珠】!" } elif roll < 90: return { "ok": true, "code": "PEARL", "result_vnum": VNUM_BLUE_PEARL, "msg": "蚌壳里开出了一颗幽蓝剔透的【蓝珍珠】!" } else: return { "ok": true, "code": "PEARL", "result_vnum": VNUM_BLOOD_PEARL, "msg": "天赐奇宝!蚌壳里开出了一颗极品【血红珍珠】!" } # --- 采矿系统 --- ## 检查是否为矿镐 static func is_pickaxe(vnum: int) -> bool: return vnum >= 29101 and vnum <= 29110 ## 检查 NPC 是否为矿脉 static func is_vein(npc_vnum: int) -> bool: return VEIN_TABLE.has(npc_vnum) ## 获取矿脉信息 static func get_vein_info(npc_vnum: int) -> Dictionary: return VEIN_TABLE.get(npc_vnum, {}) ## 采矿判定 (40250 mining.cpp:85) ## pickaxe_level: 矿镐等级 (0..9) static func perform_mining(vein_vnum: int, pickaxe_level := 0, force_success := false) -> Dictionary: if not is_vein(vein_vnum): return {"ok": false, "code": "NOT_A_VEIN", "msg": "目标不是有效的矿脉!"} var vein: Dictionary = VEIN_TABLE[vein_vnum] var base_rate := 35 + pickaxe_level * 4 var roll := 0 if force_success else (randi() % 100 + 1) if not force_success and roll > base_rate: return { "ok": false, "code": "MINING_FAIL", "msg": "用力敲击了矿脉,但没有采集到有效矿石。" } var count := 1 + (randi() % 3) # 1..3 个原石 return { "ok": true, "code": "SUCCESS", "ore_vnum": vein["ore_vnum"], "ore_name": vein["ore_name"], "count": count, "msg": "成功从【%s】采集到了 %d 个【%s】!" % [vein["name"], count, vein["ore_name"]] }