技能定义
技能定义文件存放在 skills/ 目录下,每个文件定义一个技能。技能定义描述的是"这个技能叫什么、冷却多久、消耗什么资源、对应哪个 MythicMobs 技能",而不是技能的实际效果——效果由 MythicMobs 那边配置。
完整 YAML 格式
# skills/example_fireball.yml
# 技能唯一标识
id: "fireball"
# 显示名称(支持 MiniMessage)
display_name: "<red>火球术"
# 技能描述
description:
- "<gray>向前方发射一颗火球"
- "<gray>造成范围伤害"
# GUI 中显示的图标材质
icon_material: "FIRE_CHARGE"
# 对应的 MythicMobs 技能 ID
mythic_skill: "Fireball"
# 技能冷却时间(tick,20 tick = 1 秒)
cooldown_ticks: 100
# 全局冷却时间(tick)—— 释放此技能后所有技能共享的冷却
global_cooldown_ticks: 20
# Lore 别名 —— 用于从装备 Lore 中匹配解锁此技能
lore_aliases:
- "火球术"
- "Fireball"
# GUI 分类标签
ui_category: "攻击"
# GUI 排序权重
sort_order: 1
# 技能激活类型:active(主动,默认)/ passive(被动)
trigger_type: "active"
# 是否启用
enabled: true
# ============================================================
# 技能参数 (Skill Parameters)
# 定义技能的数值参数,会随等级变化并注入到 MythicMobs
# ============================================================
skill_parameters:
# 数值型参数:用公式计算,{level} 会被替换为当前技能等级
damage:
type: "expression"
expression: "{base_damage} + {level_bonus}"
variables:
base_damage:
type: "constant"
value: 18
level_bonus:
type: "expression"
expression: "({level} - 1) * 4"
decimals: 1 # 保留 1 位小数
min: 0 # 最小值
# 另一个数值参数
radius:
type: "expression"
expression: "2 + floor(({level} - 1) / 3) * 0.5"
decimals: 2
min: 1
# 点燃时长参数
ignite_ticks:
type: "expression"
expression: "40 + ({level} - 1) * 6"
decimals: 0
min: 20
# 字符串型参数:直接传递文本
element:
type: "string"
value: "fire"
# 带变量替换的字符串参数
element_label:
type: "string"
value: "fire_lv_{level}"
# 布尔型参数:可以用比较表达式
empowered:
type: "boolean"
expression: "{level} >= 5 && {has_target} == 1"
default: false
# 随机文本参数:从候选行中随机抽取
random_bonus_lines:
type: "random_text"
rolls: "{bonus_rolls}"
allow_duplicates: false
variables:
bonus_rolls:
type: "constant"
value: 2
物理攻击:
type: "range"
min: 2
max: 6
物理防御:
type: "uniform"
min: 1
max: 4
lines:
- "物理攻击: +{物理攻击}"
- "物理防御: +{物理防御}"
# ============================================================
# 升级配置 (Upgrade)
# 定义技能的升级规则、费用和成功率
# ============================================================
upgrade:
enabled: true
max_level: 10
failure_penalty: "none" # none = 失败不降级;downgrade = 失败降一级
# 升级费用(全局默认)
economy:
enabled: true
currencies:
- provider: "vault"
base_cost: 1200
cost_formula: "{base_cost} * {target_level}"
display_name: "<gold>金币</gold>"
# 成功率表(键 = 目标等级)
success_rates:
2: 100.0
3: 95.0
5: 80.0
8: 60.0
10: 40.0
# 特定等级的额外配置
levels:
5:
materials:
- item: "minecraft-blaze_rod"
amount: 1
success_actions:
- "sendmessage text=<yellow>火球术达到 V 级!"
10:
economy:
enabled: true
currencies:
- provider: "vault"
base_cost: 50000
cost_formula: "{base_cost}"
display_name: "<gold>金币</gold>"
materials:
- item: "minecraft-nether_star"
amount: 1
# ============================================================
# 资源消耗 (Resource Costs)
# 施法前检查并消耗的资源列表
# ============================================================
resource_costs:
# 本地资源消耗
- type: "local-resource"
target_id: "mana"
amount: 30
operation: "CONSUME" # CONSUME = 检查并扣除, CHECK = 仅检查
failure_message: "<red>法力不足!需要 30 点法力。"
# EmakiAttribute 资源消耗(需要 EA 软依赖)
- type: "ea-resource"
target_id: "mp"
amount: 20
operation: "CONSUME"
failure_message: "<red>MP 不足!"
# EmakiAttribute 属性检查(仅检查,不消耗)
- type: "ea-attribute-check"
target_id: "intelligence"
amount: 50
operation: "CHECK"
failure_message: "<red>智力不足!需要 50 点智力。"关于 global_cooldown_ticks:这个冷却是"释放此技能后,所有技能都要等的时间"。和 cooldown_ticks(只影响这个技能本身)不同,它影响的是全局。典型用法是防止玩家瞬间连放多个不同技能。
关于 lore_aliases:这是 Lore 解锁机制的关键字段。系统扫描装备 Lore 时,只要发现包含列表中任意一个文本,就认为这件装备解锁了这个技能。支持多个别名是为了兼容不同语言或不同写法。
资源消耗类型
| 类型 | 说明 |
|---|---|
local-resource | 本地资源(由 Skills 自身管理,如法力值) |
ea-resource | EmakiAttribute 资源(如 MP、SP),需要 EA 软依赖 |
ea-attribute-check | EmakiAttribute 属性检查(只读,不消耗),用于设置施法门槛 |
三种类型可以混用。比如一个技能可以同时消耗本地法力和 EA 的 MP,还要求智力达到 50。
operation 操作类型
| 操作 | 说明 |
|---|---|
CONSUME | 检查资源是否充足,充足则扣除 |
CHECK | 仅检查资源是否充足,不扣除。适合用于属性门槛检查 |
本地资源定义
本地资源是 Skills 自己管理的资源系统,独立于 EmakiAttribute。最典型的用法就是法力值。定义文件存放在 resources/ 目录下。
# resources/mana.yml
# 资源唯一标识
id: "mana"
# 显示名称
display_name: "<blue>法力"
# 最大值
max: 100
# 默认当前值
default_current: 100
# 自然恢复量
regen_amount: 5
# 恢复间隔(tick)
regen_interval_ticks: 40
# 最小值钳制
clamp_min: 0
# 最大值钳制(-1 = 使用 max)
clamp_max: -1字段说明
| 字段 | 类型 | 说明 |
|---|---|---|
id | string | 资源唯一标识 |
display_name | string | 显示名称 |
max | double | 最大值 |
default_current | double | 玩家首次加入时的初始值 |
regen_amount | double | 每次恢复的量 |
regen_interval_ticks | int | 恢复间隔(tick),40 tick = 2 秒 |
clamp_min | double | 最小值下限,资源不会低于这个值 |
clamp_max | double | 最大值上限,-1 表示使用 max 字段的值 |
为什么有 clamp_max 和 max 两个字段?max 是资源的标准上限,clamp_max 是硬上限。如果某些效果临时提升了资源上限超过 max,clamp_max 可以作为最终的天花板。设为 -1 就是不额外限制。
默认技能
| 技能 ID | 名称 | 类型 | MythicMobs 技能 | 冷却 | 消耗 |
|---|---|---|---|---|---|
fireball | 火球术 | 主动 | Fireball | 5 秒 | 30 法力 |
attack_passive | 命中回响 | 被动 | ExampleAttackPassive | 2 秒 | 无 |
被动技能定义
被动技能通过 trigger_type: "passive" 标记,并用 passive_triggers 列表声明触发事件。被动技能不需要施法模式,不占用槽位,由游戏事件自动触发。
# skills/example_attack_passive.yml
id: attack_passive
display_name: "<gradient:#FFD166:#EF476F>命中回响</gradient>"
description:
- "<gray>被动技能示例:命中实体时自动触发</gray>"
- "<gray>玩家不可在 GUI 中修改此技能的触发器</gray>"
icon_material: "ECHO_SHARD"
mythic_skill: "ExampleAttackPassive"
# 标记为被动技能
trigger_type: "passive"
# 被动触发器列表(可以声明多个)
passive_triggers:
- "attack"
cooldown_ticks: 40
global_cooldown_ticks: 0
lore_aliases:
- "命中回响"
ui_category: "passive"
sort_order: 100
enabled: true
resource_costs: []主动 vs 被动对比
| 维度 | 主动技能 | 被动技能 |
|---|---|---|
trigger_type | active(默认) | passive |
passive_triggers | 无 | 必须声明触发器 ID 列表 |
| 触发方式 | 玩家进入施法模式后按键 | 游戏事件自动触发 |
| 施法模式 | 必须在施法模式中 | 不需要 |
| 槽位绑定 | 需要装备到槽位 + 绑定触发器 | 不使用槽位 |
| GUI 展示 | 出现在技能池,可装备 | 不出现在技能池 |
| 触发器选择 | 玩家可在 GUI 中自由选择 | 固定写在 YAML,不可修改 |
| 冷却/资源检查 | ✅ | ✅(与主动技能相同) |
被动触发器 ID 列表
| 触发器 ID | 说明 | MythicMobs target |
|---|---|---|
attack | 攻击命中实体 | 被攻击实体 |
damaged_by_entity | 被实体伤害 | 攻击者 |
damaged | 受到任意伤害 | 无 |
death | 玩家死亡 | 无 |
kill_entity | 击杀非玩家实体 | 被杀实体 |
kill_player | 击杀玩家 | 被杀玩家 |
shoot_bow | 射出弓箭 | 无 |
arrow_hit | 箭矢命中实体 | 命中实体 |
arrow_land | 箭矢落地 | 无(传递落点位置) |
shoot_trident | 掷出三叉戟 | 无 |
trident_hit | 三叉戟命中实体 | 命中实体 |
trident_land | 三叉戟落地 | 无(传递落点位置) |
break_block | 破坏方块 | 无(传递方块位置) |
place_block | 放置方块 | 无(传递方块位置) |
drop_item | 丢弃物品 | 掉落物实体 |
shift_drop_item | Shift+丢弃物品 | 掉落物实体 |
swap_items | 交换主副手 | 无 |
shift_swap_items | Shift+交换主副手 | 无 |
login | 玩家登录 | 无 |
sneak | 开始潜行 | 无 |
teleport | 传送 | 无(传递目标位置) |
timer | 定时触发 | 无 |
timer 触发器的检查间隔由 passive_trigger_settings.timer_interval_ticks 配置,默认 20 tick(1 秒)。
MythicMobs target 传递
被动技能触发时,系统会把事件中的目标实体和位置传递给 MythicMobs。比如 attack 触发器会把被攻击的实体作为 @target,arrow_hit 会把被命中的实体作为 @target。没有目标实体的触发器(如 timer、death)会以玩家自身为施法者,不传递额外目标。
技能参数系统
技能参数让你可以在 YAML 里定义技能的数值(比如伤害、范围、持续时间),这些数值会随着技能等级自动变化,并且在释放技能时传递给 MythicMobs。
简单来说:你在技能定义里写好公式,系统会根据玩家的技能等级算出实际数值,然后 MythicMobs 那边就能直接用这些数值。
参数类型
| 类型 | YAML 写法 | 说明 |
|---|---|---|
| 数值 | number(默认) | 用数学公式计算,支持 min/max 限制和小数位控制 |
| 表达式 | expression 或 expr 或 formula | 与 number 等价,显式声明使用表达式求值 |
| 字符串 | string 或 text | 直接传递文本,支持 {变量} 替换 |
| 布尔 | boolean 或 bool | 真/假值,支持比较表达式(如 {level} >= 3) |
| 随机文本 | random_text 或 random_text_lines 或 random_lines | 从候选行列表中随机抽取文本,适合随机词条生成 |
参数字段说明
| 字段 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
type | 否 | string | "number" | 参数类型 |
formula | 否 | string | — | 数学公式,优先于 value。可用 {level} 等变量 |
expression | 否 | string | — | 与 formula 等价,type: expression 时推荐使用此字段名 |
value | 否 | string | — | 静态值。formula/expression 为空时使用 |
decimals | 否 | int | 0 | 小数位数(仅 number/expression 类型有效,0 = 取整) |
min | 否 | double | — | 最小值限制(仅 number/expression 类型) |
max | 否 | double | — | 最大值限制(仅 number/expression 类型) |
default | 否 | string | "" | formula 和 value 都为空时的兜底值 |
variables | 否 | map | — | 嵌套变量定义,每个变量支持数值配置类型(constant/range/expression 等) |
random_text 专用字段
| 字段 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
rolls | 否 | 数值配置 | 1 | 抽取次数,支持常量、range、expression 等 |
allow_duplicates | 否 | boolean | false | 是否允许重复抽取同一行 |
lines | 是 | list | — | 候选文本行列表(别名:values、options、texts) |
variables | 否 | map | — | 局部变量定义 |
separator | 否 | string | \n | 多行合并分隔符 |
公式中可用的变量
| 变量 | 说明 |
|---|---|
{level} | 玩家当前技能等级(最常用) |
{max_level} | 技能最大等级 |
{target_level} | 升级目标等级(升级预览时使用) |
{player_level} | 玩家的 Minecraft 经验等级 |
{player_health} | 玩家当前血量 |
{player_max_health} | 玩家最大血量 |
{sneaking} | 是否潜行(0 或 1) |
{has_target} | 是否有目标实体(0 或 1) |
{skill_id} | 技能 ID |
公式支持基本数学运算(+、-、*、/)和 floor() 等函数。
简写形式
如果参数只是一个固定的字符串值,可以直接写成一行:
skill_parameters:
element: "fire" # 等价于 type: string, value: "fire"参数如何传递给 MythicMobs
释放技能时,所有参数会自动注入到 MythicMobs 的技能变量中。在 MythicMobs 技能配置里用 <skill.var.参数名> 来引用:
# MythicMobs 技能配置
ExampleFireball:
Skills:
- damage{amount=<skill.var.damage>} @target
- particles{particle=flame;amount=20;radius=<skill.var.radius>} @self系统还会自动注入以下内置变量(不需要你手动定义):
| 变量 | 说明 |
|---|---|
<skill.var.emaki_skill_id> | 技能 ID |
<skill.var.emaki_skill_level> | 当前技能等级 |
<skill.var.emaki_trigger_id> | 触发器 ID |
<skill.var.emaki_is_passive> | 是否被动技能(0 或 1) |
<skill.var.emaki_has_target> | 是否有目标实体(0 或 1) |
注意
参数 ID 不能以 emaki_ 开头,这个前缀是系统保留的。如果你定义了 emaki_ 开头的参数,加载时会被跳过。
嵌套变量
expression 类型的参数支持通过 variables 字段定义嵌套变量。每个嵌套变量本身也是一个数值配置对象,支持 constant、range、uniform、expression 等类型:
damage:
type: "expression"
expression: "{base_damage} + {level_bonus}"
variables:
base_damage:
type: "constant"
value: 18
level_bonus:
type: "expression"
expression: "({level} - 1) * 4"嵌套变量会在求值前先被解析为数值,然后替换到主表达式中。这样可以把复杂的公式拆分成更易读的部分。
random_text 参数类型
random_text 类型用于从候选行列表中随机抽取文本行,适合生成随机词条、随机描述等。抽取结果会作为字符串传递给 MythicMobs。
random_bonus_lines:
type: "random_text"
rolls: "{bonus_rolls}" # 抽取次数(支持数值配置)
allow_duplicates: false # 不允许重复
variables:
bonus_rolls:
type: "constant"
value: 2
物理攻击:
type: "range"
min: 2
max: 6
lines:
- "物理攻击: +{物理攻击}"
- "物理防御: +{物理防御}"random_text 参数的求值结果是多行文本用分隔符(默认 \n)拼接后的字符串。variables 中定义的局部变量会在每行文本中进行替换。
详细的字段说明参见表达式引擎 — 随机文本。
技能升级系统
技能升级让玩家可以花费金币和材料来提升技能等级,等级越高参数越强。
升级配置字段说明
| 字段 | 必填 | 类型 | 默认值 | 说明 |
|---|---|---|---|---|
enabled | 否 | boolean | false | 是否开启升级功能 |
max_level | 否 | int | 1 | 最大等级。设为 1 表示不可升级 |
failure_penalty | 否 | string | "none" | 升级失败的惩罚:none = 不降级;downgrade = 降一级 |
经济费用配置
upgrade:
economy:
enabled: true
currencies:
- provider: "vault" # 经济提供者:vault / excellenteconomy / auto
currency_id: "" # 货币 ID(Vault 留空)
base_cost: 1200 # 基础费用
cost_formula: "{base_cost} * {target_level}" # 费用公式
display_name: "<gold>金币</gold>" # 显示名称cost_formula 中可用的变量和技能参数公式相同({level}、{target_level}、{base_cost} 等)。
成功率配置
upgrade:
success_rates:
2: 100.0 # 升到 2 级:100% 成功
5: 80.0 # 升到 5 级:80% 成功
10: 40.0 # 升到 10 级:40% 成功键是目标等级,值是成功率百分比。没有配置的等级默认 100% 成功。
特定等级配置
你可以为某些关键等级设置额外的材料需求、费用覆盖、参数覆盖和动作:
upgrade:
levels:
5:
# 升到 5 级需要额外材料
materials:
- item: "minecraft-blaze_rod" # 物品来源(和动作系统的 source 格式相同)
amount: 1 # 需要数量
optional: false # 是否可选(可选材料不放也能升级)
protection: false # 是否为保护材料
# 覆盖这个等级的经济费用(不写就用全局的)
economy:
enabled: true
currencies:
- provider: "vault"
base_cost: 20000
cost_formula: "{base_cost}"
display_name: "<gold>金币</gold>"
# 覆盖这个等级的成功率
success_rate: 40.0
# 覆盖这个等级的参数定义(比如到了 5 级范围固定为 3.5)
parameters:
radius:
type: "number"
value: 3.5
decimals: 2
# 升级成功/失败时执行的动作
success_actions:
- "sendmessage text=<yellow>达到 V 级!"
- "playsound sound=entity.player.levelup volume=1.0 pitch=1.5"
failure_actions:
- "sendmessage text=<red>升级失败了..."升级流程
玩家执行 /eskills upgrade <技能ID> 后,系统会按以下步骤处理:
1. 检查技能是否已解锁(没解锁不能升级)
2. 检查是否已满级
3. 计算目标等级 = 当前等级 + 1
4. 检查金币是否充足
5. 检查背包材料是否充足
6. 扣除金币和材料
7. 按成功率随机判定
├─ 成功 → 等级 +1,执行 success_actions
└─ 失败 → 根据 failure_penalty 决定是否降级,执行 failure_actions如果扣费过程中出了问题(比如扣了金币但材料不够),系统会自动退还已扣除的所有费用。
升级命令
| 命令 | 权限 | 说明 |
|---|---|---|
/eskills upgrade <技能ID> | emakiskills.use | 玩家自助升级已解锁的技能 |
/eskills level get <玩家> <技能> | emakiskills.admin | 查询玩家的技能等级 |
/eskills level set <玩家> <技能> <等级> | emakiskills.admin | 直接设置玩家的技能等级 |
/eskills level add <玩家> <技能> <数值> | emakiskills.admin | 增加或减少玩家的技能等级 |
GUI 中的等级和参数展示
技能 GUI 中,每个技能图标的 Lore 会自动显示当前等级和参数预览:
等级: 3/10
参数预览:
- damage: 26.0
- radius: 2.5
- can_ignite: true最多显示 3 个参数。以 emaki_ 开头的内置参数不会显示。
默认资源
| 资源 ID | 名称 | 最大值 | 恢复 |
|---|---|---|---|
mana | 法力 | 100 | 5/2秒 |
技能解锁机制
技能不是直接"学会"的,而是通过装备来解锁。玩家穿上带有技能标记的装备,技能就可用;脱下装备,技能就从可用池中移除。有两种标记方式:
1. PDC 解锁
装备的 PersistentDataContainer 中存储技能 ID 列表:
PDC Key: emaki_skills:item.skills.ids
Value: "fireball;ice_bolt;heal"值是分号分隔的技能 ID 字符串。当玩家装备含有此 PDC 数据的物品时,对应技能自动解锁。卸下装备后技能从解锁池中移除。
这种方式适合通过插件精确控制装备带哪些技能。EmakiForge、EmakiStrengthen、EmakiGem 三个模块都支持在配方/星级/宝石定义中声明 skill 效果,锻造/强化/镶嵌完成后会自动通过 ReflectiveSkillPdcGateway 把技能 ID 写入产物的 PDC——不需要手动操作。
2. Lore 解锁
装备 Lore 中包含技能定义的 lore_aliases 中的任意文本时,该技能解锁:
# 技能定义
lore_aliases:
- "火球术"
# 装备 Lore 中包含 "火球术" → 技能解锁Lore 解锁更灵活,不需要修改物品的 PDC,只要 Lore 里有对应文本就行。适合和 MMOItems、ItemsAdder 等物品插件配合使用。
提示
两种解锁方式可以同时使用。EquipmentSkillCollector 会同时扫描 PDC 和 Lore,合并所有解锁的技能。如果同一个技能被多件装备同时解锁,也只会出现一次。
PlayerSkillProfile 数据模型
每个玩家的技能档案存储在 data/{uuid}.yml 中,记录了施法模式状态、槽位绑定、本地资源、冷却计时和技能等级:
# data/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.yml
cast_mode_enabled: true
bindings:
- slot: 0
skill_id: "fireball"
trigger_id: "right_click"
- slot: 1
skill_id: "ice_bolt"
trigger_id: "shift_right_click"
- slot: 2
skill_id: null
trigger_id: null
local_resources:
mana:
current: 75.0
timing:
last_cast_time_ms: 1700000000000
forced_delay_until_ms: 0
global_cooldown_until_ms: 1700000001000
skill_cooldowns:
fireball: 1700000005000
skill_levels:
fireball: 3
ice_bolt: 1