简体中文
伤害系统
伤害类型文件要写清的内容如下: 一次伤害是怎么一步步算出来的, 每个阶段配哪些参数, 原版伤害怎么被接管
伤害类型文件放在 damage_types/*.yml. 伤害不是用一条固定公式算的, 而是走 stages 多阶段管线 (一步一步叠加的计算流程). 每个伤害类型都能配自己的攻击, 防御, 暴击, 穿透和恢复规则
伤害类型配置
顶层字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id | string | 是 | — | 伤害类型唯一 ID, 例如 physical, projectile, spell |
display_name | string | 否 | 同 id | 显示名称 |
aliases | list<string> | 否 | [] | 别名列表, 用于兼容旧配置或简写 |
hard_lock | boolean | 否 | false | 要不要强接管这个类型的伤害. 为 true 时, 匹配到的原版伤害事件会被完全替换为属性伤害计算 |
allowed_events | list<string> | 否 | [] | 允许触发此伤害类型的事件名白名单. 空列表表示不限制 |
description | string | 否 | "" | 描述文本 |
message | string | 否 | — | 攻击者和目标共用的战斗消息, 可被下面两个字段覆盖 |
attacker_message | string | 否 | — | 攻击者收到的消息 |
target_message | string | 否 | — | 目标收到的消息 |
stages | list | 否 | [] | 伤害计算阶段列表 |
recovery | object | 否 | — | 战后恢复或吸血计算配置 |
内置伤害类型
默认生成三个伤害类型文件:
physical.yml— 物理伤害 (近战)projectile.yml— 投射物伤害 (弓箭, 三叉戟)spell.yml— 法术伤害
stages 多阶段管线
伤害计算按 stages 列表的顺序一步步执行. 每个阶段读取指定属性, 算完后叠加到最终伤害值上
stage 字段
| 字段 | 类型 | 必填 | 默认值 | 说明 |
|---|---|---|---|---|
id | string | 否 | "stage" | 阶段 ID, 用于调试输出 |
kind | enum | 否 | FLAT_PERCENT | 计算类型 |
source | enum | 否 | ATTACKER | 属性来源 |
mode | enum | 否 | ADD | 结果叠加方式 |
role | enum | 否 | 按 id 推断 | 阶段扮演的角色: NORMAL / CRITICAL / DEFENSE / BLOCK. 省略时按阶段 id 推断: crit, critical → CRITICAL; defense, target_defense → DEFENSE; block, shield_block → BLOCK; 其余 → NORMAL. 自定义 id 如果要参与暴击, 防御或格挡, 请自己显式声明 |
flat_attributes | list<string> | 否 | [] | 参与平坦加成的属性 ID 列表 |
percent_attributes | list<string> | 否 | [] | 参与百分比加成的属性 ID 列表 |
chance_attributes | list<string> | 否 | [] | 参与概率触发的属性 ID 列表 |
multiplier_attributes | list<string> | 否 | [] | 参与乘数的属性 ID 列表 |
expression | string | 否 | "" | 自定义计算表达式 (kind=CUSTOM 时使用) |
variables | map | 否 | {} | 本阶段的自定义变量 (kind=CUSTOM 时可以被 expression 引用) |
min_result | double | 否 | — | 阶段结果下限 |
max_result | double | 否 | — | 阶段结果上限 |
min_chance | double | 否 | — | 概率下限 |
max_chance | double | 否 | — | 概率上限 |
min_multiplier | double | 否 | — | 乘数下限 |
max_multiplier | double | 否 | — | 乘数上限 |
kind 计算类型
| 值 | 说明 |
|---|---|
FLAT_PERCENT | 标准模式: 先算 flat 属性总和, 再乘 percent 属性加成, 最后判断 chance 触发和 multiplier 乘数 |
CUSTOM | 自定义表达式模式: 用 expression 字段里的公式计算 |
CUSTOM 表达式变量
选了 kind: CUSTOM 后, 你在 expression 里可以用这些变量:
| 变量 | 说明 |
|---|---|
%input% / %base% | 进入本阶段时的伤害值 |
%flat% | flat_attributes 汇总值 |
%percent% | percent_attributes 汇总值 |
%chance% | chance_attributes 汇总概率 |
%multiplier% | multiplier_attributes 汇总倍率 |
%crit% | 本阶段是否判定暴击, 暴击为 1, 否则为 0 |
%roll% | 本次结算使用的随机骰值 |
内置 physical.yml 的用法示例:
yaml
- id: crit
kind: CUSTOM
source: ATTACKER
chance_attributes: [physical_crit_rate]
multiplier_attributes: [physical_crit_damage]
expression: "%input% * (1 + (%crit% * (%multiplier% / 100)))"
- id: defense
kind: CUSTOM
source: TARGET
flat_attributes: [physical_defense]
expression: "max(0, %input% - %flat%)"表达式为空或算不出来时会回退到默认结果: 没有概率属性时保持 %input% 不变, 否则按暴击倍率折算
阶段自定义变量
除了内置变量, 每个阶段还能用 variables 声明自己的变量, 给本阶段的 expression 用. 变量值可以是数值, 表达式或随机数值配置:
yaml
- id: overflow_soften
kind: CUSTOM
source: ATTACKER
variables:
soft_cap: 120
overflow: "max(0, %input% - %soft_cap%)"
jitter:
min: 0.95
max: 1.05
expression: "(%input% - %overflow% * 0.5) * %jitter%"规则:
- 变量可以引用内置变量 (如
%input%,%multiplier%), 伤害上下文变量, 以及在它之前声明的其他变量 - 变量按声明顺序解析, 因此
overflow能引用先声明的soft_cap. 自引用会被拒绝 - 同名变量会覆盖内置变量与上下文变量
- 变量只对声明它的阶段有效, 不会传给后面的阶段
- 随机数值配置在同一次表达式求值内只掷一次 (多处引用取值一致), 但每个阶段, 每次命中都会重新掷
- 变量解析失败 (例如值是非数值文本, 或引用了没声明的变量) 会导致整条表达式求值失败, 该阶段结果为
0. 这是表达式引擎一贯的行为, 改过variables后建议用/ea trace复核
source 属性来源
| 值 | 说明 |
|---|---|
ATTACKER | 从攻击方读取属性 |
TARGET | 从防御方读取属性 |
CONTEXT | 从上下文读取 (用于特殊场景) |
mode 叠加方式
| 值 | 说明 |
|---|---|
ADD | 把阶段结果加到当前伤害值上 |
SUBTRACT | 把阶段结果从当前伤害值里减去 |
内置物理伤害管线
内置 damage_types/physical.yml 的实际配置:
yaml
id: physical
display_name: "物理伤害"
aliases: [physical_damage, phys]
allowed_events:
- ENTITY_ATTACK
- ENTITY_SWEEP_ATTACK
hard_lock: true
stages:
- id: attack
kind: FLAT_PERCENT
source: ATTACKER
mode: ADD
flat_attributes: [physical_attack]
percent_attributes: [physical_damage_bonus]
- id: crit
kind: CUSTOM
source: ATTACKER
chance_attributes: [physical_crit_rate]
multiplier_attributes: [physical_crit_damage]
expression: "%input% * (1 + (%crit% * (%multiplier% / 100)))"
- id: defense
kind: CUSTOM
source: TARGET
flat_attributes: [physical_defense]
expression: "max(0, %input% - %flat%)"
- id: block
kind: CUSTOM
source: TARGET
chance_attributes: [block_rate]
multiplier_attributes: [block_reduction]
expression: "%input% * (1 - (%target_blocking% * %crit% * (%multiplier% / 100)))"
min_result: 0
recovery:
source: ATTACKER
resistance_source: TARGET
flat_attributes: [percentage_lifesteal]
percent_attributes: [lifesteal]
resistance_attributes: [lifesteal_resistance]
attacker_message: "<gray>[<gold>%damage_type%</gold>]</gray> <green>你对 <white>%target%</white> 造成了 <yellow>%final_damage%</yellow> 点伤害</green>%critical_suffix%"
target_message: "<gray>[<gold>%damage_type%</gold>]</gray> <red>%attacker%</red> 对你造成了 <yellow>%final_damage%</yellow> 点伤害%critical_suffix%"阶段按列表顺序执行: 前一阶段的输出就是下一阶段的输入. 想少刷屏的话, 把 attacker_message / target_message 填成空字符串, 对应消息就不会发
recovery 恢复配置
恢复配置用于计算攻击之后的吸血或回复效果
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
source | enum | ATTACKER | 回复属性从哪来 |
resistance_source | enum | TARGET | 抗性属性从哪来 |
flat_attributes | list<string> | [] | 平坦回复属性 |
percent_attributes | list<string> | [] | 百分比回复属性 (按最终伤害的百分比) |
resistance_attributes | list<string> | [] | 抗性属性 (会减少回复效果) |
expression | string | "" | 自定义回复表达式 |
min_result | double | — | 回复结果下限 |
max_result | double | — | 回复结果上限 |
原版伤害接管模式
全局 vanilla_event_damage.enabled 是当前原版伤害接管模式的开关:
enabled: true: 当前推荐的完美接管模式. Attribute 不取消原版伤害事件, 而是在事件返回前同步结算 EA 伤害并原地改写最终伤害值. 这样能保留原版副作用, 例如着火僵尸点燃玩家, 铁傀儡击飞, 盾牌格挡, 吸收之心, 荆棘, 死亡统计等. 盾牌格挡的归属可以由shield.mode改为交给 EA 结算, 见下文"盾牌格挡"enabled: false: 兼容模式. 按旧逻辑取消事件后由 Attribute 重放伤害与反馈, 适合需要保留旧行为, 或要和特殊战斗插件联调的服务器
完美接管模式只改变"伤害如何施加", 不改变当前的伤害数值管线. 结算结果为闪避, 事件取消, 或最终伤害小于等于 0 时, 本次原版事件会被取消. 吸血, 战斗消息和攻击冷却等 Attribute 自身的副作用仍由 Attribute 补发
盾牌格挡
原版盾牌走 EntityDamageEvent.DamageModifier.BLOCKING, 它独立于 EA 的伤害管线. 全局 shield.mode 决定格挡由谁结算
yaml
shield:
mode: vanilla
require_facing: true
facing_angle_degrees: 180| 字段 | 默认值 | 说明 |
|---|---|---|
mode | vanilla | vanilla 保留原版 BLOCKING; attribute 把它清零, 改由伤害阶段结算 |
require_facing | true | 只在 attribute 模式生效, 要不要要求来源位于正面 |
facing_angle_degrees | 180 | 正面判定的张角. 180 等价于原版的半平面判定 |
两种模式的区别
mode: vanilla (默认, 保持既有行为): 举盾时原版 BLOCKING 把 EA 算出的伤害整体抹掉, 因此 EA 的攻击, 暴击, 穿透在举盾时全部不生效. 这个模式下上下文变量 target_blocking 恒为 0, 伤害类型里的 block 阶段等价于不改变伤害
mode: attribute: EA 清零原版 BLOCKING, 改由 block 阶段读取目标的 block_rate 与 block_reduction 结算, 可以做成百分比减伤. 默认基线是 block_rate: 100 / block_reduction: 100, 等价于原版全免, 所以只切换模式不会改变手感; 把 block_reduction 调低即得到百分比格挡
相关属性
这两个都是普通 EA 属性, 所以盾牌数值可以来自 Lore 词条或 PDC, Gem, Strengthen, Forge 和套装也能照常给它们加成
| 属性 ID | 含义 |
|---|---|
block_rate | 举盾时格挡的触发概率. 为 0 时格挡永不触发 |
block_reduction | 格挡触发后削减的伤害百分比. 100 等价于原版全免 |
数值基线写在 config.yml 的 default_profile.attributes, 物品数值在基线之上叠加, 总值受属性自身 max_value 截断
block 阶段
内置 physical.yml 与 projectile.yml (原版盾牌同样能挡投射物) 都带有该阶段; spell.yml 没有, 因为原版盾牌不挡法术
yaml
- id: block
kind: CUSTOM
source: TARGET
chance_attributes: [block_rate]
multiplier_attributes: [block_reduction]
expression: "%input% * (1 - (%target_blocking% * %crit% * (%multiplier% / 100)))"
min_result: 0%target_blocking% 是本次受击是否构成有效举盾 (含正面判定), 取 1 或 0. %crit% 在这里表示 block_rate 概率是否命中
注意事项
- 自定义
block阶段时chance_attributes必须保留block_rate且基线非零, 否则%crit%恒为0, 举盾将完全不减伤 %target_blocking%在所有伤害阶段表达式中始终可用; 不带目标实体的伤害请求会回落到0- 环境伤害没有来源方向,
require_facing: true时不构成正面格挡 - 格挡与暴击共用同一次随机骰值, 这是 stages 管线一向的行为
合成命中反馈
合成命中反馈主要给兼容模式用. 完美接管模式下, 原版自己就会产生击退, 受伤动画和音效 (具体表现随伤害来源和实体而定). 需要时, synthetic_hit_feedback 会补发击退和受伤音效, 让战斗反馈更接近原版体验
yaml
synthetic_hit_feedback:
knockback: true
knockback_strength: 0.4
hurt_sound: true| 字段 | 说明 |
|---|---|
knockback | 要不要补发击退 |
knockback_strength | 击退强度. 数值越高, 目标位移越明显 |
hurt_sound | 要不要播放受伤音效 |
调参建议:
- 如果服务器有自定义击退插件, 先关闭
knockback测试兼容性 - 如果战斗节奏偏快, 过强的击退会影响近战连段, 可以降低
knockback_strength - 如果战斗消息, 粒子和音效较多, 可以关闭
hurt_sound降低反馈噪音
hard_lock 与 allowed_events
hard_lock
hard_lock 写在伤害类型上, 意思是"这个类型只接受 allowed_events 里的事件". 它会被解析并随伤害类型定义传递
与 hard_lock_damage 不是同一个字段
config.yml 顶层的 hard_lock_damage 是兼容保留项, 只被配置解析器读取, 运行时没有任何地方用到它, 改它不会改变任何行为 (config.yml 自带的注释就是这个意思). 没被 allowed_damage_causes 映射命中的原版伤害由 vanilla_event_damage 决定: enabled: true 时按 vanilla_event_damage.damage_type 进入属性管线, enabled: false 时只有 allowed_damage_causes 中允许的原因进入 EA, 其余保留原版行为
allowed_events
声明哪些原版伤害事件可以触发这个伤害类型. 空列表表示不限制. 常见事件:
ENTITY_ATTACK— 近战攻击PROJECTILE— 投射物ENTITY_SWEEP_ATTACK— 横扫攻击