using System.Runtime.CompilerServices; using PkmnLib.Dynamic.Events; using PkmnLib.Dynamic.Models; using PkmnLib.Static; namespace PkmnLib.Dynamic.ScriptHandling; /// /// Helper functions for script execution. /// public static class ScriptExecution { /// /// Executes a hook on all scripts in a source. /// public static void RunScriptHook(this IScriptSource source, Action hook) { var iterator = source.GetScripts(); List? suppressedCategories = null; foreach (var container in iterator) { if (container.IsEmpty) continue; var script = container.Script; if (script is IScriptOnBeforeAnyHookInvoked onBeforeAnyHookInvoked) onBeforeAnyHookInvoked.OnBeforeAnyHookInvoked(ref suppressedCategories); } foreach (var container in iterator) { if (container.IsEmpty) continue; var script = container.Script; if (script is not TScriptHook scriptHook) continue; if (suppressedCategories != null && suppressedCategories.Contains(script.Category)) continue; hook(scriptHook); } } /// /// Executes a hook on all scripts in a source. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void RunScriptHook(this IEnumerable sources, Action hook) { var iterator = sources.Distinct().SelectMany(x => x.GetScripts()).ToArray(); List? suppressedCategories = null; foreach (var container in iterator) { if (container.IsEmpty) continue; var script = container.Script; if (script is IScriptOnBeforeAnyHookInvoked onBeforeAnyHookInvoked) onBeforeAnyHookInvoked.OnBeforeAnyHookInvoked(ref suppressedCategories); } foreach (var container in iterator) { if (container.IsEmpty) continue; var script = container.Script; if (script is not TScriptHook scriptHook) continue; if (suppressedCategories != null && suppressedCategories.Contains(script.Category)) continue; hook(scriptHook); } } /// /// Executes a hook on all scripts in a list of sources. Note that this does not walk through the parents of the /// sources, but only the sources themselves. /// public static void RunScriptHook(this IReadOnlyList> source, Action hook) { List? suppressedCategories = null; var iterator = new ScriptIterator(source); foreach (var container in iterator) { if (container.IsEmpty) continue; var script = container.Script; if (script is IScriptOnBeforeAnyHookInvoked onBeforeAnyHookInvoked) onBeforeAnyHookInvoked.OnBeforeAnyHookInvoked(ref suppressedCategories); } foreach (var container in iterator) { if (container.IsEmpty) continue; var script = container.Script; if (script is not TScriptHook scriptHook) continue; if (suppressedCategories != null && suppressedCategories.Contains(script.Category)) continue; hook(scriptHook); } } /// /// Executes a script on an item. /// public static void RunItemScript(this IItem item, ScriptResolver scriptResolver, IPokemon? target, EventHook eventHook) { if (!scriptResolver.TryResolveBattleItemScript(item, out var itemScript)) { return; } if (!itemScript.IsItemUsable) return; itemScript.OnInitialize(item.BattleEffect!.Parameters); var requiresTarget = itemScript.RequiresTarget; if (requiresTarget) { if (target == null) throw new ArgumentNullException(nameof(target), "Item script requires a target."); itemScript.OnUseWithTarget(target, eventHook); } else { itemScript.OnUse(eventHook); } } }