diff --git a/Code/FLCC/TempleGateAllSwitches.cs b/Code/FLCC/TempleGateAllSwitches.cs index ec62eba..9304ef0 100644 --- a/Code/FLCC/TempleGateAllSwitches.cs +++ b/Code/FLCC/TempleGateAllSwitches.cs @@ -1,7 +1,12 @@ using Celeste; using Celeste.Mod.Entities; +using Celeste.Mod.Helpers; using Microsoft.Xna.Framework; +using Mono.Cecil.Cil; using Monocle; +using MonoMod.Cil; +using System.Collections.Generic; +using System.Linq; namespace vitmod { [Tracked()] @@ -11,39 +16,52 @@ public TempleGateAllSwitches(EntityData data, Vector2 offset) : base(data.Positi ClaimedByASwitch = true; } - public static void Load() { - On.Celeste.DashSwitch.Awake += DashSwitch_Awake; + private static void HookOnDashCollide(DashSwitch dashSwitch) { + DashCollision orig_OnDashCollide = dashSwitch.OnDashCollide; + + dashSwitch.OnDashCollide = (player, direction) => { + DashCollisionResults result = orig_OnDashCollide(player, direction); + if (!dashSwitch.pressed || dashSwitch.Scene.Entities.Any(entity => entity is DashSwitch { pressed: false })) + return result; + + foreach (TempleGateAllSwitches gate in dashSwitch.Scene.Tracker.GetEntities().Cast()) + gate.Open(); + + return result; + }; } + + #region Hooks - public static void Unload() { - On.Celeste.DashSwitch.Awake -= DashSwitch_Awake; + internal static void Load() { + IL.Monocle.EntityList.UpdateLists += EntityList_UpdateLists; } - private static void DashSwitch_Awake(On.Celeste.DashSwitch.orig_Awake orig, DashSwitch self, Scene scene) { - orig(self, scene); - DashCollision orig_OnDashCollide = self.OnDashCollide; - self.OnDashCollide = (Player player, Vector2 direction) => { - DashCollisionResults result = orig_OnDashCollide(player, direction); - bool finalswitch = true; - if (self.pressed) { - foreach (Solid solid in self.SceneAs().Tracker.GetEntities()) { - if (solid is DashSwitch dashSwitch) { - if (!dashSwitch.pressed) { - finalswitch = false; - break; - } - } - } - } else { - finalswitch = false; - } - if (finalswitch) { - foreach (TempleGateAllSwitches gate in self.SceneAs().Tracker.GetEntities()) { - gate.Open(); - } - } - return result; - }; + internal static void Unload() { + IL.Monocle.EntityList.UpdateLists -= EntityList_UpdateLists; + } + + private static void EntityList_UpdateLists(ILContext il) { + ILCursor cursor = new(il); + + if (!cursor.TryGotoNextBestFit(MoveType.After, + instr => instr.MatchLdloc(5), + instr => instr.MatchLdarg0(), + instr => instr.MatchCallvirt("get_Scene"), + instr => instr.MatchCallvirt("Awake"))) + return; + + cursor.EmitLdloc(5); + cursor.EmitDelegate(ProcessDashSwitch); + + return; + + static void ProcessDashSwitch(Entity entity) { + if (entity is DashSwitch dashSwitch) + HookOnDashCollide(dashSwitch); + } } + + #endregion } }