Skip to content

伤害类型与战斗管线

HNAttribute v1.6.0 的战斗层由四个核心概念组成:

  • 属性 (Attribute) -- 提供数值,通过 channel + channel-role 声明自己属于哪个伤害通道
  • Stage -- 独立的计算步骤,定义公式和终止语义
  • Pipeline -- 按攻击方式编排 Stage 的执行顺序
  • DamageType -- 伤害的显示身份(名称、颜色)+ 可选的通道减伤公式

一次攻击的完整链路:属性提供数值 -> Pipeline 按顺序执行 Stage -> 每个伤害通道按 DamageType 的 resist-formula 结算减伤 -> 输出最终伤害。


配置目录结构

text
plugins/HNAttribute/
├── attributes/          # 属性定义(含 channel / channel-role)
│   ├── base.yml
│   ├── combat.yml
│   └── element.yml
├── stages/              # Stage 定义(独立计算步骤)
│   ├── hit.yml
│   ├── dodge.yml
│   ├── crit.yml
│   ├── block.yml
│   ├── collect.yml
│   ├── damage.yml
│   ├── resist.yml
│   ├── crit_damage.yml
│   ├── lifesteal.yml
│   └── thorns.yml
├── pipelines/           # 管线定义(按攻击方式编排)
│   ├── melee.yml
│   ├── ranged.yml
│   ├── spell.yml
│   └── dot.yml
└── damage_types/        # 伤害类型(显示 + 可选 resist-formula)
    ├── physical.yml
    └── magic.yml

属性与伤害通道声明

属性本身只是数值来源。要让一个属性参与伤害通道结算,需要在属性定义中声明 channelchannel-role

yml
# 攻击力属于 physical 通道,角色是 damage(伤害来源)
attack_damage:
  display: "&c攻击力"
  names: ["攻击力", "物理伤害"]
  default: 1.0
  channel: physical
  channel-role: damage

# 防御力属于 physical 通道,角色是 resist(抗性)
defense:
  display: "&9防御力"
  names: ["防御力", "防御"]
  default: 0.0
  channel: physical
  channel-role: resist

channel-role 的可选值:

channel-role含义示例
damage伤害来源值attack_damage, fire_damage
resist抗性值defense, fire_resistance
penetration_flat固定穿透physical_penetration_flat
penetration_rate百分比穿透physical_penetration_rate

collect_channels Stage 执行时,系统会自动扫描攻击者身上所有 channel-role=damage 且值 > 0 的属性,收集出本次攻击涉及的伤害通道。

一次攻击可以产出多个伤害通道(混合伤害)。例如一把"火焰剑"同时有 attack_damage(physical 通道)和 fire_damage(fire 通道),近战攻击时会同时产出物理伤害和火焰伤害。


Stage 五种类型

Stage 是独立的计算步骤,定义在 stages/*.yml 中。

1. boolean -- 判定型

返回真/假,用于命中、闪避、暴击、格挡等判定。

yml
id: hit
type: boolean
stop_on_false: true
terminate_outcome: miss
description: "命中判定"
formula: |-
  def diff = self_accuracy - target_dodge
  return diff >= random(0, 1) ? 1 : 0

关键字段:

  • stop_on_false -- 返回 false 时终止管线
  • stop_on_true -- 返回 true 时终止管线
  • terminate_outcome -- 终止时的结果标记(miss / dodge / block / cancel)

2. value -- 数值型

产出一个数值结果,用于基础伤害、吸血值、反伤值等。

yml
id: damage
type: value
description: "基础伤害计算"
formula: |-
  if (explicit_damage) {
    return input_damage
  }
  return Math.max(0, self_attack_damage)

3. modifier -- 修饰型

基于前面某个 Stage 的结果做修正,通过 depends_on 指定修改目标。

yml
id: crit_damage
type: modifier
depends_on:
  - damage
description: "暴击伤害修正"
formula: |-
  if (!crit) {
    return damage
  }
  return damage * Math.max(1, self_crit_multiplier / 100)

depends_on 对 modifier 有两层含义:

  • 声明依赖:这个 Stage 需要 damage 先执行
  • 回写目标:计算结果会覆盖回 damage

4. collect_channels -- 通道收集

自动扫描攻击者属性,收集所有 channel-role=damage 且值 > 0 的伤害通道。

yml
id: collect
type: collect_channels
description: "收集伤害通道"

如果技能/API 已经预设了通道,则直接使用预设值。

5. per_channel -- 按通道执行

对每个伤害通道分别执行公式。系统会自动注入通道相关变量。

yml
id: resist
type: per_channel
description: "按通道减伤"
formula: |-
  effective_resist = max(0, channel_resist - channel_penetration_flat) * (1 - channel_penetration_rate / 100)
  return max(0, channel_value - effective_resist)

per_channel 自动注入的变量:

变量含义
channel_type当前通道类型(如 physical, fire)
channel_value当前通道的伤害值
channel_resist当前通道的抗性值
channel_penetration_flat当前通道的固定穿透
channel_penetration_rate当前通道的百分比穿透

如果对应的 DamageType 配置了 resist-formula,则优先使用 DamageType 的公式替代默认公式。


Pipeline -- 按攻击方式编排

Pipeline 定义在 pipelines/*.yml 中,每个 Pipeline 代表一种攻击方式。

yml
# 近战攻击管线
id: melee
description: "近战攻击"
stages:
  - hit
  - dodge
  - crit
  - block
  - collect
  - damage
  - resist
  - crit_damage
  - lifesteal
  - thorns

默认管线:

Pipeline用途特点
melee近战攻击完整流程,含格挡
ranged远程射击无格挡、无反伤
spell法术释放无格挡,含反伤
dot持续伤害只做通道收集和减伤

Stage 的执行顺序由 Pipeline 的 stages 列表决定,不是文件名排序。


DamageType -- 显示 + 可选减伤公式

DamageType 定义在 damage_types/*.yml 中,负责两件事:

  1. 伤害的显示身份(名称、颜色、格式)
  2. 可选的通道专属减伤公式(resist-formula
yml
id: physical
display-order: 0
display-name: "伤害"
display: "{color}{value}"
color: "&f"
special-color: "&f&l"
description: "物理伤害"

# 可选:自定义减伤公式
# 如果配置了,per_channel Stage 会优先使用这个公式
resist-formula: |-
  effective_defense = max(0, channel_resist - channel_penetration_flat) * (1 - channel_penetration_rate / 100)
  return max(0, channel_value - effective_defense)

DamageType 不负责编排 Stage,不负责绑定属性。它只管"这种伤害长什么样"和"这种伤害怎么减伤"。


完整执行示例:火焰剑近战攻击

假设玩家装备了一把火焰剑,属性如下:

  • attack_damage: 100(physical 通道)
  • fire_damage: 50(fire 通道)

目标怪物属性:

  • defense: 30(physical 通道抗性)
  • fire_resistance: 20(fire 通道抗性)

攻击时使用 melee 管线,执行流程:

  1. hit -- 命中判定,通过
  2. dodge -- 闪避判定,未闪避
  3. crit -- 暴击判定,未暴击
  4. block -- 格挡判定,未格挡
  5. collect -- 收集伤害通道,发现 physical(100) 和 fire(50)
  6. damage -- 基础伤害计算,取 attack_damage = 100
  7. resist -- 按通道减伤:
    • physical 通道:使用 physical.yml 的 resist-formula,100 - 30 = 70
    • fire 通道:使用 fire 的 resist-formula(如果有),50 - 20 = 30
  8. crit_damage -- 未暴击,跳过
  9. lifesteal -- 计算吸血
  10. thorns -- 计算反伤

最终伤害:物理 70 + 火焰 30 = 100,显示层分别用各自的颜色展示。


新增伤害类型的步骤

只需两步:

第一步:定义属性

attributes/*.yml 中注册伤害和抗性属性,声明 channel 和 channel-role:

yml
thunder_damage:
  display: "&e雷电伤害"
  names: ["雷电伤害", "雷伤"]
  default: 0.0
  channel: thunder
  channel-role: damage

thunder_resistance:
  display: "&e雷电抗性"
  names: ["雷电抗性", "雷抗"]
  default: 0.0
  channel: thunder
  channel-role: resist

第二步:定义显示

damage_types/thunder.yml 中定义显示和可选减伤公式:

yml
id: thunder
display-order: 20
display-name: "雷电伤害"
display: "{color}{value}"
color: "&e"
special-color: "&e&l"
description: "雷电伤害"

# 可选:自定义减伤公式
resist-formula: |-
  effective_resist = max(0, channel_resist - channel_penetration_flat) * (1 - channel_penetration_rate / 100)
  return max(0, channel_value * (1 - min(effective_resist, 100) / 100))

不需要写新的 Stage,不需要改 Pipeline。collect_channels 会自动发现 thunder 通道,per_channel 的 resist Stage 会自动使用 thunder 的 resist-formula。


技能调用示例

MythicMobs 技能

yml
# 指定管线和伤害类型
- hna-damage{a=100;pp=true;pipeline=spell;dt=thunder;st=skill} @target

# 不指定管线,使用默认
- hna-damage{a=100;pp=true;dt=thunder} @target

参数说明

参数含义
a / amount伤害数值
pp / pipeline是否进入管线结算(true/false),或指定管线 ID
dt / damage-type伤害类型 ID
st / source-type来源类型(basic / skill)

重点总结

  1. 属性通过 channel + channel-role 声明伤害通道归属,不再需要在 Stage 或 DamageType 中硬编码属性名
  2. Pipeline 按攻击方式编排 Stage,不按伤害类型编排
  3. DamageType 只负责显示和可选的减伤公式,不负责 Stage 编排
  4. collect_channels 自动发现伤害通道,per_channel 自动按通道执行减伤
  5. 新增伤害类型只需定义属性 + 定义显示,不需要写 Stage 或改 Pipeline

HN 系列插件文档