百分比护甲伤害减免框架 - BG3SE资源

百分比护甲伤害减免框架 - BG3SE资源

MODDER'S RESOURCE —— 非独立平衡模组。一个BG3脚本扩展器参考实现,用于为护甲添加真实基于百分比的伤害减免,并同步生命值伤害、头顶数字和战斗日志输出。

百分比护甲伤害减免框架

这是一个模组制作者的资源和参考技术实现,用于使用 Norbyte 的 BG3 脚本扩展器为《博德之门 3》添加基于真实百分比的护甲伤害减免。

该项目始于一项实验,旨在寻找一种可靠的方法来实现百分比护甲伤害减免,而无需依赖固定的 DamageReduction 加成或特定来源的法术/武器豁免。

内置的基线实现保持原版护甲等级不变,并为每件已映射的护甲赋予与其 AC 值相等的自定义伤害减免百分比。

例如: 板甲:AC 18 + 18% 自定义护甲伤害减免 板甲 +1:AC 19 + 19% 自定义护甲伤害减免 板甲 +2:AC 20 + 20% 自定义护甲伤害减免 板甲 +3 / AC 21 护甲:21% 自定义护甲伤害减免

此映射仅为基线。百分比曲线可以自由更改,无需改动底层的伤害处理架构。


该框架的功能

该系统是事件驱动且来源无关的。 它不需要针对个别武器、法术、炸弹、神圣打击、物品附加伤害或范围效果进行特殊处理。相反,它基于引擎产生的实际伤害数据包运作。

该实现:

  • DealDamage 期间检测目标的已映射护甲
  • 通过同步 LIFO 上下文栈将护甲信息传递到 BeforeDealDamage
  • 读取 Hit.DamageList
  • 跳过持续性的 StatusTick 伤害
  • 为当前伤害事件计算一个百分比减免
  • 通过 Hit.TotalDamageDone 写入真实 HP 结果
  • 同步 Hit.DamageList,使飘字伤害数字和战斗日志显示相同的结果
  • DealtDamage 期间弹出上下文

最重要的实证发现是 BG3 暴露了两个具有不同实际效果的可写伤害表示: Hit.TotalDamageDone 控制实际的 HP 损失。 Hit.DamageList[].Amount 控制用于飘字和战斗日志的显示伤害路径。

仅修改 DamageList 可以使显示的伤害看起来减少,但目标仍会损失原始 HP 量。一个正确的实现需要以协调的方式同时更新两者。


伤害类型

内置基线将护甲伤害减免应用于所有 13 种标准 BG3 伤害类型,条件是事件为直接 / 非 StatusTick

强酸 钝击 冷冻 火焰 力场 闪电 黯蚀 穿刺 毒素 心灵 光耀 挥砍 雷鸣

持续性伤害被全局处理: CauseType == StatusTick → 无自定义护甲伤害减免

这意味着诸如持续的燃烧、强酸伤害和持续性区域效果的脉冲会绕过自定义护甲层,而无需法术特定的豁免。


强酸护甲腐蚀

参考实现还包含了与原版 ACID 状态的可选交互。 该状态本身可以保留: AC(-2)

当目标处于 ACID 状态时,Lua 层会额外将自定义护甲伤害减免降低 2 个百分点,最低为 0%。

示例: 皮甲:11% → 9% 锁子甲:16% → 14% 板甲:18% → 16% AC 21 护甲:21% → 19%

这让强酸能够表现为真正的护甲腐蚀,而不仅仅是在伤害上加成。


重要的引擎发现

在达成当前实现之前,测试了多种方法。

仅修改 DamageList 不会改变真实 HP 伤害 早期实验直接修改了 Hit.DamageListAttack.DamageList。 飘字伤害数字和战斗日志发生了改变,但实际 HP 损失并未改变。 这最初看起来像是一个失败的方法,但后来在真实伤害值被修改后,它成为同步 UI 的解决方案。

Hit.TotalDamageDone 是真实的每事件 HP 写入 写入: hit.TotalDamageDone = finalDamage 在测试路径中一致地改变了实际的 HP 损失。

不要使用 Attack.TotalDamageDone 作为每事件伤害 在神圣打击测试期间,Attack.TotalDamageDone 在构成性伤害事件之间变得具有累积性。 例如,一个 32 伤害的主事件后跟一个 12 伤害的反应神圣打击事件,在第二个事件期间产生了 44 的攻击总伤害。 因此,该框架从不使用 Attack.TotalDamageDone 作为权威的每事件值。

不要使用 Hit/Attack 指针身份关联事件 DealDamageBeforeDealDamage 暴露的 Hit 和 Attack 对象在测试期间没有保留有用的指针身份。 同步的 LIFO 上下文栈保持对齐,并被证明是实用的解决方案。

CauseType == Attack 并不意味着"攻击检定" 豁免/范围法术路径(如闪电链)可能显示为 CauseType = Attack,而反应神圣打击伤害可能显示为 CauseType = None。 因此,该框架不使用 CauseType 作为通用的伤害来源分类器。 唯一的特殊全局情况是: StatusTick → 绕过护甲伤害减免。


混合伤害与取整

混合伤害需要特别注意。 考虑: 5 挥砍 + 5 火焰 在 13% 护甲伤害减免下。

正确的事件级减免为: round(10 × 0.13) = 1

如果每个数据包独立取整: round(5 × 0.13) + round(5 × 0.13) = 1 + 1 = 2 则 UI 会显示 8 点伤害,而实际 HP 损失会是 9。

因此,内置的同步函数一次计算总减免量,并将该精确的整数减免分配到符合条件的 Hit.DamageList 数据包中。 这保证了: 实际 HP 损失 = 飘字伤害 = 战斗日志伤害


已测试的伤害路径

该架构针对多种伤害来源进行了测试,包括:

  • 普通近战和远程攻击
  • 混合伤害数据包
  • 强酸箭
  • 魔法飞弹
  • 符文火药爆炸
  • 寒冰锥
  • 闪电链
  • 震荡猛击 / 姿态破坏
  • 神圣打击
  • 反应神圣打击
  • 强化神圣打击
  • 武器和物品附加伤害
  • 范围法术伤害
  • StatusTick 效果,如燃烧、强酸和匕首之云

神圣打击测试尤其有用,因为引擎对普通神圣打击、反应神圣打击和强化神圣打击有着不同的打包方式。基于 DamageList 的方法无需神圣打击特定代码即可处理所有情况。


与原版减伤机制的交互

自定义护甲伤害减免作用于已经到达 BeforeDealDamage 的伤害值。 在一个测试过的地狱狱甲路径中: 13 点原始伤害

-3 点火焰至高守护

= 10 点进入自定义护甲伤害减免的伤害

百分比减免随后基于该剩余值计算。

因此,在测试设置中,抗性也是以乘法而非加法方式组合的。 示例: 100 点伤害

50% 抗性 → 50

18% 护甲伤害减免 → 41

总有效减免为 59%,而非 68%。


包含的文件

压缩包内包含: BootstrapServer.lua 可用的基线 BG3SE 实现。

技术文档 (.docx) 包含实验、失败方法、引擎观察、伤害策略决策和实现架构的详细记录。

功能性的 BootstrapClient.lua 对此资源并非必需,因为伤害系统在服务端运行。


重要集成说明

包含的示例通过自定义的隐藏 LIB_* 被动技能来识别护甲。 这些被动 ID 是原型识别数据,而非该架构的必需条件。

如果将该系统集成到另一个模组中,请用适合您项目的任何系统替换护甲映射/识别层。

可复用的关键部分包括:

  • DealDamage → BeforeDealDamage → DealtDamage 的 LIFO 桥接
  • Hit.TotalDamageDone 真实伤害写入
  • Hit.DamageList 分类和 UI 同步
  • 事件级百分比计算
  • 精确的混合数据包减免分配

护甲百分比表本身只是调优数据。


要求

Norbyte 的《博德之门 3》脚本扩展器

这主要被设计为模组制作者的资源,而非一个成品独立游戏模组。 建议具备 BG3 数据基础和脚本扩展器 Lua 的基本知识。


已知边界

  • StatusTick 被有意排除在护甲伤害减免之外。
  • 坠落伤害未出现在测试过的 DealDamage → BeforeDealDamage 桥接中。
  • 测试过的流血状态脉冲也未出现在该桥接中。
  • 每个伤害事件执行一次百分比取整运算。
  • 如果一个概念性攻击被分割为多个引擎伤害事件,每个事件独立取整。
  • 未知的未来伤害类型不会被盲目减免,除非添加到已识别的类型表中。

这些是刻意的架构边界,而非试图对每种可能的伤害来源进行特殊处理。


为何将此作为资源发布?

这个项目的有用之处不仅在于最终的 Lua 文件。 大量测试用于确定哪些可写伤害值实际影响 HP,哪些仅影响 UI 输出,多事件伤害如何表现,以及哪些事件关联是可靠的。

与其将这些发现保密,不如将资源发布,以便其他 BG3 模组制作者可以使用、修改、改进或在此基础上构建。 这里并未声称这是 BG3 有史以来第一个百分比护甲伤害减免实现。 目标只是记录一种经过测试的方法,并让底层信息对社区可用。


安装 / 集成

这主要是一个模组制作者资源

示例脚本扩展器结构为:

Mods
└── ArmorDR
    └── ScriptExtender
        ├── Config.json
        └── Lua
            ├── BootstrapServer.lua
            └── BootstrapClient.lua

伤害实现本身运行在 BootstrapServer.lua 中。 BootstrapClient.lua 不需要功能代码即可运行该系统。

包含的 Lua 期望原型 LIB_* 护甲识别被动技能。如果在其他项目中使用该资源,请复现相关的被动映射,或使用您自己的护甲检测方法替换 GetArmorProfile()

提供的基线期望护甲 AC 值保持原版,并将相同的数值映射为护甲伤害减免百分比。


兼容性

该资源不会直接替换原版伤害法术、武器攻击或个别伤害来源。

兼容性主要取决于:

  • 其他模组如何识别或修改护甲
  • 其他脚本扩展器模组是否在同一伤害事件期间也写入 Hit.TotalDamageDoneHit.DamageList
  • 其他模组是否大幅改变 BG3SE 伤害事件的管线

只添加武器、法术、炸弹或伤害附加效果的模组通常不需要来源特定的支持,因为该框架作用于最终的伤害数据包,而非硬编码的法术或武器 ID。

如果另一个模组也在 BeforeDealDamage 中修改最终伤害,应测试加载/顺序交互,而非凭空假设。


权限

欢迎将本代码和记录的发现自由使用、修改、改编或整合到您自己的 BG3 模组中。 无需请求许可。 注明出处值得感谢,但并非强制要求。

如果您改进了实现或发现了额外的引擎行为,欢迎与社区分享这些发现。