地牢模板编写
abysses/<地牢ID>/ 下各 YAML 的字段规范
地牢模板编写
每个地牢是 plugins/ArcartX-Suite/data/abyss/abysses/<地牢ID>/ 下的一个目录,目录名即地牢 ID(建议小写英文+下划线)。模块首次启动会自动导出 abysses/example/ 示例地牢——直接复制改配置即可得到新副本。
目录结构
除
config.yml外所有文件均可省略,缺失时使用空配置。external/是「这个副本需要哪些 Chemdah 会话/任务、questgps 呈现层」的随包清单——abyss 在模板加载(启动//axs abyss reload)时自动部署:目标插件缺席整组跳过、目标文件已存在不覆盖,写入后自动chemdah reload并重载 questgps 模块。目录结构与上表一致即可被部署器识别。
config.yml — 地牢主配置
links 跨模块联动
声明式联动——不写脚本即可接其他模块。announce-clear 支持占位 {party}(队伍名)、{dungeon}(地牢显示名)、{time}(用时)。如需更细粒度(首通播报、成员名单、自定义条件),在 scripts.yml 生命周期脚本里用 signal/announce_global/qq_group/bp_task 等联动动作(见 脚本系统)。
entrance 推送为地图紫色外部目标,玩家可在地图面板点"导航",由地图内置导航栈寻路(不占玩家路径点上限);入口指向主城等固定世界坐标,不要指向副本世界内部。
地图标记 vs 物理入口:
links.entrance只是地图上的导航标记(指路用);真正右键进本要配下面的entrances世界入口点。两者通常指向同一位置。
plans 作战方案
进本前选择的作战方案(如"强攻/潜入/破局"),影响本局怪组与脚本分支,不影响剧情走向。
- 定义:
plans节每个 key 是方案 id,name显示名(支持&)、lore描述行(菜单展示用) - 选择入口(三处都生效):
- 命令:
/abyss enter <地牢> <方案id> - 入口点
plan:字段固定方案(适合"不同物理入口=不同打法") - 入口点不配
plan且方案多于一个时,点击者收到可点击的方案选择菜单(聊天栏,点击自动执行进本命令)
- 命令:
- 不选方案:模板定义了 plans 但没指定时,默认取第一个方案
- 实例变量:进本后
{plan}=方案 id、{plan_name}=显示名,可在脚本/消息文本中引用 - 事件:
axs.abyss.enter/axs.abyss.player_enter的 payload 附带plan
方案怎么影响玩法(两条路,可混用):
- 怪组过滤——
monsters.yml和rooms.yml的怪物组加plans: [方案id]字段后,只有该方案进本才注册此组。不同方案刷完全不同的怪群: - 脚本分支——
{plan}变量配合check动作分流奖励/机制:
entrances 世界入口点
主世界/场景里的物理进本点——玩家右键登记的方块(或区域内任意方块)触发进本,命中后交互事件自动取消(门/箱子不会真的打开)。
world:入口所在世界名(主世界场景,不是副本世界——副本世界名带axs_abyss_前缀且是实例世界)location:单点"x,y,z";region:立方区域"x1,y1,z1;x2,y2,z2"——两者可都填,同一入口多点命中plan:可选,固定方案 id(对应plans键名);不配且模板多方案 → 弹方案菜单name:可选显示名- 队伍带入:点击者是队长且有队员 → 自动带全队进本(沿用进本条件校验:体力/冷却/道具按
require-all-players规则判定) - 进本失败(条件不满足/冷却中/实例满等)会给点击者发失败原因
- 与
links.entrance地图标记独立,建议配合使用:地图指路 + 到点右键进本
world.template(世界来源)
| 值 | 说明 |
|---|---|
void | 生成虚空世界(全空气),用 init 脚本现场搭场景。零依赖最简方案 |
| 目录名 | abysses/<地牢ID>/world/ 下的完整世界存档文件夹(需含 level.dat),逐实例复制 |
maps/<名> 或 .schem | WorldEdit/FAWE schematic,粘贴到虚空世界。需安装 WorldEdit 或 FAWE |
world 世界治理
gamerules:按副本覆盖游戏规则(如keepInventory、randomTickSpeed),未知规则名自动跳过;模块默认已内置一套副本规则(关日夜/天气/火焰蔓延/自然刷怪、keepInventory=true 等)disable-natural-spawn:拦截自然/刷怪笼/巡逻/袭击等环境驱动生成;副本脚本刷怪走CUSTOM来源不受影响disabled-spawn-reasons:按CreatureSpawnEvent.SpawnReason名精确禁用(含CUSTOM,可彻底锁死生成)command-control:副本级命令黑/白名单,mode: inherit时沿用全局restrictions.command-mode;whitelist适合 PVP/硬核副本「只许用这几个命令」
monsters.yml — 怪物组/波次
顶层每个 key 是一个怪物组 ID,组内 monsters 为刷怪点列表:
| spawn-timing | 触发时机 |
|---|---|
AUTO_START | monsters.yml 全局组=start 即刷;floors 房间内组=锁门即刷(delay-seconds 起延迟) |
DELAYED | 全局组=进本延迟刷;房间内组=锁门 delay-seconds 后刷 |
TRIGGERED | trigger-after 列出的组全部清完后自动触发(房间内同样生效) |
MANUAL / SCRIPTED | 仅脚本动作 spawn_group 触发(锁门不刷——随机波次、条件波次用) |
房间清判:
combat/boss房要求groups列出的全部组进入 COMPLETED。MANUAL组若本轮不刷,须kill_group跳过(PENDING 组被 kill 视同完成,照走完成链);remove_group是静默移除,不会计入完成,慎用。
不要在
on-end里手动spawn_group——trigger-after已自动触发,手写会双通道刷两遍。
mob-id 路由规则:vanilla: 前缀强制原版;其余尝试 MythicMobs,加载失败自动回退原版同类型实体。
波次休整(delay-seconds / rest-seconds / on-prespawn)
TRIGGERED 组前置清完后不立即刷,按休整规则延迟:
delay-seconds:组级覆盖——触发后延迟 N 秒刷(对 TRIGGERED 也生效)rest-seconds:组级兜底——delay-seconds<=0时用;floors 房间还可在房间级写wave-rest作为整房组的兜底on-prespawn:预告段——组被触发、休整期开始瞬间执行(写「下一波来袭」title/音效/actionbar,给玩家喘息提示)
优先级:delay-seconds > 组 rest-seconds > 房间 wave-rest;三者都 ≤0 时照旧立即刷(向后兼容)。
tasks.yml — 副本内任务
| type | 触发方式 |
|---|---|
TIMED | 副本进行到 times 列出的秒数时执行对应 timed-scripts |
INTERVAL | 每 interval 秒循环执行 script |
EVENT | 指定事件发生时执行(如 monster_kill,上下文含 {killer}) |
interacts.yml — 交互点
| type | 说明 |
|---|---|
RIGHT_CLICK_BLOCK / LEFT_CLICK_BLOCK | 右键/左键 location 处指定方块 |
BREAK_BLOCK / PLACE_BLOCK | 破坏/放置 location 处方块 |
STEP_ON | 站上 location 处方块 |
ENTER_REGION | 进入 region 区域(边沿触发,离开后再进可重触发) |
RIGHT_CLICK_ENTITY | 右键名为 entity-name 的实体 |
防抖:同一玩家对同一交互点 500ms 内不重复触发;条件失败的提示消息独立节流 5 秒。
puzzles.yml — 机关解谜
每个地牢目录可放 puzzles.yml 定义实例级机关——状态随副本创建/销毁,不占主世界。两种类型:
sequence— 按顺序触发一组 interact 点名(压力阀/符文顺序/接线板)input— 弹 ArcartX 输入面板,玩家键盘输入密码/口令(电梯通行码)
联动方式
- 步骤点名 =
interacts.yml键名。interact 触发成功即上报谜题系统——步骤点可以不挂script(纯机关点),也可以同时挂脚本做额外反馈 - input 面板入口:interact/NPC 脚本里用
puzzle_prompt <机关id>打开;指定玩家用puzzle_prompt_player <玩家|@all> <机关id> - 实例变量:
{var:puzzle.<id>}=进度(sequence=步数/input=尝试次数)、{var:puzzle.<id>.done}="1"、{var:puzzle.<id>.locked}="1" - 事件:
axs.abyss.puzzle_step/axs.abyss.puzzle_complete/axs.abyss.puzzle_fail(reason:miss_sequence/miss_input/locked) - 管理/脚本动作:
puzzle_reset/puzzle_solve/puzzle_state <id> <变量>—— 跳关、动态重置、状态读取 - 安全模型:答案只在服务端比对;UI 提交需 action_token + 玩家实例校验,伪造包/跨实例提交无效
管理员局内操作
所有操作只改当前实例内存状态,不写回 puzzles.yml——局内调试完不影响下个副本实例。
buffs.yml — 增益选择池
roguelike 式"祝福"系统:清房/层间/神龛交互等时机,给玩家弹三选一增益卡片(或静默按权重直接生效)。触发不写在本文件——在任何生命周期段 / interact / 机关脚本里用 buff_offer <池id> 动作发起,时机完全由编排决定。
效果三通道
effects 是完整脚本行列表,落地路径全走现有机制:
- 药水:
apply_potion @trigger SPEED 1 9999 - 属性加成:
apply_attribute @trigger <属性> <值> [percent](Symphony/AttributePlus/MythicLib/Crane 统一属性桥,装了哪个走哪个) - 变量驱动:
setvar buff_ember_mark 1—— 伤害加成/特殊机制在怪物组/武器脚本里check变量分支实现,策划自由度最大
触发方式(脚本动作)
buff_grant <池id> <选择器> [optionId] 直接赋予不弹窗(剧情强制增益/调试);buff_clear <池id> 撤下未完成的待选面板。
联动
- 实例变量:
{var:buff.<poolId>}=最近所选 option id、{var:buff.<poolId>.count}=已发放人次 - 事件:
axs.abyss.buff_offer/axs.abyss.buff_pick(payload 含pool/option) - 超时:
timeout到时按timeout-auto兜底,客户端面板自动关闭
obstacles.yml — 障碍物
障碍物是副本开始时自动放置的方块组,可用于封路/边界/装饰:
| trigger-mode | 说明 |
|---|---|
NONE | 纯方块组,无触发 |
ENTER / LEAVE | 玩家进入/离开障碍区域时触发脚本 |
PERSIST | 玩家在区域内持续期间按周期触发 |
脚本可用 create_obstacle <名> / delete_obstacle <名> 动态控制。
npcs.yml — 副本 NPC
副本 NPC 由 Adyeshach 渲染:每个 npcs.yml 条目在副本实例里生成一个公共临时实体(EntityManagerPublicTemporary,随实例销毁,不落 Adyeshach 持久库),实体 id 固定取配置 key——Chemdah 会话按 npc id: 'adyeshach <key>' 精确绑定。
点击时的判定顺序:
- 该 NPC id 绑定了 Chemdah 会话且 conversation 模块在线 → 打开 ArcartX 真会话 UI(选项/回复走 Chemdah)
- 否则 →
dialogs聊天栏逐句播放兜底 click-script无论哪条路径都会执行
相关脚本动作:spawn_npc / remove_npc(动态生成/移除)、npc_dialog <npc> [sel](同点击判定)、open_conversation <npcId> [sel](强制开 Chemdah 会话,不要求 NPC 在 npcs.yml)、play_cinematic <序列> [sel](播 conversation 电影序列)、play_model_animation(Adyeshach 模型动画)。
实体类型注意:
VILLAGER/WANDERING_TRADER这类实体自带原版交易 GUI——Adyeshach 缺席时 NPC 降级为真实体,右键会先弹原版交易界面盖住自定义交互。接对话/商店的 NPC 推荐WITCH(无交易界面,两条路径都安全);PLAYER型仅在 Adyeshach 在场时可用(降级路径会变 ZOMBIE)。Adyeshach 缺席时副本仍可进入,NPC 退化为原版实体 + 聊天栏对话;装 Adyeshach 未装 conversation 时对话同样走
dialogs兜底。
quests.yml — 副本任务(Chemdah/QuestGPS 适配层)
任务语义(目标/进度/完成判定)100% 由 Chemdah 任务定义承担,abyss 不自建任务引擎。quests.yml 只是「副本编排面」:本地 id → Chemdah id 的映射 + 副本内钩子脚本。
脚本动作(均按本地 id 解析成 chemdah-id 后委托 questgps/Chemdah):
| 动作 | 行为 |
|---|---|
accept_quest <任务> [sel] | 通过 QuestGpsNavigable.acceptQuest 接取;成功跑 on-accept,auto-track 时顺带追踪 |
submit_quest <任务> [sel] | 已完成的 Chemdah 任务 → 跑 on-complete 领副本奖励(manual-claim 场景) |
quest_step <任务> [sel] | 未接取→接取;已完成未领→提交。NPC click-script 一站式用法 |
quest_track <任务> [步骤] [sel] | QuestGPS 追踪卡片(整个任务或指定步骤) |
quest_status <任务> <变量> [sel] | 写 NONE/ACTIVE/COMPLETED 到实例变量,配合 check 分支 |
完成路由:Chemdah 判定完成 → questgps 发 EventBus axs.questgps.quest_completed → abyss 反查 chemdah-id 命中本地任务 → manual-claim: false 直接跑 on-complete。
注意:Chemdah 任务是玩家级持久档案——副本任务应在 Chemdah 侧配置为可重复接取(
agent: restart类),否则玩家二刷副本时任务已 COMPLETED 无法再进状态机。QuestGPS 缺席时相关动作静默跳过,副本其余玩法不受影响。任务定义文件放plugins/Chemdah/(questgps 呈现层放data/questgps/quests/),示例见 example 模板external/目录。
rewards.yml — 奖励集与宝箱
命名奖励集
grant_reward <集名> 脚本动作调用:
物品写法 material:<Material>:<数量>;MythicMobs/NeigeItems 等外源物品经宿主 ItemSourceRegistry 生成(写法见 integration 页)。
随机奖励集:
宝箱奖励
open_chest_ui @trigger <名> 打开宝箱 UI(无 ArcartX 客户端时直接发放):
宝箱 UI 支持单个/全部领取;玩家未领取关闭时服务端自动全发兜底,不吞奖励。
shops.yml — 副本商店
open_shop_ui <选择器> <商店id> 打开自定义商店 UI(替代台座购买):商品行列表展示图标/名称/描述/价格,顶部实时余额,金币不足自动置灰。
- 结算模型:服务端校验 token + 副本实例身份 +
currency-var余额 → 扣实例变量 → 跑script→ 回推余额刷新 UI;购买是原子扣费,伪造包/跨实例无效 - NPC 入口:
npcs.yml的click-script里写open_shop_ui @trigger caravan;同店多台座/多入口并存不冲突 - 类型注意:接商店的 NPC 不要用
VILLAGER/WANDERING_TRADER——Adyeshach 缺席降级真实体时,右键会先弹原版交易 GUI 盖住交互;WITCH无交易界面两条路径都安全 - 商品
script是完整动作行列表,随机档位/条件分支照常用random+if_var+run_script模式
scripts.yml — 生命周期脚本
段执行时机:
| 段 | 时机 |
|---|---|
world-init | 世界就绪后、玩家传送之前——造平台/铺场景专用(void 世界必须用它建落脚处) |
init | 玩家全部进图后、副本激活前(玩法对象尚未初始化) |
start | 副本激活时(怪组已注册,AUTO_START 组已刷) |
complete / fail / exit | 通关 / 失败 / 玩家离开 |
player-death / all-death | 单人阵亡 / 全员阵亡 |
虚空世界务必用
world-init而不是init建平台——init在玩家传送之后才跑,先传送会掉虚空。即使没写world-init,系统也会检测出生点下方无支撑时自动垫一块 5×5 基岩兜底。
详见 脚本系统。
floors.yml + rooms.yml — 多层房间地牢
config.yml 设 mode: floors 后启用:地牢由若干层(floor)组成,每层是房间图——房间在世界里真实互连(走廊物理可走),玩家自由探索/回退,不必按 rooms 列表顺序访问(类元气骑士迷宫结构)。房间 region/doors 定义边界和物理门洞,拓扑由 world-init 的建筑布局决定——门洞后接走廊=真通路,挖死=假门/装饰。
floors.yml
| 字段 | 说明 |
|---|---|
source: region | 房间已手工建在世界模板里,坐标写世界绝对值 |
source: pool | 虚空世界 + 房间 .schem 随机抽取粘贴(需 WorldEdit/FAWE,进本时校验) |
advance: portal | 层/房清完激活出口区,玩家踩 exit 传送;advance-timeout 超时自动推 |
advance: auto | 清完 3 秒后自动传送下一目标 |
rooms.yml
运行规则
- 房间图遍历:引擎每 tick 扫描层内全部房间做进出检测——进任意房触发 on-enter/锁门,可回退/绕支线/走回头路;
rooms列表只是集合而非路线 - 终点语义:
boss-room显式指定层终点——终点房清完 → 层清 → 进下一层;非终点房清完只解锁自家门,不自动传送 - 多门洞:
doors是列表,一房可配任意多个门洞(锁门时全部填塞、清完还原原方块);门洞是否通向真房间由 world-init 的建筑布局决定——封死=假门/装饰,通走廊=真通路 - 房间物化:进本时按层生成房间链;pool 房沿轴粘贴,一切坐标(region/spawn/doors/groups/exit)自动按锚点偏移为绝对值
- 怪组物化:房内组注册为
f{层}_r{房序}_{模板id}:{组名};trigger-after引用房内短名自动加前缀 - 事件:
axs.abyss.room_enter/room_clear/floor_enter/floor_clear - 脚本变量:
{floor}{floor_name}{floors_total}{room}写入实例变量 - 脚本动作:
floor_next(强制推层)/room_lock <房>/room_unlock <房>/room_status <房> <变量> - 虚空防护:玩家掉出所在房底部 8 格以下自动拉回该房中心
- 无怪组的安全房进房即清(不广播"肃清");最终层终点房清完自动
complete_dungeon - Boss 之门模式:world-init 把终点房门洞封死 → 战斗房
on-clear累加fN_cleared变量 → 首个肃清房触发fN_gate段fillblocks AIR开门(example 副本的实现方式,纯脚本无引擎依赖)
内置示例:元气试炼之地(example)
abysses/example/ 是一个零外部资源即可跑通的元气骑士式三层迷宫地牢——world.template: void 虚空世界,全部建筑由 scripts.yml 的 world-init 段用 fillblocks 程序化生成(每层 7 房×3 层,40×40 大房(内空 38×38)+ 16×8 走廊物理互连成图,祭坛/Boss 房挑高 22,无需 schematic)。
| 层 | 拓扑 | 演示点 |
|---|---|---|
| f1 苔痕前哨 | 入口—战斗A—战斗B—Boss / 入口—祭坛 / 战斗B—宝箱 | 向导 NPC(Adyeshach+Chemdah 会话+委托)、随机波次包+休整预告、金币祭坛三选一、Boss 之门(肃清任一战斗房开门) |
| f2 熔岩矿道 | 入口—战斗A—战斗B—谜题 / 入口—商店 / 战斗B—战斗C—Boss | 商店 UI+台座购买、彩窗提示序列拉杆机关、唤魔者+增援 |
| f3 深渊王座 | 入口—战斗A—Boss(环形)/ 祭坛—战斗B—宝箱厅 / 战斗B—精英 | 灵魂沙+岩浆块陷阱带(obstacles)、精英卫队房、终层独立宝箱池、凋零+两阶段增援 |
贯穿机制:击杀掉全队金币(tasks.yml monster_kill 事件)、祭坛/商店 %axsabyss_var_coins% 条件扣费、每层 Boss 后 buff_offer 三选一天赋、guide_point 路标链(向导→东廊→首战)、portal 出口垫传送 + 走廊可回溯、房间可任意顺序探索。
外部配套(随包自动部署,详见 example/external/README.md):Chemdah 会话文件绑 adyeshach guide/adyeshach merchant(NPC 右键开真会话 UI);Chemdah 任务 sk_slayer + questgps 呈现层(quests.yml 的 slayer 委托线)。abyss 加载模板时自动把 external/ 部署到 plugins/Chemdah/core/ 与 data/questgps/quests/ 并触发重载。缺依赖时自动降级:原版实体 NPC、聊天栏对话、委托线静默跳过。
区域模板 regions/
手工搭好的建筑可以整片圈选存为模板,副本脚本一键铺放——比逐行 fillblocks 快几个量级。
管理(见 命令页·区域模板):/axs abyss region pos1|pos2 圈选 → save <地牢> <名> 存到 abysses/<地牢>/regions/<名>.yml。
使用(scripts.yml 任意段,world-init 最常用):
模板是调色板(BlockData 串,保留朝向/状态)+ 逐层索引的 YAML——方块实体内容不迁移(箱内物品/刷怪笼/告示牌文字这些纯 NBT 不复制)。铺放同 fillblocks 免物理更新,不会触发邻接级联。