跳转到内容

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 # 是否只能交互一次
类型说明
PLAYER玩家外形,需要同时写 skin,见下方「玩家皮肤 NPC」
VILLAGER村民
ZOMBIE僵尸
SKELETON骷髅
WITCH女巫
CREEPER苦力怕
ENDERMAN末影人
BLAZE烈焰人
PILLAGER掠夺者
WANDERING_TRADER流浪商人
IRON_GOLEM铁傀儡

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不支持,按村民显示,控制台提示一次
字段类型必填默认值说明
nameString否NPC key头顶显示名称,支持 & 颜色代码
typeString否PLAYERNPC 实体类型
locationString否0,64,0坐标 x,y,z(或 x,y,z,yaw,pitch),相对副本世界原点
skinString否-皮肤:正版玩家名,或 值;签名,仅 PLAYER 类型
look_at_playerBoolean否true是否自动朝向附近玩家
dialogueList否[]对话文本列表
dialogue_delayLong否30对话行间延迟(tick,20tick = 1秒)
click_scriptString否-点击时执行的 JavaScript 脚本
onceBoolean否false是否只能交互一次
dialogue_choicesSection否-聊天栏可点击的对话选项
shopSection否-商店配置(购买 / 出售)
questsSection否-NPC 任务配置
dialogue_stagesSection否-多段对话阶段(按顺序推进)

在聊天栏显示可点击的对话选项,玩家点击后执行对应脚本。每个子项的键为选项 ID。

字段类型必填默认值说明
textString否""选项显示文本,支持 & 颜色代码
scriptString否-点击该选项执行的脚本
conditionString否""显示条件(空=无条件显示)
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', '长老货柜')

商店分为 购买 / buy(玩家花费货币或物品换取物品)和 出售 / sell(玩家用物品换取奖励)两个子段。

字段类型必填默认值说明
nameString否子项 key商品名称
iconString否STONE图标材质名
price_typeString否money价格类型
priceInt否0价格数值
price_itemString否""价格物品(当用物品支付时)
give_itemString否""购买后给予的物品
give_scriptString否-购买后执行的脚本
字段类型必填默认值说明
nameString否子项 key商品名称
iconString否STONE图标材质名
require_itemString否""出售所需物品
reward_typeString否money奖励类型
rewardInt否0奖励数值
reward_scriptString否-出售后执行的脚本
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: 50

price_item、give_item、require_item 都支持三种写法:

写法例子说明
材质:数量PRISMARINE_SHARD:3原版物品,界面里按玩家客户端语言显示中文名
mm:物品ID:数量mm:AT_TideBlade:1MythicMobs 物品,显示 MM 里配的名字;扣材料时按 MM 物品 ID 认,改过名的普通物品不会被误扣
base64:...编辑器生成手里拿着的物品原样保存,在网页或游戏编辑器里设置
tide_blade:
name: "&b潮汐之刃"
price_item: "mm:AT_TideShard:5" # 5 个 MM 材料
give_item: "mm:AT_TideBlade:1"

NPC 可发布任务,玩家点击接受、满足条件后提交。每个子项的键为任务 ID(也可用 id 字段覆盖)。

字段类型必填默认值说明
idString否子项 key任务唯一 ID
nameString否子项 key任务名称
descriptionString否""任务描述
accept_textString否&a[接受]接受按钮文本
accept_scriptString否-接受时执行的脚本
submit_textString否&e[提交]提交按钮文本
submit_conditionString否""提交条件(满足才可提交)
submit_scriptString否-提交时执行的脚本
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任务完成,奖励已发放!')

多段对话按顺序推进,每次点击播放当前阶段的对话并前进到下一阶段,支持条件门控和循环。每个子项的键为阶段 ID。

字段类型必填默认值说明
linesList否[]该阶段的对话行
conditionString否""推进条件(空=无条件推进)
scriptString否-播放该阶段后执行的脚本
loopBoolean否false是否为循环阶段(所有阶段播完后回退到此阶段)
choicesSection否-当前阶段的选项,包含 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

click_script 中可使用以下选择器:

选择器说明
@trigger点击 NPC 的玩家
@all副本内所有玩家
@party队伍内所有玩家
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 脚本动作。