(基于BeiDou)
下面是完整的 NPC 脚本添加流程:
📋 添加 NPC 脚本的完整流程
第一步:确认 NPC ID
NPC ID 来自游戏 WZ 资源文件。你可以用 HaRepacker 或 WZExplorer 打开 NPC.wz,找到你要用的 NPC 外观 ID(例如 9000000)。
自定义 NPC 一般用 9000000 以上的 ID 避免与官方冲突。
第二步:在数据库 npc_data 表中配置 NPC 的地图位置
sql
-- 将 NPC 放到某张地图中(例如新手村 map: 10000)
INSERT INTO npc_data (id, x, y, f, fh, cx, cy, rx0, rx1, ry0, ry1, type, hide, limitedname, mobtime)
VALUES (9900000, 0, 0, 0, 0, 0, 0, -50, 50, -100, 100, 0, 0, '', 0);
-- 或者在 life 表添加到地图
INSERT INTO life (id, life, type, x, y, f, fh, cx, cy, rx0, rx1, mobtime, hide, ms)
VALUES (10000, 9900000, 'n', 0, 0, 0, 0, -50, 50, -200, -100, 0, 0, 1);
更简单的方式:直接通过 GM 命令 在游戏内召唤 NPC 测试,例如
!spawnnpc 9900000
第三步:创建 NPC 脚本文件
脚本路径(根据你的语言配置选择):
gms-server/scripts/npc/ ← 默认英文
gms-server/script-zh-CN/npc/ ← 中文
文件名就是 NPC ID ,例如 9900000.js
第四步:编写脚本
以下是几个典型模板:
① 最简单的对话 NPC
javascript
var status = 0;
function start(mode, type, selection) {
if (mode == -1) {
cm.dispose();
return;
}
status++;
if (status == 1) {
cm.sendNext("你好,冒险家!欢迎来到这里。");
} else if (status == 2) {
cm.sendNextPrev("我是一个测试 NPC,目前没什么能帮你的。");
} else {
cm.dispose();
}
}
② 带选项菜单的 NPC
javascript
var status = 0;
function start(mode, type, selection) {
if (mode == -1) {
cm.dispose();
return;
}
if (status == 0 && mode == 1) {
status++;
cm.sendSimple("你好!我能帮你什么?\r\n#L0#给我 1000 金币#l\r\n#L1#传送到新手村#l\r\n#L2#什么都不用#l");
} else if (status == 1) {
if (selection == 0) {
// 给金币
cm.gainMeso(1000);
cm.sendOk("给你 1000 金币!");
} else if (selection == 1) {
// 传送
cm.warp(10000, 0);
} else {
cm.sendOk("好的,再见!");
}
cm.dispose();
}
}
③ 商店 NPC
javascript
function start(mode, type, selection) {
cm.openShop(1234); // 对应 shops 表中的 shopid
cm.dispose();
}
④ 给物品的 NPC
javascript
var status = 0;
function start(mode, type, selection) {
if (mode == -1) {
cm.dispose();
return;
}
status++;
if (status == 1) {
cm.sendYesNo("要领取新手套装吗?");
} else {
if (mode == 1) {
cm.gainItem(1040002, 1); // 物品ID, 数量
cm.gainItem(1060002, 1);
cm.sendOk("给你新手装备,加油!");
} else {
cm.sendOk("好的,有需要再来找我。");
}
cm.dispose();
}
}
常用 cm API 速查表
| 方法 | 说明 |
|---|---|
cm.sendOk("文字") |
弹出只有确认按钮的对话框 |
cm.sendNext("文字") |
弹出有"下一步"按钮的对话框 |
cm.sendNextPrev("文字") |
弹出有"上一步/下一步"的对话框 |
cm.sendYesNo("文字") |
弹出是/否对话框 |
cm.sendSimple("文字") |
弹出带 #L# 选项的菜单 |
cm.gainMeso(数量) |
给玩家金币 |
cm.gainItem(ID, 数量) |
给玩家物品 |
cm.warp(地图ID, 传送点) |
传送玩家 |
cm.openShop(商店ID) |
打开商店 |
cm.getPlayer().getLevel() |
获取玩家等级 |
cm.dispose() |
必须调用,结束对话释放资源 |
cm.getPlayer().getMeso() |
获取玩家当前金币 |
⚠️ 注意事项
cm.dispose()一定要调用,否则玩家会卡住无法再次对话。mode == -1代表玩家点了关闭按钮,必须处理。mode == 1代表"确认/是",mode == 0代表"否/上一步"。- 脚本修改后不需要重启服务端,下次触发 NPC 对话时会自动重新加载。