多轮审查和修复
This commit is contained in:
@@ -5,12 +5,13 @@ namespace BaseGames.Combat
|
||||
{
|
||||
/// <summary>
|
||||
/// 单次伤害信息。流水线:RawDamage → Amount(护盾修改)→ FinalDamage(防御减免后)。
|
||||
/// ⚠️ 非 readonly struct — Builder 就地写入字段。
|
||||
/// ⚠️ 保留为可变 struct:HurtBox 流水线需要在方法内修改本地副本的 Amount / FinalDamage。
|
||||
/// Builder 通过独立字段构造,不直接修改 DamageInfo 实例。
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public struct DamageInfo
|
||||
{
|
||||
public int RawDamage; // HitBox 设定的原始值(Builder.SetRaw 写入一次)
|
||||
public int RawDamage; // HitBox 设定的原始值(工厂/Builder 写入一次)
|
||||
public int Amount; // 流水线中被护盾/防御修改
|
||||
public int FinalDamage; // HurtBox 写入,最终 HP 扣除量
|
||||
public Vector2 KnockbackDirection;
|
||||
@@ -28,50 +29,92 @@ namespace BaseGames.Combat
|
||||
public string SkillId;
|
||||
|
||||
// ── Builder ──────────────────────────────────────────────────────────
|
||||
/// <summary>
|
||||
/// 通过独立字段构造 DamageInfo,避免直接持有可变 DamageInfo 实例。
|
||||
/// </summary>
|
||||
public class Builder
|
||||
{
|
||||
private DamageInfo _d;
|
||||
private int _raw;
|
||||
private DamageType _type;
|
||||
private DamageCategory _category;
|
||||
private DamageFlags _flags;
|
||||
private DamageTags _tags;
|
||||
private string _skillId;
|
||||
private string _sourceId;
|
||||
private Vector2 _knockbackDirection;
|
||||
private float _knockbackForce;
|
||||
private float _hitStunDuration;
|
||||
private HitFxType _fxType;
|
||||
private BreakLevel _break;
|
||||
private Vector2 _sourcePosition;
|
||||
private int _sourceLayer;
|
||||
|
||||
public Builder() { }
|
||||
|
||||
// SetRaw 同步初始化 Amount(Amount 始终以 RawDamage 为起点)
|
||||
public Builder SetRaw(int v) { _d.RawDamage = v; _d.Amount = v; return this; }
|
||||
public Builder SetType(DamageType v) { _d.Type = v; return this; }
|
||||
public Builder SetCategory(DamageCategory v){ _d.Category = v; return this; }
|
||||
public Builder SetFlags(DamageFlags v) { _d.Flags = v; return this; }
|
||||
public Builder SetTags(DamageTags v) { _d.Tags = v; return this; }
|
||||
public Builder SetSkillId(string v) { _d.SkillId = v; return this; }
|
||||
public Builder SetSourceId(string v) { _d.SourceId = v; return this; }
|
||||
public Builder SetKnockback(Vector2 dir, float force)
|
||||
{ _d.KnockbackDirection = dir; _d.KnockbackForce = force; return this; }
|
||||
public Builder SetStun(float dur) { _d.HitStunDuration = dur; return this; }
|
||||
public Builder SetFx(HitFxType v) { _d.FxType = v; return this; }
|
||||
public Builder SetBreak(BreakLevel v) { _d.Break = v; return this; }
|
||||
public Builder SetSourcePos(Vector2 v) { _d.SourcePosition = v; return this; }
|
||||
public Builder SetLayer(int v) { _d.SourceLayer = v; return this; }
|
||||
public DamageInfo Build() => _d;
|
||||
public Builder SetRaw(int v) { _raw = v; return this; }
|
||||
public Builder SetType(DamageType v) { _type = v; return this; }
|
||||
public Builder SetCategory(DamageCategory v) { _category = v; return this; }
|
||||
public Builder SetFlags(DamageFlags v) { _flags = v; return this; }
|
||||
public Builder SetTags(DamageTags v) { _tags = v; return this; }
|
||||
public Builder SetSkillId(string v) { _skillId = v; return this; }
|
||||
public Builder SetSourceId(string v) { _sourceId = v; return this; }
|
||||
public Builder SetKnockback(Vector2 dir, float force) { _knockbackDirection = dir; _knockbackForce = force; return this; }
|
||||
public Builder SetStun(float dur) { _hitStunDuration = dur; return this; }
|
||||
public Builder SetFx(HitFxType v) { _fxType = v; return this; }
|
||||
public Builder SetBreak(BreakLevel v) { _break = v; return this; }
|
||||
public Builder SetSourcePos(Vector2 v) { _sourcePosition = v; return this; }
|
||||
public Builder SetLayer(int v) { _sourceLayer = v; return this; }
|
||||
|
||||
public DamageInfo Build() => new DamageInfo
|
||||
{
|
||||
RawDamage = _raw,
|
||||
Amount = _raw,
|
||||
Type = _type,
|
||||
Category = _category,
|
||||
Flags = _flags,
|
||||
Tags = _tags,
|
||||
SkillId = _skillId,
|
||||
SourceId = _sourceId,
|
||||
KnockbackDirection = _knockbackDirection,
|
||||
KnockbackForce = _knockbackForce,
|
||||
HitStunDuration = _hitStunDuration,
|
||||
FxType = _fxType,
|
||||
Break = _break,
|
||||
SourcePosition = _sourcePosition,
|
||||
SourceLayer = _sourceLayer,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ⚡ 零堆分配工厂(热路径首选)。直接从 DamageSourceSO 填入基础字段。
|
||||
/// KnockbackDirection / SourcePosition / SourceLayer 等运行时字段由调用方就地赋值。
|
||||
/// ⚡ 零堆分配工厂(热路径首选)。从 DamageSourceSO 填入所有静态字段;
|
||||
/// 可选传入运行时字段(knockbackDir、sourcePos、sourceLayer),
|
||||
/// 无需调用方事后就地赋值。
|
||||
/// </summary>
|
||||
public static DamageInfo From(DamageSourceSO so)
|
||||
public static DamageInfo From(
|
||||
DamageSourceSO so,
|
||||
Vector2 knockbackDir = default,
|
||||
Vector2 sourcePos = default,
|
||||
int sourceLayer = 0)
|
||||
{
|
||||
int baseAmt = Mathf.RoundToInt(so.BaseDamage * so.DamageMultiplier);
|
||||
return new DamageInfo
|
||||
{
|
||||
RawDamage = baseAmt,
|
||||
Amount = baseAmt,
|
||||
Type = so.Type,
|
||||
Category = so.Category,
|
||||
Flags = so.Flags,
|
||||
Tags = so.Tags,
|
||||
HitStunDuration = so.HitStunDuration,
|
||||
FxType = so.FxType,
|
||||
Break = so.BreakLevel,
|
||||
SourceId = so.sourceId,
|
||||
SkillId = so.skillId,
|
||||
RawDamage = baseAmt,
|
||||
Amount = baseAmt,
|
||||
Type = so.Type,
|
||||
Category = so.Category,
|
||||
Flags = so.Flags,
|
||||
Tags = so.Tags,
|
||||
HitStunDuration = so.HitStunDuration,
|
||||
FxType = so.FxType,
|
||||
Break = so.BreakLevel,
|
||||
SourceId = so.sourceId,
|
||||
SkillId = so.skillId,
|
||||
KnockbackDirection = knockbackDir,
|
||||
KnockbackForce = so.KnockbackForce,
|
||||
SourcePosition = sourcePos,
|
||||
SourceLayer = sourceLayer,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user