using UnityEngine; using BaseGames.Combat; using BaseGames.Enemies.Abilities; namespace BaseGames.Enemies.StatusEffects { /// /// 冻结效果:停止敌人移动,中断所有能力,降低 BT Tick 频率。 /// 效果持续期间每帧强制停止水平移动。 /// public sealed class FrozenEffect : IStatusEffect { public StatusEffectType Type => StatusEffectType.Frozen; public float Duration { get; } public bool IsFinished => _elapsed >= Duration; private float _elapsed; public FrozenEffect(float duration) => Duration = duration; public void OnApplied(EnemyBase enemy) { _elapsed = 0f; enemy.Abilities?.InterruptAll(InterruptReason.ExternalRequest); enemy.StopMovement(); enemy.SetAggroTickRate(false); } public void Tick(EnemyBase enemy, float deltaTime) { _elapsed += deltaTime; enemy.Movement?.StopHorizontal(); } public void OnRemoved(EnemyBase enemy) { } } /// /// 睡眠效果:敌人进入休眠状态,受到任意伤害立即唤醒。 /// 持续时间可为负值(永久,直到被击醒)。 /// public sealed class SleepEffect : IStatusEffect { public StatusEffectType Type => StatusEffectType.Sleep; public float Duration { get; } public bool IsFinished => _awoken || (Duration >= 0f && _elapsed >= Duration); private float _elapsed; private bool _awoken; private int _lastHP; public SleepEffect(float duration = -1f) => Duration = duration; public void OnApplied(EnemyBase enemy) { _elapsed = 0f; _awoken = false; _lastHP = enemy.Stats != null ? enemy.Stats.CurrentHP : int.MaxValue; enemy.Abilities?.InterruptAll(InterruptReason.ExternalRequest); enemy.StopMovement(); enemy.SetAggroTickRate(false); } public void Tick(EnemyBase enemy, float deltaTime) { _elapsed += deltaTime; enemy.Movement?.StopHorizontal(); // 受击检测:HP 减少则唤醒 if (enemy.Stats != null && enemy.Stats.CurrentHP < _lastHP) _awoken = true; if (enemy.Stats != null) _lastHP = enemy.Stats.CurrentHP; } public void OnRemoved(EnemyBase enemy) { } } /// /// 灼烧效果:每 tickInterval 秒对敌人造成 damagePerTick 点持续伤害。 /// 不触发霸体判定(无 DamageFlags.ForceBreak),允许受击动作打断。 /// public sealed class BurningEffect : IStatusEffect { public StatusEffectType Type => StatusEffectType.Burning; public float Duration { get; } public bool IsFinished => _elapsed >= Duration; private readonly float _damagePerTick; private readonly float _tickInterval; private float _elapsed; private float _nextTick; public BurningEffect(float duration, float damagePerTick, float tickInterval = 0.5f) { Duration = duration; _damagePerTick = damagePerTick; _tickInterval = tickInterval; } public void OnApplied(EnemyBase enemy) { _elapsed = 0f; _nextTick = _tickInterval; } public void Tick(EnemyBase enemy, float deltaTime) { _elapsed += deltaTime; if (_elapsed >= _nextTick) { _nextTick += _tickInterval; var info = new DamageInfo { RawDamage = (int)_damagePerTick, Amount = (int)_damagePerTick, FinalDamage = (int)_damagePerTick, Type = DamageType.Fire, Flags = DamageFlags.None, }; enemy.TakeDamage(info); } } public void OnRemoved(EnemyBase enemy) { } } }