using Unity.Collections; using Unity.Entities; namespace ProjectM.Simulation { /// /// Pure, deterministic folding of a StatModifier set into an effective value for one StatTarget: /// effective = (base + sum flat) * (1 + sum percentAdd) * product(1 + percentMult). /// Order-independent within each op class, Burst-friendly, and unit-tested like AutoTarget.Resolve. /// Returns the raw fold; consumers clamp domain bounds (e.g. cooldown >= 1 tick). /// public static class StatMath { public static float Apply(float baseValue, StatTarget target, in DynamicBuffer mods) { return Apply(baseValue, target, mods.AsNativeArray()); } public static float Apply(float baseValue, StatTarget target, in NativeArray mods) { float flat = 0f; float percentAdd = 0f; float percentMult = 1f; byte t = (byte)target; for (int i = 0; i < mods.Length; i++) { var m = mods[i]; if (m.Target != t) continue; switch ((ModOp)m.Op) { case ModOp.Flat: flat += m.Value; break; case ModOp.PercentAdd: percentAdd += m.Value; break; case ModOp.PercentMult: percentMult *= 1f + m.Value; break; } } return (baseValue + flat) * (1f + percentAdd) * percentMult; } } }