主题
HNAttribute 的周期系统是一套统一 runtime,可以同时承载:
- 周期回血: 每隔一段时间恢复生命值
- 周期掉血: 每隔一段时间扣除生命值
- DOT (持续伤害): Damage Over Time,比如中毒、灼烧、流血
- HOT (持续治疗): Healing Over Time,比如回春术、生命恢复
- 带来源/目标语义的实例效果: 知道是谁施加的、对谁生效
- 带条件、重施策略、生命周期 hooks 的运行时实例: 可以配置复杂的触发条件和行为
简单来说,如果你想做"每隔一段时间自动执行某个动作"的效果,就用周期系统。
一、周期系统的核心定位
周期系统负责什么
周期系统更像"周期实例运行时"。
它主要负责:
- 周期跳动: 按 interval(间隔时间)周期执行动作,比如每 20 tick(1 秒)执行一次
- 执行动作: 每次 tick 执行配置的动作,比如扣血、回血、施加 Buff
- 重施管理: 处理 refresh(刷新) / merge(合并) / stack(叠加) / inspect(查看) / debug(调试)
- 实例生命周期: 管理实例的创建、跳动、跳过、取消、过期等状态
举个例子:
- 你给玩家施加了一个"中毒"效果
- 配置为:每 20 tick(1 秒)扣 5 点血,持续 100 tick(5 秒)
- 系统会创建一个周期实例,每秒自动扣血
- 如果再次施加"中毒",可以配置为刷新时间、叠加层数、或合并伤害
- 你可以用命令查看当前有哪些周期实例在运行,每个实例的状态如何
周期系统与 Buff 的区别
- Buff: 状态标记 + 属性修饰。比如"力量提升"增加 50 点攻击力,这个加成是持续存在的,不是周期执行的
- 周期效果: 周期行为 + 运行时实例。比如"中毒"每秒扣 5 点血,这是周期执行的动作
什么时候用 Buff?
- 你想改变角色的属性(攻击力、防御力、移速等)
- 这个改变是持续的,不需要周期执行
什么时候用周期效果?
- 你想周期性地执行某个动作(扣血、回血、施加 Buff)
- 你需要追踪实例状态(剩余时间、层数、来源)
可以同时用吗? 可以!比如"中毒"效果:
- 用 Buff 做"中毒状态"(降低移速 20%、降低防御 10 点)
- 用周期效果做"中毒伤害"(每秒扣 5 点血)
- 两者互不冲突,可以同时生效
如果你要做的是:
- 中毒: 用周期效果
- 灼烧: 用周期效果
- 流血: 用周期效果
- 持续回血: 用周期效果
应该使用周期效果系统。
二、direct vs instance
direct 模式
适合什么场景?
- 简单周期回血(比如脱战后每秒回血)
- 简单周期掉血(比如在毒气区域每秒扣血)
- 不需要单独实例追踪的效果
工作方式:
- 定时扫描实体(比如每 20 tick 扫描一次所有玩家)
- 检查条件是否成立(比如玩家是否脱战、血量是否未满)
- 条件成立就直接执行动作(比如回血)
它更像"定时规则"或"定时器"。
举个例子:
yml
玩家脱战回血:
mode: direct
selector: players
interval: 20 # 每 20 tick(1 秒)扫描一次
condition:
script: target_health < target_max_health # 血量未满
actions:
- type: heal
amount: 5 # 回 5 点血这个配置会每秒检查所有玩家,如果血量未满就回 5 点血。不会创建单独的实例,不需要追踪状态。
instance 模式
适合什么场景?
- DOT / HOT(持续伤害/治疗)
- 需要
stack / merge / refresh的状态(比如可以叠加层数的流血) - 需要运行时
inspect / debug的效果(比如你想查看某个玩家身上有哪些 DOT) - 需要生命周期 hooks 的效果(比如中毒开始时播放音效、结束时清除粒子)
工作方式:
- 定时扫描实体(比如每 40 tick 扫描一次)
- 检查条件是否成立(比如玩家是否在毒气区域)
- 条件成立就创建一个目标周期实例
- 后续由统一运行系统持续驱动它跳动(比如每 20 tick 扣一次血)
它更像"真正活着的一条状态实例"。
举个例子:
yml
中毒效果:
mode: instance
selector: players
interval: 40 # 每 40 tick 检查一次是否需要创建实例
instance:
interval: 20 # 实例每 20 tick(1 秒)跳动一次
duration: 100 # 实例持续 100 tick(5 秒)
reapply-mode: refresh # 重复施加时刷新时间
actions:
- type: damage
amount: 5 # 每次跳动扣 5 点血这个配置会:
- 每 40 tick 检查一次玩家
- 如果满足条件,创建一个"中毒"实例
- 这个实例每 20 tick 扣 5 点血,持续 100 tick
- 如果再次触发,会刷新持续时间
- 你可以用
/hnattr periodic list查看所有实例 - 你可以用
/hnattr periodic inspect 中毒效果查看详情
选型建议
- 简单周期动作 →
direct(比如脱战回血、区域伤害) - 真正状态玩法 →
instance(比如中毒、灼烧、流血、持续治疗)
三、周期效果的基本结构
effect 层
决定"什么时候创建效果":
- enabled: 是否启用这个效果。
true表示启用,false表示禁用 - selector: 选择哪些实体。比如
players(所有玩家)、mobs(所有怪物)、living(所有生物) - interval: 多久扫描一次(单位:tick,20 tick = 1 秒)。比如
40表示每 2 秒扫描一次 - mode: 模式,
direct(直接执行) 还是instance(创建实例) - condition: 满足什么条件才命中。比如"玩家血量低于 50%"、"玩家在特定区域"
- actions: 命中后执行什么动作。比如扣血、回血、施加 Buff
- tags: 给效果统一打标签,方便批量管理和查询。比如
[poison, debuff]
instance 层
决定"实例怎么活":
- source: 来源实体怎么选。比如
self(目标自己)、owner(宠物的主人)、nearest-player(最近的玩家) - interval: 实例多久跳一次(单位:tick)。比如
20表示每秒跳一次 - duration: 实例活多久(单位:tick)。比如
100表示持续 5 秒 - reapply-mode: 重复施加时怎么处理。
refresh(刷新时间)、stack(叠加层数)、merge(合并数值)、ignore(忽略) - max-stacks: 最多叠多少层。比如
5表示最多叠 5 层,超过就不再叠加 - tick-condition: 每跳前再检查什么。比如"目标血量大于 1"、"目标在特定区域"
- fail-policy: 条件失败是
skip(跳过本次,保留实例) 还是cancel(直接结束实例)
hooks 层
决定"关键生命周期要不要做附加动作":
- on-apply: 施加时执行。比如播放音效、显示粒子、发送消息
- on-tick: 每次跳动时执行。比如播放粒子效果、更新显示
- on-skip: 跳过时执行。比如记录日志、发送调试信息
- on-cancel: 取消时执行。比如清除粒子、发送提示
- on-expire: 过期时执行。比如播放结束音效、发送消息
举个例子:
yml
中毒效果:
hooks:
on-apply:
- type: message
text: "&a你中毒了!"
on-tick:
- type: particle
particle: VILLAGER_ANGRY
on-expire:
- type: message
text: "&a中毒效果已结束"这样配置后:
- 中毒开始时,玩家会收到"你中毒了!"的消息
- 每次跳动时,会显示愤怒的村民粒子
- 中毒结束时,玩家会收到"中毒效果已结束"的消息
四、重施策略
当同一个周期效果被重复施加时,系统会根据 reapply-mode 决定如何处理。
refresh (刷新)
已有实例时刷新持续时间与参数。
适合什么场景?
- 中毒刷新:每次中毒都重置持续时间
- HOT 刷新:每次施加治疗都重置持续时间
- 大多数传统状态技能
举个例子:
yml
中毒:
instance:
duration: 100 # 持续 5 秒
reapply-mode: refresh- 玩家中毒,剩余 5 秒
- 2 秒后再次中毒,剩余时间重置为 5 秒
- 不会叠加层数,只是刷新时间
stack (叠加)
在层数上限内叠层。
适合什么场景?
- 流血层数:每次攻击叠加一层流血
- 灼烧层数:每次火焰伤害叠加一层灼烧
- 可见层数玩法
举个例子:
yml
流血:
instance:
duration: 100
reapply-mode: stack
max-stacks: 5 # 最多叠 5 层
actions:
- type: damage
amount: "2 * stacks" # 每层 2 点伤害- 第 1 次攻击:1 层流血,每秒 2 点伤害
- 第 2 次攻击:2 层流血,每秒 4 点伤害
- 第 5 次攻击:5 层流血,每秒 10 点伤害
- 第 6 次攻击:仍然 5 层(达到上限)
merge (合并)
把数值和次数一起合并。
适合什么场景?
- 想让重复命中越来越痛
- 希望持续时间也叠加的效果
举个例子:
yml
灼烧:
instance:
duration: 60
reapply-mode: merge
actions:
- type: damage
amount: 5- 第 1 次灼烧:每秒 5 点伤害,持续 3 秒
- 第 2 次灼烧:每秒 10 点伤害,持续 6 秒(数值和时间都叠加)
ignore (忽略)
已有实例就跳过。
适合什么场景?
- 同 key 只允许存在一个实例的玩法
- 防止重复施加
举个例子:
yml
无敌:
instance:
duration: 100
reapply-mode: ignore- 玩家有无敌状态时,再次施加会被忽略
- 必须等当前无敌结束后才能再次施加
五、来源选择
instance.source 支持:
none: 无来源self: 目标自己owner: 宠物/召唤物的主人nearest-player: 最近的玩家nearest-mob: 最近的怪物nearest-living: 最近的生物
推荐这样记:
- 目标自己承受效果 →
self - 宠物 / 召唤物类玩法 →
owner - 光环 / 最近施法者类效果 →
nearest-player或nearest-living
六、条件与失败策略
tick-condition
每一跳执行前再检查一次。
例如:
yml
tick-condition:
mode: expression
script: target_health > 1fail-policy
常用两个值:
skip: 本次不执行,但实例保留到下一跳cancel: 本次失败就直接结束实例
选择方法:
- 条件偶尔不满足,只跳过一下 →
skip - 条件不满足就直接结束状态 →
cancel
七、周期效果的脚本上下文
周期脚本当前支持:
source: 来源实体target: 目标实体self: 等于targetattr: 等于target_attrsource_attr: 来源属性target_attr: 目标属性effect: 效果信息
平铺变量:
target_health: 目标生命值target_max_health: 目标最大生命值source_health: 来源生命值source_present: 来源是否存在target_attack_damage: 目标攻击力source_fire_damage: 来源火焰伤害effect_run: 当前执行次数effect_completed_runs: 已完成次数effect_max_runs: 最大执行次数
八、周期效果调试命令
查看实例列表
text
/hnattr periodic list
/hnattr periodic list all
/hnattr periodic list <玩家名>查看实例详情
text
/hnattr periodic inspect <key>打开调试
text
/hnattr periodic debug detail <key>清理实例
text
/hnattr periodic clear <玩家名> <key>
/hnattr periodic clearpair <来源> <目标> <key>
/hnattr periodic clearall九、MythicMobs 集成
hna-dot / hna-hot
向周期 runtime 发起目标周期请求。
text
hna-dot{amount=2;duration=60;interval=20;mode=refresh;key="burn-dot"} @target
hna-hot{amount=2;duration=60;interval=20;mode=refresh;key="regen-hot"} @targethna-triggerot / hna-triggerdot / hna-triggerhot
对匹配实例立刻额外执行一次 tick。
hna-detonateot / hna-detonatedot / hna-detonatehot
按 stacks 提前结算若干次剩余 repeat。
十、这一页最该记住的重点
- 周期系统是统一 runtime,承载 DOT / HOT / 周期回血等效果
direct适合简单周期动作,instance适合真正状态运行时tick-condition + fail-policy + hooks是这套系统最强的三件套- 周期系统的排查入口是
/hnattr periodic list和/hnattr periodic inspect - DOT / HOT 现在已经和声明式实例统一进同一套 runtime
