From f29687783b175ba86e1af2c462d2b67bbb14f586 Mon Sep 17 00:00:00 2001 From: aonkeeper4 Date: Mon, 31 Mar 2025 16:15:45 +0100 Subject: [PATCH 1/3] Allow Color Switch to be triggered by theo and jelly collisions + set flag corresponding to current switch block color --- Code/Entities/ColorSwitch.cs | 41 +++++++++++++++++- Code/Entities/ColorSwitchFlagsController.cs | 48 +++++++++++++++++++++ Code/VortexHelperModule.cs | 6 ++- Loenn/entities/color_switch.lua | 6 ++- Loenn/lang/en_gb.lang | 1 + 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 Code/Entities/ColorSwitchFlagsController.cs diff --git a/Code/Entities/ColorSwitch.cs b/Code/Entities/ColorSwitch.cs index f8817ca..71bb4e9 100644 --- a/Code/Entities/ColorSwitch.cs +++ b/Code/Entities/ColorSwitch.cs @@ -29,12 +29,14 @@ public class ColorSwitch : Solid private int nextColorIndex = 0; private readonly bool singleColor, random; + private readonly bool holdableActivated; + public ColorSwitch(EntityData data, Vector2 offset) : this(data.Position + offset, data.Width, data.Height, - data.Bool("blue"), data.Bool("rose"), data.Bool("orange"), data.Bool("lime"), data.Bool("random")) + data.Bool("blue"), data.Bool("rose"), data.Bool("orange"), data.Bool("lime"), data.Bool("random"), data.Bool("holdableActivated")) { } - public ColorSwitch(Vector2 position, int width, int height, bool blue, bool rose, bool orange, bool lime, bool random) + public ColorSwitch(Vector2 position, int width, int height, bool blue, bool rose, bool orange, bool lime, bool random, bool holdableActivated) : base(position, width, height, true) { this.SurfaceSoundIndex = SurfaceIndex.ZipMover; @@ -78,6 +80,7 @@ public ColorSwitch(Vector2 position, int width, int height, bool blue, bool rose SetEdgeColor(this.EdgeColor, this.EdgeColor); SetBackgroundColor(col, col); + this.holdableActivated = holdableActivated; this.OnDashCollide = Dashed; } @@ -267,4 +270,38 @@ private void SmashParticles(Vector2 dir, ParticleType smashParticle) num += 2; SceneAs().Particles.Emit(smashParticle, num, position, positionRange, direction); } + + internal static class Hooks + { + public static void Hook() + { + On.Celeste.TheoCrystal.OnCollideH += TheoCrystal_OnCollideH; + On.Celeste.TheoCrystal.OnCollideV += TheoCrystal_OnCollideV; + On.Celeste.Glider.OnCollideH += Glider_OnCollideH; + } + + public static void Unhook() + { + On.Celeste.TheoCrystal.OnCollideH -= TheoCrystal_OnCollideH; + On.Celeste.TheoCrystal.OnCollideV -= TheoCrystal_OnCollideV; + On.Celeste.Glider.OnCollideH -= Glider_OnCollideH; + } + + private static void ActivateSwitch(Action callOrig, CollisionData data, Func speedChecker) + { + if (data.Hit is ColorSwitch colorSwitch + && colorSwitch.holdableActivated + && !colorSwitch.colors[colorSwitch.nextColorIndex].IsActive() + && speedChecker()) + { + colorSwitch.Switch(data.Direction); + } + + callOrig(); + } + + private static void TheoCrystal_OnCollideH(On.Celeste.TheoCrystal.orig_OnCollideH orig, TheoCrystal self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => Math.Abs(self.Speed.X) > 100f); + private static void TheoCrystal_OnCollideV(On.Celeste.TheoCrystal.orig_OnCollideV orig, TheoCrystal self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => self.Speed.Y > 160f); + private static void Glider_OnCollideH(On.Celeste.Glider.orig_OnCollideH orig, Glider self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => Math.Abs(self.Speed.X) > 60f); + } } diff --git a/Code/Entities/ColorSwitchFlagsController.cs b/Code/Entities/ColorSwitchFlagsController.cs new file mode 100644 index 0000000..6c1f19a --- /dev/null +++ b/Code/Entities/ColorSwitchFlagsController.cs @@ -0,0 +1,48 @@ +using Monocle; +using Microsoft.Xna.Framework; +using System.Collections.Generic; + +namespace Celeste.Mod.VortexHelper.Entities; + +public class ColorSwitchFlagsController : Entity +{ + private static readonly Dictionary colorsToFlagNames = new() { + { VortexHelperSession.SwitchBlockColor.Blue, "VortexHelper/SwitchBlockColor_Blue" }, + { VortexHelperSession.SwitchBlockColor.Rose, "VortexHelper/SwitchBlockColor_Rose" }, + { VortexHelperSession.SwitchBlockColor.Lime, "VortexHelper/SwitchBlockColor_Lime" }, + { VortexHelperSession.SwitchBlockColor.Orange, "VortexHelper/SwitchBlockColor_Orange" }, + }; + + public ColorSwitchFlagsController() : base(Vector2.Zero) + { + Depth = -int.MaxValue; // update last + Tag = Tags.Global | Tags.TransitionUpdate; + } + + public override void Update() + { + Session session = SceneAs().Session; + + foreach (string flag in colorsToFlagNames.Values) + { + session.SetFlag(flag, false); + } + + session.SetFlag(colorsToFlagNames[VortexHelperModule.SessionProperties.SessionSwitchBlockColor]); + } + + internal static class Hooks + { + public static void Hook() + { + Everest.Events.LevelLoader.OnLoadingThread += OnLoadingThread; + } + + public static void Unhook() + { + Everest.Events.LevelLoader.OnLoadingThread -= OnLoadingThread; + } + + private static void OnLoadingThread(Level level) => level.Add(new ColorSwitchFlagsController()); + } +} \ No newline at end of file diff --git a/Code/VortexHelperModule.cs b/Code/VortexHelperModule.cs index c5fd84d..8d2b521 100644 --- a/Code/VortexHelperModule.cs +++ b/Code/VortexHelperModule.cs @@ -67,10 +67,12 @@ public override void Load() BowlPuffer.Hooks.Hook(); PufferBarrierRenderer.Hooks.Hook(); StaticMoverWithLiftSpeed.Hooks.Hook(); + ColorSwitch.Hooks.Hook(); + ColorSwitchFlagsController.Hooks.Hook(); MiscHooks.Hook(); Util.LoadDelegates(); - + typeof(GravityHelperInterop.Imports).ModInterop(); } @@ -84,6 +86,8 @@ public override void Unload() BowlPuffer.Hooks.Unhook(); PufferBarrierRenderer.Hooks.Unhook(); StaticMoverWithLiftSpeed.Hooks.Unhook(); + ColorSwitch.Hooks.Unhook(); + ColorSwitchFlagsController.Hooks.Unhook(); MiscHooks.Unhook(); } diff --git a/Loenn/entities/color_switch.lua b/Loenn/entities/color_switch.lua index ec6acca..d9a01ba 100644 --- a/Loenn/entities/color_switch.lua +++ b/Loenn/entities/color_switch.lua @@ -17,7 +17,8 @@ colorSwitch.placements = { rose = true, orange = true, lime = true, - random = false + random = false, + holdableActivated = false } }, { @@ -29,7 +30,8 @@ colorSwitch.placements = { rose = true, orange = true, lime = true, - random = true + random = true, + holdableActivated = false } } } diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index cfc6e4f..28b73e2 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -35,6 +35,7 @@ entities.VortexHelper/ColorSwitch.attributes.description.rose=Enables switch to entities.VortexHelper/ColorSwitch.attributes.description.orange=Enables switch to ORANGE through this Color Switch. entities.VortexHelper/ColorSwitch.attributes.description.lime=Enables switch to LIME through this Color Switch. entities.VortexHelper/ColorSwitch.attributes.description.random=Makes this Color Switch randomly pick one of its enabled colors. +entities.VortexHelper/ColorSwitch.attributes.description.holdableActivated=Makes collisions with holdables (Jellyfish and Theo Crystals) activate this Color Switch. # Vortex Switch Gate entities.VortexHelper/VortexSwitchGate.placements.name.crush=Custom Switch Gate (Crush) From b7982d964019c67adc0b1780e0817384873ce832 Mon Sep 17 00:00:00 2001 From: aonkeeper4 Date: Mon, 31 Mar 2025 16:29:56 +0100 Subject: [PATCH 2/3] Tweak speed conditions for Color Switch triggering --- Code/Entities/ColorSwitch.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Code/Entities/ColorSwitch.cs b/Code/Entities/ColorSwitch.cs index 71bb4e9..30d3995 100644 --- a/Code/Entities/ColorSwitch.cs +++ b/Code/Entities/ColorSwitch.cs @@ -278,6 +278,7 @@ public static void Hook() On.Celeste.TheoCrystal.OnCollideH += TheoCrystal_OnCollideH; On.Celeste.TheoCrystal.OnCollideV += TheoCrystal_OnCollideV; On.Celeste.Glider.OnCollideH += Glider_OnCollideH; + On.Celeste.Glider.OnCollideV += Glider_OnCollideV; } public static void Unhook() @@ -285,6 +286,7 @@ public static void Unhook() On.Celeste.TheoCrystal.OnCollideH -= TheoCrystal_OnCollideH; On.Celeste.TheoCrystal.OnCollideV -= TheoCrystal_OnCollideV; On.Celeste.Glider.OnCollideH -= Glider_OnCollideH; + On.Celeste.Glider.OnCollideV -= Glider_OnCollideV; } private static void ActivateSwitch(Action callOrig, CollisionData data, Func speedChecker) @@ -300,8 +302,9 @@ private static void ActivateSwitch(Action callOrig, CollisionData data, Func ActivateSwitch(() => orig(self, data), data, () => Math.Abs(self.Speed.X) > 100f); - private static void TheoCrystal_OnCollideV(On.Celeste.TheoCrystal.orig_OnCollideV orig, TheoCrystal self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => self.Speed.Y > 160f); - private static void Glider_OnCollideH(On.Celeste.Glider.orig_OnCollideH orig, Glider self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => Math.Abs(self.Speed.X) > 60f); + private static void TheoCrystal_OnCollideH(On.Celeste.TheoCrystal.orig_OnCollideH orig, TheoCrystal self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => true); + private static void TheoCrystal_OnCollideV(On.Celeste.TheoCrystal.orig_OnCollideV orig, TheoCrystal self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => self.Speed.Y > 160f || self.Speed.Y < 0f); + private static void Glider_OnCollideH(On.Celeste.Glider.orig_OnCollideH orig, Glider self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => true); + private static void Glider_OnCollideV(On.Celeste.Glider.orig_OnCollideV orig, Glider self, CollisionData data) => ActivateSwitch(() => orig(self, data), data, () => self.Speed.Y < 0f); } } From 51e805af1764eb08731c6daa645450c7d303162a Mon Sep 17 00:00:00 2001 From: aonkeeper4 Date: Mon, 31 Mar 2025 21:35:32 +0100 Subject: [PATCH 3/3] Only set color switch flagswhen necessary and clean up color switch field ordering --- Code/Entities/ColorSwitchFlagsController.cs | 10 ++++++---- Loenn/entities/color_switch.lua | 6 ++++++ 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/Code/Entities/ColorSwitchFlagsController.cs b/Code/Entities/ColorSwitchFlagsController.cs index 6c1f19a..6556c05 100644 --- a/Code/Entities/ColorSwitchFlagsController.cs +++ b/Code/Entities/ColorSwitchFlagsController.cs @@ -22,13 +22,15 @@ public ColorSwitchFlagsController() : base(Vector2.Zero) public override void Update() { Session session = SceneAs().Session; + VortexHelperSession.SwitchBlockColor current = VortexHelperModule.SessionProperties.SessionSwitchBlockColor; - foreach (string flag in colorsToFlagNames.Values) + foreach (var color in colorsToFlagNames) { - session.SetFlag(flag, false); + if (current != color.Key && session.GetFlag(color.Value)) + session.SetFlag(color.Value, false); + else if (current == color.Key && !session.GetFlag(color.Value)) + session.SetFlag(color.Value, true); } - - session.SetFlag(colorsToFlagNames[VortexHelperModule.SessionProperties.SessionSwitchBlockColor]); } internal static class Hooks diff --git a/Loenn/entities/color_switch.lua b/Loenn/entities/color_switch.lua index d9a01ba..57bdc1d 100644 --- a/Loenn/entities/color_switch.lua +++ b/Loenn/entities/color_switch.lua @@ -7,6 +7,12 @@ colorSwitch.name = "VortexHelper/ColorSwitch" colorSwitch.resizable = {true, true} colorSwitch.minimumSize = {16, 16} +colorSwitch.fieldOrder = { + "x", "y", "width", "height", + "blue", "rose", "orange", "lime", "random", + "holdableActivated" +} + colorSwitch.placements = { { name = "all_cycle",