# demon_tower_system.gd —— 恶魔之塔 1~9 层单机爬塔挑战循环与塔顶免费铁匠(40250 官方 1:1 对齐) # 对齐源码: # - 40250 server/share/locale/english/quest/deviltower_zone.quest # - 40250 server/game/src/dungeon.cpp # - 40250 server/game/src/char_battle.cpp class_name DemonTowerSystem extends RefCounted signal floor_changed(floor_num: int, floor_name: String) signal floor_completed(floor_num: int) signal tower_completed signal tower_failed(reason: String) signal blacksmith_spawned(blacksmith_vnum: int, blacksmith_name: String) # 核心怪物与 NPC Vnum (40250 官方标准) const VNUM_METIN_FLOOR1 := 8015 # 坚韧之石 (1层入口封印) const VNUM_DEMON_KING := 1091 # 恶魔王 (3层 BOSS) const VNUM_METIN_FLOOR4 := 8016 # 恶魔封印石 (4层真伪封印石) const VNUM_ELITE_DEMON_KING := 1092 # 精英恶魔王 (6层 BOSS) const VNUM_METIN_DEATH := 8017 # 死亡之石 (7层) const VNUM_DEATH_REAPER := 1093 # 死神 (9层 最终 BOSS) # 塔顶免费铁匠 NPC const NPC_TOWER_WEAPON_SMITH := 20074 # 恶魔之塔武器铁匠 const NPC_TOWER_ARMOR_SMITH := 20075 # 恶魔之塔防具铁匠 const NPC_TOWER_JEWELRY_SMITH := 20076 # 恶魔之塔首饰铁匠 # 核心任务道具 const VNUM_ZIN_KEY_FLOOR5 := 50084 # 解除 5 层石碑钥匙 const VNUM_ZIN_MAP_FLOOR7 := 30302 # 7 层恶魔封印地图 const VNUM_ZIN_KEY_FLOOR8 := 30304 # 8 层通往塔顶钥匙 const VNUM_DEATH_REAPER_CHEST := 50082 # 9 层死神宝箱 const TOTAL_FLOORS := 9 const FLOOR_NAMES := { 1: "第 1 层:恶魔入口", 2: "第 2 层:恶魔集结所", 3: "第 3 层:恶魔王大殿", 4: "第 4 层:迷幻封印之阵", 5: "第 5 层:五柱封印禁地", 6: "第 6 层:恶魔之塔顶峰", 7: "第 7 层:死神迷宫前厅", 8: "第 8 层:死神结界禁地", 9: "第 9 层:死神王座决战", } # 运行期状态 var current_floor := 1 var is_active := false var floor_time_left := 1200.0 # 20 分钟单层时限 var floor4_real_metin_idx := -1 var floor5_unlocked_pillars := 0 var floor6_blacksmith_vnum := 0 var floor6_free_refine_used := false func start_tower() -> void: current_floor = 1 is_active = true floor_time_left = 1200.0 floor4_real_metin_idx = -1 floor5_unlocked_pillars = 0 floor6_blacksmith_vnum = 0 floor6_free_refine_used = false floor_changed.emit(1, FLOOR_NAMES[1]) func get_floor() -> int: return current_floor func get_floor_name() -> String: return FLOOR_NAMES.get(current_floor, "未知层") ## 第 1 层判定:击碎封印石 8015 即可通关 func on_floor1_metin_destroyed(vnum: int) -> bool: if current_floor != 1 or not is_active: return false if vnum == VNUM_METIN_FLOOR1: _advance_floor() return true return false ## 第 2 层判定:清理全图怪物 func on_floor2_mobs_cleared(mob_count: int) -> bool: if current_floor != 2 or not is_active: return false if mob_count <= 0: _advance_floor() return true return false ## 第 3 层判定:击杀恶魔王 1091 func on_floor3_boss_killed(boss_vnum: int) -> bool: if current_floor != 3 or not is_active: return false if boss_vnum == VNUM_DEMON_KING: _advance_floor() return true return false ## 第 4 层判定:初始化 7 座封印石并在打破真石时通关 func setup_floor4_metins() -> void: # 7 座封印石 (索引 0..6),随机指定 1 座为真石 floor4_real_metin_idx = randi() % 7 func on_floor4_metin_hit(stone_idx: int) -> Dictionary: if current_floor != 4 or not is_active: return {"ok": false, "msg": "当前不在第 4 层!"} if stone_idx == floor4_real_metin_idx: _advance_floor() return {"ok": true, "is_real": true, "msg": "找到了真实的恶魔封印石!通往第 5 层的传送门开启!"} else: return {"ok": true, "is_real": false, "msg": "这是一座虚假的封印石,迷雾尚未散开!"} ## 第 5 层判定:使用钥匙解除 5 座恶魔石柱 func on_floor5_unlock_pillar(key_vnum: int) -> Dictionary: if current_floor != 5 or not is_active: return {"ok": false, "msg": "当前不在第 5 层!"} if key_vnum != VNUM_ZIN_KEY_FLOOR5: return {"ok": false, "msg": "钥匙不匹配!"} floor5_unlocked_pillars += 1 var remain := 5 - floor5_unlocked_pillars if floor5_unlocked_pillars >= 5: _advance_floor() return {"ok": true, "completed": true, "msg": "5 座恶魔石碑全部解除封印!传送至第 6 层!"} else: return {"ok": true, "completed": false, "remain": remain, "msg": "成功解除了一座石碑封印,还剩 %d 座!" % remain} ## 第 6 层判定:击杀精英恶魔王 1092 并召唤免费铁匠 func on_floor6_boss_killed(boss_vnum: int) -> Dictionary: if current_floor != 6 or not is_active: return {"ok": false, "msg": "当前不在第 6 层!"} if boss_vnum == VNUM_ELITE_DEMON_KING: # 随机召唤三位塔顶铁匠之一 var smiths := [ {"vnum": NPC_TOWER_WEAPON_SMITH, "name": "恶魔之塔武器铁匠"}, {"vnum": NPC_TOWER_ARMOR_SMITH, "name": "恶魔之塔防具铁匠"}, {"vnum": NPC_TOWER_JEWELRY_SMITH, "name": "恶魔之塔首饰铁匠"} ] var chosen: Dictionary = smiths[randi() % smiths.size()] floor6_blacksmith_vnum = chosen["vnum"] floor6_free_refine_used = false blacksmith_spawned.emit(chosen["vnum"], chosen["name"]) return { "ok": true, "blacksmith_vnum": chosen["vnum"], "blacksmith_name": chosen["name"], "msg": "击杀了精英恶魔王!塔顶现身了一位【%s】!" % chosen["name"] } return {"ok": false, "msg": "目标不是精英恶魔王!"} ## 第 6 层塔顶免费铁匠强化 (无需材料,单人爬塔经典福利) func perform_tower_free_refine(item: Dictionary, item_type: int) -> Dictionary: if current_floor != 6 or floor6_blacksmith_vnum == 0: return {"ok": false, "code": "NO_BLACKSMITH", "msg": "塔顶铁匠尚未出现!"} if floor6_free_refine_used: return {"ok": false, "code": "ALREADY_USED", "msg": "恶魔之塔铁匠本次只能免费强化一次!"} # 校验铁匠类型与物品类型匹配 if floor6_blacksmith_vnum == NPC_TOWER_WEAPON_SMITH and item_type != 1: return {"ok": false, "code": "TYPE_MISMATCH", "msg": "武器铁匠只能强化武器!"} if floor6_blacksmith_vnum == NPC_TOWER_ARMOR_SMITH and item_type != 2: return {"ok": false, "code": "TYPE_MISMATCH", "msg": "防具铁匠只能强化防具!"} floor6_free_refine_used = true var cur_vnum := int(item.get("vnum", 0)) var new_vnum := cur_vnum + 1 item["vnum"] = new_vnum return { "ok": true, "code": "SUCCESS", "old_vnum": cur_vnum, "new_vnum": new_vnum, "msg": "【%s】为你施展了恶魔神工,免费强化成功!装备晋升为 #%d!" % [ "武器铁匠" if floor6_blacksmith_vnum == NPC_TOWER_WEAPON_SMITH else "防具铁匠", new_vnum ] } ## 从第 6 层前往第 7 层 (要求角色等级 >= 75) func advance_to_floor7(player_level: int) -> Dictionary: if current_floor != 6: return {"ok": false, "msg": "不在第 6 层!"} if player_level < 75: return {"ok": false, "code": "LEVEL_TOO_LOW", "msg": "只有等级达到 75 级的真正勇者,才能踏入恶魔之塔第 7 层禁地!"} _advance_floor() return {"ok": true, "msg": "踏入了死神禁地第 7 层!"} ## 第 7 层判定:使用恶魔地图 30302 通关 func on_floor7_map_used(map_vnum: int) -> bool: if current_floor != 7 or not is_active: return false if map_vnum == VNUM_ZIN_MAP_FLOOR7: _advance_floor() return true return false ## 第 8 层判定:使用钥匙 30304 通关 func on_floor8_key_used(key_vnum: int) -> bool: if current_floor != 8 or not is_active: return false if key_vnum == VNUM_ZIN_KEY_FLOOR8: _advance_floor() return true return false ## 第 9 层终极对决:击杀死神 1093 func on_floor9_boss_killed(boss_vnum: int) -> Dictionary: if current_floor != 9 or not is_active: return {"ok": false, "msg": "当前不在第 9 层!"} if boss_vnum == VNUM_DEATH_REAPER: is_active = false tower_completed.emit() return { "ok": true, "code": "TOWER_CLEAR", "drop_vnum": VNUM_DEATH_REAPER_CHEST, "msg": "壮举!你成功斩杀了死神,恶魔之塔被彻底征服!获得了【死神宝箱】!" } return {"ok": false, "msg": "目标不是死神!"} func _advance_floor() -> void: floor_completed.emit(current_floor) current_floor += 1 floor_time_left = 1200.0 floor_changed.emit(current_floor, FLOOR_NAMES.get(current_floor, "第 %d 层" % current_floor))