词缀脚本(JS)
所属:开发者 · 同组:事件大全 · Provider 与桥接 相关:词缀系统 · 秘境与钥石
声明式词缀(数量 / 等级 / 环境 / 状态 / 战利品)配不出来的复杂效果,可以下沉到 JS 脚本词缀。引擎复用 QinhCoreLib 的 GraalJS(与 QS 同一套运行时)。本页讲引用格式、ctx 上下文、降级行为,并给完整示例。
🔑 架构红线:脚本是给词缀加「世界 / 玩家交互」效果(上药水、发物品、发钱、加属性),不是让 QR 自己算伤害。它跟词缀其他类别一样,受危险预算约束。
1. 在 affixes.yml 里挂脚本
词缀的 effect.type 设为 script,用 script 指向脚本里的函数:
affixes:
blood_ritual:
name: "§4血祭"
lore: ["§7秘境激活时降下血之考验"]
category: ENV
danger: 25 # 危险值(受 realm.tiers.danger-budget 约束)
reward: 20
min-tier: 3
effect:
type: script # ★ 用脚本作为效果
script: "qinhruins:affix_example.js:onActivate" # 命名空间:文件:函数引用格式
qinhruins:路径.js[:函数名]| 段 | 说明 |
|---|---|
qinhruins: | 命名空间前缀(QR 启动时 RuinScriptBridge.register 向 QCL 注册到此命名空间) |
路径.js | 相对 QR 脚本目录 plugins/QinhRuins/scripts/ 的文件路径 |
:函数名 | 可选;指定调用文件里的某个函数。省略则调用约定的默认函数(示例文件里是 main) |
脚本文件放在 plugins/QinhRuins/scripts/,首次启动会自动释放示例 affix_example.js。
2. 触发时机
脚本在 秘境激活的那一瞬间,对当时 在场的每位玩家各执行一次(onActivate(ctx) 收到的 ctx.player() 是当前这名玩家)。这是 fire-and-forget:抛异常只记日志,不影响秘境激活本身。
3. 两个全局对象:ctx 与 qcl
GraalJS 运行时给脚本绑定 两个 全局对象(由 CoreLib QinhScriptApi 提供):
ctx—— 只读上下文:拿玩家、读注入变量。qcl—— 动作 API:发物品、上药水、加属性、发钱、打日志、切线程等。
注意
常见误区:动作方法挂在 qcl 上,不是 ctx 上。ctx 只有 player() / get() / set() / vars()。写成 ctx.itemGive(...) 会因方法不存在而报错。
ctx —— 上下文(读变量)
脚本可读变量只有三个(由秘境运行时注入):
| 调用 | 含义 |
|---|---|
ctx.player() | 当前玩家(Bukkit Player,可能为 null,需判空) |
ctx.get("tier") | 秘境层数(Int) |
ctx.get("affix") | 当前词缀 id(String) |
ctx.get("danger") | 当前词缀危险值(Int) |
只有这三个键(
tier/affix/danger)。不存在skill、level、var_*等 —— 那些是 QinhSkills 脚本的键,QR 不注入。
qcl —— 动作 API
| 调用 | 作用 |
|---|---|
qcl.itemGive(ref, amount) | 给当前玩家物品;ref 支持 minecraft:、qinhitems:、mythicmobs:、qinhruins: 等前缀 |
qcl.addPotion(目标, 类型, tick, 等级) | 给目标上药水效果(类型为 Bukkit PotionEffectType 名,如 "SPEED") |
qcl.heal(n) | 给当前玩家回血 |
qcl.damage(目标, n) | 对目标造成伤害 |
qcl.buff(目标, key, 值, 运算, tick, 来源) | 加 CoreLib 属性增益(运算如 FLAT / RELATIVE / MULTIPLY,来源用于分源叠加) |
qcl.economyDeposit(n, provider, currency) | 发货币(另有 economyHas / economyWithdraw) |
qcl.runSyncLater(tick, function) | 延迟若干 tick 后在 主线程 执行回调(另有 runSync / runSyncAndWait) |
qcl.logInfo(msg) | 打信息日志(另有 logWarn / logError) |
注意
脚本可能在异步语境调用。任何动世界 / 实体的操作(传送、改方块、生成实体等)务必包进 qcl.runSyncLater(0, ...) 切回主线程,否则可能抛线程异常。上药水 / 发物品 / 发钱这些 qcl 动作方法已自行处理线程。
4. 完整示例
QR 首次启动会在 plugins/QinhRuins/scripts/ 释放一份示例 affix_example.js。下面是 可直接运行 的写法(读变量用 ctx,做动作用 qcl):
function onActivate(ctx) {
var player = ctx.player();
if (!player) return;
var tier = ctx.get("tier") || 1;
var amp = Math.min(tier, 5) - 1; // 层数越高,增益越强
// 给玩家上「迅捷」30 秒,等级随层数
qcl.addPotion(player, "SPEED", 20 * 30, amp);
// 高层额外奖励一个金苹果
if (tier >= 5) {
qcl.itemGive("minecraft:golden_apple", 1);
}
player.sendMessage("§4[血祭] §7秘境注入了 §cT" + tier + " §7之力……");
qcl.logInfo("[QR词缀] " + player.getName() + " 触发脚本词缀 T" + tier);
}
// 默认函数:引用里不写 :函数名 时调用 main
function main(ctx) {
onActivate(ctx);
}提示
牢记前缀分工:读数据用 ctx(player() / get()),做动作用 qcl(itemGive / addPotion / …)。写成 ctx.itemGive(...) 会因方法不存在而报错。
引用方式:
qinhruins:affix_example.js:onActivate—— 显式调onActivateqinhruins:affix_example.js—— 省略函数名,调main
5. 降级(引擎不可用时)
QR 经 反射 桥接 QCL 的 QinhScriptBridge。GraalJS 运行时未就绪时,脚本词缀 静默跳过(打一条 warning,不影响秘境其他词缀生效):
[QR-JS] GraalJS 未就绪,跳过词缀脚本 ref=qinhruins:affix_example.js:onActivate
(需 CoreLib 拉到 GraalJS 且 javascript.enabled=true)GraalJS 需要 Paper / Purpur 运行时拉到 GraalJS 库且 javascript.enabled=true。如果你的脚本词缀没生效,先查这条日志。
6. 何时用脚本、何时用声明式词缀
| 需求 | 用 |
|---|---|
| 刷怪 ×N / 怪等级 +N / 禁疗 / 限时 / 缓慢虚弱 / 贪婪鎏金等 | 声明式词缀(无引擎依赖,见 词缀系统) |
| 按层数发不同物品 / 发钱 / 加临时属性 / 复杂分支 | type: script JS 词缀 |
声明式优先 —— 零引擎依赖、永不降级。