using System; using UnityEngine; using BigFloatNumerics; using System.Collections.Generic; public enum StatID { SkillDamage = 1, CoolTime, CastDistance, MoveSpeedPerSec, Hp, Attack, ActionDelay, AttackSpeedPerSec, AttackDistance, } [CreateAssetMenu(fileName = "StatProperty", menuName = "ScriptableObject/Stat/StatProperty")] public class StatProperty : ScriptableObject { public enum ValueType { Flat, Percent = 5 } public uint id; public string nameKey; public string iconImgAtlasName; public string iconImgNameInAtlas; public string limitMin, limitMax; public ValueType valueType; } [Serializable] public class StatCreator { public StatProperty property; public string value; public StatData CreateStat() { return new StatData(property, BigFloat.Parse(value)); } } public class StatData { StatProperty statProperty; bool hasLimitMin, hasLimitMax; BigFloat limitMin, limitMax; BFValue currentValue; public BigFloat Max => limitMax; public BigFloat Min => limitMin; public BigFloat DefaultValue { get => currentValue.DefaultValue; set { currentValue.DefaultValue = value; OnValueChanged?.Invoke(); } } public BigFloat Value { get { if (hasLimitMin && currentValue.ModifiedValue < limitMin) return limitMin; else if (hasLimitMax && currentValue.ModifiedValue > limitMax) return limitMax; else return currentValue.ModifiedValue; } } public string NameKey => statProperty.nameKey; public string IconImgAtlasName => statProperty.iconImgAtlasName; public string IconImgNameInAtlas => statProperty.iconImgNameInAtlas; public StatProperty.ValueType ValueType => statProperty.valueType; public event Action OnValueChanged; public StatData(StatProperty property, BigFloat value) { statProperty = property; if (!string.IsNullOrEmpty(property.limitMax)) { limitMax = BigFloat.Parse(property.limitMax); hasLimitMax = true; } if (!string.IsNullOrEmpty(property.limitMin)) { limitMin = BigFloat.Parse(property.limitMin); hasLimitMin = true; } currentValue = new BFValue(value); } public void AddModifier(ValueModifier modifier) { currentValue.AddModifiers(modifier); OnValueChanged?.Invoke(); } public void RemoveModifier(ValueModifier modifier) { currentValue.RemoveModifier(modifier); OnValueChanged?.Invoke(); } public override string ToString() { if (ValueType == StatProperty.ValueType.Flat) return Value.ToString(0); else return $"{Value.ToString(0)}%"; } } public class StatGroup { Dictionary stats = new(); public IReadOnlyList Stats => new List(stats.Values); public StatGroup(StatCreator[] statCreators) { foreach (var creator in statCreators) { stats.Add(creator.property.id, creator.CreateStat()); } } public bool TryGetStat(uint id, out StatData stat) { return stats.TryGetValue(id, out stat); } public bool TryGetStat(StatID id, out StatData stat) => TryGetStat((uint)id, out stat); public bool TryGetStat(StatProperty property, out StatData stat) => stats.TryGetValue(property.id, out stat); public bool TryGetStatByName(string nameKey, out StatData stat) { foreach (var item in stats) { if (item.Value.NameKey == nameKey) { stat = item.Value; return true; } } stat = null; return false; } }