阶段配置 stages.yml
stages.yml 给副本一条流程主线:清怪 → 开门 → Boss → 结算。以前这类推进逻辑只能在 scripts.yml 里用 setVar + if 手搓状态机,现在有了正经的落点。
这个文件是可选的——不建它,副本行为与以前完全一致。
五行能跑:清完一波怪自动进 Boss 阶段,打完 Boss 通关。
清怪: 通关条件: "dungeon.isGroupCleared('wave_1')" 下一阶段: BossBoss: 通关条件: "dungeon.isGroupCleared('boss')"不写 入口 就取文件里第一个阶段;最后一个阶段不写 下一阶段,通关后走 scripts.yml 的 complete 流程。
阶段少的时候也可以直接内联在 scripts.yml 的 阶段:(或 stages:)段下,不必单开文件。
入口: 清怪 # 可省略,默认取第一个阶段
清怪: 名称: "&e清理前厅" # 可省略,默认用阶段 key 通关条件: "dungeon.isGroupCleared('wave_1')" 超时: 300 # 秒,可省略;0 或不写 = 不限时 开始脚本: |- action.title('@all', '&e第一阶段', '&7清理所有敌人') action.spawn_group('wave_1') 通关脚本: |- action.remove_obstacle('Boss房大门') 超时脚本: |- action.fail('超时') 下一阶段: Boss
Boss: 名称: "&c击败守卫者" 通关条件: "dungeon.isGroupCleared('boss')" 开始脚本: |- action.spawn_group('boss') 下一阶段: # 分支写法 - 目标: 隐藏房 条件: "getVar('找到密道') == 1" - 目标: 结算 # 无条件兜底,放最后顶层
| 键(中/英) | 类型 | 默认 | 说明 |
|---|---|---|---|
入口 / entry | String | 第一个阶段 | 起始阶段 key |
单个阶段
| 键(中/英) | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
名称 / name | String | 否 | 阶段 key | 显示名,支持 & 颜色 |
通关条件 / complete_when | String | 是 | — | JS 表达式,返回真值即完成 |
超时 / timeout | Int | 否 | 0 | 秒,0 = 不限时 |
开始脚本 / on_start | 列表/多行 | 否 | 空 | 进入该阶段时执行一次 |
通关脚本 / on_complete | 列表/多行 | 否 | 空 | 该阶段完成时执行一次 |
超时脚本 / on_timeout | 列表/多行 | 否 | 空 | 超时时执行;不写则什么都不做 |
下一阶段 / next | String 或 List | 否 | 无 | 不写 = 最终阶段 |
分支项(下一阶段 写成列表时)
| 键(中/英) | 类型 | 必填 | 说明 |
|---|---|---|---|
目标 / target | String | 是 | 目标阶段 key |
条件 / condition | String | 否 | 不写 = 无条件兜底 |
分支按列表顺序判定,第一个成立的命中;都不成立就走无条件兜底;没有兜底则视为最终阶段,副本直接通关。
阶段 ID 不能含点号,也不能叫 入口 / entry。
阶段完全由事件驱动,没有任何定时器在轮询通关条件。以下事件发生后会重新判定一次当前阶段:
- 怪物组全灭(或被
skip_group跳过) - 交互点被触发
- 玩家进入或离开区域
- 脚本调用
action.complete_stage() - 阶段超时
进入一个阶段时也会立即判定一次,所以条件在进入瞬间就成立的话会直接连跳到下一阶段。
脚本 API
Section titled “脚本 API”| 动作 | 说明 |
|---|---|
action.complete_stage() | 跳过通关条件,直接完成当前阶段 |
action.goto_stage('阶段ID') | 跳转到指定阶段,不执行当前阶段的通关脚本 |
action.restart_stage() | 重新进入当前阶段,会再跑一次开始脚本 |
中文别名分别是 完成阶段 / 跳转阶段 / 重启阶段。
action.complete() 仍然可以随时直接通关,不受阶段限制——这是保留的紧急出口。
| 方法 | 返回 | 说明 |
|---|---|---|
dungeon.stage | String | 当前阶段 key,未启用返回空 |
dungeon.stageName | String | 当前阶段显示名 |
dungeon.stageIndex | Int | 当前是第几个阶段,1 起;未启用返回 0 |
dungeon.stageCount | Int | 阶段总数 |
dungeon.isFinalStage() | Boolean | 当前是否最终阶段 |
dungeon.stageElapsed | Long | 当前阶段已进行秒数 |
写通关条件常用的几个查询:
| 方法 | 返回 | 说明 |
|---|---|---|
dungeon.isGroupCleared('组ID') | Boolean | 该组是否已启动过并且全灭 |
dungeon.isGroupActive('组ID') | Boolean | 该组是否正在进行中 |
dungeon.getAliveMonsterCount('组ID') | Int | 该组存活怪物数 |
dungeon.getMobKillCount('怪物ID') | Int | 按怪物类型统计的击杀数 |
dungeon.getZonePlayerCount('区域') | Int | 区域内玩家数 |
getVar('变量名') | Any | 脚本变量 |
PAPI 变量
Section titled “PAPI 变量”| 变量 | 说明 |
|---|---|
%quedp_stage% | 当前阶段 key |
%quedp_stage_name% | 当前阶段显示名 |
%quedp_stage_index% | 当前是第几个阶段 |
%quedp_stage_count% | 阶段总数 |
主编辑器界面的「阶段」入口进管理界面:
- 阶段列表:显示顺序、显示名、通关条件、超时、流向、哪个是入口。左键编辑,右键设为入口,Shift+左键上移,Shift+右键删除(点击确认)
- 单阶段编辑:改显示名 / 通关条件 / 超时 / 三个脚本 / 下一阶段
- 通关条件模板:常用条件(清空怪物组、击杀数达标、变量达标、区域内有人)可以直接挑一个套上再改,不用背 JS
删除阶段时,其他阶段指向它的分支会一并断开,避免留下加载时报错的配置。
条件分支在阶段编辑里 Shift+左键「下一阶段」 进入分支管理:新增(选目标再输条件)、改条件、换目标、上移、删除;输入 none 表示无条件兜底。
与现有机制的关系
Section titled “与现有机制的关系”- 和怪物组
TRIGGERED并存:两套推进机制可以同时用,但建议二选一。用了阶段就别再配TRIGGERED链,否则两条线互相推进很难排查 - 不替换生命周期脚本:
scripts.yml的init/start/complete/fail语义完全不变。阶段是叠加在上面的一层,最终阶段完成后仍然走complete - 入口阶段在
start脚本之后进入:所以start脚本里可以先铺好前置状态
- 只有单条主线 + 条件分支,没有并行阶段和阶段树,一次只有一个当前阶段
- 一条推进链最多连跳 8 个阶段。超过会打 warn 并停在原地——通常意味着某个通关条件恒为真
- 条件表达式在运行期求值,语法错误只会 warn 一次并当作
false,不会在加载时报出来。分支目标写错、入口写错、通关条件漏填这三类会在加载期报错 - 条件表达式请保持简短,只做查询不要有副作用。它是同步求值的,
action.*在条件里不可用