JavaScript 脚本
EmakiSkills 通过 CoreLib 的脚本系统注册脚本模块,模块 ID 为 skills。emaki.module("skills") 在不同上下文中返回不同对象:
- 在普通触发脚本(
runjs动作、examples/等)中,返回查询门面ScriptSkillsModuleApi,用于探针和查询已注册技能脚本动作。 - 在 Skills 专属扩展脚本(
extensions/skills/目录,通过register()加载)中,返回注册 API,用于注册自定义技能脚本动作。
本页只介绍 EmakiSkills 专属内容。通用脚本机制请阅读 CoreLib JavaScript 脚本系统。
调用任何业务方法前,先用
available()守卫。EmakiSkills 是 CoreLib 的 softdepend。
查询门面(触发脚本上下文)
在普通触发脚本中,emaki.module("skills") 返回查询门面。
| 方法 | 返回 | 说明 |
|---|---|---|
available() | boolean | 模块是否可用。 |
hasScriptAction(actionId) | boolean | 注册表中是否存在该技能脚本动作 id。 |
registeredScriptActions() | list | 返回所有已注册技能脚本动作 id 列表。 |
查询门面只有上述方法,没有
ready()/apiVersion()/pluginName()。返回的列表在 JS 中用.size()取长度。
触发脚本可通过 emaki.context 读取技能上下文:
| 读取方式 | 键 | 说明 |
|---|---|---|
emaki.context.placeholder("skills_skill_id") | skills_skill_id | 技能 id(占位符形式)。 |
emaki.context.attribute("skill_id") | skill_id | 技能 id(attribute 形式)。 |
触发示例
EmakiSkills 自带触发型示例脚本 scripts/examples/skills_upgrade_success.js:
function main(ctx) {
const skills = emaki.module("skills");
const skillId = emaki.context.placeholder("skills_skill_id") || emaki.context.attribute("skill_id");
if (emaki.player.exists()) {
emaki.player.sendMessage("[EmakiJS] 技能升级成功脚本: " + skillId + " skills=" + skills.available());
}
return {
success: true,
output: {
skill_id: String(skillId || ""),
skills_available: skills.available(),
registered_script_actions: skills.registeredScriptActions().size()
}
};
}注册 API(扩展脚本上下文)
在 extensions/skills/ 目录下的扩展脚本中,CoreLib 调用脚本的 register() 函数并把注册 API 绑定为 emaki.module("skills")。
| 方法 | 返回 | 说明 |
|---|---|---|
registerAction(definition) | boolean | 注册一个自定义技能脚本动作。 |
unregisterAction(actionId) | void | 按 id 注销技能脚本动作。 |
动作 definition 字段
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
id | string | 是 | 无 | 动作 id,会被规范化;为空注册失败。 |
category | string | 否 | javascript | 动作分类。 |
description | string | 否 | 同 id | 描述。 |
parameters | list | 否 | 空 | 参数定义列表,见下表。 |
executionMode | string | 否 | SYNC | 执行模式,SYNC 或 ASYNC_IO(大小写不敏感,非法回退 SYNC)。 |
timeoutMillis | number | 否 | 引擎默认超时 | 单次脚本超时。 |
execute | string | 否 | execute | 执行函数名。 |
validate | string | 否 | 空(不校验) | 校验函数名。 |
parameters 每个元素的字段:
| 字段 | 类型 | 必填 | 默认 | 说明 |
|---|---|---|---|---|
name | string | 是 | 无 | 参数名,会被规范化;为空跳过该参数。 |
type | string | 否 | STRING | 参数类型枚举(大小写不敏感,非法回退 STRING)。 |
required | bool / string | 否 | false | 是否必填。 |
defaultValue | string | 否 | 空 | 默认值,仅可选参数使用。 |
description | string | 否 | 空 | 描述。 |
执行与校验函数
execute(ctx, args):执行函数,ctx是技能脚本上下文 API(见下),args是参数 Map。validate(args):校验函数,仅收到参数 Map。
执行模式 ASYNC_IO 在异步线程执行,SYNC 在调用线程同步执行。返回值映射为技能动作结果:{skipped:true} 跳过,成功返回 output / return / message,{success:false} 失败。
技能脚本上下文 API(ctx)
| 方法 | 返回 | 说明 |
|---|---|---|
skillId() | string | 当前技能 id。 |
triggerId() | string | 触发器 id。 |
variable(key) | string | 读取变量。 |
setVariable(key, value) | void | 设置变量。 |
variables() | map | 全部变量。 |
caster() | entity | 施法者实体包装。 |
target() | entity | 目标实体包装。 |
hasTarget() | boolean | 是否有目标。 |
setTarget(entity) | void | 设置目标。 |
targetLocation() | map | 目标位置,键 world / x / y / z / yaw / pitch。 |
runAction(actionId, arguments) | boolean | 执行 CoreLib 动作。 |
runActionLine(line) | boolean | 执行单行动作脚本。 |
castMythic(mythicSkillId) | boolean | 释放 MythicMobs 技能。 |
castMythic(mythicSkillId, parameters) | boolean | 带参数释放 MythicMobs 技能。 |
applyDamage(target, damageTypeId, baseDamage) | boolean | 通过 EmakiAttribute 施加伤害。 |
applyDamage(target, damageTypeId, baseDamage, damageContext) | boolean | 带伤害上下文施加伤害。 |
ctx.state 是跨调用共享状态访问器:get(key)、set(key, value)、has(key)、remove(key)。
注册示例
EmakiSkills 自带扩展型示例脚本 scripts/examples/js_lightning_strike.js:
function register() {
const skills = emaki.module("skills");
skills.registerAction({
id: "js_lightning_strike",
category: "javascript",
description: "攻击当前技能目标,并可选择通过EmakiAttribute传递伤害",
executionMode: "SYNC",
timeoutMillis: 1000,
parameters: [
{ name: "damage", type: "DOUBLE", required: false, defaultValue: "10", description: "应用基础伤害" },
{ name: "damage_type", type: "STRING", required: false, defaultValue: "lightning", description: "Emaki属性伤害类型ID" }
],
validate: "validateLightning",
execute: "executeLightning"
});
}
function validateLightning(args) {
const damage = Number(read(args, "damage", "10"));
if (!Number.isFinite(damage) || damage <= 0) {
return { success: false, message: "伤害必须是一个正数" };
}
return true;
}
function executeLightning(ctx, args) {
const caster = ctx.caster();
const target = ctx.target();
if (!target.exists()) {
return { skipped: true, message: "未选择目标" };
}
const damage = Number(read(args, "damage", "10"));
const damageType = String(read(args, "damage_type", "lightning"));
let applied = false;
const attribute = emaki.module("attribute");
if (attribute.available()) {
applied = attribute.applyDamage(caster, target, damageType, damage, {
source: "js_lightning_strike",
skill_id: ctx.skillId(),
trigger_id: ctx.triggerId()
});
}
if (!applied) {
target.damage(damage);
}
return { success: true, message: "JavaScript闪电技能执行成功" };
}
function read(object, key, fallback) {
if (object == null) {
return fallback;
}
if (typeof object.get === "function") {
const value = object.get(key);
return value == null ? fallback : value;
}
const value = object[key];
return value == null ? fallback : value;
}启用扩展脚本
Skills 扩展脚本加载自 CoreLib 脚本根目录下的 extensions/skills/:
plugins/EmakiCoreLib/scripts/extensions/skills/js_lightning_strike.js/corelib script reload示例文件默认释放到
plugins/EmakiCoreLib/scripts/examples/,不会自动启用。需要启用时复制到extensions/skills/再重载。
内置技能脚本动作
EmakiSkills 内置了一批 Java 技能脚本动作,技能配置可直接调用:
| 动作 id | 分类 | 主要参数 |
|---|---|---|
message | feedback | text(必填);target(默认 caster)。 |
sound | feedback | sound(必填);volume=1;pitch=1;at=caster。 |
particle | feedback | particle(必填);at=target;count=1;speed=0。 |
ray | target | range=16;width=1;save=target(保存到 state 的键)。 |
damage | combat | amount(必填);target=target;damage_type=generic;element=空。 |
aoe_damage | combat | amount(必填);radius=5;center=target;shape=sphere;filter=hostile;max_targets=20;exclude_caster=true。 |
projectile | combat | speed=1.5;gravity=0.05;lifetime=60;hit_radius=0.5;pierce=0;homing=false;particle=FLAME;damage=0;direction=look。 |
ignite | combat | ticks(必填);target=target。 |
heal | combat | amount(必填);target=caster。 |
mythic | bridge | skill(必填,Mythic skill id)。 |
目标解析约定:
caster/self/player为施法者;look为视线前方约 3 格;其它字符串先查 state 共享值,否则使用目标实体。
注意事项
- 注册方法要求 CoreLib 脚本系统已启用,否则注册返回
false或静默跳过。 applyDamage经 EmakiAttribute 反射调用,EmakiAttribute 缺失时返回 false;target 须为生物实体。- CoreLib 缺失时模块自动降级。
- 扩展脚本重载时会先注销旧注册动作,再重新执行
register(),避免热重载残留。