JavaScript 脚本
EmakiLevel 通过 CoreLib 的脚本系统注册脚本模块,模块 ID 为 level。脚本中通过 emaki.module("level") 获取模块门面,用于查询等级类型与玩家等级、注册经验调整规则和升级钩子。
本页只介绍 EmakiLevel 专属的脚本方法、注册字段、上下文和示例。通用脚本机制请阅读 CoreLib JavaScript 脚本系统。
调用任何业务方法前,先用
available()守卫。EmakiLevel 是 CoreLib 的 softdepend。
获取模块
function main(ctx) {
const level = emaki.module("level");
if (!level.available()) {
return { skipped: true, message: "EmakiLevel 不可用" };
}
// ...
return true;
}基础探针方法
| 方法 | 返回 | 说明 |
|---|---|---|
available() | boolean | 模块是否可用。 |
EmakiLevel 模块门面只提供
available()探针。
查询方法
| 方法 | 返回 | 说明 |
|---|---|---|
typeIds() | list | 返回所有等级类型 id,已排序。 |
type(typeId) | map | 返回单个类型详情;不存在时返回空 Map。 |
level(playerUuid, typeId) | int | 玩家某类型当前等级;UUID 非法时返回 0。 |
exp(playerUuid, typeId) | double | 当前经验;UUID 非法时返回 0。 |
totalExp(playerUuid, typeId) | double | 累计总经验;UUID 非法时返回 0。 |
requiredExp(playerUuid, typeId, targetLevel) | double | 升到目标等级所需经验;UUID 非法时返回 0。 |
playerUuid必须是合法的 UUID 字符串,内部用UUID.fromString解析,失败即返回 0。
type(typeId) 返回的 Map 字段:id、displayName、description、primary、enabled、startLevel、maxLevel、autoUpgrade、manualUpgrade、attributes。
经验规则
经验规则在玩家获得经验时执行,可以读取上下文并调整最终经验或取消本次获取。
| 方法 | 返回 | 说明 |
|---|---|---|
registerExpRule(definition) | boolean | 注册一条经验规则。 |
registerExpRule(id, definition) | boolean | 重载:把 id 合并进 definition 后注册。 |
unregisterExpRule(id) | void | 按 id 注销规则。 |
registeredExpRules() | list | 返回已注册经验规则 id 列表。 |
规则 definition 字段
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
id | string | 是 | 无 | 规则唯一 id,会被规范化;为空注册失败。 |
priority | int | 否 | 0 | 优先级,数值小者先执行;相同按 id 排序。 |
typeIds | string / list | 否 | 空(全部类型) | 限定生效的等级类型,也可用 types。 |
reasons | string / list | 否 | 空(全部来源) | 限定生效的经验来源 reason。 |
function | string | 否 | modifyExp | 规则回调函数名,也可用 execute。 |
timeoutMillis | long | 否 | 引擎默认超时 | 单次脚本超时。 |
规则回调的 ctx 字段
| 字段 | 类型 | 说明 |
|---|---|---|
ruleId | string | 当前规则 id。 |
playerUuid | string | 玩家 UUID。 |
typeId | string | 等级类型 id。 |
reason | string | 经验来源。 |
originalAmount | double | 原始经验值。 |
currentAmount | double | 当前累积修改后的经验值。 |
multiplier | double | 当前倍率。 |
multipliedAmount | double | 应用倍率后的经验值。 |
dailyLimit | double | 当日经验上限。 |
gainedToday | double | 当日已获得经验。 |
规则回调的返回字段
| 返回字段 | 类型 | 说明 |
|---|---|---|
cancel | boolean | true 则本次经验置 0。 |
actualAmount 或 amount | number | 显式设定结果经验(取非负值,优先于 multiplier)。 |
multiplier | number | 否则用 当前值 × multiplier(取非负值)。 |
message | string | 写入轨迹的消息。 |
返回非对象或执行失败时保持原值并记录轨迹。
升级钩子
升级钩子在玩家升级后触发,用于发奖励、播报等副作用。
| 方法 | 返回 | 说明 |
|---|---|---|
onLevelUp(definition) | boolean | 注册一个升级钩子。 |
onLevelUp(id, definition) | boolean | 重载:把 id 合并进 definition 后注册。 |
unregisterLevelUpHook(id) | void | 按 id 注销升级钩子。 |
registeredLevelUpHooks() | list | 返回已注册升级钩子 id 列表。 |
钩子 definition 字段
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
id | string | 是 | 无 | 钩子唯一 id;为空注册失败。 |
typeIds | string / list | 否 | 空(全部类型) | 限定触发的等级类型,也可用 type。 |
function | string | 否 | onLevelUp | 回调函数名,也可用 execute。 |
timeoutMillis | long | 否 | 引擎默认超时 | 单次脚本超时。 |
升级钩子无 priority 字段,多个钩子按 id 字典序依次触发。
钩子回调的 event 字段
| 字段 | 类型 | 说明 |
|---|---|---|
hookId | string | 钩子 id。 |
playerUuid | string | 玩家 UUID。 |
playerName | string | 玩家名。 |
typeId | string | 等级类型 id。 |
oldLevel | int | 升级前等级。 |
newLevel | int | 升级后等级。 |
oldExp | double | 升级前经验。 |
newExp | double | 升级后经验。 |
cause | string | 升级原因。 |
requiredExp | double | 所需经验。 |
查询示例
EmakiLevel 自带触发型示例脚本 scripts/examples/level_status.js:
function main(ctx) {
const level = emaki.module("level");
const typeIds = level.typeIds();
const typeId = typeIds.size() > 0 ? typeIds.get(0) : "main";
let currentLevel = 0;
let currentExp = 0;
if (emaki.player.exists() && typeId) {
currentLevel = level.level(emaki.player.uuid(), typeId);
currentExp = level.exp(emaki.player.uuid(), typeId);
emaki.player.sendMessage("[EmakiJS] 等级模块状态: type=" + typeId + " level=" + currentLevel + " exp=" + currentExp);
}
return {
success: true,
output: {
level_available: level.available(),
type_count: typeIds.size(),
sample_type: String(typeId || ""),
current_level: currentLevel,
current_exp: currentExp
}
};
}注册示例
EmakiLevel 自带扩展型示例脚本 scripts/examples/level_exp_rule.js:
function register() {
const level = emaki.module("level");
level.registerExpRule({
id: "js_weekend_bonus",
priority: 10,
function: "modifyExp"
});
level.onLevelUp({
id: "js_levelup_message",
function: "onLevelUp"
});
}
function modifyExp(ctx) {
const day = new Date().getDay();
if (day === 0 || day === 6) {
return {
multiplier: 2.0,
message: "weekend bonus"
};
}
return {};
}
function onLevelUp(event) {
emaki.logger.info("Level up hook: " + event.playerName + " " + event.typeId + " " + event.oldLevel + " -> " + event.newLevel);
return true;
}启用扩展脚本
把脚本放到 CoreLib 的全局扩展目录后重载:
plugins/EmakiCoreLib/scripts/extensions/global/level_exp_rule.js/corelib script reload示例文件默认释放到
plugins/EmakiCoreLib/scripts/examples/,不会自动启用。
脚本调试
开启名为 script 的调试子模块后,EmakiLevel 的 JS 规则每次执行都会把逐条规则的执行轨迹(trace)输出到服务端控制台,便于服务器管理员调试脚本规则。
开启命令:
/elv debug module scripttrace 输出字段:规则 id、before(执行前值)、after(执行后值)、message。该输出位于服务端控制台,面向服务器管理员调试,不会发送给玩家。
注意事项
- 所有注册方法都要求 CoreLib 脚本系统已启用,否则注册返回
false或静默跳过。 - CoreLib 缺失时模块自动降级,规则和钩子不生效但不会报错。
- 经验规则按优先级升序执行(数值小者先)。