NPC 配置 npcs.yml
npcs.yml 定义了副本中的 NPC 角色。NPC 可以与玩家对话、响应点击事件、执行脚本。
使用内置实体实现,无需安装任何外部 NPC 插件。
npcs: 引导者: name: "&6&l副本引导者" # 显示名称(支持颜色代码) type: PLAYER # NPC 类型 location: "0,64,0" # 相对副本原点的坐标 x,y,z skin: "Notch" # 皮肤玩家名(仅 PLAYER 类型有效) look_at_player: true # 是否朝向附近玩家
dialogue: # 对话内容列表 - "&e[引导者] &7欢迎来到试炼副本!" - "&e[引导者] &7前方有强大的敌人,请做好准备。" dialogue_delay: 40 # 对话行间延迟(tick)
click_script: | # 点击时执行的脚本 action.sound('@trigger', 'ENTITY_VILLAGER_YES', 1.0, 1.0) action.message('@trigger', '&e引导者向你点了点头。')
once: false # 是否只能交互一次NPC 类型
Section titled “NPC 类型”| 类型 | 说明 |
|---|---|
PLAYER | 玩家外形,需要同时写 skin,见下方「玩家皮肤 NPC」 |
VILLAGER | 村民 |
ZOMBIE | 僵尸 |
SKELETON | 骷髅 |
WITCH | 女巫 |
CREEPER | 苦力怕 |
ENDERMAN | 末影人 |
BLAZE | 烈焰人 |
PILLAGER | 掠夺者 |
WANDERING_TRADER | 流浪商人 |
IRON_GOLEM | 铁傀儡 |
玩家皮肤 NPC
Section titled “玩家皮肤 NPC”type: PLAYER 并且写了 skin,NPC 就会显示成玩家外形:
npcs: 商人: name: "&6拾潮人 · 贝砂" type: PLAYER skin: Notch # 正版玩家名skin 有两种写法:
- 正版玩家名:第一次用时向 Mojang 查询,结果缓存在
plugins/QueDP/cache/npc-skins.yml,之后重启不再联网(缓存 7 天后刷新,查询失败时继续用旧缓存) - 皮肤数据:
值;签名,可以从 mineskin.org 这类网站复制,不联网也能用
| 服务端 | 实现方式 |
|---|---|
| 1.21.9 及以上(含 26.x) | 原版人偶实体(Mannequin),Paper、Spigot 都支持 |
| Paper 1.17 ~ 1.21.8 | 发包生成的假人,外加一个隐形村民负责点击和寻路 |
| 1.16 及以下,或 Spigot 1.17 ~ 1.21.8 | 不支持,按村民显示,控制台提示一次 |
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | String | 否 | NPC key | 头顶显示名称,支持 & 颜色代码 |
type | String | 否 | PLAYER | NPC 实体类型 |
location | String | 否 | 0,64,0 | 坐标 x,y,z(或 x,y,z,yaw,pitch),相对副本世界原点 |
skin | String | 否 | - | 皮肤:正版玩家名,或 值;签名,仅 PLAYER 类型 |
look_at_player | Boolean | 否 | true | 是否自动朝向附近玩家 |
dialogue | List | 否 | [] | 对话文本列表 |
dialogue_delay | Long | 否 | 30 | 对话行间延迟(tick,20tick = 1秒) |
click_script | String | 否 | - | 点击时执行的 JavaScript 脚本 |
once | Boolean | 否 | false | 是否只能交互一次 |
dialogue_choices | Section | 否 | - | 聊天栏可点击的对话选项 |
shop | Section | 否 | - | 商店配置(购买 / 出售) |
quests | Section | 否 | - | NPC 任务配置 |
dialogue_stages | Section | 否 | - | 多段对话阶段(按顺序推进) |
对话选项 dialogue_choices
Section titled “对话选项 dialogue_choices”在聊天栏显示可点击的对话选项,玩家点击后执行对应脚本。每个子项的键为选项 ID。
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
text | String | 否 | "" | 选项显示文本,支持 & 颜色代码 |
script | String | 否 | - | 点击该选项执行的脚本 |
condition | String | 否 | "" | 显示条件(空=无条件显示) |
npcs: 长老: name: "&6村庄长老" type: VILLAGER location: "0,64,0" dialogue_choices: ask_quest: text: "&a我想接受任务" script: | action.message('@trigger', '&7长老:很好,去消灭森林里的怪物吧。') condition: "" ask_shop: text: "&e我想看看商品" script: | action.open_chest_ui('@trigger', '长老货柜')商店 shop
Section titled “商店 shop”商店分为 购买 / buy(玩家花费货币或物品换取物品)和 出售 / sell(玩家用物品换取奖励)两个子段。
购买 buy
Section titled “购买 buy”| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | String | 否 | 子项 key | 商品名称 |
icon | String | 否 | STONE | 图标材质名 |
price_type | String | 否 | money | 价格类型 |
price | Int | 否 | 0 | 价格数值 |
price_item | String | 否 | "" | 价格物品(当用物品支付时) |
give_item | String | 否 | "" | 购买后给予的物品 |
give_script | String | 否 | - | 购买后执行的脚本 |
出售 sell
Section titled “出售 sell”| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
name | String | 否 | 子项 key | 商品名称 |
icon | String | 否 | STONE | 图标材质名 |
require_item | String | 否 | "" | 出售所需物品 |
reward_type | String | 否 | money | 奖励类型 |
reward | Int | 否 | 0 | 奖励数值 |
reward_script | String | 否 | - | 出售后执行的脚本 |
npcs: 商人: name: "&d神秘商人" type: VILLAGER location: "5,64,5" shop: buy: apple: name: "&c回复苹果" icon: APPLE price_type: money price: 100 give_item: "GOLDEN_APPLE" sell: old_sword: name: "&7回收旧剑" icon: IRON_SWORD require_item: "IRON_SWORD" reward_type: money reward: 50price_item、give_item、require_item 都支持三种写法:
| 写法 | 例子 | 说明 |
|---|---|---|
材质:数量 | PRISMARINE_SHARD:3 | 原版物品,界面里按玩家客户端语言显示中文名 |
mm:物品ID:数量 | mm:AT_TideBlade:1 | MythicMobs 物品,显示 MM 里配的名字;扣材料时按 MM 物品 ID 认,改过名的普通物品不会被误扣 |
base64:... | 编辑器生成 | 手里拿着的物品原样保存,在网页或游戏编辑器里设置 |
tide_blade: name: "&b潮汐之刃" price_item: "mm:AT_TideShard:5" # 5 个 MM 材料 give_item: "mm:AT_TideBlade:1"任务 quests
Section titled “任务 quests”NPC 可发布任务,玩家点击接受、满足条件后提交。每个子项的键为任务 ID(也可用 id 字段覆盖)。
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id | String | 否 | 子项 key | 任务唯一 ID |
name | String | 否 | 子项 key | 任务名称 |
description | String | 否 | "" | 任务描述 |
accept_text | String | 否 | &a[接受] | 接受按钮文本 |
accept_script | String | 否 | - | 接受时执行的脚本 |
submit_text | String | 否 | &e[提交] | 提交按钮文本 |
submit_condition | String | 否 | "" | 提交条件(满足才可提交) |
submit_script | String | 否 | - | 提交时执行的脚本 |
npcs: 任务发布者: name: "&b任务官" type: VILLAGER location: "0,64,0" quests: kill_zombies: name: "&a清剿僵尸" description: "击杀 10 只僵尸" accept_text: "&a[接受任务]" accept_script: | action.message('@trigger', '&7任务已接受!') submit_text: "&e[提交任务]" submit_condition: "" submit_script: | action.message('@trigger', '&a任务完成,奖励已发放!')对话阶段 dialogue_stages
Section titled “对话阶段 dialogue_stages”多段对话按顺序推进,每次点击播放当前阶段的对话并前进到下一阶段,支持条件门控和循环。每个子项的键为阶段 ID。
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
lines | List | 否 | [] | 该阶段的对话行 |
condition | String | 否 | "" | 推进条件(空=无条件推进) |
script | String | 否 | - | 播放该阶段后执行的脚本 |
loop | Boolean | 否 | false | 是否为循环阶段(所有阶段播完后回退到此阶段) |
choices | Section | 否 | - | 当前阶段的选项,包含 text、script、condition;点击选项后才推进 |
1.4.1 抢先版支持在每个阶段里保存独立的 choices。例如任务向导第一步的「接受任务」会在第一步显示,点击后执行 track_task 并推进。顶层 dialogue_choices 仍是所有阶段结束后的选项,请勿把接任务选项放在那里、再用任务进度作为最后阶段的条件。
npcs: 剧情NPC: name: "&6神秘老人" type: VILLAGER location: "0,64,0" dialogue_stages: stage1: lines: - "&e[老人] &7年轻人,你终于来了……" condition: "" stage2: lines: - "&e[老人] &7前方的封印需要你来解开。" script: | action.message('@trigger', '&a你获得了封印之钥。') stage3: lines: - "&e[老人] &7祝你好运。" loop: true脚本中的选择器
Section titled “脚本中的选择器”click_script 中可使用以下选择器:
| 选择器 | 说明 |
|---|---|
@trigger | 点击 NPC 的玩家 |
@all | 副本内所有玩家 |
@party | 队伍内所有玩家 |
示例:带路 NPC
Section titled “示例:带路 NPC”npcs: 带路人: name: "&a&l带路人" type: VILLAGER location: "0,64,0" look_at_player: true dialogue: - "&e[带路人] &7跟我来,我带你去下一个区域。" dialogue_delay: 30 click_script: | action.npc_talk('@trigger', '带路人') action.delay(80) action.npc_walk('带路人', '20,64,30', 0.3)NPC 相关的脚本动作详见 NPC 脚本动作。