Skip to content

属性定义 ​

属性定义文件要写清的内容如下: 一个属性有哪些字段, 每个字段起什么作用, 数值类型有哪几种, 以及属性 ID 和数值范围怎么设计

属性文件放在 attributes/*.yml, 一个属性一个文件. 你写的这份定义决定一个数值怎么被识别, 怎么限制, 怎么展示, 以及怎么参与战斗

完整字段参考 ​

字段类型必填默认值说明
idstring是—属性的唯一 ID, 其他模块引用这个属性时就用它
display_namestring否同 id展示用的名称, 也用在 Lore 匹配的 %Key% 变量里
value_kindenum否FLAT数值类型 (见下方枚举说明)
target_typeenum否GENERIC属性目标类型 (见下方枚举说明)
target_idstring否""目标 ID. DAMAGE 类型对应伤害类型 ID; RESOURCE 对应资源 ID; VANILLA 对应原版属性名
mmoitems_statstring否""MMOItems stat ID 的映射; 装了 MMOItems 时用它把属性读取接过去
default_valuedouble否0默认基础值
min_valuedouble否无限制最小值限制. 聚合后的最终值低于这个值会被抬到这个值
max_valuedouble否无限制最大值限制. 聚合后的最终值高于这个值会被压到这个值
allow_negativeboolean否true要不要允许负值; 填 false 时最终值如果是负的会归零, 效果等同 min_value: 0
priorityinteger否0Lore 匹配的优先级; 越高越先匹配, 避免短名称抢在长名称前面被误匹配
lore_format_idstring否""关联的 Lore 格式 ID (定义在 lore_formats/ 中)
lore_patternstring否—单条 Lore 匹配正则表达式, 与 lore_patterns 二选一
lore_patternslist<string>否[]多条 Lore 匹配正则表达式
attribute_powerdouble否1.0属性战力权重系数, 用来算装备或玩家的总战力
tagslist<string>否[]属性标签列表 (如 DEBUFF). 供 MythicMobs 的 emaki_attribute_add_tag / emaki_attribute_clear_tag 按标签批量增删临时属性. 标签不区分大小写
temporary_stack_modeenum否REPLACE该属性作为临时属性, 在同一效果组内对同一属性重复施加时的叠加模式: REPLACE 覆盖, STACK 数值与剩余时间相加. 不同效果组之间的同属性始终并存 (ADD 求和), 不受此项影响. 技能显式传 stack_mode 时以技能为准
parent_attributeboolean否false要不要作为父级属性参与属性点系统. 父级属性也可以从物品 Lore / EA 属性 PDC 进入快照, 并展开 child_bonuses
child_bonusesmap<string,double>否{}每投入 1 点父级属性时, 额外贡献到子属性的数值. 目标子属性必须存在, 而且不能也是父级属性
descriptionstring / list否""描述文本, 可以用在 GUI 或帮助展示里

升级须知: 值域限制现在作用于最终值

过去 min_value / max_value / allow_negative 只在解析单行物品 Lore 时生效, 聚合后的最终值不受任何限制. 因此暴击率这类属性可以靠多件装备叠到 150% 并真的按 150% 结算

现在这三项会在所有来源聚合完毕后统一作用于最终值. 随附的 47 个属性定义全部声明了这三项, 所以每一个属性都会受影响, 其中上限为 100 的 9 个属性 (physical_crit_rate, projectile_crit_rate, spell_crit_rate, block_rate, block_reduction, dodge_chance 与三个 *_crit_evasion) 最容易被察觉

  • 若服主此前依赖越界值生效, 上线后会被压回声明区间. 需要更高上限就改对应属性的 max_value, 不要靠越界叠加
  • 最终值稳定下来的顺序是缩放曲线 → 派生属性 → 值域限制, 所以派生属性的输入不会被提前截断, 但派生结果本身也受自己的区间约束
  • 单件装备的贡献不受限制, 只有实体最终值受限. 因此"+80 的装备"与"-50 的临时减益"都照常参与计算, 减益不会因为中间值越界而失效
  • 范围值 (1-5 形态) 只有下界参与稳定, 区间宽度保持不变. 若下界被抬升, 整段区间会随之上移而不是被裁短

父级属性与属性点 ​

父级属性对应"属性点"玩法: 玩家把可用属性点投进 parent_attribute: true 的属性, 系统会把投入的点数计入该父级属性, 再按 child_bonuses 算出对子属性的额外贡献. 玩家数据存在 data/parent_attributes/<UUID>.yml, 里面有 available_points, reset_points 和 allocations

yaml
id: strength
display_name: '<red>力量'
value_kind: FLAT
parent_attribute: true
child_bonuses:
  physical_attack: 1.0
  projectile_attack: 0.5

父级属性会进入属性追踪和最终快照, 也可以像普通数值属性一样从物品 Lore 或 ea_attribute.ea_attributes PDC 读取. 物品上的父级值会保留自身 ID, 并按 child_bonuses 叠加到对应子属性 ID; Lore 与 PDC 中的同一父级属性先按普通来源相加, 再展开子属性. 系统不内置固定的父级或子级 ID, 也不会在缺少父级定义时创建备用属性; 所有关系都来自当前加载的属性 YAML. EmakiItem 的 variables 仍只负责文本占位, 不会自动成为 EA 属性. child_bonuses 指向不存在的属性或另一个父级属性时, /ea lint 会报告配置问题

value_kind 数值类型 ​

值说明典型用途
FLAT平坦数值 (默认), 就是直接加减的固定值物理攻击 +10, 防御 +5
PERCENT百分比数值; Lore 匹配时会自动处理 % 后缀物理伤害 +8%, 防御加成 +12%
CHANCE概率数值, 和 PERCENT 类似, 都按百分比处理暴击率 +15%, 闪避率 +10%
REGEN回复速率, 表示每秒或每游戏刻回复多少生命恢复 +2/s, 法力恢复 +5/s
RESOURCE资源上限加成, 增加资源的最大值最大生命 +100, 最大法力 +50
DERIVED派生属性, 由其他属性算出来, 不直接从装备读取综合战力, 有效生命

target_type 目标类型 ​

值说明target_id 用途
GENERIC通用属性 (默认), 不参与特定系统, 供条件, 展示或其他模块读取不需要
DAMAGE伤害相关属性, 参与 damage_types/*.yml 中的伤害计算管线对应伤害类型 ID, 如 physical, spell
RESOURCE资源类属性, 影响玩家资源的最大值或回复对应资源 ID, 如 health, mana
VANILLA映射到 Minecraft 原版属性, 属性值变化时同步到 Bukkit 原版属性系统对应原版属性名, 用裸名而不是 generic. 前缀, 如 max_health, attack_speed, scale

示例: 物理攻击 ​

yaml
id: physical_attack
display_name: '<red>物理攻击'
value_kind: FLAT
target_type: DAMAGE
target_id: physical
default_value: 0
min_value: 0
max_value: 999999
allow_negative: false
priority: 100
lore_format_id: default_flat
attribute_power: 1.0
description:
  - '提高物理伤害。'

示例: 暴击率 ​

yaml
id: physical_crit_rate
display_name: '<yellow>物理暴击率'
value_kind: CHANCE
target_type: DAMAGE
target_id: physical
default_value: 0
min_value: 0
max_value: 100
allow_negative: false
priority: 90
lore_format_id: default_percent
attribute_power: 1.0
description:
  - '提高物理暴击触发概率。'
  - '数值范围 0~100,15 表示 15%。'

示例: 生命值 (资源上限) ​

yaml
id: health
display_name: '<green>生命值'
value_kind: RESOURCE
target_type: RESOURCE
target_id: health
default_value: 0
min_value: 0
max_value: 1000000
allow_negative: false
priority: 100
lore_format_id: default_resource
attribute_power: 1.0

若需要同步到 Bukkit 的原版生命上限, 改用 target_type: VANILLA 并把 target_id 写成裸名 max_health (内置 max_health_vanilla.yml 即此写法)

示例: 移动速度 ​

yaml
id: movement_speed
display_name: '<aqua>移动速度'
value_kind: FLAT
target_type: GENERIC
target_id: movement_speed
default_value: 0.0
min_value: -1000
max_value: 1000
allow_negative: true
priority: 51
lore_format_id: default_flat
attribute_power: 1.0

示例: 法力恢复 ​

yaml
id: mana_regen
display_name: '<blue>法力恢复'
value_kind: REGEN
target_type: RESOURCE
target_id: mana
default_value: 0
min_value: 0
max_value: 100
allow_negative: false
priority: 60
lore_format_id: default_regen
attribute_power: 0.8
description:
  - '每秒恢复的法力值。'

区间随机值 ​

Attribute 支持把单个属性贡献写成区间值. 解析时会得到最小值, 最大值和本次实际取值, 正好用在"随机攻击力""随机百分比加成"这类装备词条上

常见写法示例:

yaml
ea_attributes:
  physical_attack: "10-20"
  physical_crit_rate: "5%-12%"

使用建议:

  • 整数或普通数值区间适合攻击, 防御, 资源上限这类平坦属性
  • 百分比区间适合 PERCENT / CHANCE 类型属性; 系统内部仍建议统一用同一个数值尺度, 避免 0.15 与 15 混用
  • 区间最终会写入快照贡献, 调试时要同时看最小值, 最大值和实际取值
  • 新装备系统仍优先通过 PDC 属性 payload 写入区间结果, 不建议只依赖 Lore 文本

Lore 解析 ​

lore_pattern 模板变量 ​

你在 lore_pattern / lore_patterns 里可以用下面这些模板变量:

变量展开为
%Key% / %key%属性 display_name 的正则转义字符串
%Value% / %value%数值捕获组 ([+-]?\d+(?:\.\d+)?)(?:\s*[-~~]\s*([+-]?\d+(?:\.\d+)?))?. 一共两个捕获组: 第一组是数值本身, 第二组是可选的区间上界, 区间分隔符支持 -, ~ 与全角 ~. 只匹配到第一组时, 上下界相同

示例 ​

yaml
lore_patterns:
  - '%Key%:%Value%'
  - '%Key% \\+%Value%'

如果 display_name 为 物理攻击, 上面的模式会匹配:

  • 物理攻击:15
  • 物理攻击 +15

Lore 解析的局限性 ​

lore_patterns 是从已有物品 Lore 里读出属性的, 适合兼容旧物品或外部插件物品. 但做新装备系统时别把它当主要数据来源, 原因是:

  • 文本解析容易受颜色, 语言, 格式影响
  • 玩家或其他插件可能修改 Lore
  • 性能和稳定性不如 PDC
  • 正则匹配可能误匹配到相似的文本

新系统建议让 EmakiItem, Forge, Strengthen, Gem 等模块直接把属性写进 PDC 属性 payload

lore_format_id 优先级 ​

内置 Lore 格式的默认优先级:

格式 ID优先级
default_percent100
default_regen80
default_resource60
default_flat50

优先级越高, 在 Lore 中越先匹配

数值范围设计 ​

百分比属性 ​

记住, 本模块统一按 0~100 结算百分比与概率, 15 就是 15%. 内置属性与配置全部遵循这一尺度: physical_crit_rate 的 max_value 为 100.0, config.yml 的 default_profile.attributes 里 physical_crit_damage: 150.0, block_rate / block_reduction: 100.0, damage_types/physical.yml 的表达式也统一写成 (%multiplier% / 100). 概率类输入在结算时会被夹到 [0, 100]

yaml
# 推荐: 统一使用 0~100
min_value: 0
max_value: 100  # 100% 上限

# 不推荐: 混用 0~1 尺度
min_value: 0
max_value: 1  # 结算按 0~100 处理, 这里的 1 只相当于 1%

攻击和防御 ​

建议设置合理上限, 防止数值膨胀:

yaml
# 攻击
max_value: 999999

# 防御 (通常不应超过攻击上限)
max_value: 999999

# 穿透 (通常不应超过防御上限)
max_value: 999999