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
}