Skip to content

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 模式

适合什么场景?

  • 简单周期回血(比如脱战后每秒回血)
  • 简单周期掉血(比如在毒气区域每秒扣血)
  • 不需要单独实例追踪的效果

工作方式:

  1. 定时扫描实体(比如每 20 tick 扫描一次所有玩家)
  2. 检查条件是否成立(比如玩家是否脱战、血量是否未满)
  3. 条件成立就直接执行动作(比如回血)

它更像"定时规则"或"定时器"。

举个例子:

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 的效果(比如中毒开始时播放音效、结束时清除粒子)

工作方式:

  1. 定时扫描实体(比如每 40 tick 扫描一次)
  2. 检查条件是否成立(比如玩家是否在毒气区域)
  3. 条件成立就创建一个目标周期实例
  4. 后续由统一运行系统持续驱动它跳动(比如每 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 点血

这个配置会:

  1. 每 40 tick 检查一次玩家
  2. 如果满足条件,创建一个"中毒"实例
  3. 这个实例每 20 tick 扣 5 点血,持续 100 tick
  4. 如果再次触发,会刷新持续时间
  5. 你可以用 /hnattr periodic list 查看所有实例
  6. 你可以用 /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-playernearest-living

六、条件与失败策略

tick-condition

每一跳执行前再检查一次。

例如:

yml
tick-condition:
  mode: expression
  script: target_health > 1

fail-policy

常用两个值:

  • skip: 本次不执行,但实例保留到下一跳
  • cancel: 本次失败就直接结束实例

选择方法:

  • 条件偶尔不满足,只跳过一下 → skip
  • 条件不满足就直接结束状态 → cancel

七、周期效果的脚本上下文

周期脚本当前支持:

  • source: 来源实体
  • target: 目标实体
  • self: 等于 target
  • attr: 等于 target_attr
  • source_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"} @target

hna-triggerot / hna-triggerdot / hna-triggerhot

对匹配实例立刻额外执行一次 tick。

hna-detonateot / hna-detonatedot / hna-detonatehot

stacks 提前结算若干次剩余 repeat。

十、这一页最该记住的重点

  1. 周期系统是统一 runtime,承载 DOT / HOT / 周期回血等效果
  2. direct 适合简单周期动作,instance 适合真正状态运行时
  3. tick-condition + fail-policy + hooks 是这套系统最强的三件套
  4. 周期系统的排查入口是 /hnattr periodic list/hnattr periodic inspect
  5. DOT / HOT 现在已经和声明式实例统一进同一套 runtime

HN 系列插件文档