# spider_dungeon_system.gd —— Metin2 40250 蜘蛛洞穴三层与男爵夫人巢穴 1:1 # 对照 40250 服务端 spider_dungeon_3.quest, dungeon.cpp, Boss 2094 & Mob 2095 class_name SpiderDungeonSystem extends RefCounted signal dungeon_started(duration: float) signal egg_destroyed(eggs_left: int, current_atk: int, current_def: int) signal minions_summoned() signal dungeon_cleared(drops: Array[Dictionary]) signal dungeon_failed(reason: String) const NPC_GRAVESTONE := 20371 # 守墓人碑文 const ITEM_ARACHNID_KEY := 30327 # 蜘蛛之钥 const BOSS_SPIDER_BARONESS := 2094 # 蜘蛛男爵夫人 const MOB_SPIDER_EGG := 2095 # 蜘蛛卵 const ITEM_BARONESS_CHEST := 50157 # 男爵宝箱 const ITEM_TITAN_SHIELD := 13129 # 泰坦盾牌+9 const REQUIRED_LEVEL := 50 const DUNGEON_TIME_LIMIT := 1200.0 # 20 分钟 (秒) const BASE_BARONESS_MAX_HP := 250000 const BASE_BARONESS_DEF := 400 const BASE_BARONESS_ATK := 800 var is_active: bool = false var remaining_time: float = 0.0 var eggs_remaining: int = 4 var baroness_hp: int = 0 var baroness_max_hp: int = BASE_BARONESS_MAX_HP var baroness_def: int = BASE_BARONESS_DEF var baroness_atk: int = BASE_BARONESS_ATK var minions_spawned: bool = false var dungeon_completed: bool = false # 开启地牢密室 (spider_dungeon_3.quest) func enter_dungeon(player_level: int, inventory: Array) -> Dictionary: if is_active: return {"ok": false, "reason": "ALREADY_ACTIVE", "msg": "地牢密室已经在进行中!"} if player_level < REQUIRED_LEVEL: return {"ok": false, "reason": "LEVEL_TOO_LOW", "msg": "等级未满 50 级,无法承受蜘蛛巢穴的剧毒!"} # 查找并扣除蜘蛛之钥 (30327) var key_slot := -1 for i in range(inventory.size()): var it = inventory[i] if it != null and int(it.get("vnum", 0)) == ITEM_ARACHNID_KEY: key_slot = i break if key_slot == -1: return {"ok": false, "reason": "MISSING_KEY", "msg": "进入蜘蛛男爵夫人巢穴需要消耗【蜘蛛钥匙】!"} inventory[key_slot] = null # 初始化地牢状态 is_active = true remaining_time = DUNGEON_TIME_LIMIT eggs_remaining = 4 baroness_max_hp = BASE_BARONESS_MAX_HP baroness_hp = baroness_max_hp baroness_def = BASE_BARONESS_DEF baroness_atk = BASE_BARONESS_ATK minions_spawned = false dungeon_completed = false dungeon_started.emit(remaining_time) return { "ok": true, "time_limit": remaining_time, "eggs_count": eggs_remaining, "baroness_hp": baroness_hp, "baroness_atk": baroness_atk, "baroness_def": baroness_def, "msg": "密室封印已破除!蜘蛛男爵夫人苏醒,你有 20 分钟时间击杀它!" } # 击碎一枚蜘蛛卵 (狂暴激怒机制: 防御 -15%, 攻击 +20%) func destroy_egg() -> Dictionary: if not is_active: return {"ok": false, "reason": "DUNGEON_NOT_ACTIVE"} if eggs_remaining <= 0: return {"ok": false, "reason": "NO_EGGS_LEFT", "msg": "所有蜘蛛卵均已被击碎!"} eggs_remaining -= 1 var eggs_broken := 4 - eggs_remaining # 每碎 1 卵:防御降低 15% (最高 -60%), 攻击提升 20% (最高 +80%) var def_reduction_pct: float = float(eggs_broken) * 0.15 var atk_bonus_pct: float = float(eggs_broken) * 0.20 baroness_def = int(round(float(BASE_BARONESS_DEF) * (1.0 - def_reduction_pct))) baroness_atk = int(round(float(BASE_BARONESS_ATK) * (1.0 + atk_bonus_pct))) egg_destroyed.emit(eggs_remaining, baroness_atk, baroness_def) return { "ok": true, "eggs_left": eggs_remaining, "eggs_broken": eggs_broken, "baroness_def": baroness_def, "baroness_atk": baroness_atk, "msg": "蜘蛛卵被击碎!男爵夫人防御大幅削弱,但陷入了极度狂暴!" } # 攻击男爵夫人 func damage_baroness(raw_damage: int) -> Dictionary: if not is_active: return {"ok": false, "reason": "DUNGEON_NOT_ACTIVE"} if dungeon_completed: return {"ok": false, "reason": "ALREADY_COMPLETED"} var eff_dmg: int = maxi(1, raw_damage - baroness_def) baroness_hp = maxi(0, baroness_hp - eff_dmg) # 50% 血量召唤蜘蛛群 var triggered_minions := false if not minions_spawned and baroness_hp <= int(baroness_max_hp * 0.5): minions_spawned = true triggered_minions = true minions_summoned.emit() if baroness_hp <= 0: dungeon_completed = true is_active = false var drops: Array[Dictionary] = [ {"vnum": ITEM_BARONESS_CHEST, "count": 1, "name": "男爵宝箱"}, {"vnum": ITEM_TITAN_SHIELD, "count": 1, "name": "泰坦盾牌+9"} ] dungeon_cleared.emit(drops) return { "ok": true, "dead": true, "baroness_hp": 0, "damage_dealt": eff_dmg, "drops": drops, "msg": "蜘蛛男爵夫人轰然倒地!巢穴通关!" } return { "ok": true, "dead": false, "baroness_hp": baroness_hp, "damage_dealt": eff_dmg, "minions_summoned": triggered_minions } # 逐帧更新倒计时 func update(dt: float) -> Dictionary: if not is_active: return {} remaining_time -= dt if remaining_time <= 0.0: remaining_time = 0.0 is_active = false dungeon_failed.emit("TIME_OUT") return {"failed": true, "reason": "TIME_OUT", "msg": "挑战超时!你已被移出蜘蛛男爵夫人巢穴!"} return {"failed": false, "remaining_time": remaining_time}