Skip to content

HNAttribute 的属性系统可以用一句话概括:

先把装备、Buff、外部来源统一成属性修饰符,再按 source 分组管理,最后进入战斗、显示、原版同步等后续流程。

这页会帮你建立对整个属性系统的全局理解,让你清楚地知道属性是如何从装备上读取、如何计算、如何生效的。

一、属性系统的核心流程

整个属性系统的工作流程是:

  1. 读取层: 从 Lore、PDC、NBT 等来源识别属性
  2. 来源管理: 按 source 分组管理所有修饰符
  3. 属性计算: 合并所有来源,计算最终属性值
  4. 应用层: 进入战斗、显示、原版同步等系统

二、什么是属性修饰符

属性修饰符是 HNAttribute 里最基础的概念。你可以把它理解成"一条属性变化记录"。

一个修饰符包含四个核心信息:

  • 属性 ID: 要修改哪个属性,例如 attack_damage(攻击力)、max_health(最大生命值)
  • 操作类型: 用什么方式修改,是直接加(ADD)、基础乘法(MULTIPLY_BASE)还是总值乘法(MULTIPLY_TOTAL)
  • 数值: 具体的增减量,比如 +120 或 +50%
  • 来源: 这个修饰符从哪里来,比如主手武器、某个 Buff、或者任务奖励

举个例子,当你装备一件武器,上面写着"攻击力: 120",系统会把它转换成:

  • 属性 ID: attack_damage
  • 操作: ADD(加法)
  • 数值: 120
  • 来源: equipment:mainhand(主手装备)

这样系统就知道:"主手武器给玩家增加了 120 点攻击力"。

三、什么是 source (来源)

source 是整个属性系统里最重要的概念之一。你可以把它理解成"属性的身份证"。

为什么需要来源?因为系统需要知道每个属性值是从哪里来的,这样才能:

  • 在你换装备时,精确删除旧装备的属性
  • 在 Buff 结束时,准确移除 Buff 带来的属性
  • 让你用命令查看"这个属性到底是哪些东西加起来的"

所有修饰符都会按 source 分组管理,常见的来源包括:

装备来源

  • equipment:mainhand
  • equipment:offhand
  • equipment:helmet
  • equipment:chestplate
  • equipment:leggings
  • equipment:boots

Buff 来源

  • buff:力量提升
  • buff:钢铁护体

自定义来源

  • custom:quest-reward
  • custom:artifact-bonus

属性映射来源

  • mapping:strength
  • mapping:vitality

source 的价值

通过 source 系统,你可以:

  1. 追踪属性来源: 用 /hnattr source 命令查看所有正在生效的来源
  2. 精确管理属性: 换装备时只删除旧装备的属性,不影响 Buff 和其他来源
  3. 快速排查问题: 用 /hnattr trace <属性ID> 查看某个属性是由哪些来源组成的

举个例子:

  • 你装备了一把武器,获得 100 攻击力 → 来源是 equipment:mainhand
  • 你又吃了一个力量 Buff,获得 50 攻击力 → 来源是 buff:力量提升
  • 你换了另一把武器,获得 150 攻击力 → 系统会删除旧的 equipment:mainhand 来源,添加新的
  • 这时你的总攻击力是 150(新武器) + 50(Buff) = 200,而不是 100 + 50 + 150 = 300

四、属性的三种操作类型

ADD (加法)

最常用的操作类型,直接增加数值。

示例:

装备攻击力: 100 (ADD)
→ 最终攻击力 = 100

MULTIPLY_BASE (基础乘法)

✖️

对基础值进行百分比加成。多个 MULTIPLY_BASE 之间是加法叠加

示例:

装备: 100 (ADD)
Buff1: 50% (MULTIPLY_BASE)
Buff2: 30% (MULTIPLY_BASE)

计算: 100 × (1 + 0.5 + 0.3) = 180

MULTIPLY_TOTAL (总值乘法)

对最终值进行百分比加成,在所有计算的最后阶段应用。

示例:

装备: 100 (ADD)
Buff1: 50% (MULTIPLY_BASE)
Buff2: 20% (MULTIPLY_TOTAL)

计算:
  1. 基础值: 100
  2. 应用 MULTIPLY_BASE: 100 × 1.5 = 150
  3. 应用 MULTIPLY_TOTAL: 150 × 1.2 = 180

计算顺序

1
收集所有 ADD得到基础值
2
应用所有 MULTIPLY_BASE(百分比相加)得到中间值
3
应用所有 MULTIPLY_TOTAL(逐个相乘)得到最终值

更详细的说明请参考: Buff 系统与修饰符

五、属性映射与派生

属性映射允许你定义"主属性"到"战斗属性"的转换。

例如:

  • strength (力量) → attack_damage (攻击力)
  • vitality (体质) → max_health (最大生命值)
  • vitality (体质) → health_regen (生命恢复)

这样玩家只需要关注"力量"、"体质"等主属性,系统会自动计算出战斗属性。

一层映射:最常见的用法

最常见的是一层映射,也就是:

text
主属性 → 最终属性

比如:

text
力量 → 攻击力
体质 → 最大生命值

为什么要用映射?

假设你想让玩家通过"力量"属性来提升攻击力,如果不用映射,你需要:

  1. 在每件装备上都写"攻击力: XXX"
  2. 玩家升级时手动调整所有装备的攻击力

但如果用映射,你只需要:

  1. 在装备上写"力量: 10"
  2. 配置"每 1 点力量 = 2 点攻击力"
  3. 系统会自动计算:10 力量 = 20 攻击力

这样配置更简单,调整数值也更方便。适合简单服,配置直观,调试也最省心。

链式派生:把成长拆成多层

如果你看到 Wiki 里提到"链式派生",不要被这个名字吓到。

它本质上只是:

text
A → B → C

也就是多个普通映射串起来

例如:

text
智力 → 法术强度 → 魔法伤害
智力 → 神圣亲和 → 治疗强度
智力 → 召唤精通 → 宠物伤害

为什么要这样做?

假设你在做一个法师职业系统:

  • 法师的智力会影响魔法伤害、治疗强度、宠物伤害
  • 但你希望法师可以选择专精方向:
    • 元素专精:智力更多地转化为魔法伤害
    • 神圣专精:智力更多地转化为治疗强度
    • 召唤专精:智力更多地转化为宠物伤害

如果直接用一层映射,你只能让智力同时影响所有三个属性,无法做专精差异。

但如果用链式派生:

  1. 上层(角色成长): 智力 → 法术强度、神圣亲和、召唤精通
  2. 中层(职业专精): 不同专精对中间层属性有不同加成
  3. 下层(最终效果): 法术强度 → 魔法伤害,神圣亲和 → 治疗强度,召唤精通 → 宠物伤害

这样做的好处是:

  • 你可以让多个最终属性共用同一个中间层
  • 你可以单独调整中间层,而不用把所有最终公式重写一遍
  • 更容易做职业差异化成长,而不是所有职业都直接吃同一套最终属性

你可以把它理解成:

映射是在"把一个属性换算成另一个属性";链式派生是在"把一条成长路径拆成几段,各段各管各的"。

什么时候用?

  • 如果你只是想快速做一套属性,先用一层映射就够了
  • 如果你要做职业分化、专精成长、复杂平衡,再考虑链式派生

更完整的配置示例和实战说明,可以继续看:如何注册属性

六、伤害通道声明

属性可以通过 channelchannel-role 字段声明自己属于哪个伤害通道。这是 v1.6.0 管线系统的核心机制。

yml
attack_damage:
  display: "&c攻击力"
  names: ["攻击力", "物理伤害"]
  default: 1.0
  channel: physical
  channel-role: damage

defense:
  display: "&9防御力"
  names: ["防御力", "防御"]
  default: 0.0
  channel: physical
  channel-role: resist

channel

声明这个属性属于哪个伤害通道。例如 physicalfireicethunder

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 通道),攻击时会同时产出物理伤害和火焰伤害。

更多细节参考:伤害类型与战斗管线

七、属性的读取方式

HNAttribute 支持多种属性读取方式:

Lore 读取

最常见的方式,从物品的 Lore 中读取属性。

text
攻击力: 120
攻击速度: 15%
最大生命值: 60

PDC 读取

从 PersistentDataContainer 中读取结构化数据。

NBT 读取

从原始 NBT 标签中读取属性。

条件系统

支持在属性行后面带条件:

text
攻击力: 100/Lv.10,权限: vip

八、属性的自动刷新

当玩家进行以下操作时,属性会自动刷新:

  • 切换主手/副手
  • 点击/拖拽背包
  • 关闭背包
  • 丢弃/捡起物品
  • 加入服务器

刷新时,插件会:

  1. 移除旧的槽位来源
  2. 读取新的物品结果
  3. 按对应 source 写回系统

九、最重要的调试命令

查看物品属性

text
/hnattr inspect

查看手持物品被读取到的属性。

查看最终属性

text
/hnattr lookup

查看自己当前的最终属性值。

查看所有来源

text
/hnattr source

查看所有正在生效的属性来源。

追踪单个属性

text
/hnattr trace <属性ID>

查看某个属性由哪些修饰符组成。

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

  1. 属性系统的核心是"修饰符 + source 管理"
  2. 所有属性来源(装备、Buff、外部注入)都会转换成修饰符
  3. source 是整个系统的核心标识,用于精确管理和删除
  4. 属性映射允许主属性自动派生战斗属性
  5. 属性通过 channel + channel-role 声明伤害通道归属
  6. 调试属性问题的起手式是 /hnattr inspect/hnattr trace

HN 系列插件文档