[MD]
### 技能脚本写法迁移
- **技能脚本的写法整体换新, 大部分动作行会自动改写, 但技能文件有四处必须你自己动手。** 首次启动时 CoreLib 会把 `plugins/` 下所有 Emaki 插件的配置文件改写成新写法, `skills/` 目录里的技能文件也在范围内, 只做一次。每个被改过的文件旁边都会留一份 `.legacy-backup` 后缀的原文件备份。万一某一行转换不成功, 插件不会拿这行去覆盖你的配置, 而是单独写到一个 `.v2-failed` 文件里、原配置保持不动, 控制台也会列出是哪个文件的哪一行。
- **`ray` 和 `aoe_damage` 两个动作不会被自动改写, 而且不会有任何提示。** 自动改写认不出这两个名字, 会当成普通文字原样留下, 控制台也不会报。请务必自己搜一遍技能文件:
- `ray range=18 width=2 save=target` → `looking_at range=18 width=2 | keep`, 也就是先用 `looking_at` 选中视线上的目标, 再用 `keep` 记下来交给 `hit` 阶段。
- `aoe_damage amount=20 radius=4 center=target filter=hostile` 拆成两段写: `nearby radius=4 limit=20 | damage amount=20`。`nearby` 默认就不含玩家自己, 等价于旧的 `filter=hostile`。
- `aoe_damage` 的 `shape=cylinder` 没有对应写法, `nearby` 只做球形范围。
- 旧的 `%aoe_hit_count%` 命中计数没有对应变量, 用到它的提示文字请改掉。
- **技能自己定义的变量, 引用时要加 `var.` 前缀。** 自动改写只管 `%player%`、`%target_name%` 这类通用占位符, 你在技能里定义的 `damage`、`radius` 这些不在范围内。现在只认 `%var.damage%` 这种写法, 还写 `%damage%` 的话取不到值。
- **`skill_parameters` 这一段已经不再被读取, 请把里面的内容并进 `variables` 段。** 原先技能参数和技能变量是两段, 现在合成一段, 段内的 `expression:` 字段改叫 `value:`。升级配置里按里程碑等级覆盖参数的 `parameters:` 段同样不再被读取, 请删掉。
- 新旧写法对照:
```yaml
# 旧写法
skill_parameters:
damage:
type: "expression"
expression: "18 + (%level% - 1) * 4"
variables:
element: "fire"
script:
actions:
cast:
- "playsound sound=entity.blaze.shoot volume=1"
- "ray range=18 width=%radius% save=target"
hit:
- "damage target=target amount=%damage%"
- "@if='%level% >= 3' ignite target=target ticks=40"
# 新写法
variables:
damage:
type: "expression"
value: "18 + (%level% - 1) * 4"
element: "fire"
script:
actions:
cast:
- "self | play_sound sound=entity.blaze.shoot volume=1"
- "looking_at range=18 width=%var.radius% | keep"
hit:
- "inherited | damage amount=%var.damage%"
- "if %var.level%>=3 [ inherited | ignite duration=40t ]"
```
- **原先用 JS 脚本写的技能动作要重做。** JS 脚本功能整体取消了, 也没有自动转换的办法, 请改用技能脚本里的动作实现。随包的两个示例脚本 `scripts/examples/js_lightning_strike.js` 与 `scripts/examples/skills_upgrade_success.js` 一并删除。
- `projectile` 投射物动作有两点变化要知道: 命中的实体不会传给后面的动作行, 后续行要自己选目标; 发射后立刻往下执行, 不等飞行结束, 想延后的效果请用 `after` 时间段。随包的投射物示例已经改成在施法瞬间用 `looking_at` 锁定目标再 `keep`, 所以爆炸中心由「投射物实际命中的位置」变成了「施法瞬间视线锁定的位置」。
### 技能升级界面
- **新增技能升级界面, 开箱即用。** 打开技能界面, 在已装配技能的槽位上**右键**就能进入。界面里能看到当前等级与升级后等级、要花的货币、要交的材料 (带「拥有/需要」对照, 不够的显示红色)、成功率与失败惩罚, 确认后直接升级。Shift+右键仍然是原来的触发器操作。
- 界面模板是新增的 `gui/upgrade_gui.yml`, 布局、材质、文案都能改。想给某个技能单独换一套界面, 在该技能的 `upgrade.gui_template` 里填模板文件的 `id` 即可; 不填就用内置的 `upgrade_gui`, 填了不存在的 id 会回落到内置模板并在控制台提示一句。
- 注意旧配置里的默认值 `upgrade/default` 指向一个并不存在的模板, 这个键以前也从来没生效过。新的默认值是 `upgrade_gui`, 沿用旧技能文件的话建议改一下, 或者直接删掉这一行。
- 货币、材料两份清单改成每项各占一行。模板里只写一个 `%currencies%` 或 `%materials%` 占位符, 插件会按实际条目数自动展开成对应行数, 条目文案见语言文件的 `gui.upgrade_currency_entry`、`gui.upgrade_material_entry`。
- 技能界面的技能槽 lore 补上了完整操作说明 (左键卸下、右键升级、Shift+左键设触发器), 并写明技能必须绑定触发器才能释放。触发器选择界面的每一项改用 `%status%` 占位符, 会显示「点击绑定」「当前已绑定」或者具体的冲突提示, 不再只显示一行冲突文字。
- 补齐了升级界面与技能界面共 20 多个中英文文案键。其中「升级条件未满足」这条提示以前由代码产出但语言文件里没有, 一直显示不出来, 现在补上了。
### 触发器与提示
- **修复被其他插件拦下来的操作还是会放技能。** 原先在 WorldGuard、领地保护这类插件禁止交互的区域里, 左右键、丢弃 (Q 键)、切换快捷栏这些操作虽然被拦住了, 技能却照样释放, 照样扣蓝、照样进冷却。现在这些被拦下的操作不再触发技能。如果你的服务器暂时离不开旧行为, 可以在 `config.yml` 把新增的 `trigger_settings.legacy_dispatch_cancelled_events` 改成 `true` 先过渡, 启用后控制台会提示一次。这个开关只保留一个小版本, 下个大版本会删掉。
- **修复空手挥动不触发技能。** 左右键触发器原先的判定方式会把空手挥动一起挡掉, 现在只在方块交互真正被禁止时才不触发。
- **修复技能放不出来却什么提示都没有。** 原先技能脚本写错了 (动作名写错、语法写错、必填参数漏了), 玩家只会看到一句笼统的失败提示, 服主也不知道错在哪。现在玩家会收到分类提示, 控制台同时输出带技能 ID 与行号的警告, 还会在启动时的配置预检里直接列出来。
- **修复施法模式动作栏每 10 tick 刷一次警告。** 技能槽还没绑定触发器时, 动作栏显示会拿空的触发器 ID 去查询, 导致控制台反复刷警告, 现在不会了。
- 配置预检与技能脚本的报错文案改成了给人看的句子, 会说明问题出在哪一行、哪个动作, 不再直接抛出内部代号。预检的问题行按严重级别整行着色, 警告为黄色、错误为红色。
- 未知动作的报错不再附上「当前可用动作」的全量清单, 缺参数的报错也去掉了恒为「-」的无用字段, 控制台输出短了很多。
- **配置改错了不会再让插件带着半份配置跑。** 现在重载时先校验再应用, 校验不通过就保留上一份有效配置并报错, 不会出现一部分新配置一部分旧配置的情况。
### 开发者相关
- **`emaki-skills-protocol` 构件不再单独发布。** 原先 `emaki.jiuwu.craft.skills.protocol` 包下的 `EquipmentSkillPayload`、`EquipmentSkillPdcCodec`、`RawSnapshot`、`SkillPdcMutation` 四个类并入 `emaki-skills-api` 的 `emaki.jiuwu.craft.skills.api.pdc` 包。二次开发需要改两处:
- 依赖坐标从 `emaki.jiuwu.craft:emaki-skills-protocol` 换成 `emaki.jiuwu.craft:emaki-skills-api`。
- import 从 `emaki.jiuwu.craft.skills.protocol.*` 改为 `emaki.jiuwu.craft.skills.api.pdc.*`。
- 三个 PDC key (`emaki_skills` 命名空间下的 `item.skills.ids`、`item.skills.active_slot`、`item.skills.triggers`) 与序列化格式逐字未变, 值类型仍为 `PersistentDataType.STRING`, 技能 ID 仍以 `;` 连接。**现网物品数据不受影响, 对服主没有配置变更**, 已有携带技能的物品继续可用。
- `EmakiSkillsApiProvider` 已移除, 直接使用 `EmakiSkillsApi` 的静态方法。`EmakiSkillsApi.available()` 由 `status()` 替代 (返回 `ApiStatus`)。
- 新增三层公开 API: `EmakiSkillsApi.catalog()` (技能定义与玩家状态只读查询)、`operations()` (释放、装备、升级等状态变更)、`extensions()` (注册外部技能来源)。三者均非 null, 插件未加载时返回稳定的不可用实现, 不再抛异常, 调用方改为判断 `status()` 或按 `FailureKind` 分类。
- `EmakiSkillsApi.Bridge` 标记 `@ApiStatus.NonExtendable`, 第三方插件不得实现。访问器不要缓存到字段, 重载会换掉底层实现。
- 技能脚本动作的自建 SPI 整体移除: `SkillScriptAction`、`SkillScriptActionRegistry`、`SkillScriptContext`、`SkillActionResult`、`SkillActionErrorType`、`SkillActionParameter`、`SkillActionParameterType`、`SkillActionExecutionMode` 九个类型不再提供, `SkillExtensions` 也移除了脚本动作注册入口。第三方自定义动作改为向 CoreLib 注册管道段。
- 新增 `SkillPostCastEvent` (技能释放完成后触发, 覆盖主动触发器、被动触发器、管道施法段与公开 API 四条路径)。
- 新增 `model` 包公开视图类型: `PlayerSkillView`、`SkillDefinitionView`、`SkillCastOutcome`、`SkillUpgradeOutcome`、`SkillUpgradePreview`; 新增 `SkillSourceEntry`、`SkillSourceProvider`、`SkillSourceRegistration` 用于外部技能来源接入。
### 升级说明
- 需要先把 EmakiCoreLib 升到 `4.7.0`。
- **升级前请备份 `plugins/EmakiSkills/` 整个目录。**
- 技能文件里大部分动作行由插件自动改写, 但下面四处要你自己动手:
- `ray` 与 `aoe_damage` 两个动作要按上面的对照改写, 这两个不会被自动改写也不会报错。
- 技能自己定义的变量, 引用处要加 `var.` 前缀。
- `skill_parameters` 段并进 `variables` 段, 段内 `expression:` 改成 `value:`。
- 用 JS 脚本写的技能动作要改成用技能脚本里的动作实现。
- 沿用旧技能文件的话, 记得把 `upgrade.gui_template` 从 `upgrade/default` 改成 `upgrade_gui` 或直接删掉这一行, 并删掉升级里程碑等级下的 `parameters:` 段。
- 启动后请看一眼控制台的配置预检, 技能脚本的错误会带技能 ID 与行号列出来。
- 玩家档案路径、技能等级键与物品上的技能数据都没有变化, 已有携带技能的物品继续可用, 不需要迁移。
[/MD]