Skip to content

这页不主讲大段原理,而是专门回答一个更实际的问题:

我要配一个 DOT、HOT 或周期实例,到底该改哪些字段?

如果你已经知道 HNAttribute 有 directinstance 两种模式,但一到真正落配置时就容易混乱,这页就是给你准备的。

延伸阅读:

一、先记住文件分工

周期系统现在的配置入口是:

text
plugins/HNAttribute/periodic/settings.yml
plugins/HNAttribute/periodic/*.yml

可以这样理解:

periodic/settings.yml

负责:

  • 周期系统全局设置
  • 调试开关
  • 战斗状态超时等公共行为

periodic/*.yml

负责:

  • 具体效果定义
  • direct 周期规则
  • instance 周期实例模板
  • DOT/HOT 行为本体

如果你在纠结“到底去改哪个文件”,通常按这句判断就够了:

  • 改全局行为settings.yml
  • 改某个具体效果periodic/*.yml

二、先理解三类常见需求

在服主视角里,最常见其实不是“我要配 periodic”,而是下面三类需求:

1. 简单周期回血/掉血

例如:

  • 脱战回血
  • 安全区回血
  • 中毒地形定时掉血

这种通常优先考虑:

  • direct

2. 真正的 DOT/HOT 状态

例如:

  • 中毒
  • 灼烧
  • 流血
  • 持续治疗

这种通常优先考虑:

  • instance

因为你往往需要:

  • 持续时间
  • 重施策略
  • 叠层
  • 运行时实例追踪
  • 生命周期钩子

3. 可调试、可 inspect 的运行时状态玩法

例如:

  • 一个技能给目标挂 5 秒 DOT
  • 再次施放时 refresh / stack / ignore
  • 需要 /hnattr periodic list / inspect 看实例

这种也优先:

  • instance

一句话速记:

  • 简单规则型周期动作direct
  • 真正状态型玩法instance

三、全局配置:periodic/settings.yml

默认示例通常会像这样:

yml
combat-timeout: 100

debug:
  level: off
  key-filter: []

1. combat-timeout

表示战斗状态保留时长,单位通常是 tick。

最常见用途:

  • 脱战回血什么时候允许开始
  • 某些基于 in_combat 的周期条件什么时候恢复成立

例如默认回血示例里会用到:

text
in_combat <= 0

所以如果你发现“脱战回血迟迟不触发”,要先回来看这里是不是超时时间太长。

2. debug.level

周期实例调试级别。

常见级别:

  • off
  • basic
  • detail
  • trace

建议:

  • 日常服务器用 off
  • 配置调试时先开 basic
  • 真要追某个实例为什么没跳,再开 detailtrace

3. debug.key-filter

只调试指定 key。

示例:

yml
debug:
  level: detail
  key-filter:
    - poison-dot

适合:

  • 不想让整个周期系统刷屏
  • 只想盯某个 DOT/HOT 模板

四、一个周期效果最小长什么样

1. direct 最小模板

yml
玩家脱战回血:
  enabled: true
  selector: players
  interval: 20
  delay: 20
  source-type: internal
  tags: [periodic, regen]
  condition:
    mode: expression
    script: "dead <= 0 && in_combat <= 0 && health < max_health && health_regen > 0"
  actions:
    - type: heal
      amount:
        mode: expression
        script: health_regen

它的心智模型是:

  1. 定时扫描目标
  2. 条件成立
  3. 直接执行动作

你可以把它理解成:

定时规则,而不是独立实例。

2. instance 最小模板

yml
玩家中毒实例演示:
  enabled: false
  mode: instance
  selector: players
  interval: 40
  tags: [periodic, poison]
  condition:
    mode: expression
    script: target_health > 4
  instance:
    source: nearest-player
    interval: 20
    delay: 0
    duration: 100
    reapply-mode: refresh
    tick-condition:
      mode: expression
      script: target_health > 1
    fail-policy: cancel
  actions:
    - type: damage
      amount: 1.5

它的心智模型是:

  1. 定时扫描目标
  2. 条件成立
  3. 创建一个目标周期实例
  4. 之后由运行时系统持续驱动它跳动

你可以把它理解成:

真正活着的一条状态实例。

五、顶层字段怎么理解

下面是你在 periodic/*.yml 里最常见的字段。


1. 顶层 key

例如:

yml
玩家中毒实例演示:

这是效果定义名,同时通常也会成为你调试时最容易识别的 key。

建议:

  • 名字能看出用途
  • 别太口语化
  • 最好和玩法语义一致

如果后期要大量 debug,命名清晰非常重要。


2. enabled

是否启用。

yml
enabled: true

调试新效果时推荐先显式写上,避免你忘了为什么它完全不生效。


3. mode

周期模式。

常见:

  • 不写:默认按 direct 理解
  • instance

如果你的目标是 DOT/HOT,建议显式写:

yml
mode: instance

这样自己和后续维护的人都更容易读。


4. selector

扫描目标范围。

常见写法:

  • players
  • 其他由系统支持的实体选择方式

如果你只是做玩家相关效果,最常见就是:

yml
selector: players

5. interval

扫描间隔,单位一般是 tick。

注意:

  • 对 direct 来说,它就是执行周期的频率
  • 对 instance 来说,它是“创建实例的扫描频率”,不是实例跳动频率

这点非常容易搞混。

最常见误区

yml
mode: instance
interval: 20

很多人会以为这表示实例每秒跳一次。

其实不一定。

真正控制实例跳动频率的通常是:

yml
instance:
  interval: 20

也就是说:

  • 顶层 interval:多久扫描一次、多久尝试挂实例
  • instance.interval:实例自己多久跳一次

6. delay

仅在某些 direct 模式下常见,用于初始延迟。

例如脱战回血,常见会写:

yml
delay: 20

表示不是立即开始,而是有一个初始等待。


7. source-type

周期动作的来源类型。

例如:

yml
source-type: internal
source-type: dot

这个字段很重要,因为它会影响:

  • 战斗上下文
  • 你在管线与调试里如何区分普通攻击、技能、DOT、内部回复
  • 后续统计与问题排查时的分类心智

常见建议:

  • 脱战回血:internal
  • 持续伤害:dot
  • 持续治疗:通常也可按你的体系决定是否单独分 source-type

8. damage-type

当动作是伤害时,用于指定它属于哪个伤害类型。

例如:

yml
damage-type: dot

或者你也可以让某个 DOT 走元素类型:

yml
damage-type: fire

这取决于你想让它:

  • 显示为 DOT 分类
  • 还是直接显示为火焰/冰霜/毒伤等通道

如果你想让 DOT 也吃某种元素表现,这里就非常关键。


9. tags

给这个周期效果附加标签。

示例:

yml
tags: [periodic, burn]

用途通常是:

  • 做调试分类
  • 给 MythicMobs 或内部逻辑提供语义区分
  • 给你自己的玩法体系留出额外标记位

建议:

  • 保留一个通用标签,如 periodic
  • 再加一个玩法标签,如 burnpoisonregen

10. participate-pipeline(新增)

从 2.2.0 版本开始,周期伤害可以通过此参数进入战斗管线。

示例:

yml
actions:
  - type: damage
    amount: 5
    participate-pipeline: true

作用:

  • 开启后,每跳伤害会作为显式伤害输入进入战斗管线
  • 继续走命中、闪避、格挡、增减伤、暴击等阶段
  • 系统会自动附加 participate-pipelineexplicit-damagefixed-damage / percent-damage 标签

默认行为(不开启):

  • DOT 每跳直接结算,不经过战斗管线
  • 保持原有的周期伤害语义

适用场景:

  • 想让 DOT 也吃增伤、减伤、暴击等效果
  • 需要通过管线配置统一控制所有伤害
  • 想让周期伤害和普通伤害使用相同的计算规则

注意事项:

  • 只对 type: damage 的动作生效
  • type: heal 不会进入战斗管线
  • 可在管线配置中通过标签控制显式伤害的处理(如排除 DOT 不暴击)

六、条件相关字段


1. condition

表示“这个效果现在有没有资格触发/创建实例”。

示例:

yml
condition:
  mode: expression
  script: target_health > 4

最适合做:

  • 玩家未满血才回血
  • 目标血量足够时才挂中毒
  • 脱战后才触发回复

这个条件是效果入口条件

可以把它理解成:

这个效果现在要不要开始干活?


2. tick-condition

只在 instance 模式里最常见。

示例:

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

它不是决定“要不要创建实例”,而是决定:

这个已经创建出来的实例,在每一跳时还能不能继续执行。

所以它更偏运行中条件。


3. fail-policy

tick 条件失败时怎么办。

常见值:

  • cancel
  • 其他按系统支持的失败策略

最常见理解:

  • cancel:条件不满足就直接结束这个实例
  • 非 cancel:可能只是跳过这一 tick

所以:

  • 想让低血时中毒直接停止 → cancel
  • 想让某 tick 不满足时只是跳过 → 选跳过型策略

七、instance 节点里的核心字段

如果你在做 DOT/HOT,最关键的通常是 instance: 下面这些字段。


1. source

示例:

yml
instance:
  source: nearest-player

表示这个实例的来源是谁。

不同来源会影响:

  • 调试里看到的 source
  • 某些伤害归属
  • 某些与来源有效性相关的行为

如果你只是做自作用效果,也可能使用:

  • self

2. interval

示例:

yml
instance:
  interval: 20

表示实例每多久跳一次。

这是 DOT/HOT 最关键的节奏字段之一。


3. delay

示例:

yml
instance:
  delay: 0

表示实例创建后第一次跳前的延迟。

常见理解:

  • 0:马上开始
  • 20:延迟 1 秒再开始

4. duration

示例:

yml
instance:
  duration: 100

表示实例总持续时长。

如果配合 interval: 20,那大致就是持续 5 秒、每秒跳一次。


5. reapply-mode

示例:

yml
instance:
  reapply-mode: refresh

这是 DOT/HOT 最重要的玩法字段之一。

它决定:

已经存在同类实例时,再次施加要怎么处理。

常见理解:

  • refresh:刷新持续时间
  • ignore:已有就不重复挂
  • 其他模式:按系统支持的叠层/重施规则处理

如果你想做:

  • “持续时间重置型中毒” → refresh
  • “已有灼烧就不重复挂” → ignore

6. max-stacks

示例:

yml
instance:
  max-stacks: 3

表示最多可叠多少层。

如果你的玩法需要:

  • 流血可叠层
  • 中毒最多 3 层
  • HOT 最多 2 层

这个字段就很关键。

八、动作:actions

最终真正执行的内容通常在 actions: 里。

例如:

yml
actions:
  - type: damage
    amount: 1

或者:

yml
actions:
  - type: heal
    amount:
      mode: expression
      script: health_regen

最常见动作类型:

  • damage
  • heal

amount

可以是:

  • 固定数值
  • 脚本表达式

例如固定值:

yml
amount: 1.5

例如表达式:

yml
amount:
  mode: expression
  script: health_regen

建议:

  • 先用固定值验证流程
  • 确认效果会跳后,再换表达式

这样排错最省时间。

participate-pipeline(新增)

从 2.2.0 版本开始,可在动作级别配置是否参与战斗管线:

yml
actions:
  - type: damage
    amount: 5
    participate-pipeline: true

详见前文"顶层字段"中的 participate-pipeline 说明。

九、生命周期钩子怎么理解

instance 模式最强的地方之一,就是生命周期钩子。

常见有:

  • on-apply
  • on-skip
  • on-cancel
  • on-expire

例如:

yml
on-apply:
  - type: damage
    amount: 0.25
on-expire:
  - type: heal
    amount: 0.3

可以这样理解:

on-apply

实例刚挂上时触发一次。

on-skip

某一跳因为条件或策略被跳过时触发。

on-cancel

实例被取消时触发。

on-expire

实例自然到期时触发。

这让你能做很多传统 DOT/HOT 配置做不到的玩法,例如:

  • 挂毒时先爆一下
  • 中途失败时返一点血
  • 到期时触发额外结算

十、最常见的 4 种实际模板思路

1. 脱战回血

优先:

  • direct
  • source-type: internal
  • type: heal

2. 简单自伤 DOT 演示

优先:

  • direct
  • source-type: dot
  • damage-type: dot
  • type: damage

适合做冒烟测试。

3. 真正中毒/灼烧/流血

优先:

  • mode: instance
  • reapply-mode
  • tick-condition
  • fail-policy
  • max-stacks

4. 持续治疗状态

优先:

  • mode: instance
  • type: heal
  • 需要时加 refresh 或叠层

十一、排查顺序

如果一个 DOT/HOT 没生效,建议按这个顺序查:

1. 先看有没有加载

  • 文件有没有放到 periodic/*.yml
  • enabled 有没有开
  • /hnattr reload 有没有执行

2. 再看入口条件过没过

重点看:

  • selector
  • condition
  • 顶层 interval

3. 如果是 instance,再看实例有没有创建

命令:

text
/hnattr periodic list
/hnattr periodic inspect <key>

如果 list 里没有,问题通常在:

  • 创建条件没过
  • 模板没启用
  • 扫描频率还没到

4. 如果实例创建了,再看运行中逻辑

重点看:

  • instance.interval
  • duration
  • tick-condition
  • fail-policy
  • actions

5. 最后看显示与伤害上下文

如果你觉得“它没打出来”,还要确认:

  • 是不是真的没跳
  • 还是跳了但显示不明显
  • damage-type 是否配到了你预期的通道
  • source-type / tags 是否被 pipeline 过滤了

十二、最实用的速记版本

如果你不想记太多,就记下面这几句:

  1. 改全局行为看 settings.yml,改具体效果看 periodic/*.yml
  2. 简单周期规则用 direct,状态型 DOT/HOT 用 instance
  3. 顶层 interval 是扫描频率,instance.interval 才是实例跳动频率。
  4. condition 管入口,tick-condition 管实例运行中。
  5. reapply-modemax-stacks、生命周期 hooks 决定玩法上限。
  6. 从 2.2.0 开始,可通过 participate-pipeline: true 让 DOT 参与战斗管线。

十三、相关页面

HN 系列插件文档