135 lines
4.6 KiB
C#
135 lines
4.6 KiB
C#
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
|
|
public class TickingEffectHandler : StatusEffectHandler
|
|
{
|
|
// Separate list for ONLY ticking effects
|
|
protected List<TickingRuntimeEffectInstance> tickingEffects = new List<TickingRuntimeEffectInstance>();
|
|
|
|
protected override void UpdateEffects(float deltaTime)
|
|
{
|
|
// Only iterate effects that can tick
|
|
for (int i = 0; i < tickingEffects.Count; i++)
|
|
{
|
|
tickingEffects[i].Tick(deltaTime);
|
|
}
|
|
}
|
|
|
|
protected override void UpdateCollections(StatusEffect effect, RuntimeEffectInstance runtimeEffect)
|
|
{
|
|
base.UpdateCollections(effect, runtimeEffect);
|
|
|
|
// Track ticking effects separately
|
|
if (runtimeEffect is TickingRuntimeEffectInstance tickingEffect)
|
|
{
|
|
tickingEffects.Add(tickingEffect);
|
|
}
|
|
}
|
|
|
|
protected override void RemoveFromCollections(RuntimeEffectInstance runtimeEffect)
|
|
{
|
|
base.RemoveFromCollections(runtimeEffect);
|
|
|
|
// Remove from ticking list
|
|
if (runtimeEffect is TickingRuntimeEffectInstance tickingEffect)
|
|
{
|
|
tickingEffects.Remove(tickingEffect);
|
|
}
|
|
}
|
|
|
|
#region Effect Query Utilities
|
|
|
|
/// <summary>
|
|
/// Get all effects of a specific type, optionally from a specific source
|
|
/// </summary>
|
|
public List<RuntimeEffectInstance> GetEffects(StatusEffect effectType, Taggable source = null)
|
|
{
|
|
if (!activeEffectsByType.TryGetValue(effectType, out var effects))
|
|
return new List<RuntimeEffectInstance>();
|
|
|
|
if (source == null)
|
|
return new List<RuntimeEffectInstance>(effects);
|
|
|
|
return effects.Where(e => e.user == source).ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get total stack count for a specific effect type
|
|
/// </summary>
|
|
public int GetStackCount(StatusEffect effectType, Taggable source = null)
|
|
{
|
|
var effects = GetEffects(effectType, source);
|
|
return effects.Sum(e => e.numberOfStacks);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the strongest effect of a type (highest stack count)
|
|
/// </summary>
|
|
public RuntimeEffectInstance GetStrongestEffect(StatusEffect effectType)
|
|
{
|
|
if (!activeEffectsByType.TryGetValue(effectType, out var effects) || effects.Count == 0)
|
|
return null;
|
|
|
|
return effects.OrderByDescending(e => e.numberOfStacks).First();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get all damage ticking effects of a specific damage type
|
|
/// </summary>
|
|
public List<DamageTickingRuntimeEffectInstance> GetDamageEffects(DamageType damageType)
|
|
{
|
|
return tickingEffects
|
|
.OfType<DamageTickingRuntimeEffectInstance>()
|
|
.Where(effect => effect.sourceEffect is DamageOverTimeEffect source &&
|
|
source.damageType == damageType)
|
|
.ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get total damage per second from all DOTs of a specific type
|
|
/// </summary>
|
|
public float GetTotalDPS(DamageType damageType)
|
|
{
|
|
return GetDamageEffects(damageType)
|
|
.Sum(effect => (effect.sourceEffect as DamageOverTimeEffect).baseDamagePerTick /
|
|
GameConstants.GameBalancing.EffectsTickingRate);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Generic method to check for any effect matching a condition
|
|
/// </summary>
|
|
public bool HasEffectWhere<T>(System.Func<T, bool> predicate) where T : RuntimeEffectInstance
|
|
{
|
|
return activeEffects.OfType<T>().Any(predicate);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get remaining time for the longest duration effect of a type
|
|
/// </summary>
|
|
public float GetRemainingTime(StatusEffect effectType)
|
|
{
|
|
if (!activeEffectsByType.TryGetValue(effectType, out var effects) || effects.Count == 0)
|
|
return 0f;
|
|
|
|
var longestEffect = effects.OrderByDescending(e => e.endEffectTime).First();
|
|
return Mathf.Max(0f, longestEffect.endEffectTime - Time.time);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Simplified Status Checks
|
|
|
|
// Your existing methods can now be simplified:
|
|
public bool IsBurning() => GetDamageEffects(DamageType.Fire).Count > 0;
|
|
public bool IsPoisoned() => GetDamageEffects(DamageType.Poison).Count > 0;
|
|
public bool IsBleeding() => GetDamageEffects(DamageType.Physical).Count > 0;
|
|
|
|
// Additional useful checks:
|
|
public int GetBurnStacks() => GetDamageEffects(DamageType.Fire).Sum(e => e.numberOfStacks);
|
|
public float GetBurnDPS() => GetTotalDPS(DamageType.Fire);
|
|
public float GetBurnTimeRemaining() => GetDamageEffects(DamageType.Fire).Max(e => e?.endEffectTime - Time.time ?? 0f);
|
|
|
|
#endregion
|
|
}
|