using BigFloatNumerics; using System.Collections.Generic; using System.Numerics; public class ValueBase { protected bool isDirty; protected List valueModifiers; public IReadOnlyCollection ValueModifiers => valueModifiers; public ValueBase() { isDirty = true; valueModifiers = new List(); } public void AddModifiers(params ValueModifier[] modifiers) { isDirty = true; for(int i = 0;i < modifiers.Length; i++) valueModifiers.OrderInsert(modifiers[i], (a, b) => a.Order.CompareTo(b.Order)); } public bool RemoveModifier(ValueModifier modifier) { isDirty = valueModifiers.Remove(modifier); return isDirty; } public bool RemoveAllModifiersWithFrom(object from) { bool isRemoved = false; for (int i = valueModifiers.Count - 1; i >= 0; i--) { if (valueModifiers[i].From == from) { isDirty = true; isRemoved = true; valueModifiers.RemoveAt(i); } } return isRemoved; } public void ClearModifiers() { isDirty = true; valueModifiers.Clear(); } } public class FValue : ValueBase { float defaultValue; public float DefaultValue { get => defaultValue; set { if(defaultValue != value) { defaultValue = value; isDirty = true; } } } float modifiedValue; public float ModifiedValue { get { if(isDirty) { CalculateValue(); isDirty = false; } return modifiedValue; } } public FValue(float defaultValue = 0) { this.defaultValue = defaultValue; } public void CalculateValue() { modifiedValue = defaultValue; float appendablePercent = 0; for (int i = 0; i < ValueModifiers.Count; i++) { var mod = valueModifiers[i]; if(mod.type == ValueModifier.Type.LowestFlat) { float lowestValue = mod.value; for(i++; i < valueModifiers.Count; i++) { if (valueModifiers[i].type != ValueModifier.Type.LowestFlat) break; if (valueModifiers[i].value < lowestValue) lowestValue = valueModifiers[i].value; } modifiedValue += lowestValue; } else if(mod.type == ValueModifier.Type.GreatestFlat) { float greatestValue = mod.value; for(i++; i < valueModifiers.Count; i++) { if (valueModifiers[i].type != ValueModifier.Type.GreatestFlat) break; if (valueModifiers[i].value > greatestValue) greatestValue = valueModifiers[i].value; } modifiedValue += greatestValue; } else if(mod.type == ValueModifier.Type.Flat) { modifiedValue += mod.value; } else if(mod.type == ValueModifier.Type.AppendablePercent) { appendablePercent += mod.value; if(i == valueModifiers.Count - 1 || valueModifiers[i + 1].type != ValueModifier.Type.AppendablePercent) { modifiedValue *= 1 + appendablePercent / 100; appendablePercent = 0; } } else if(mod.type == ValueModifier.Type.Percent) { modifiedValue *= 1 + mod.value / 100; } else if(mod.type == ValueModifier.Type.Set) { modifiedValue = mod.value; } } } } public class BIValue : ValueBase { BigInteger defaultValue; public BigInteger DefaultValue { get => defaultValue; set { if (defaultValue != value) { defaultValue = value; isDirty = true; } } } BigInteger modifiedValue; public BigInteger ModifiedValue { get { if (isDirty) { CalculateValue(); isDirty = false; } return modifiedValue; } } public BIValue() { defaultValue = 0; } public BIValue(BigInteger defaultValue) { this.defaultValue = defaultValue; } public void CalculateValue() { modifiedValue = defaultValue; float appendablePercent = 0; for (int i = 0; i < ValueModifiers.Count; i++) { var mod = valueModifiers[i]; if (mod.type == ValueModifier.Type.AppendablePercent) { appendablePercent += mod.value; if (i == valueModifiers.Count - 1 || valueModifiers[i + 1].type != ValueModifier.Type.AppendablePercent) { modifiedValue = modifiedValue.Multiply(1 + appendablePercent / 100); appendablePercent = 0; } } else if (mod.type == ValueModifier.Type.Percent) { modifiedValue = modifiedValue.Multiply(1 + mod.value / 100); } } } } public class BFValue : ValueBase { BigFloat defaultValue; public BigFloat DefaultValue { get => defaultValue; set { defaultValue = value; isDirty = true; } } BigFloat modifiedValue; public BigFloat ModifiedValue { get { if (isDirty) { CalculateValue(); isDirty = false; } return modifiedValue; } } public BFValue() { defaultValue = 0; } public BFValue(BigFloat defaultValue) { this.defaultValue = defaultValue; } public void CalculateValue() { modifiedValue = defaultValue; float appendablePercent = 0; for (int i = 0; i < ValueModifiers.Count; i++) { var mod = valueModifiers[i]; if (mod.type == ValueModifier.Type.LowestFlat) { float lowestValue = mod.value; for (i++; i < valueModifiers.Count; i++) { if (valueModifiers[i].type != ValueModifier.Type.LowestFlat) break; if (valueModifiers[i].value < lowestValue) lowestValue = valueModifiers[i].value; } modifiedValue += lowestValue; } else if (mod.type == ValueModifier.Type.GreatestFlat) { float greatestValue = mod.value; for (i++; i < valueModifiers.Count; i++) { if (valueModifiers[i].type != ValueModifier.Type.GreatestFlat) break; if (valueModifiers[i].value > greatestValue) greatestValue = valueModifiers[i].value; } modifiedValue += greatestValue; } else if (mod.type == ValueModifier.Type.Flat) { modifiedValue += mod.value; } else if (mod.type == ValueModifier.Type.AppendablePercent) { appendablePercent += mod.value; if (i == valueModifiers.Count - 1 || valueModifiers[i + 1].type != ValueModifier.Type.AppendablePercent) { modifiedValue *= 1 + appendablePercent / 100; appendablePercent = 0; } } else if (mod.type == ValueModifier.Type.Percent) { modifiedValue *= 1 + mod.value / 100; } else if (mod.type == ValueModifier.Type.Set) { modifiedValue = mod.value; } } } }