Snowygems

技能与 BUFF

技能行语法、24 个内置函数、触发标记、条件与概率、形态切换、常驻 BUFF 的完整配置参考。

技能与 BUFF

技能定义放在 plugins/SnowyGems/skills/ 下,文件名任意。技能不是绑在宝石上的,而是绑在装备的 lore 文本上:装备 lore 里出现某段文字,就获得对应技能。

一个最小可用的技能:

向前闪现:                        # 技能 ID
  Lore: "右键即可闪现"            # 装备 lore 含这段文字就绑定此技能
  Cooldown: 10.0                 # 冷却 10 秒
  Skills:
    - Blink{distance=32} ~onUse @Forward

玩家拿着一件 lore 里有「右键即可闪现」的装备,右键就会向前闪现 32 格。


技能定义的字段

字段说明
Lore绑定标记。装备 lore 含这段文字即生效(去色比较,可含颜色码)
Cooldown冷却秒数,不写或 0 表示无冷却
CooldownTip冷却中的提示,本身也是一个函数表达式
Skills技能行列表
Lore 留空的技能定义不会被任何装备触发——它只能作为形态切换的目标(见下文 Switch),或者被 Reward{...} 嵌套调用。

冷却是按技能定义计算的,不是按技能行。同一个定义里多行技能共享一个冷却。


技能行结构

函数名{参数1=值;参数2=值} ~触发标记 @作用目标

三部分:

部分必填说明
函数名{参数}做什么。参数用 ; 分隔
~触发标记什么时候触发。不写则永远不会触发
@作用目标作用于谁,默认 @Self

作用目标:

写法含义
@Self作用于自己(默认)
@Entity作用于被攻击/被命中的实体
@Location作用于命中坐标(闪现、粒子、闪电常用)

触发标记

标记触发时机
~onUse右键使用
~onShiftUse潜行 + 右键
~onSwing左键挥臂
~onShiftSwing潜行 + 左键(三叉戟/矛也可用)
~onAttack近战攻击命中实体
~onKill击杀实体
~onHit发射物命中(任意类型)
~onHit:类型发射物命中指定类型
~onLaunch发射物射出(任意类型)
~onLaunch:类型发射物射出指定类型
~onBreak挖掉方块
~onDamaged物品即将损失耐久
~onTimer每秒轮询(常驻 BUFF 用)

~onHit:类型 的类型直接取实体类型名,不是固定清单ARROWTRIDENTSPEAREGGSNOWBALLFIREBALL… 服务端有什么实体就能写什么。所以 1.21.11 的矛投出去后写 ~onHit:SPEAR 直接可用。

游戏内用 /sgem triggers 查看清单(内容来自 lang.yml,可自行增删措辞)。


函数清单

游戏内用 /sgem skills [关键字] 查看,会标出每个函数在当前版本是否可用。

位移

函数别名用法
BlinkTeleport 闪现{distance=10} 沿视线瞬移;配合 @Location 传送到命中处
VelocityPush 击退 冲刺{forward=1.5;up=0.5}{x=0;y=1;z=0}

Blink 会沿视线逐格前进,撞到非空气就停在前一格,不会把玩家塞进墙里。

战斗

函数别名用法
Damage伤害{amount=5}
Heal治疗 恢复{amount=5}
Fire点燃 燃烧{ticks=100}(20 tick = 1 秒)
Lightning闪电 雷击{damage=true}false 则只有视觉效果

反馈

函数别名用法
ChatMessage Msg 消息{m=&a技能发动!}
ActionBar动作栏{m=&b蓄力完成}
Title标题{m=主标题;s=副标题;fadeIn=10;stay=40;fadeOut=10}
Sound音效{name=ENTITY_PLAYER_LEVELUP;volume=1;pitch=1}
Particle粒子{name=FLAME;count=20;ox=0.5;oy=0.5;oz=0.5;speed=0}

音效名和粒子名随版本增删,写错或版本不支持会跳过并在日志说明,不会报错崩溃。

药水效果

函数别名用法
PotionPotionBuff Buff 药水{type=SPEED;level=2;duration=10},duration 单位为
Debuff负面{type=move;duration=5}{type=BLINDNESS;level=1;duration=5}
ClearPotionRemovePotion 清除效果{type=POISON},不带参数则清除全部

Debuff 有两个语义化的特殊值:type=move 是强力缓慢(定身),type=fly 是禁飞。其余一律按效果名解析,所以 Debuff{type=weaving} 这种新版本效果也能写。

level 是「第几级」(从 1 起),不是 amplifier。

物品操作

函数别名用法
Enchant附魔{name=sharpness;level=5}{name=fortune;limit=3}
Switch形态切换 切换{s=精准;时运}
Repair修复 耐久{amount=100}amount=full 则完全修复

Enchant 的四种语义:

写法效果
level=5设为 5 级
level=0移除,并记住原等级(供 restore 用)
level=restore恢复之前记住的等级
不写 level当前等级 +1,受 limit 限制

控制流

这一层是「技能引擎足够聪明」的关键:有了条件和组合,你可以自己拼出复杂逻辑,不需要等插件加新函数。

函数别名用法
AllGroup 组合{Damage{amount=5};Fire{ticks=60}} 依次执行多个
ChanceRandom 概率{p=0.3;Damage{amount=10}},p 为 0~1
IfCondition 条件{c=health<0.3;Heal{amount=10}}
Delay延迟{t=20;Damage{amount=5}} 延迟 20 tick
Repeat循环{times=3;interval=6;Damage{amount=2}}
RewardDo 执行{Chat{m=&a触发!}} 包一层(兼容老配置)
CommandCmd 命令{c=give %player% diamond 1;as=console}

嵌套里可以再套控制流,例如 If{c=health<0.3;All{Heal{amount=20};Potion{type=RESISTANCE;level=3}}}

If 支持的条件变量:

变量含义
health自己的生命比例(0~1)
raw_health自己的生命绝对值
max_health自己的生命上限
food饱食度(0~20)
level经验等级
y所在高度
target_health目标的生命比例(0~1)
target_raw_health目标的生命绝对值

运算符:> >= < <= == !=

target_* 在这次触发没有目标实体时取不到值,条件直接判为不成立(不是报错)。

Commandas 参数:player(默认)、op(临时提权后还原)、console。命令里可用 %player%%uuid% 占位符。

Command{as=op} 会临时给玩家 OP 权限执行命令。虽然执行完立即还原,但如果命令内容里含玩家可控的文本(比如从 lore 读来的值),存在被利用的风险。能用 as=console 就别用 as=op

Repeattimes 上限是 100,防止手滑写 times=99999 卡死主线程。


CooldownTip:冷却提示

CooldownTip 本身也是一个函数表达式,支持三种:

CooldownTip: ActionBar{p=&c冷却时间;s=&a%.2fs;empty=&f|;full=&a|;length=75}

ActionBar 模式的参数:

参数说明
p前缀文字
s后缀模板,%.2f 会被替换成剩余秒数
empty进度条未填充部分的字符
full已填充部分的字符
length进度条长度

完整示例

条件技能:濒死保命

濒死守护:
  Lore: "&c濒死守护"
  Cooldown: 30.0
  CooldownTip: ActionBar{p=&c守护冷却;s=&c%.2fs;empty=&8|;full=&c|;length=40}
  Skills:
    # 被打到 30% 以下时,回血 + 抗性 + 音效
    - If{c=health<0.3;All{Heal{amount=20};Potion{type=RESISTANCE;level=3;duration=6};Sound{name=ITEM_TOTEM_USE}}} ~onDamaged
    - If{c=health<0.3;Title{m=&c&l守护发动;s=&7生命已恢复}} ~onDamaged

概率技能:攻击时随机触发

雷霆之刃:
  Lore: "&b雷霆之刃"
  Skills:
    - Chance{p=0.2;Lightning{damage=true}} ~onAttack @Entity
    - Chance{p=0.3;Fire{ticks=80}} ~onAttack @Entity
    - Chance{p=0.2;ActionBar{m=&e&l雷霆!}} ~onAttack

连招:延迟与重复

三段斩:
  Lore: "&6三段斩"
  Cooldown: 8.0
  Skills:
    - Repeat{times=3;interval=6;All{Damage{amount=4};Particle{name=SWEEP_ATTACK;count=8}}} ~onAttack @Entity
    - Sound{name=ENTITY_PLAYER_ATTACK_SWEEP} ~onAttack

发射物技能:飞雷神

飞雷神三叉戟:
  Lore: "飞雷神三叉戟"
  Cooldown: 15.0
  Skills:
    - Blink{distance=120} ~onHit:TRIDENT @Location
    - Reward{Title{m=&e飞雷神之术}} ~onHit:TRIDENT

矛技能(1.21.11+)

穿云长矛:
  Lore: "&f穿云长矛"
  Cooldown: 6.0
  Skills:
    # 投出瞬间
    - Sound{name=ITEM_TRIDENT_THROW} ~onLaunch:SPEAR
    - ActionBar{m=&f长矛已投出} ~onLaunch:SPEAR
    # 命中处
    - Particle{name=EXPLOSION;count=1} ~onHit:SPEAR @Location
    - Damage{amount=6} ~onHit:SPEAR @Entity
    - Blink{distance=120} ~onHit:SPEAR @Location

从 lore 读数值:$LORE:$

技能参数可以从装备 lore 里动态读数值:

$LORE:标签?默认值$
向前闪现:
  Lore: "右键即可闪现"
  Skills:
    - Blink{distance=$LORE:闪现距离?32$} ~onUse @Forward

装备 lore 里写「闪现距离 64」就用 64,没写就用 32。标签要写去掉颜色码的形式——插件会先把 lore 去色再比较,所以颜色码穿插在中间也能匹配。

这套机制让「同一个技能定义,不同装备不同数值」成为可能,配合宝石的 LoreVar 就能做出可升级的技能。


形态切换:Switch

「精准 ↔ 时运」这类切换:两个形态各自是一个技能定义,用 RewardSwitch 声明进入该形态要做什么。

精准时运切换:
  Lore: "§2Shift+右键切换模式(精准/时运)"
  Cooldown: 4.0
  CooldownTip: ActionBar{p=&c切换冷却;s=&a%.2fs;empty=&f|;full=&c|;length=75}
  Skills:
    - Switch{s=精准;时运} ~onShiftUse

# 精准模式:收起时运,恢复精准
精准:
  Skills:
    - RewardSwitch{Enchant{name=fortune;level=0}}
    - RewardSwitch{Enchant{name=silk_touch;level=restore}}
    - RewardSwitch{ActionBar{m=&b&l切换为精准模式}}

# 时运模式:收起精准,恢复时运
时运:
  Skills:
    - RewardSwitch{Enchant{name=silk_touch;level=0}}
    - RewardSwitch{Enchant{name=fortune;level=restore}}
    - RewardSwitch{ActionBar{m=&a&l切换为时运模式}}

工作原理:level=0 移除附魔并记住原等级,level=restore 恢复记住的等级。切换状态存在物品的 PDC 里。

你新写任意一组切换都不需要改插件。 引擎会读取两个形态各自声明的「特征附魔」(level=restorelevel>0 的那些),看物品上实际带着谁的附魔,据此反推当前形态。所以「忠诚 ↔ 激流」「经验修补 ↔ 无限」「火焰附加 ↔ 击退」都能照抄上面的结构直接用。

两个形态定义不需要写 Lore——它们不由装备直接触发,而是被 Switch 调用。

如果目标形态自己配了 Chat/ActionBar/Title,就以配置为准;没配的话插件会发一条来自 lang.yml 的兜底提示,避免按下去毫无反应像是插件坏了。


常驻 BUFF

BUFF 引擎每秒扫描每个在线玩家的主手、副手、四件盔甲,命中 lore 标记就执行该定义里带 ~onTimer 的技能行。

发光:
  Lore: "&6&l[&c&lBUFF&6&l] &b&l发光"
  Skills:
    - Potion{type=GLOWING} ~onTimer

因为是每秒重新施加,效果时长只要 ≥2 秒就不会闪断(插件内部会把时长夹到至少 40 tick)。

可叠加等级的 BUFF

配合宝石的 LoreVar 写数字,这里用 $LORE:$ 读回来:

抗性提升:
  Lore: "&6&l[&c&lBUFF&6&l] &b&l抗性提升 "
  Skills:
    - Potion{type=DAMAGE_RESISTANCE;level=$LORE:[BUFF] 抗性提升?1$} ~onTimer
$LORE: 引用的标记必须和自己的 Lore 一致(去色后比较),否则等级永远读默认值 1——不报错,只是等级不涨。

智能 BUFF

~onTimer 上同样能用控制流,于是可以写「满足条件才生效」的 BUFF:

濒死爆发:
  Lore: "&6&l[&c&lBUFF&6&l] &c&l濒死爆发"
  Skills:
    - If{c=health<0.3;All{Potion{type=resistance;level=2};Potion{type=regeneration;level=2}}} ~onTimer
引擎没有 in_water 这类环境变量。想判断「在水下」只能用 y<你服的海平面高度 近似。

BUFF 与宝石配对

BUFF 定义只是「准备好一个标记」。要让玩家能获得它,二选一:

  1. gems/ 里写一颗宝石,RewardsLoreAdd{lore=这里的 Lore 文本}
  2. 直接把这行 lore 加到装备上(用其他插件或命令)

skills/ModernBuffs.yml 里有 7 个已标注为「模板」的定义就属于第一种情况——标记准备好了但没配套宝石,需要你自己加。


性能提醒

BUFF 引擎每秒对每个在线玩家扫 6 个物品槽 × 所有带 Lore 的技能定义。定义数量大(几百个)且在线人数多(上百)时会有可观开销。建议:

  • 不需要的 BUFF 定义直接删掉,别留着
  • 常驻 BUFF 用 ~onTimer,一次性效果用 ~onUse 等事件触发标记
  • Repeat + 短 interval 会在短时间内塞入大量调度任务,谨慎用于高频触发的技能

验证

改完技能配置后 /sgem reload,然后:

  • /sgem skills 确认函数名没写错
  • /sgem triggers 确认触发标记没写错
  • /sgem compat all 查看配置自检结果

配置自检会明确报出「不是已注册的技能函数」(含拼写建议)和「这一行没有写触发标记,永远不会被触发」这两类最常见的笔误。

Copyright © 2026