# biologist_chaegirab_research_system.gd —— Metin2 40250 官方生物学者车齿木全套调查研究链与永久属性嘉奖系统 1:1 # 对照 40250 服务端 collect_quest_lv30.quest ~ collect_quest_lv94.quest, char.cpp class_name BiologistChaegirabResearchSystem extends RefCounted signal sample_submitted(item_name: String, success: bool, current: int, target: int) signal capstone_submitted(stone_name: String, stage_name: String) signal stage_completed(stage_name: String, rewards: Dictionary) const NPC_BIOLOGIST := 20084 # 生物学者车齿木 (Biologist Chaegirab) const VNUM_RESEARCH_ELIXIR := 71035 # 贤者之药 (提高提交成功率至 90%) # 40250 官方 8 大里程碑阶段全量研究任务链 const RESEARCH_STAGES: Array = [ { "stage_id": 1, "title": "【Lv 30 研究】兽人牙齿调查", "min_level": 30, "sample_vnum": 30006, # 兽人牙齿 "sample_name": "兽人牙齿", "target_count": 10, "soul_stone_vnum": 30220, # 兽人灵魂石 "soul_stone_name": "兽人灵魂石", "reward_stats": {"move_speed": 10}, "desc": "永久移动速度 +10" }, { "stage_id": 2, "title": "【Lv 40 研究】诅咒之书调查", "min_level": 40, "sample_vnum": 30047, # 诅咒之书 "sample_name": "诅咒之书", "target_count": 15, "soul_stone_vnum": 30221, # 诅咒灵魂石 "soul_stone_name": "诅咒灵魂石", "reward_stats": {"cast_speed_pct": 5}, "desc": "永久施法速度 +5%" }, { "stage_id": 3, "title": "【Lv 50 研究】恶魔纪念物调查", "min_level": 50, "sample_vnum": 30015, # 恶魔纪念物 "sample_name": "恶魔纪念物", "target_count": 15, "soul_stone_vnum": 30222, # 恶魔灵魂石 "soul_stone_name": "恶魔灵魂石", "reward_stats": {"defense": 60}, "desc": "永久防御力 +60" }, { "stage_id": 4, "title": "【Lv 60 研究】冰之碎片调查", "min_level": 60, "sample_vnum": 30050, # 冰之碎片 "sample_name": "冰之碎片", "target_count": 20, "soul_stone_vnum": 30223, # 冰霜灵魂石 "soul_stone_name": "冰霜灵魂石", "reward_stats": {"attack_power": 50}, "desc": "永久物理攻击力 +50" }, { "stage_id": 5, "title": "【Lv 70 研究】幽灵树枝调查", "min_level": 70, "sample_vnum": 30165, # 幽灵树枝 "sample_name": "幽灵树枝", "target_count": 25, "soul_stone_vnum": 30224, # 森林灵魂石 "soul_stone_name": "森林灵魂石", "reward_stats": {"move_speed": 11, "damage_reduction_pct": 10}, "desc": "永久移动速度 +11, 伤害抗性 +10%" }, { "stage_id": 6, "title": "【Lv 80 研究】巨灵石碑调查", "min_level": 80, "sample_vnum": 30166, # 巨灵石碑 "sample_name": "巨灵石碑", "target_count": 30, "soul_stone_vnum": 30225, # 巨灵灵魂石 "soul_stone_name": "巨灵灵魂石", "reward_stats": {"attack_speed": 6, "attack_pct": 10}, "desc": "永久攻击速度 +6, 物理伤害 +10%" }, { "stage_id": 7, "title": "【Lv 85 研究】红木灵枝调查", "min_level": 85, "sample_vnum": 30167, # 红木灵枝 "sample_name": "红木灵枝", "target_count": 40, "soul_stone_vnum": 30226, # 灵魂之石 "soul_stone_name": "灵魂之石", "reward_stats": {"all_resistance_pct": 10}, "desc": "永久全属性抗性 +10%" }, { "stage_id": 8, "title": "【Lv 90 研究】首领领主证书调查", "min_level": 90, "sample_vnum": 30168, # 领主证书 "sample_name": "首领领主证书", "target_count": 50, "soul_stone_vnum": 30227, # 首领灵魂石 "soul_stone_name": "首领灵魂石", "reward_stats": {"boss_damage_pct": 10}, "desc": "永久对野外首领伤害 +10%" } ] var current_stage_index: int = 0 var current_samples: int = 0 var waiting_for_soul_stone: bool = false var completed_stages: Array = [] var permanent_bonuses: Dictionary = {} # 获取当前正在进行的研究任务配置 func get_current_stage() -> Dictionary: if current_stage_index >= RESEARCH_STAGES.size(): return {} # 已全部完成 return RESEARCH_STAGES[current_stage_index].duplicate(true) # 交付样本材料 func submit_sample(inventory: Array, slot_index: int, player_level: int, force_success: bool = false, use_elixir: bool = false) -> Dictionary: var stage = get_current_stage() if stage.is_empty(): return {"ok": false, "reason": "ALL_RESEARCH_COMPLETED", "msg": "所有生物学者调查研究均已登峰造极!"} if player_level < int(stage["min_level"]): return { "ok": false, "reason": "PLAYER_LEVEL_TOO_LOW", "msg": "等级不足!开启该阶段研究需达到 %d 级。" % int(stage["min_level"]) } if waiting_for_soul_stone: return { "ok": false, "reason": "WAITING_FOR_SOUL_STONE", "msg": "样本已全部收集齐!请交付【%s】以完成终极认证。" % stage["soul_stone_name"] } if slot_index < 0 or slot_index >= inventory.size() or inventory[slot_index] == null: return {"ok": false, "reason": "INVALID_SLOT"} var item: Dictionary = inventory[slot_index] var item_vnum := int(item.get("vnum", 0)) if item_vnum != int(stage["sample_vnum"]): return { "ok": false, "reason": "WRONG_SAMPLE_ITEM", "msg": "车齿木摇了摇头:当前阶段需要研究的是【%s】!" % stage["sample_name"] } # 消耗 1 件样本 var cnt := int(item.get("count", 1)) if cnt > 1: item["count"] = cnt - 1 else: inventory[slot_index] = null # 判定成功率 (基础 60%,使用贤者之药 90%) var success_chance := 0.90 if use_elixir else 0.60 var is_success := force_success or (randf() <= success_chance) if is_success: current_samples += 1 sample_submitted.emit(stage["sample_name"], true, current_samples, stage["target_count"]) # 检查样本是否集齐 if current_samples >= int(stage["target_count"]): waiting_for_soul_stone = true return { "ok": true, "success": true, "current": current_samples, "target": stage["target_count"], "need_soul_stone": true, "soul_stone_name": stage["soul_stone_name"], "msg": "样本品质极高!%d 件样本已全部收集完毕,请寻找【%s】交付!" % [current_samples, stage["soul_stone_name"]] } return { "ok": true, "success": true, "current": current_samples, "target": stage["target_count"], "need_soul_stone": false, "msg": "样本验证成功!研究进度:(%d / %d)。" % [current_samples, stage["target_count"]] } else: sample_submitted.emit(stage["sample_name"], false, current_samples, stage["target_count"]) return { "ok": true, "success": false, "current": current_samples, "target": stage["target_count"], "need_soul_stone": false, "msg": "学者车齿木叹息:这件样本受损严重,无法用于精炼分析。" } # 交付关底灵魂石完成该阶段 func submit_soul_stone(inventory: Array, slot_index: int, player_stats: Dictionary) -> Dictionary: var stage = get_current_stage() if stage.is_empty(): return {"ok": false, "reason": "ALL_RESEARCH_COMPLETED"} if not waiting_for_soul_stone: return {"ok": false, "reason": "SAMPLES_NOT_COMPLETED", "msg": "样本尚未收集齐,无法交付灵魂石!"} if slot_index < 0 or slot_index >= inventory.size() or inventory[slot_index] == null: return {"ok": false, "reason": "INVALID_SLOT"} var item: Dictionary = inventory[slot_index] if int(item.get("vnum", 0)) != int(stage["soul_stone_vnum"]): return { "ok": false, "reason": "WRONG_SOUL_STONE", "msg": "需要交付的是专属的【%s】!" % stage["soul_stone_name"] } # 消耗灵魂石 var cnt := int(item.get("count", 1)) if cnt > 1: item["count"] = cnt - 1 else: inventory[slot_index] = null # 注入永久属性加成 var rewards: Dictionary = stage.get("reward_stats", {}) for k in rewards.keys(): var val = int(rewards[k]) player_stats[k] = int(player_stats.get(k, 0)) + val permanent_bonuses[k] = int(permanent_bonuses.get(k, 0)) + val completed_stages.append(stage["stage_id"]) current_stage_index += 1 current_samples = 0 waiting_for_soul_stone = false capstone_submitted.emit(stage["soul_stone_name"], stage["title"]) stage_completed.emit(stage["title"], rewards) return { "ok": true, "completed_stage": stage["title"], "rewards": rewards, "permanent_bonuses": permanent_bonuses, "msg": "【%s】圆满达成!永久获得属性加成:%s!" % [stage["title"], stage["desc"]] } # 序列化 func serialize() -> Dictionary: return { "current_stage_index": current_stage_index, "current_samples": current_samples, "waiting_for_soul_stone": waiting_for_soul_stone, "completed_stages": completed_stages.duplicate(true), "permanent_bonuses": permanent_bonuses.duplicate(true) } # 反序列化 func deserialize(data: Dictionary) -> void: current_stage_index = int(data.get("current_stage_index", 0)) current_samples = int(data.get("current_samples", 0)) waiting_for_soul_stone = bool(data.get("waiting_for_soul_stone", false)) completed_stages = data.get("completed_stages", []).duplicate(true) permanent_bonuses = data.get("permanent_bonuses", {}).duplicate(true)