Files
zeling_v2/Assets/_Game/Scripts/Enemies/EnemyStats.cs

84 lines
2.7 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;
using BaseGames.Core.Events;
namespace BaseGames.Enemies
{
/// <summary>
/// 敌人运行时数值组件(架构 07_EnemyModule §2
/// 由 EnemyBase.Awake() 通过 Initialize(EnemyStatsSO) 注入配置。
/// 同时订阅难度变更事件,支持游戏进行中切换难度(架构 19 §5
/// </summary>
public class EnemyStats : MonoBehaviour
{
private EnemyStatsSO _config;
[SerializeField] private DifficultyChangedEventChannel _onDifficultyChanged;
public int MaxHP { get; private set; }
public int CurrentHP { get; private set; }
public int Defense { get; private set; }
public float AttackCooldownTimer { get; private set; }
/// <summary>
/// 每帧由 EnemyBase 更新sqrMagnitude避免 sqrt 开销)。
/// 使用方请与 range*range 比较,而非直接与 range 比较。
/// </summary>
public float SqrDistanceToPlayer { get; set; }
private readonly CompositeDisposable _subs = new();
private void OnEnable()
{
_onDifficultyChanged?.Subscribe(HandleDifficultyChanged).AddTo(_subs);
}
private void OnDisable()
{
_subs.Clear();
}
public void Initialize(EnemyStatsSO so)
{
_config = so;
Defense = so.Defense; // Defense 不随难度缩放(架构 19 §5
ApplyHPScaler();
CurrentHP = MaxHP;
}
/// <summary>难度变更时重算 HP保持 HP 比例,架构 19 §5。</summary>
private void HandleDifficultyChanged(DifficultyLevel _)
{
if (_config == null) return;
float hpRatio = MaxHP > 0 ? (float)CurrentHP / MaxHP : 1f;
ApplyHPScaler();
CurrentHP = Mathf.Clamp(Mathf.RoundToInt(MaxHP * hpRatio), 1, MaxHP);
}
private void ApplyHPScaler()
{
if (_config == null) return;
var scaler = ServiceLocator.GetOrDefault<IDifficultyService>()?.CurrentScaler;
MaxHP = scaler != null
? Mathf.Max(1, Mathf.RoundToInt(_config.MaxHP * scaler.EnemyHPMultiplier))
: _config.MaxHP;
}
public void TakeDamage(int amount)
{
CurrentHP = Mathf.Max(0, CurrentHP - amount);
}
public void TickAttackCooldown(float dt)
{
if (AttackCooldownTimer > 0f)
AttackCooldownTimer -= dt;
}
public void ResetAttackCooldown()
{
AttackCooldownTimer = _config.AttackCooldown;
}
}
}