238 lines
6.2 KiB
C#
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 CharacterStatType statType;
|
|
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
|
|
|