fix(combat): 统一受击无敌闸门并修复 DoT 失效

将无敌判定收口到 PlayerController.TakeDamage(DamageInfo) 单一闸门并认 DamageFlags.IgnoreIFrame,PlayerStats 拆出原始扣血 ApplyDamage;新增 DamageFlags.IsDoT,持续伤害只扣血不打断硬直、不授予无敌。修复 DoT 绕过 HurtBox 时被 flag-blind 的整数 TakeDamage 静默吞没、且 FinalDamage 未结算(恒为0)的双重失效;敌人侧 DoT 标记 IsDoT 避免每 Tick 重置硬直。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-11 16:30:56 +08:00
parent 523f7c842a
commit 0491e3f919
8 changed files with 54 additions and 15 deletions

View File

@@ -33,6 +33,12 @@ namespace BaseGames.Combat
NoKnockback = 1 << 7,
/// <summary>击飞:使敌人进入 KnockUp 状态(腾空 + 落地)。仅在伤害量 &gt;= HitTierConfig.launchThreshold 时生效。</summary>
Launch = 1 << 8,
/// <summary>
/// 持续伤害DoT。承伤方据此区分"持续伤害"与"一次性打击"
/// 只扣血,不触发受击硬直/打断,也不授予新的无敌帧。
/// 通常与 <see cref="IgnoreIFrame"/> 同时设置DoT 既不被无敌挡、也不刷新无敌)。
/// </summary>
IsDoT = 1 << 9,
}
// ── 交互标签 ────────────────────────────────────────────────────────────

View File

@@ -32,7 +32,7 @@ namespace BaseGames.Combat.StatusEffects
var info = new DamageInfo.Builder()
.SetRaw(1)
.SetType(DamageType.True)
.SetFlags(DamageFlags.IgnoreIFrame)
.SetFlags(DamageFlags.IgnoreIFrame | DamageFlags.IsDoT)
.Build();
Owner?.ApplyDirectDamage(info);
}

View File

@@ -34,7 +34,7 @@ namespace BaseGames.Combat.StatusEffects
var info = new DamageInfo.Builder()
.SetRaw(StackCount) // 叠层越多伤害越高
.SetType(DamageType.True)
.SetFlags(DamageFlags.IgnoreIFrame)
.SetFlags(DamageFlags.IgnoreIFrame | DamageFlags.IsDoT)
.Build();
Owner?.ApplyDirectDamage(info);
}

View File

@@ -130,6 +130,9 @@ namespace BaseGames.Combat.StatusEffects
/// </summary>
public void ApplyDirectDamage(DamageInfo info)
{
// DoT 绕过 HurtBox不经过其防御减免步骤需在此自行结算最终伤害。
// True 伤害不计防御,直接以 Amount 作为 FinalDamageBuilder 未设置 FinalDamage默认 0
if (info.FinalDamage <= 0) info.FinalDamage = info.Amount;
_damageable?.TakeDamage(info);
}