using System.Collections.Generic; public static class ModifierPipeline { // Application order (explicit): // 1. Category-level additive (AddPerDieValue) // 2. Category-level multiplicative (MultiplyPerDieValue) // 3. Final-score additive (AddFlatToFinalScore) // 4. Final-score multiplicative (MultiplyFinalScore) public static void Apply( IReadOnlyList activeModifiers, ref ScoreResult result, ModifierScope currentScope) { if (activeModifiers == null) return; // Pass 1: Category-level additive for (int i = 0; i < activeModifiers.Count; i++) { var mod = activeModifiers[i]; if (!ShouldApply(mod, ref result, currentScope)) continue; if (mod.IsCategoryLevel && mod.IsAdditive) ModifierEffect.Apply(mod, ref result); } // Pass 2: Category-level multiplicative for (int i = 0; i < activeModifiers.Count; i++) { var mod = activeModifiers[i]; if (!ShouldApply(mod, ref result, currentScope)) continue; if (mod.IsCategoryLevel && mod.IsMultiplicative) ModifierEffect.Apply(mod, ref result); } // Pass 3: Final-score additive for (int i = 0; i < activeModifiers.Count; i++) { var mod = activeModifiers[i]; if (!ShouldApply(mod, ref result, currentScope)) continue; if (mod.IsFinalScoreLevel && mod.IsAdditive) ModifierEffect.Apply(mod, ref result); } // Pass 4: Final-score multiplicative for (int i = 0; i < activeModifiers.Count; i++) { var mod = activeModifiers[i]; if (!ShouldApply(mod, ref result, currentScope)) continue; if (mod.IsFinalScoreLevel && mod.IsMultiplicative) ModifierEffect.Apply(mod, ref result); } } private static bool ShouldApply(ModifierData mod, ref ScoreResult result, ModifierScope currentScope) { if (mod == null) return false; if (mod.Scope != currentScope) return false; if (mod.Target.HasCategoryFilter && mod.Target.TargetCategory != result.Category) return false; return true; } }