Files
zeling_v2/Assets/_Game/Scripts/Combat/DamageInfo.cs
2026-05-19 23:20:44 +08:00

137 lines
7.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using BaseGames.Core.Events;
namespace BaseGames.Combat
{
/// <summary>
/// 单次伤害信息。流水线RawDamage → Amount护盾修改→ FinalDamage防御减免后
/// ⚠️ 保留为可变 structHurtBox 流水线需要在方法内修改本地副本的 Amount / FinalDamage。
/// Builder 通过独立字段构造,不直接修改 DamageInfo 实例。
/// </summary>
[System.Serializable]
public struct DamageInfo
{
public int RawDamage; // HitBox 设定的原始值(工厂/Builder 写入一次)
public int Amount; // 流水线中被护盾/防御修改
public int FinalDamage; // HurtBox 写入,最终 HP 扣除量
public Vector2 KnockbackDirection;
public float KnockbackForce;
public float HitStunDuration;
public DamageType Type;
public DamageCategory Category;
public DamageFlags Flags;
public DamageTags Tags;
public Vector2 SourcePosition;
public int SourceLayer;
public HitFxType FxType;
public BreakLevel Break;
public string SourceId;
public string SkillId;
/// <summary>
/// 攻击来源投射物(仅当攻击方是 Projectile 时非 null
/// 用于弹反成功时调用 ReflectAsPlayerProjectile() 翻转阵营。
/// [NonSerialized]MonoBehaviour 引用不参与 Unity 资产序列化。
/// </summary>
[System.NonSerialized] public Projectile SourceProjectile;
// ── Builder ──────────────────────────────────────────────────────────
/// <summary>
/// 通过独立字段构造 DamageInfo避免直接持有可变 DamageInfo 实例。
/// </summary>
public class Builder
{
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;
private Projectile _sourceProjectile;
public Builder() { }
// SetRaw 同步初始化 AmountAmount 始终以 RawDamage 为起点)
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 Builder SetProjectile(Projectile v) { _sourceProjectile = 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,
SourceProjectile = _sourceProjectile,
};
}
/// <summary>
/// ⚡ 零堆分配工厂(热路径首选)。从 DamageSourceSO 填入所有静态字段;
/// 可选传入运行时字段knockbackDir、sourcePos、sourceLayer
/// 无需调用方事后就地赋值。
/// </summary>
public static DamageInfo From(
DamageSourceSO so,
Vector2 knockbackDir = default,
Vector2 sourcePos = default,
int sourceLayer = 0,
Projectile sourceProjectile = null)
{
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,
KnockbackDirection = knockbackDir,
KnockbackForce = so.KnockbackForce,
SourcePosition = sourcePos,
SourceLayer = sourceLayer,
SourceProjectile = sourceProjectile,
};
}
}
/// <summary>伤害事件频道EVT_DamageDealt。</summary>
[UnityEngine.CreateAssetMenu(menuName = "Events/DamageDealt")]
public class DamageInfoEventChannelSO : BaseEventChannelSO<DamageInfo> { }
}