using System.Diagnostics; using System.Runtime.InteropServices; using RobotAndDonkey.Game.Execution.Results; using RobotAndDonkey.Game.GameState; using RobotAndDonkey.Game.Intents; namespace RobotAndDonkey.Game.Modifiers; public class ModifierStack { public void Push(Entity entity) { m_Stack.Push((entity, entity.Modifiers)); } public void Pop() { _ = m_Stack.Pop(); } private IEnumerable<(Entity Owner, Modifier Modifier)> GetModifiers() { foreach (var (owner, modifiers) in m_Stack) { foreach (var modifier in modifiers) { if (modifier.DebuffSources.Count == 0) yield return (owner, modifier); } } } public void Execute(Guid requestId, CoreLoop coreLoop, List intents, List results, bool force, bool verbose) { var newIntents = new List(); var index = 0; do { var currentIntents = intents[index..]; var modifiableIntents = currentIntents.Where(i => !i.Immune).ToArray(); foreach (var (owner, modifier) in GetModifiers()) { if (modifier.DebuffSources.Count == 0) { if (verbose) Debug.WriteLine($"Before {modifier}"); modifier.Before(requestId, modifiableIntents, coreLoop, owner, newIntents, results); } } foreach (var intent in currentIntents) { var isValid = intent.IsValid(coreLoop); if (force || isValid) { if (verbose) Debug.WriteLine($"Run {(isValid ? "Valid" : "Invalid")} intent: {intent}"); intent.Run(requestId, coreLoop, newIntents, results); } } foreach (var (owner, modifier) in GetModifiers()) { if (modifier.DebuffSources.Count == 0) { if (verbose) Debug.WriteLine($"After {modifier}"); modifier.After(requestId, modifiableIntents, coreLoop, owner, newIntents, results); } } index = intents.Count; intents.AddRange(newIntents); newIntents.Clear(); } while (index < intents.Count); } private readonly Stack<(Entity Owner, IReadOnlyList Modifiers)> m_Stack = []; }