diff --git a/Ahorn/entities/maxHelpingHandRespawningBounceJellyfish.jl b/Ahorn/entities/maxHelpingHandRespawningBounceJellyfish.jl new file mode 100644 index 0000000..5f72c2d --- /dev/null +++ b/Ahorn/entities/maxHelpingHandRespawningBounceJellyfish.jl @@ -0,0 +1,32 @@ +module MaxHelpingHandRespawningBounceJellyfish + +using ..Ahorn, Maple + +@mapdef Entity "MaxHelpingHand/RespawningBounceJellyfish" RespawningBounceJellyfish(x::Integer, y::Integer, platform::Bool=true, soulBound::Bool=true, baseDashCount::Integer=1, + respawnTime::Number=2.0, spriteDirectory::String="objects/MaxHelpingHand/glider") + +const placements = Ahorn.PlacementDict( + "Respawning Bounce Jellyfish (Bounce Helper + Maddie's Helping Hand)" => Ahorn.EntityPlacement( + RespawningBounceJellyfish + ) +) + +function Ahorn.selection(entity::RespawningBounceJellyfish) + x, y = Ahorn.position(entity) + sprite = get(entity, "spriteDirectory", "objects/MaxHelpingHand/glider") * "/idle0" + + return Ahorn.getSpriteRectangle(sprite, x, y - 4) +end + +function Ahorn.render(ctx::Ahorn.Cairo.CairoContext, entity::RespawningBounceJellyfish, room::Maple.Room) + sprite = get(entity, "spriteDirectory", "objects/MaxHelpingHand/glider") * "/idle0" + Ahorn.drawSprite(ctx, sprite, 0, -4) + + if get(entity, "platform", false) + curve = Ahorn.SimpleCurve((-7, -1), (7, -1), (0, -6)) + Ahorn.drawSimpleCurve(ctx, curve, (1.0, 1.0, 1.0, 1.0), thickness=1) + end +end + + +end \ No newline at end of file diff --git a/Ahorn/lang/en_gb.lang b/Ahorn/lang/en_gb.lang index c49af72..d615e47 100644 --- a/Ahorn/lang/en_gb.lang +++ b/Ahorn/lang/en_gb.lang @@ -152,6 +152,13 @@ placements.entities.MaxHelpingHand/RespawningJellyfish.tooltips.tutorial=Whether placements.entities.MaxHelpingHand/RespawningJellyfish.tooltips.respawnTime=The jellyfish will respawn at its starting location after this amount of time (in seconds) after being destroyed. placements.entities.MaxHelpingHand/RespawningJellyfish.tooltips.spriteDirectory=The directory containing all the sprites for the respawning jellyfish.\nTo make your own, copy Graphics/Atlases/Gameplay/objects/MaxHelpingHand/glider from the mod zip to Mods/yourmod/Graphics/Atlases/Gameplay/MyMap/myglider and type MyMap/myglider in this field. +# Respawning Bounce Jellyfish +placements.entities.MaxHelpingHand/RespawningBounceJellyfish.tooltips.platform=Whether the jelly starts floating. +placements.entities.MaxHelpingHand/RespawningBounceJellyfish.tooltips.soulBound=Whether the jelly kills the player on death and can't be left behind. +placements.entities.MaxHelpingHand/RespawningBounceJellyfish.tooltips.baseDashCount=How many dashes the jelly will start with and refill to. +placements.entities.MaxHelpingHand/RespawningBounceJellyfish.tooltips.respawnTime=The jellyfish will respawn at its starting location after this amount of time (in seconds) after being destroyed. +placements.entities.MaxHelpingHand/RespawningBounceJellyfish.tooltips.spriteDirectory=The directory containing all the sprites for the respawning jellyfish.\nTo make your own, copy Graphics/Atlases/Gameplay/objects/MaxHelpingHand/glider from the mod zip to Mods/yourmod/Graphics/Atlases/Gameplay/MyMap/myglider and type MyMap/myglider in this field. + # Grouped Trigger Spikes placements.entities.MaxHelpingHand/GroupedTriggerSpikesUp.tooltips.type=Changes the visual appearance of the spikes. placements.entities.MaxHelpingHand/GroupedTriggerSpikesDown.tooltips.type=Changes the visual appearance of the spikes. diff --git a/Entities/RespawningBounceJellyfish.cs b/Entities/RespawningBounceJellyfish.cs new file mode 100644 index 0000000..a34ba7d --- /dev/null +++ b/Entities/RespawningBounceJellyfish.cs @@ -0,0 +1,55 @@ +using Celeste.Mod.BounceHelper; +using Celeste.Mod.Entities; +using Microsoft.Xna.Framework; +using System.Collections; +using Monocle; + +namespace Celeste.Mod.MaxHelpingHand.Entities { + [CustomEntity("MaxHelpingHand/RespawningJellyfish")] + public class RespawningBounceJellyfish : BounceJellyfish { + public static void LoadBounceHelper() { + RespawningJellyfishGeneric.Load(); + Everest.Events.Level.OnLoadEntity += onLoadEntity; + On.Monocle.Tracker.Initialize += onTrackerInitialize; + } + + public static void UnloadBounceHelper() { + RespawningJellyfishGeneric.Unload(); + Everest.Events.Level.OnLoadEntity -= onLoadEntity; + On.Monocle.Tracker.Initialize -= onTrackerInitialize; + } + + private static bool onLoadEntity(Level level, LevelData levelData, Vector2 offset, EntityData entityData) { + if (entityData.Name == "MaxHelpingHand/RespawningBounceJellyfish") { + level.Add(new RespawningBounceJellyfish(entityData, offset)); + return true; + } + + return false; + } + + private static void onTrackerInitialize(On.Monocle.Tracker.orig_Initialize orig) { + orig(); + Tracker.TrackedEntityTypes[typeof(RespawningBounceJellyfish)] = [typeof(BounceJellyfish)]; + } + + + private RespawningJellyfishGeneric manager; + + public RespawningBounceJellyfish(EntityData data, Vector2 offset) : base(data, offset) { + manager = new RespawningJellyfishGeneric(this, data, () => Speed, speed => Speed = speed); + } + + public override void Update() { + manager.Update(base.Update); + } + + protected override void OnSquish(CollisionData data) { + manager.OnSquish(base.OnSquish, data); + } + + private IEnumerator destroyThenRespawnRoutine() { + return manager.destroyThenRespawnRoutine(); + } + } +} diff --git a/Entities/RespawningJellyfish.cs b/Entities/RespawningJellyfish.cs index df90c23..d7ee9d3 100644 --- a/Entities/RespawningJellyfish.cs +++ b/Entities/RespawningJellyfish.cs @@ -1,156 +1,26 @@ using Celeste.Mod.Entities; using Microsoft.Xna.Framework; -using Mono.Cecil.Cil; -using Monocle; -using MonoMod.Cil; -using MonoMod.Utils; -using System; using System.Collections; namespace Celeste.Mod.MaxHelpingHand.Entities { [CustomEntity("MaxHelpingHand/RespawningJellyfish")] public class RespawningJellyfish : Glider { - public static void Load() { - IL.Celeste.Glider.Update += modGliderUpdate; - } - - public static void Unload() { - IL.Celeste.Glider.Update -= modGliderUpdate; - } - - private static ParticleType P_NotGlow; - - private DynData self; - - private float respawnTime; - private bool bubble; - - private Sprite sprite; - - private Vector2 initialPosition; - private bool respawning; - - private bool shouldRespawn = true; + private RespawningJellyfishGeneric manager; public RespawningJellyfish(EntityData data, Vector2 offset) : base(data, offset) { - if (P_NotGlow == null) { - // P_NotGlow is a transparent particle. - P_NotGlow = new ParticleType(P_Glow) { - Color = Color.Transparent, - Color2 = Color.Transparent - }; - } - - respawnTime = data.Float("respawnTime"); - bubble = data.Bool("bubble"); - initialPosition = Position; - respawning = false; - - // get the sprite, and replace it depending on the path in entity properties. - self = new DynData(this); - sprite = self.Get("sprite"); - new DynData(sprite)["atlas"] = GFX.Game; - sprite.Path = data.Attr("spriteDirectory", defaultValue: "objects/MaxHelpingHand/glider") + "/"; - sprite.Stop(); - sprite.ClearAnimations(); - sprite.AddLoop("idle", "idle", 0.1f); - sprite.AddLoop("held", "held", 0.1f); - sprite.Add("fall", "fall", 0.06f, "fallLoop"); - sprite.AddLoop("fallLoop", "fallLoop", 0.06f); - sprite.Add("death", "death", 0.06f); - sprite.Add("respawn", "respawn", 0.03f, "idle"); - sprite.Play("idle"); - - // make the jelly go invisible when the death animation is done. - sprite.OnFinish += anim => { - if (anim == "death") { - Visible = false; - } - }; - - // listen for transitions: if the jelly is carried to another screen, it should not respawn anymore. - Add(new TransitionListener() { - OnOutBegin = () => shouldRespawn = false - }); + manager = new RespawningJellyfishGeneric(this, data, () => Speed, speed => Speed = speed); } public override void Update() { - if (shouldRespawn && !respawning && Top + Speed.Y * Engine.DeltaTime > (SceneAs().Bounds.Bottom + 16)) { - // the jellyfish glided off-screen. - removeAndRespawn(); - } - - // if the jelly is invisible, "disable" the particles (actually make them invisible). - ParticleType vanillaGlow = P_Glow; - if (!Visible) P_Glow = P_NotGlow; - - base.Update(); - - P_Glow = vanillaGlow; - } - - private static void modGliderUpdate(ILContext il) { - ILCursor cursor = new ILCursor(il); - - while (cursor.TryGotoNext(MoveType.After, instr => instr.MatchNewobj())) { - Logger.Log("MaxHelpingHand/RespawningJellyfish", $"Replacing coroutine to make jellyfish respawn at {cursor.Index} in IL for Glider.Update"); - - cursor.Emit(OpCodes.Ldarg_0); - cursor.EmitDelegate>((orig, self) => { - if (self is RespawningJellyfish jelly) { - return new Coroutine(jelly.destroyThenRespawnRoutine()); - } - - return orig; - }); - } + manager.Update(base.Update); } protected override void OnSquish(CollisionData data) { - if (shouldRespawn) { - if (!TrySquishWiggle(data)) { - // the jellyfish was squished. - removeAndRespawn(); - } - } else { - // vanilla behavior - base.OnSquish(data); - } - } - - private void removeAndRespawn() { - Collidable = false; - Visible = false; - self["destroyed"] = true; - Add(new Coroutine(respawnRoutine())); + manager.OnSquish(base.OnSquish, data); } private IEnumerator destroyThenRespawnRoutine() { - // do like vanilla, but instead of removing the jelly, wait then have it respawn. - Audio.Play("event:/new_content/game/10_farewell/glider_emancipate", Position); - sprite.Play("death"); - - return respawnRoutine(); - } - - private IEnumerator respawnRoutine() { - respawning = true; - - // wait for the respawn time - yield return respawnTime; - - // then respawn at the initial position - Visible = true; - Position = initialPosition; - Speed = Vector2.Zero; - sprite.Play("respawn"); - - yield return 0.24f; - - respawning = false; - self["destroyed"] = false; - self["bubble"] = bubble; - Collidable = true; + return manager.destroyThenRespawnRoutine(); } } } diff --git a/Entities/RespawningJellyfishGeneric.cs b/Entities/RespawningJellyfishGeneric.cs new file mode 100644 index 0000000..7de9b73 --- /dev/null +++ b/Entities/RespawningJellyfishGeneric.cs @@ -0,0 +1,174 @@ +using Microsoft.Xna.Framework; +using Mono.Cecil.Cil; +using Monocle; +using MonoMod.Cil; +using MonoMod.RuntimeDetour; +using MonoMod.Utils; +using System; +using System.Collections; +using System.Reflection; + +namespace Celeste.Mod.MaxHelpingHand.Entities { + internal static class RespawningJellyfishCache { + internal static MethodInfo trySquishWiggle = typeof(Actor).GetMethod("TrySquishWiggle", BindingFlags.NonPublic | BindingFlags.Instance); + } + public class RespawningJellyfishGeneric where T : Actor, U where U : Actor { + private static ILHook hookGliderUpdate = null; + + public static void Load() { + hookGliderUpdate = new ILHook(typeof(U).GetMethod("Update"), modGliderUpdate); + } + + public static void Unload() { + hookGliderUpdate?.Dispose(); + hookGliderUpdate = null; + } + + private static ParticleType P_NotGlow; + + private T self; + private DynData selfData; + + private float respawnTime; + private bool bubble; + + private Sprite sprite; + + private Vector2 initialPosition; + private bool respawning; + + private bool shouldRespawn = true; + + private Func getSpeed; + private Action setSpeed; + + public RespawningJellyfishGeneric(T self, EntityData data, Func getSpeed, Action setSpeed) { + this.self = self; + this.getSpeed = getSpeed; + this.setSpeed = setSpeed; + + if (P_NotGlow == null) { + // P_NotGlow is a transparent particle. + P_NotGlow = new ParticleType(Glider.P_Glow) { + Color = Color.Transparent, + Color2 = Color.Transparent + }; + } + + respawnTime = data.Float("respawnTime"); + bubble = data.Bool("bubble") || data.Bool("platform"); + initialPosition = self.Position; + respawning = false; + + // get the sprite, and replace it depending on the path in entity properties. + selfData = new DynData(self); + sprite = selfData.Get("sprite"); + new DynData(sprite)["atlas"] = GFX.Game; + sprite.Path = data.Attr("spriteDirectory", defaultValue: "objects/MaxHelpingHand/glider") + "/"; + sprite.Stop(); + sprite.ClearAnimations(); + foreach (string suffix in new string[] { "", "B", "R", "RH", "P", "PH", "F" }) { + sprite.AddLoop("idle" + suffix, "idle", 0.1f); + sprite.AddLoop("held" + suffix, "held", 0.1f); + sprite.Add("fall" + suffix, "fall", 0.06f, "fallLoop" + suffix); + sprite.AddLoop("fallLoop" + suffix, "fallLoop", 0.06f); + sprite.Add("death" + suffix, "death", 0.06f); + sprite.Add("respawn" + suffix, "respawn", 0.03f, "idle" + suffix); + } + sprite.Play("idle"); + + // make the jelly go invisible when the death animation is done. + sprite.OnFinish += anim => { + if (anim == "death") { + self.Visible = false; + } + }; + + // listen for transitions: if the jelly is carried to another screen, it should not respawn anymore. + self.Add(new TransitionListener() { + OnOutBegin = () => shouldRespawn = false + }); + } + + public void Update(Action baseUpdate) { + if (shouldRespawn && !respawning && self.Top + getSpeed().Y * Engine.DeltaTime > (self.SceneAs().Bounds.Bottom + 16)) { + // the jellyfish glided off-screen. + removeAndRespawn(); + } + + // if the jelly is invisible, "disable" the particles (actually make them invisible). + ParticleType vanillaGlow = Glider.P_Glow; + if (!self.Visible) Glider.P_Glow = P_NotGlow; + + baseUpdate(); + + Glider.P_Glow = vanillaGlow; + } + + private static void modGliderUpdate(ILContext il) { + ILCursor cursor = new ILCursor(il); + + if (cursor.TryGotoNext(MoveType.After, instr => instr.MatchNewobj())) { + MethodInfo method = typeof(T).GetMethod("destroyThenRespawnRoutine", BindingFlags.NonPublic | BindingFlags.Instance); + Logger.Log("MaxHelpingHand/RespawningJellyfish", $"Replacing coroutine to make jellyfish respawn at {cursor.Index} in IL for {cursor.Method.FullName}, calling {method.DeclaringType.FullName}.{method.Name}"); + + cursor.Emit(OpCodes.Ldarg_0); + cursor.EmitDelegate>((orig, self) => { + if (self is T) { + return new Coroutine((IEnumerator) method.Invoke(self, [])); + } + + return orig; + }); + } + } + + public void OnSquish(Action baseOnSquish, CollisionData data) { + if (shouldRespawn) { + if (!((bool) RespawningJellyfishCache.trySquishWiggle.Invoke(self, [data]))) { + // the jellyfish was squished. + removeAndRespawn(); + } + } else { + // vanilla behavior + baseOnSquish(data); + } + } + + private void removeAndRespawn() { + self.Collidable = false; + self.Visible = false; + selfData["destroyed"] = true; + self.Add(new Coroutine(respawnRoutine())); + } + + internal IEnumerator destroyThenRespawnRoutine() { + // do like vanilla, but instead of removing the jelly, wait then have it respawn. + Audio.Play("event:/new_content/game/10_farewell/glider_emancipate", self.Position); + sprite.Play("death"); + + return respawnRoutine(); + } + + private IEnumerator respawnRoutine() { + respawning = true; + + // wait for the respawn time + yield return respawnTime; + + // then respawn at the initial position + self.Visible = true; + self.Position = initialPosition; + setSpeed(Vector2.Zero); + sprite.Play("respawn"); + + yield return 0.24f; + + respawning = false; + selfData["destroyed"] = false; + selfData["bubble"] = bubble; + selfData["platform"] = bubble; + self.Collidable = true; + } + } +} diff --git a/Loenn/entities/movingFlagTouchSwitch.lua b/Loenn/entities/movingFlagTouchSwitch.lua index 10f645a..1381854 100644 --- a/Loenn/entities/movingFlagTouchSwitch.lua +++ b/Loenn/entities/movingFlagTouchSwitch.lua @@ -7,7 +7,7 @@ touchSwitch.name = "MaxHelpingHand/MovingFlagTouchSwitch" touchSwitch.depth = 2000 touchSwitch.nodeLimits = {0, -1} touchSwitch.nodeLineRenderType = "line" -touchSwitch.associatedMods = { "OutbackHelper" } +touchSwitch.associatedMods = { "MaxHelpingHand", "OutbackHelper" } touchSwitch.placements = { { name = "touch_switch", diff --git a/Loenn/entities/respawningBounceJellyfish.lua b/Loenn/entities/respawningBounceJellyfish.lua new file mode 100644 index 0000000..f147073 --- /dev/null +++ b/Loenn/entities/respawningBounceJellyfish.lua @@ -0,0 +1,80 @@ +local drawableSprite = require("structs.drawable_sprite") +local drawableLine = require("structs.drawable_line") +local drawing = require("utils.drawing") + +local respawningBounceJellyfish = {} + +respawningBounceJellyfish.name = "MaxHelpingHand/RespawningBounceJellyfish" +respawningBounceJellyfish.depth = -5 +respawningBounceJellyfish.associatedMods = { "MaxHelpingHand", "BounceHelper" } +local respawningBounceJellyfishDashCounts = { + 0, 1, 2 +} + +respawningBounceJellyfish.fieldInformation = { + baseDashCount = { + options = respawningBounceJellyfishDashCounts, + editable = false + } +} +respawningBounceJellyfish.placements = { + { + name = "normal", + data = { + platform = true, + soulBound = false, + baseDashCount = 0, + respawnTime = 2.0, + spriteDirectory = "objects/MaxHelpingHand/glider" + } + }, + { + name = "single", + data = { + platform = true, + soulBound = false, + baseDashCount = 1, + respawnTime = 2.0, + spriteDirectory = "objects/MaxHelpingHand/glider" + } + }, + { + name = "double", + data = { + platform = true, + soulBound = false, + baseDashCount = 2, + respawnTime = 2.0, + spriteDirectory = "objects/MaxHelpingHand/glider" + } + } +} + +function respawningBounceJellyfish.sprite(room, entity) + local bubble = entity.platform + local texture = entity.spriteDirectory .. "/idle0" + + if entity.bubble then + local x, y = entity.x or 0, entity.y or 0 + local points = drawing.getSimpleCurve({x - 11, y - 1}, {x + 11, y - 1}, {x - 0, y - 6}) + local lineSprites = drawableLine.fromPoints(points):getDrawableSprite() + local jellySprite = drawableSprite.fromTexture(texture, entity) + jellySprite:setOffset(jellySprite.meta.width / 2, jellySprite.meta.height / 2 + 4) + + table.insert(lineSprites, 1, jellySprite) + + return lineSprites + + else + return drawableSprite.fromTexture(texture, entity) + end +end + +function respawningBounceJellyfish.rectangle(room, entity) + local texture = entity.spriteDirectory .. "/idle0" + local sprite = drawableSprite.fromTexture(texture, entity) + + return sprite:getRectangle() +end + +return respawningBounceJellyfish \ No newline at end of file diff --git a/Loenn/entities/saveFileStrawberryGate.lua b/Loenn/entities/saveFileStrawberryGate.lua index 1f850cf..5d064db 100644 --- a/Loenn/entities/saveFileStrawberryGate.lua +++ b/Loenn/entities/saveFileStrawberryGate.lua @@ -9,7 +9,7 @@ heartDoor.name = "MaxHelpingHand/SaveFileStrawberryGate" heartDoor.depth = 0 heartDoor.nodeLimits = {0, 1} heartDoor.minimumSize = {40, 8} -heartDoor.associatedMods = { "LunaticHelper" } +heartDoor.associatedMods = { "MaxHelpingHand", "LunaticHelper" } heartDoor.fieldInformation = { requires = { diff --git a/Loenn/entities/shatterFlagSwitchGate.lua b/Loenn/entities/shatterFlagSwitchGate.lua index 2e9990f..4426f9f 100644 --- a/Loenn/entities/shatterFlagSwitchGate.lua +++ b/Loenn/entities/shatterFlagSwitchGate.lua @@ -6,7 +6,7 @@ local switchGate = {} switchGate.name = "MaxHelpingHand/ShatterFlagSwitchGate" switchGate.depth = 0 switchGate.minimumSize = {16, 16} -switchGate.associatedMods = { "VortexHelper" } +switchGate.associatedMods = { "MaxHelpingHand", "VortexHelper" } switchGate.placements = {} local textures = { diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index 79c61c9..8009d5d 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -644,6 +644,19 @@ entities.MaxHelpingHand/RespawningJellyfish.attributes.description.tutorial=Whet entities.MaxHelpingHand/RespawningJellyfish.attributes.description.respawnTime=The jellyfish will respawn at its starting location after this amount of time (in seconds) after being destroyed. entities.MaxHelpingHand/RespawningJellyfish.attributes.description.spriteDirectory=The directory containing all the sprites for the respawning jellyfish.\nTo make your own, copy Graphics/Atlases/Gameplay/objects/MaxHelpingHand/glider from the mod zip to Mods/yourmod/Graphics/Atlases/Gameplay/MyMap/myglider and type MyMap/myglider in this field. +# Respawning Bounce Jellyfish +entities.MaxHelpingHand/RespawningBounceJellyfish.placements.name.normal=Respawning Bounce Jellyfish +entities.MaxHelpingHand/RespawningBounceJellyfish.placements.name.single=Respawning Bounce Jellyfish (One Dash) +entities.MaxHelpingHand/RespawningBounceJellyfish.placements.name.double=Respawning Bounce Jellyfish (Two Dashes) +entities.MaxHelpingHand/RespawningBounceJellyfish.placements.description.normal=A Jellyfish compatible with Bounce Mode. +entities.MaxHelpingHand/RespawningBounceJellyfish.placements.description.single=Bounce Mode exclusive jellyfish that can dash. +entities.MaxHelpingHand/RespawningBounceJellyfish.placements.description.double=Bounce Mode exclusive jellyfish that can dash twice. +entities.MaxHelpingHand/RespawningBounceJellyfish.attributes.description.platform=Whether the jelly starts floating. +entities.MaxHelpingHand/RespawningBounceJellyfish.attributes.description.soulBound=Whether the jelly kills the player on death and can't be left behind. +entities.MaxHelpingHand/RespawningBounceJellyfish.attributes.description.baseDashCount=How many dashes the jelly will start with and refill to. +entities.MaxHelpingHand/RespawningBounceJellyfish.attributes.description.respawnTime=The jellyfish will respawn at its starting location after this amount of time (in seconds) after being destroyed. +entities.MaxHelpingHand/RespawningBounceJellyfish.attributes.description.spriteDirectory=The directory containing all the sprites for the respawning jellyfish.\nTo make your own, copy Graphics/Atlases/Gameplay/objects/MaxHelpingHand/glider from the mod zip to Mods/yourmod/Graphics/Atlases/Gameplay/MyMap/myglider and type MyMap/myglider in this field. + # Rotating Bumper entities.MaxHelpingHand/RotatingBumper.placements.name.bumper=Bumper (Rotating) entities.MaxHelpingHand/RotatingBumper.attributes.description.speed=The rotating speed in degrees per second. Use a negative number for counterclockwise rotation. diff --git a/Loenn/triggers/activateTimedTouchSwitchesTimer.lua b/Loenn/triggers/activateTimedTouchSwitchesTimer.lua index 54c7223..ff045d2 100644 --- a/Loenn/triggers/activateTimedTouchSwitchesTimer.lua +++ b/Loenn/triggers/activateTimedTouchSwitchesTimer.lua @@ -1,7 +1,7 @@ local trigger = {} trigger.name = "MaxHelpingHand/ActivateTimedTouchSwitchesTimerTrigger" -trigger.associatedMods = { "OutbackHelper" } +trigger.associatedMods = { "MaxHelpingHand", "OutbackHelper" } trigger.placements = { name = "trigger" } diff --git a/MaddieHelpingHand.csproj b/MaddieHelpingHand.csproj index f8865ef..156ce7c 100644 --- a/MaddieHelpingHand.csproj +++ b/MaddieHelpingHand.csproj @@ -7,6 +7,10 @@ preview + + lib-stripped\BounceHelper.dll + False + lib-stripped\Celeste.exe False diff --git a/Module/MaxHelpingHandModule.cs b/Module/MaxHelpingHandModule.cs index 7cda1ca..1dc0984 100644 --- a/Module/MaxHelpingHandModule.cs +++ b/Module/MaxHelpingHandModule.cs @@ -11,6 +11,7 @@ namespace Celeste.Mod.MaxHelpingHand.Module { public class MaxHelpingHandModule : EverestModule { private bool hookedSineParallax = false; + private bool bounceHelperLoaded = false; private static FieldInfo contentLoaded = typeof(Everest).GetField("_ContentLoaded", BindingFlags.NonPublic | BindingFlags.Static); @@ -84,7 +85,7 @@ public override void Load() { ReskinnableCrystalHeart.Load(); SetFlagOnButtonPressController.Load(); FlagPickup.Load(); - RespawningJellyfish.Load(); + RespawningJellyfishGeneric.Load(); SetFlagOnSpawnTrigger.Load(); CustomSeekerBarrier.Load(); MoreCustomNPC.Load(); @@ -163,7 +164,7 @@ public override void Unload() { SetFlagOnButtonPressController.Unload(); FlagPickup.Unload(); AvBdaySpeechBubbleFixup.Unload(); - RespawningJellyfish.Unload(); + RespawningJellyfishGeneric.Unload(); ReskinnableStarRotateSpinner.Unload(); ReskinnableStarTrackSpinner.Unload(); SetFlagOnSpawnTrigger.Unload(); @@ -191,6 +192,10 @@ public override void Unload() { if (hookedSineParallax) { unhookSineParallax(); } + + if (bounceHelperLoaded) { + unloadBounceHelper(); + } } public override void LoadContent(bool firstLoad) { @@ -231,6 +236,10 @@ private void HookMods() { if (!hookedSineParallax && Everest.Loader.DependencyLoaded(new EverestModuleMetadata() { Name = "FlaglinesAndSuch", Version = new Version(1, 4, 17) })) { hookSineParallax(); } + + if (!bounceHelperLoaded && Everest.Loader.DependencyLoaded(new EverestModuleMetadata { Name = "BounceHelper", Version = new Version(1, 8, 0) })) { + loadBounceHelper(); + } } private void hookSineParallax() { @@ -243,6 +252,16 @@ private void unhookSineParallax() { hookedSineParallax = false; } + private void loadBounceHelper() { + RespawningBounceJellyfish.LoadBounceHelper(); + bounceHelperLoaded = true; + } + + private void unloadBounceHelper() { + RespawningBounceJellyfish.UnloadBounceHelper(); + bounceHelperLoaded = false; + } + private Backdrop onLoadBackdrop(MapData map, BinaryPacker.Element child, BinaryPacker.Element above) { if (child.Name.Equals("MaxHelpingHand/HeatWaveNoColorGrade", StringComparison.OrdinalIgnoreCase)) { return new HeatWaveNoColorGrade(child.AttrBool("controlColorGradeWhenActive"), child.AttrBool("renderParticles", defaultValue: true)); diff --git a/everest.yaml b/everest.yaml index df50067..c3fd352 100644 --- a/everest.yaml +++ b/everest.yaml @@ -14,3 +14,5 @@ Version: 1.1.1 - Name: OutbackHelper Version: 1.7.2 + - Name: BounceHelper + Version: 1.8.0 diff --git a/lib-stripped/BounceHelper.dll b/lib-stripped/BounceHelper.dll new file mode 100644 index 0000000..5ff6786 Binary files /dev/null and b/lib-stripped/BounceHelper.dll differ