RiftMayhem/Assets/Character Stats/CharacterStat.cs

238 lines
6.2 KiB
C#

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using UnityEngine.Events;
public enum CharacterStatType
{
Cunning,
Flow,
Presence,
AttackDamage,
SpellDamage,
AttackSpeed,
CritChance,
CritDamage,
AuraPower,
MaxHealth,
HealthRegen,
MaxMana,
ManaRegen,
Armor,
MagicResistance,
DodgeChance,
BlockChance,
BlockEffectiveness,
AreaEffectiveness,
CooldownReduction,
MovementSpeed,
ReputationGainIncrease,
GoldCostReduction
}
public static class CharacterStatHelper
{
public static List<CharacterStatType> Attributes = new List<CharacterStatType>()
{
CharacterStatType.Cunning,
CharacterStatType.Flow,
CharacterStatType.Presence
};
public static bool IsAttribute(CharacterStatType type)
{
return Attributes.Contains(type);
}
public static List<CharacterStatType> Damage = new List<CharacterStatType>()
{
CharacterStatType.AttackDamage,
CharacterStatType.SpellDamage,
};
public static bool IsDamage(CharacterStatType type)
{
return Damage.Contains(type);
}
public static List<CharacterStatType> Offensive = new List<CharacterStatType>()
{
CharacterStatType.AttackSpeed,
CharacterStatType.CritChance,
CharacterStatType.CritDamage,
//CharacterStatType.AuraPower,
};
public static bool IsOffensive(CharacterStatType type)
{
return Offensive.Contains(type);
}
public static List<CharacterStatType> Defensive = new List<CharacterStatType>()
{
CharacterStatType.Armor,
CharacterStatType.MagicResistance,
CharacterStatType.DodgeChance,
CharacterStatType.BlockChance,
CharacterStatType.BlockEffectiveness,
};
public static bool IsDefensive(CharacterStatType type)
{
return Defensive.Contains(type);
}
public static List<CharacterStatType> Resource = new List<CharacterStatType>()
{
CharacterStatType.MaxHealth,
CharacterStatType.HealthRegen,
CharacterStatType.MaxMana,
CharacterStatType.ManaRegen,
};
public static bool IsResource(CharacterStatType type)
{
return Resource.Contains(type);
}
public static List<CharacterStatType> Control = new List<CharacterStatType>()
{
CharacterStatType.AreaEffectiveness,
CharacterStatType.CooldownReduction,
CharacterStatType.MovementSpeed,
};
public static bool IsControl(CharacterStatType type)
{
return Control.Contains(type);
}
public static List<CharacterStatType> Misc = new List<CharacterStatType>()
{
CharacterStatType.ReputationGainIncrease,
CharacterStatType.GoldCostReduction,
};
public static bool IsMisc(CharacterStatType type)
{
return Misc.Contains(type);
}
}
namespace Kryz.CharacterStats
{
[Serializable]
public class CharacterStat
{
public GameTag statTag;
public StatDefinition statDefinition;
public float BaseValue;
protected bool isDirty = true;
protected float lastBaseValue;
protected float _value;
public virtual float Value
{
get
{
if (isDirty || lastBaseValue != BaseValue)
{
lastBaseValue = BaseValue;
_value = CalculateFinalValue();
isDirty = false;
}
return _value;
}
}
protected readonly List<StatModifier> statModifiers;
public readonly ReadOnlyCollection<StatModifier> StatModifiers;
public CharacterStat()
{
statModifiers = new List<StatModifier>();
StatModifiers = statModifiers.AsReadOnly();
}
public CharacterStat(float baseValue) : this()
{
isDirty = true;
BaseValue = baseValue;
}
public virtual void AddModifier(StatModifier mod)
{
isDirty = true;
statModifiers.Add(mod);
}
public virtual bool RemoveModifier(StatModifier mod)
{
if (statModifiers.Remove(mod))
{
isDirty = true;
return true;
}
return false;
}
public virtual bool HasModifiersFromSource(object source)
{
return StatModifiers.Any(mod => mod.Source == source);
}
public virtual bool RemoveAllModifiersFromSource(object source)
{
int numRemovals = statModifiers.RemoveAll(mod => mod.Source == source);
if (numRemovals > 0)
{
isDirty = true;
return true;
}
return false;
}
protected virtual int CompareModifierOrder(StatModifier a, StatModifier b)
{
if (a.Order < b.Order)
return -1;
else if (a.Order > b.Order)
return 1;
return 0; //if (a.Order == b.Order)
}
protected virtual float CalculateFinalValue()
{
float finalValue = BaseValue;
float sumPercentAdd = 0;
statModifiers.Sort(CompareModifierOrder);
for (int i = 0; i < statModifiers.Count; i++)
{
StatModifier mod = statModifiers[i];
if (mod.Type == StatModType.Flat)
{
finalValue += mod.Value;
}
else if (mod.Type == StatModType.PercentAdd)
{
sumPercentAdd += mod.Value;
if (i + 1 >= statModifiers.Count || statModifiers[i + 1].Type != StatModType.PercentAdd)
{
finalValue *= 1 + sumPercentAdd;
sumPercentAdd = 0;
}
}
else if (mod.Type == StatModType.PercentMult)
{
finalValue *= 1 + mod.Value;
}
}
// Workaround for float calculation errors, like displaying 12.00001 instead of 12
return (float)Math.Round(finalValue, 4);
}
}
}