多轮审查和修复

This commit is contained in:
2026-05-12 15:34:08 +08:00
parent f55d2a57c3
commit ebbbb7332e
805 changed files with 838724 additions and 1905 deletions

View File

@@ -1,20 +1,137 @@
using UnityEngine;
using System;
using BaseGames.Core.Events;
namespace BaseGames.Combat
{
/// <summary>
/// 护盾组件Phase 1 存根)。实现 IShieldable 接口供 HurtBox 注入。
/// Phase 2 实现完整护盾逻辑(护盾值、再生、破盾事件)
/// 护盾组件。实现 IShieldable 接口供 HurtBox 注入。
/// 护盾参数通过 ShieldConfigSO 集中配置
/// </summary>
public class ShieldComponent : MonoBehaviour, IShieldable
{
public bool HasShield { get; private set; }
[Header("配置资产")]
[SerializeField] private ShieldConfigSO _config;
[Header("VFX 事件频道")]
[SerializeField] private VoidEventChannelSO _onShieldBrokenChannel; // 护盾破碎 → 播放破碎 VFX
[SerializeField] private VoidEventChannelSO _onShieldRestoredChannel; // 护盾恢复 → 播放恢复 VFX
// ── 运行时属性 ────────────────────────────────────────────────────────
public int MaxShieldHP => _config.MaxShieldHP;
public int CurrentShieldHP { get; private set; }
/// <summary>当前是否能吸收伤害(护盾 HP > 0 且不在破碎惩罚期)。</summary>
public bool HasShield => CurrentShieldHP > 0 && _brokenPenaltyTimer <= 0f;
private float AbsorptionRatio => _config.DamageAbsorptionRatio;
private float RechargeDelay => _config.RechargeDelay;
private float RechargeRate => _config.RechargeRate;
private float BrokenPenaltyDur => _config.BrokenPenaltyDuration;
private float ParryRestoreRatio => _config.ParryRestoreRatio;
public event Action<int, int> OnShieldChanged; // (current, max)
public event Action OnShieldBroken;
private float _regenDelayTimer;
private float _brokenPenaltyTimer;
private void Awake()
{
Debug.Assert(_config != null, "[ShieldComponent] _config 未赋值,请在 Inspector 中指定 ShieldConfigSO。", this);
CurrentShieldHP = MaxShieldHP;
}
private void Update()
{
int maxHP = MaxShieldHP;
if (maxHP <= 0) return;
// 破碎惩罚计时
if (_brokenPenaltyTimer > 0f)
{
_brokenPenaltyTimer -= Time.deltaTime;
// 破碎惩罚结束 → 广播护盾恢复事件VFX 钩子)
if (_brokenPenaltyTimer <= 0f)
_onShieldRestoredChannel?.Raise();
return;
}
if (CurrentShieldHP >= maxHP) return;
if (RechargeRate <= 0f) return;
if (_regenDelayTimer > 0f)
{
_regenDelayTimer -= Time.deltaTime;
return;
}
int prev = CurrentShieldHP;
CurrentShieldHP = Mathf.Min(CurrentShieldHP + Mathf.CeilToInt(RechargeRate * Time.deltaTime), maxHP);
if (CurrentShieldHP != prev)
OnShieldChanged?.Invoke(CurrentShieldHP, maxHP);
}
/// <summary>
/// 尝试以护盾吸收伤害。
/// 返回穿透量0 = 全部吸收,>0 = 穿透量继续走 TakeDamage 流程)。
/// Phase 1护盾不存在全量穿透。
/// 尝试以护盾吸收伤害。返回穿透量0=全部吸收,>0=穿透量继续走 TakeDamage 流程)。
/// </summary>
public int AbsorbDamage(int amount) => amount;
public int AbsorbDamage(int amount)
{
if (!HasShield) return amount;
_regenDelayTimer = RechargeDelay;
int maxHP = MaxShieldHP;
// 按吸收比例计算实际由护盾承担的伤害
int toAbsorb = Mathf.FloorToInt(amount * AbsorptionRatio);
toAbsorb = Mathf.Min(toAbsorb, CurrentShieldHP);
int passthrough = amount - toAbsorb;
CurrentShieldHP -= toAbsorb;
OnShieldChanged?.Invoke(CurrentShieldHP, maxHP);
if (CurrentShieldHP <= 0)
{
CurrentShieldHP = 0;
_brokenPenaltyTimer = BrokenPenaltyDur;
OnShieldBroken?.Invoke();
_onShieldBrokenChannel?.Raise(); // VFX 钩子:播放护盾破碎特效
}
return passthrough;
}
/// <summary>存档点 / 复活时调用:完全恢复护盾并清除惩罚状态。</summary>
public void FullRecharge()
{
bool wasBroken = _brokenPenaltyTimer > 0f || CurrentShieldHP <= 0;
_brokenPenaltyTimer = 0f;
_regenDelayTimer = 0f;
CurrentShieldHP = MaxShieldHP;
OnShieldChanged?.Invoke(CurrentShieldHP, MaxShieldHP);
if (wasBroken)
_onShieldRestoredChannel?.Raise(); // VFX 钩子:护盾已满血恢复
}
/// <summary>弹反成功时调用:按 ParryRestoreRatio 恢复护盾(会清除惩罚状态)。</summary>
public void OnParrySuccess()
{
int maxHP = MaxShieldHP;
if (maxHP <= 0) return;
_brokenPenaltyTimer = 0f;
_regenDelayTimer = 0f;
int restore = Mathf.CeilToInt(maxHP * ParryRestoreRatio);
CurrentShieldHP = Mathf.Min(CurrentShieldHP + restore, maxHP);
OnShieldChanged?.Invoke(CurrentShieldHP, maxHP);
}
/// <summary>Inspector / 道具系统调用:设置最大护盾并重置当前值。</summary>
public void SetMaxShieldHP(int max)
{
_maxShieldHP = Mathf.Max(0, max);
_brokenPenaltyTimer = 0f;
CurrentShieldHP = MaxShieldHP;
OnShieldChanged?.Invoke(CurrentShieldHP, MaxShieldHP);
}
}
}