From 1d8e6f5d4d30fc50285993f72f99d29222c35299 Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Thu, 14 Sep 2023 03:48:48 -0400 Subject: [PATCH 01/10] slingshot wouncing, also rewrites all DynData uses to DynamicData --- Code/Entities/FloorBooster.cs | 10 ++-- Code/Entities/LavenderBooster.cs | 2 +- Code/Entities/PurpleBooster.cs | 89 +++++++++++++++++++++++++------ Code/Misc/Extensions/PlayerExt.cs | 13 ----- Code/Misc/Util.cs | 9 ++++ Code/VortexHelperModule.cs | 2 + 6 files changed, 91 insertions(+), 34 deletions(-) delete mode 100644 Code/Misc/Extensions/PlayerExt.cs diff --git a/Code/Entities/FloorBooster.cs b/Code/Entities/FloorBooster.cs index b05837d..0d4122c 100644 --- a/Code/Entities/FloorBooster.cs +++ b/Code/Entities/FloorBooster.cs @@ -275,18 +275,18 @@ private static bool Player_RefillDash(On.Celeste.Player.orig_RefillDash orig, Pl private static void Player_NormalBegin(On.Celeste.Player.orig_NormalBegin orig, Player self) { orig(self); - DynData playerData = self.GetData(); + DynamicData playerData = DynamicData.For(self); playerData.Set("floorBoosterSpeed", 0f); - playerData.Set("lastFloorBooster", null); + playerData.Set("lastFloorBooster", null); } private static int Player_NormalUpdate(On.Celeste.Player.orig_NormalUpdate orig, Player self) { - DynData playerData = self.GetData(); + DynamicData playerData = DynamicData.For(self); // thanks max480 for the bug report. if (!playerData.Data.ContainsKey("lastFloorBooster")) - playerData.Set("lastFloorBooster", null); + playerData.Set("lastFloorBooster", null); FloorBooster lastFloorBooster = playerData.Get("lastFloorBooster"); @@ -300,7 +300,7 @@ private static int Player_NormalUpdate(On.Celeste.Player.orig_NormalUpdate orig, self.LiftSpeed += vec / 1.6f; self.Speed += vec / 1.6f; - playerData.Set("lastFloorBooster", null); + playerData.Set("lastFloorBooster", null); } bool touchedFloorBooster = false; diff --git a/Code/Entities/LavenderBooster.cs b/Code/Entities/LavenderBooster.cs index d710770..e8bb62c 100644 --- a/Code/Entities/LavenderBooster.cs +++ b/Code/Entities/LavenderBooster.cs @@ -60,7 +60,7 @@ private static void Booster_PlayerReleased(On.Celeste.Booster.orig_PlayerRelease { Audio.Play(SFX.game_05_redbooster_end, player.Center); PurpleBooster.LaunchPlayerParticles(player, player.DashDir, P_BurstExplodeLavender); - PurpleBooster.PurpleBoosterExplodeLaunch(player, player.GetData(), self.Center - player.DashDir, null, -1f); + PurpleBooster.PurpleBoosterExplodeLaunch(player, DynamicData.For(player), self.Center - player.DashDir, null, -1f); } } diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index dba862e..1486d0b 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -3,7 +3,10 @@ using Celeste.Mod.VortexHelper.Misc; using Celeste.Mod.VortexHelper.Misc.Extensions; using Microsoft.Xna.Framework; +using Mono.Cecil.Cil; using Monocle; +using MonoMod.Cil; +using MonoMod.RuntimeDetour; using MonoMod.Utils; using System; using System.Collections; @@ -15,6 +18,7 @@ namespace Celeste.Mod.VortexHelper.Entities; public class PurpleBooster : Entity { internal const string POSSIBLE_EARLY_DASHSPEED = "purpleBoostPossibleEarlyDashSpeed"; + internal const string CAN_WALLBOUNCE_FROM_SLINGSHOT = "purpleBoostCanWallBounce"; private readonly Sprite sprite; private readonly Wiggler wiggler; @@ -43,8 +47,11 @@ public bool BoostingPlayer public static readonly ParticleType P_BurstExplode = new(Booster.P_Burst); private readonly SoundSource loopingSfx; + public readonly bool CanWallbounce; public PurpleBooster(EntityData data, Vector2 offset) - : this(data.Position + offset) { } + : this(data.Position + offset) { + CanWallbounce = data.Bool("CanWallbounce", true); + } public PurpleBooster(Vector2 position) : base(position) @@ -124,8 +131,9 @@ public static void Boost(Player player, PurpleBooster booster) { player.StateMachine.State = VortexHelperModule.PurpleBoosterState; player.Speed = Vector2.Zero; - DynData playerData = player.GetData(); + DynamicData playerData = DynamicData.For(player); playerData.Set("boostTarget", booster.Center); + playerData.Set(CAN_WALLBOUNCE_FROM_SLINGSHOT, booster.CanWallbounce); booster.StartedBoosting = true; } @@ -352,7 +360,7 @@ public static void PurpleBoostBegin() public static int PurpleBoostUpdate() { Util.TryGetPlayer(out Player player); - DynData playerData = player.GetData(); + DynamicData playerData = DynamicData.For(player); Vector2 boostTarget = playerData.Get("boostTarget"); Vector2 value = Input.Aim.Value * 3f; @@ -385,10 +393,9 @@ public static int PurpleBoostUpdate() public static void PurpleBoostEnd() { Util.TryGetPlayer(out Player player); - - Vector2 boostTarget = player.GetData().Get("boostTarget"); + DynamicData playerData = DynamicData.For(player); + Vector2 boostTarget = playerData.Get("boostTarget"); Vector2 vector = (boostTarget - player.Collider.Center).Floor(); - player.MoveToX(vector.X, null); player.MoveToY(vector.Y, null); } @@ -407,7 +414,7 @@ public static void PurpleDashingBegin() Celeste.Freeze(0.05f); // this freeze makes fastbubbling much more lenient Util.TryGetPlayer(out Player player); - DynData playerData = player.GetData(); + DynamicData playerData = DynamicData.For(player); player.DashDir = Input.GetAimVector(player.Facing); playerData.Set(POSSIBLE_EARLY_DASHSPEED, Vector2.Zero); @@ -426,16 +433,29 @@ public static void PurpleDashingBegin() public static int PurpleDashingUpdate() { + Util.TryGetPlayer(out Player player); + DynamicData playerData = DynamicData.For(player); if (Input.DashPressed || Input.CrouchDashPressed) { - Util.TryGetPlayer(out Player player); - DynData playerData = player.GetData(); player.LiftSpeed += playerData.Get(POSSIBLE_EARLY_DASHSPEED); return player.StartDash(); } - + if (playerData.Get(CAN_WALLBOUNCE_FROM_SLINGSHOT) && Math.Abs(player.DashDir.X) <= 0.02 && + Input.Jump.Pressed && player.CanUnDuck && + (player.DashDir.Y < 0 ? playerData.Get(POSSIBLE_EARLY_DASHSPEED).Y == 0 : playerData.Get(POSSIBLE_EARLY_DASHSPEED).Y < 0)) + { + if ((bool)Util.player_WallJumpCheck.Invoke(player, 1)) + { + Util.player_SuperWallJump.Invoke(player,-1); + return 0; + }else if ((bool) Util.player_WallJumpCheck.Invoke(player, -1)) + { + Util.player_SuperWallJump.Invoke(player, 1); + return 0; + } + } return VortexHelperModule.PurpleBoosterDashState; } @@ -443,7 +463,7 @@ public static IEnumerator PurpleDashingCoroutine() { float t = 0f; Util.TryGetPlayer(out Player player); - DynData playerData = player.GetData(); + DynamicData playerData = DynamicData.For(player); Vector2 origin = playerData.Get("boostTarget"); Vector2 earlyExitBoost; @@ -453,7 +473,7 @@ public static IEnumerator PurpleDashingCoroutine() Vector2 vec = origin + Vector2.UnitY * 6f + player.DashDir * 60f * (float) Math.Sin(t * Math.PI); playerData.Set(POSSIBLE_EARLY_DASHSPEED, earlyExitBoost = (t > .6f) ? (t - .5f) * 200f * -player.DashDir : Vector2.Zero); - + Console.WriteLine(earlyExitBoost); if (player.CollideCheck(vec)) { player.StateMachine.State = Player.StNormal; @@ -467,11 +487,17 @@ public static IEnumerator PurpleDashingCoroutine() PurpleBoosterExplodeLaunch(player, playerData, player.Center - player.DashDir, origin); } - public static void PurpleBoosterExplodeLaunch(Player player, DynData playerData, Vector2 from, Vector2? origin, float factor = 1f) + public static void PurpleDashingEnd() + { + Util.TryGetPlayer(out Player player); + DynamicData playerData = DynamicData.For(player); + playerData.Set(CAN_WALLBOUNCE_FROM_SLINGSHOT, false); + } + public static void PurpleBoosterExplodeLaunch(Player player, DynamicData playerData, Vector2 from, Vector2? origin, float factor = 1f) { Input.Rumble(RumbleStrength.Strong, RumbleLength.Medium); Celeste.Freeze(0.1f); - playerData.Set("launchApproachX", null); + playerData.Set("launchApproachX", null); Level level = player.SceneAs(); if (origin is not null) @@ -501,14 +527,18 @@ public static void PurpleBoosterExplodeLaunch(Player player, DynData pla internal static class Hooks { + public static void Hook() { On.Celeste.Player.ctor += Player_ctor; + IL.Celeste.Player.WallJumpCheck += Player_WallJumpCheck; } + public static void Unhook() { On.Celeste.Player.ctor -= Player_ctor; + IL.Celeste.Player.WallJumpCheck -= Player_WallJumpCheck; } private static void Player_ctor(On.Celeste.Player.orig_ctor orig, Player self, Vector2 position, PlayerSpriteMode spriteMode) @@ -519,7 +549,36 @@ private static void Player_ctor(On.Celeste.Player.orig_ctor orig, Player self, V VortexHelperModule.PurpleBoosterState = self.StateMachine.AddState(PurpleBoostUpdate, PurpleBoostCoroutine, PurpleBoostBegin, PurpleBoostEnd); // Custom Purple Booster State (Arc Motion) - VortexHelperModule.PurpleBoosterDashState = self.StateMachine.AddState(PurpleDashingUpdate, PurpleDashingCoroutine, PurpleDashingBegin); + VortexHelperModule.PurpleBoosterDashState = self.StateMachine.AddState(PurpleDashingUpdate, PurpleDashingCoroutine, PurpleDashingBegin, PurpleDashingEnd); } + + private static void Player_WallJumpCheck(ILContext il) + { + ILCursor cursor = new ILCursor(il); + if (cursor.TryGotoNext(MoveType.After, i => i.MatchCallvirt("get_DashAttacking"))) + { + cursor.Emit(OpCodes.Ldarg_0); + cursor.EmitDelegate>((b, p) => + { + if (b) return true; + try { if (DynamicData.For(p).TryGet(CAN_WALLBOUNCE_FROM_SLINGSHOT, out bool c) && c) return true; } + catch (NullReferenceException) { return false; } + return false; + }); + } + if(cursor.TryGotoNext(MoveType.After, i => i.MatchLdcR4(-1) && i.Next.MatchCeq())) + { + cursor.Emit(OpCodes.Ldarg_0); + cursor.EmitDelegate>((f, p) => + { + try { if (DynamicData.For(p).TryGet(CAN_WALLBOUNCE_FROM_SLINGSHOT, out bool c) && c) return p.DashDir.Y; } + catch (NullReferenceException) { return f; } + return f; + }); + } + + + } + } } diff --git a/Code/Misc/Extensions/PlayerExt.cs b/Code/Misc/Extensions/PlayerExt.cs deleted file mode 100644 index d0c6dca..0000000 --- a/Code/Misc/Extensions/PlayerExt.cs +++ /dev/null @@ -1,13 +0,0 @@ -using MonoMod.Utils; - -namespace Celeste.Mod.VortexHelper.Misc.Extensions; - -public static class PlayerExt -{ - private static DynData cachedPlayerData; - - public static DynData GetData(this Player player) - => cachedPlayerData is not null && cachedPlayerData.IsAlive && cachedPlayerData.Target == player - ? cachedPlayerData - : (cachedPlayerData = new DynData(player)); -} diff --git a/Code/Misc/Util.cs b/Code/Misc/Util.cs index 37c3bae..1984846 100644 --- a/Code/Misc/Util.cs +++ b/Code/Misc/Util.cs @@ -1,4 +1,5 @@ using Monocle; +using MonoMod.Utils; namespace Celeste.Mod.VortexHelper.Misc; @@ -10,4 +11,12 @@ public static bool TryGetPlayer(out Player player) player = Engine.Scene?.Tracker?.GetEntity(); return player is not null; } + + public static void LoadDelegates() + { + player_WallJumpCheck = typeof(Player).GetMethod("WallJumpCheck", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetFastDelegate(); + player_SuperWallJump = typeof(Player).GetMethod("SuperWallJump", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetFastDelegate(); + } + public static FastReflectionDelegate player_WallJumpCheck; + public static FastReflectionDelegate player_SuperWallJump; } diff --git a/Code/VortexHelperModule.cs b/Code/VortexHelperModule.cs index f2de985..22c14e3 100644 --- a/Code/VortexHelperModule.cs +++ b/Code/VortexHelperModule.cs @@ -67,6 +67,8 @@ public override void Load() PufferBarrierRenderer.Hooks.Hook(); StaticMoverWithLiftSpeed.Hooks.Hook(); MiscHooks.Hook(); + + Util.LoadDelegates(); } public override void Unload() From fae63038311ef706a100e02f4aed83637a643cc5 Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Thu, 14 Sep 2023 04:05:13 -0400 Subject: [PATCH 02/10] added feature to plugins, also removed console writeline --- Ahorn/entities/purpleBooster.jl | 5 ++++- Code/Entities/PurpleBooster.cs | 4 ++-- Loenn/entities/purple_booster.lua | 3 ++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/Ahorn/entities/purpleBooster.jl b/Ahorn/entities/purpleBooster.jl index 63b0d0a..37cba26 100644 --- a/Ahorn/entities/purpleBooster.jl +++ b/Ahorn/entities/purpleBooster.jl @@ -6,7 +6,10 @@ using ..Ahorn, Maple const placements = Ahorn.PlacementDict( "Booster (Purple) (Vortex Helper)" => Ahorn.EntityPlacement( PurpleBooster, - "point" + "point", + Dict{String,Any} ( + "CanWallbounce" => false + ) ), "Booster (Lavender) (Vortex Helper)" => Ahorn.EntityPlacement( PurpleBooster, diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index 1486d0b..0d523a6 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -50,7 +50,7 @@ public bool BoostingPlayer public readonly bool CanWallbounce; public PurpleBooster(EntityData data, Vector2 offset) : this(data.Position + offset) { - CanWallbounce = data.Bool("CanWallbounce", true); + CanWallbounce = data.Bool("CanWallbounce", false); } public PurpleBooster(Vector2 position) @@ -473,7 +473,7 @@ public static IEnumerator PurpleDashingCoroutine() Vector2 vec = origin + Vector2.UnitY * 6f + player.DashDir * 60f * (float) Math.Sin(t * Math.PI); playerData.Set(POSSIBLE_EARLY_DASHSPEED, earlyExitBoost = (t > .6f) ? (t - .5f) * 200f * -player.DashDir : Vector2.Zero); - Console.WriteLine(earlyExitBoost); + if (player.CollideCheck(vec)) { player.StateMachine.State = Player.StNormal; diff --git a/Loenn/entities/purple_booster.lua b/Loenn/entities/purple_booster.lua index 7c5b3c8..b7263c1 100644 --- a/Loenn/entities/purple_booster.lua +++ b/Loenn/entities/purple_booster.lua @@ -9,7 +9,8 @@ purpleBooster.placements = { { name = "purple", data = { - lavender = false + lavender = false, + CanWallbounce = false } }, { From 019b89ba1801efa88b3b6f573b914f4408787e9a Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Thu, 2 Nov 2023 01:34:10 -0400 Subject: [PATCH 03/10] Added more QoL effects - Wallbounce, DashCooldownTimer, fixed early dash to actually give a boost --- Ahorn/entities/purpleBooster.jl | 5 +-- Ahorn/lang/en_gb.lang | 3 ++ Code/Entities/FloorBooster.cs | 4 +-- Code/Entities/LavenderBooster.cs | 9 ++++-- Code/Entities/PurpleBooster.cs | 53 +++++++++++++++++++++++-------- Loenn/entities/purple_booster.lua | 5 +-- Loenn/lang/en_gb.lang | 2 ++ 7 files changed, 59 insertions(+), 22 deletions(-) diff --git a/Ahorn/entities/purpleBooster.jl b/Ahorn/entities/purpleBooster.jl index 37cba26..5ed9e93 100644 --- a/Ahorn/entities/purpleBooster.jl +++ b/Ahorn/entities/purpleBooster.jl @@ -8,14 +8,15 @@ const placements = Ahorn.PlacementDict( PurpleBooster, "point", Dict{String,Any} ( - "CanWallbounce" => false + "QoL" => true, ) ), "Booster (Lavender) (Vortex Helper)" => Ahorn.EntityPlacement( PurpleBooster, "point", Dict{String, Any}( - "lavender" => true + "lavender" => true, + "QoL" => true ) ) ) diff --git a/Ahorn/lang/en_gb.lang b/Ahorn/lang/en_gb.lang index b68c2f6..a8b9d9f 100644 --- a/Ahorn/lang/en_gb.lang +++ b/Ahorn/lang/en_gb.lang @@ -49,6 +49,9 @@ placements.entities.VortexHelper/Lilly.tooltips.maxLength=The maximum distance a # Purple Booster placements.entities.VortexHelper/PurpleBooster.tooltips.lavender=Whether the booster should instead be lavender in color, and launch the player forward instead of arcing back. +placements.entities.VortexHelper/PurpleBooster.names.QoL=Version 2 +placements.entities.VortexHelper/PurpleBooster.tooltips.QoL=Enables Wallbouncing during the windup animation.\nFixes speedboost not applying when dashing early from booster.\nReduces Freeze Timer upon launch exit and ensures a shorter dashCooldownTimer. + # Switch Block placements.entities.VortexHelper/SwitchBlock.tooltips.index=Changes the index and color of this Switch Block. diff --git a/Code/Entities/FloorBooster.cs b/Code/Entities/FloorBooster.cs index 0d4122c..4c179b5 100644 --- a/Code/Entities/FloorBooster.cs +++ b/Code/Entities/FloorBooster.cs @@ -324,8 +324,8 @@ private static int Player_NormalUpdate(On.Celeste.Player.orig_NormalUpdate orig, } } - if (!touchedFloorBooster) - floorBoosterSpeed = Calc.Approach(playerData.Get("floorBoosterSpeed"), 0f, 4f * Engine.DeltaTime); + if (!touchedFloorBooster && playerData?.Get("floorBoosterSpeed") is float f) + floorBoosterSpeed = Calc.Approach(f, 0f, 4f * Engine.DeltaTime); playerData.Set("floorBoosterSpeed", floorBoosterSpeed); return orig(self); diff --git a/Code/Entities/LavenderBooster.cs b/Code/Entities/LavenderBooster.cs index e8bb62c..24e1073 100644 --- a/Code/Entities/LavenderBooster.cs +++ b/Code/Entities/LavenderBooster.cs @@ -16,11 +16,12 @@ public class LavenderBooster : Booster public static readonly ParticleType P_BurstExplodeLavender = new(P_Burst); private readonly DynData boosterData; - + private readonly bool QoL; public LavenderBooster(EntityData data, Vector2 offset) : base(data.Position + offset, red: false) { this.boosterData = new DynData(this); + QoL = data.Bool("QoL", false); Sprite oldSprite = this.boosterData.Get("sprite"); Remove(oldSprite); @@ -56,11 +57,13 @@ public static void Unhook() private static void Booster_PlayerReleased(On.Celeste.Booster.orig_PlayerReleased orig, Booster self) { orig(self); - if (Util.TryGetPlayer(out Player player) && player.LastBooster is LavenderBooster) + if (Util.TryGetPlayer(out Player player) && player.LastBooster is LavenderBooster l) { Audio.Play(SFX.game_05_redbooster_end, player.Center); PurpleBooster.LaunchPlayerParticles(player, player.DashDir, P_BurstExplodeLavender); - PurpleBooster.PurpleBoosterExplodeLaunch(player, DynamicData.For(player), self.Center - player.DashDir, null, -1f); + DynamicData dyn = DynamicData.For(player); + dyn.Set(PurpleBooster.QUALITYOFLIFEUPDATE, l.QoL); + PurpleBooster.PurpleBoosterExplodeLaunch(player, dyn, self.Center - player.DashDir, null, -1f); } } diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index 0d523a6..335e4d3 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -18,7 +18,7 @@ namespace Celeste.Mod.VortexHelper.Entities; public class PurpleBooster : Entity { internal const string POSSIBLE_EARLY_DASHSPEED = "purpleBoostPossibleEarlyDashSpeed"; - internal const string CAN_WALLBOUNCE_FROM_SLINGSHOT = "purpleBoostCanWallBounce"; + internal const string QUALITYOFLIFEUPDATE = "purpleBoostQoL"; private readonly Sprite sprite; private readonly Wiggler wiggler; @@ -47,10 +47,10 @@ public bool BoostingPlayer public static readonly ParticleType P_BurstExplode = new(Booster.P_Burst); private readonly SoundSource loopingSfx; - public readonly bool CanWallbounce; + public readonly bool QoL; public PurpleBooster(EntityData data, Vector2 offset) : this(data.Position + offset) { - CanWallbounce = data.Bool("CanWallbounce", false); + QoL = data.Bool("QoL"); } public PurpleBooster(Vector2 position) @@ -133,7 +133,7 @@ public static void Boost(Player player, PurpleBooster booster) player.Speed = Vector2.Zero; DynamicData playerData = DynamicData.For(player); playerData.Set("boostTarget", booster.Center); - playerData.Set(CAN_WALLBOUNCE_FROM_SLINGSHOT, booster.CanWallbounce); + playerData.Set(QUALITYOFLIFEUPDATE, booster.QoL); booster.StartedBoosting = true; } @@ -435,14 +435,17 @@ public static int PurpleDashingUpdate() { Util.TryGetPlayer(out Player player); DynamicData playerData = DynamicData.For(player); + bool QoL = playerData.Get(QUALITYOFLIFEUPDATE) is bool b && b; if (Input.DashPressed || Input.CrouchDashPressed) { + if (QoL) player.Speed += playerData.Get(POSSIBLE_EARLY_DASHSPEED); + else player.LiftSpeed += playerData.Get(POSSIBLE_EARLY_DASHSPEED); - player.LiftSpeed += playerData.Get(POSSIBLE_EARLY_DASHSPEED); + Console.WriteLine(player.Speed); return player.StartDash(); } - if (playerData.Get(CAN_WALLBOUNCE_FROM_SLINGSHOT) && Math.Abs(player.DashDir.X) <= 0.02 && + if (QoL && Math.Abs(player.DashDir.X) <= 0.02 && Input.Jump.Pressed && player.CanUnDuck && (player.DashDir.Y < 0 ? playerData.Get(POSSIBLE_EARLY_DASHSPEED).Y == 0 : playerData.Get(POSSIBLE_EARLY_DASHSPEED).Y < 0)) { @@ -466,14 +469,35 @@ public static IEnumerator PurpleDashingCoroutine() DynamicData playerData = DynamicData.For(player); Vector2 origin = playerData.Get("boostTarget"); - Vector2 earlyExitBoost; + Vector2 earlyExitBoost = Vector2.Zero; while (t < 1f) { t = Calc.Approach(t, 1.0f, Engine.DeltaTime * 1.5f); Vector2 vec = origin + Vector2.UnitY * 6f + player.DashDir * 60f * (float) Math.Sin(t * Math.PI); - - playerData.Set(POSSIBLE_EARLY_DASHSPEED, earlyExitBoost = (t > .6f) ? (t - .5f) * 200f * -player.DashDir : Vector2.Zero); + if(playerData.Get(QUALITYOFLIFEUPDATE) is bool b && b) + { + if(t == 1f) + { + // frame 0: mimics speed at launch exit exactly, Input.MoveX.Value == -Math.Sign(player.DashDir) ? 300 : 250 + earlyExitBoost = 250f * -player.DashDir; + Vector2 aim = Input.GetAimVector(player.Facing).EightWayNormal().Sign(); + if (aim.X == Math.Sign(earlyExitBoost.X)) earlyExitBoost.X *= 1.2f; + if (aim.Y == Math.Sign(earlyExitBoost.Y)) earlyExitBoost.Y *= 1.2f; + } else if(t > 0.93f) + { + // frame -2 : 200 speed + // frame -1 : 205 speed + earlyExitBoost = (float)Math.Round(210f * t) * -player.DashDir; + } + } + else if (t > 0.6f) + { + earlyExitBoost = (t - .5f) * 200f * -player.DashDir; + } + Console.WriteLine(t + "," + earlyExitBoost); + playerData.Set(POSSIBLE_EARLY_DASHSPEED, earlyExitBoost); + if (player.CollideCheck(vec)) { player.StateMachine.State = Player.StNormal; @@ -491,12 +515,13 @@ public static void PurpleDashingEnd() { Util.TryGetPlayer(out Player player); DynamicData playerData = DynamicData.For(player); - playerData.Set(CAN_WALLBOUNCE_FROM_SLINGSHOT, false); + playerData.Set(QUALITYOFLIFEUPDATE, false); } public static void PurpleBoosterExplodeLaunch(Player player, DynamicData playerData, Vector2 from, Vector2? origin, float factor = 1f) { + bool QoL = playerData?.Get(QUALITYOFLIFEUPDATE) is bool b && b; Input.Rumble(RumbleStrength.Strong, RumbleLength.Medium); - Celeste.Freeze(0.1f); + Celeste.Freeze(QoL ? 0.05f : 0.1f); playerData.Set("launchApproachX", null); Level level = player.SceneAs(); @@ -519,6 +544,8 @@ public static void PurpleBoosterExplodeLaunch(Player player, DynamicData playerD if (!player.Inventory.NoRefills) player.RefillDash(); player.RefillStamina(); + if (QoL && playerData?.Get("dashCooldownTimer") is float f) + playerData.Set("dashCooldownTimer", f > 0.06f ? 0.06f : f); player.StateMachine.State = Player.StLaunch; player.Speed *= factor; } @@ -561,7 +588,7 @@ private static void Player_WallJumpCheck(ILContext il) cursor.EmitDelegate>((b, p) => { if (b) return true; - try { if (DynamicData.For(p).TryGet(CAN_WALLBOUNCE_FROM_SLINGSHOT, out bool c) && c) return true; } + try { if (DynamicData.For(p).TryGet(QUALITYOFLIFEUPDATE, out bool c) && c) return true; } catch (NullReferenceException) { return false; } return false; }); @@ -571,7 +598,7 @@ private static void Player_WallJumpCheck(ILContext il) cursor.Emit(OpCodes.Ldarg_0); cursor.EmitDelegate>((f, p) => { - try { if (DynamicData.For(p).TryGet(CAN_WALLBOUNCE_FROM_SLINGSHOT, out bool c) && c) return p.DashDir.Y; } + try { if (DynamicData.For(p).TryGet(QUALITYOFLIFEUPDATE, out bool c) && c) return p.DashDir.Y; } catch (NullReferenceException) { return f; } return f; }); diff --git a/Loenn/entities/purple_booster.lua b/Loenn/entities/purple_booster.lua index b7263c1..5c60e36 100644 --- a/Loenn/entities/purple_booster.lua +++ b/Loenn/entities/purple_booster.lua @@ -10,13 +10,14 @@ purpleBooster.placements = { name = "purple", data = { lavender = false, - CanWallbounce = false + QoL = true } }, { name = "lavender", data = { - lavender = true + lavender = true, + QoL = true } } } diff --git a/Loenn/lang/en_gb.lang b/Loenn/lang/en_gb.lang index c2312a7..7289f99 100644 --- a/Loenn/lang/en_gb.lang +++ b/Loenn/lang/en_gb.lang @@ -70,6 +70,8 @@ entities.VortexHelper/PufferBarrier.placements.name.puffer_barrier=Puffer Barrie entities.VortexHelper/PurpleBooster.placements.name.purple=Booster (Purple) entities.VortexHelper/PurpleBooster.placements.name.lavender=Booster (Lavender) entities.VortexHelper/PurpleBooster.attributes.description.lavender=Whether the booster should instead be lavender in color, and launch the player forward instead of arcing back. +entities.VortexHelper/PurpleBooster.attributes.name.QoL=Version 2 +entities.VortexHelper/PurpleBooster.attributes.description.QoL=Enables Wallbouncing during the windup animation.\nFixes speedboost not applying when dashing early from booster.\nReduces Freeze Timer upon launch exit and ensures a shorter dashCooldownTimer. # Switch Block entities.VortexHelper/SwitchBlock.placements.name.switch_block_0=Switch Block (0 - Blue) From d8542a1dabeeba2e996808f22f5eee4b29340878 Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Thu, 2 Nov 2023 01:40:42 -0400 Subject: [PATCH 04/10] remove Console.WriteLine --- Code/Entities/PurpleBooster.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index 335e4d3..de1c1c6 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -440,9 +440,6 @@ public static int PurpleDashingUpdate() { if (QoL) player.Speed += playerData.Get(POSSIBLE_EARLY_DASHSPEED); else player.LiftSpeed += playerData.Get(POSSIBLE_EARLY_DASHSPEED); - - Console.WriteLine(player.Speed); - return player.StartDash(); } if (QoL && Math.Abs(player.DashDir.X) <= 0.02 && @@ -495,7 +492,6 @@ public static IEnumerator PurpleDashingCoroutine() { earlyExitBoost = (t - .5f) * 200f * -player.DashDir; } - Console.WriteLine(t + "," + earlyExitBoost); playerData.Set(POSSIBLE_EARLY_DASHSPEED, earlyExitBoost); if (player.CollideCheck(vec)) From 568918be454090a763bd7ec07d19b9e975c7fd8e Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:09:57 -0500 Subject: [PATCH 05/10] implemented standard dash aim leniency with QOL --- Code/Entities/PurpleBooster.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index de1c1c6..6499cd8 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -465,6 +465,10 @@ public static IEnumerator PurpleDashingCoroutine() Util.TryGetPlayer(out Player player); DynamicData playerData = DynamicData.For(player); Vector2 origin = playerData.Get("boostTarget"); + if(playerData.GET(QUALITYOFLIFEUPDATE) is bool b && b) { + yield return null; + player.DashDir = lastAim; + } Vector2 earlyExitBoost = Vector2.Zero; while (t < 1f) From 4282bda385c1db27ca6bbf0ea6ad6408823495c2 Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:19:22 -0500 Subject: [PATCH 06/10] Remove FastReflectionInfo, breaks on Core --- Code/Misc/Util.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Misc/Util.cs b/Code/Misc/Util.cs index 1984846..002a2b6 100644 --- a/Code/Misc/Util.cs +++ b/Code/Misc/Util.cs @@ -14,9 +14,9 @@ public static bool TryGetPlayer(out Player player) public static void LoadDelegates() { - player_WallJumpCheck = typeof(Player).GetMethod("WallJumpCheck", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetFastDelegate(); - player_SuperWallJump = typeof(Player).GetMethod("SuperWallJump", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetFastDelegate(); + player_WallJumpCheck = typeof(Player).GetMethod("WallJumpCheck", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + player_SuperWallJump = typeof(Player).GetMethod("SuperWallJump", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); } - public static FastReflectionDelegate player_WallJumpCheck; - public static FastReflectionDelegate player_SuperWallJump; + public static MethodInfo player_WallJumpCheck; + public static MethodInfo player_SuperWallJump; } From 90774704894e6af3901ee40ac19007159dc04700 Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:23:31 -0500 Subject: [PATCH 07/10] remove errors with FastReflectionDelegate --- Code/Entities/PurpleBooster.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index 6499cd8..ae58cfc 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -446,13 +446,13 @@ public static int PurpleDashingUpdate() Input.Jump.Pressed && player.CanUnDuck && (player.DashDir.Y < 0 ? playerData.Get(POSSIBLE_EARLY_DASHSPEED).Y == 0 : playerData.Get(POSSIBLE_EARLY_DASHSPEED).Y < 0)) { - if ((bool)Util.player_WallJumpCheck.Invoke(player, 1)) + if ((bool)Util.player_WallJumpCheck.Invoke(player, new object[1]{1})) { - Util.player_SuperWallJump.Invoke(player,-1); + Util.player_SuperWallJump.Invoke(player,new object[1]{-1}); return 0; - }else if ((bool) Util.player_WallJumpCheck.Invoke(player, -1)) + }else if ((bool) Util.player_WallJumpCheck.Invoke(player, new object[1]{-1})) { - Util.player_SuperWallJump.Invoke(player, 1); + Util.player_SuperWallJump.Invoke(player, new object[1]{1}); return 0; } } From 7f269e6383a86ae0cf93efbced70f84c1088e56d Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:25:52 -0500 Subject: [PATCH 08/10] fix crash --- Code/Misc/Util.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Code/Misc/Util.cs b/Code/Misc/Util.cs index 002a2b6..df0c04a 100644 --- a/Code/Misc/Util.cs +++ b/Code/Misc/Util.cs @@ -1,5 +1,6 @@ using Monocle; using MonoMod.Utils; +using System.Reflection; namespace Celeste.Mod.VortexHelper.Misc; @@ -14,8 +15,8 @@ public static bool TryGetPlayer(out Player player) public static void LoadDelegates() { - player_WallJumpCheck = typeof(Player).GetMethod("WallJumpCheck", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); - player_SuperWallJump = typeof(Player).GetMethod("SuperWallJump", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance); + player_WallJumpCheck = typeof(Player).GetMethod("WallJumpCheck", BindingFlags.NonPublic | BindingFlags.Instance); + player_SuperWallJump = typeof(Player).GetMethod("SuperWallJump", BindingFlags.NonPublic | BindingFlags.Instance); } public static MethodInfo player_WallJumpCheck; public static MethodInfo player_SuperWallJump; From bb8b8fd40a9e7d6f6f77c652ff126ca4b8322bda Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:28:05 -0500 Subject: [PATCH 09/10] fix crash 2 --- Code/Entities/PurpleBooster.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index ae58cfc..55bcc01 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -465,7 +465,7 @@ public static IEnumerator PurpleDashingCoroutine() Util.TryGetPlayer(out Player player); DynamicData playerData = DynamicData.For(player); Vector2 origin = playerData.Get("boostTarget"); - if(playerData.GET(QUALITYOFLIFEUPDATE) is bool b && b) { + if(playerData.Get(QUALITYOFLIFEUPDATE) is bool a && a) { yield return null; player.DashDir = lastAim; } From ea3f8d7e6dca6861bfadc6a82ca5eb9b28045057 Mon Sep 17 00:00:00 2001 From: Vivian <71410564+Viv-0@users.noreply.github.com> Date: Tue, 16 Jan 2024 17:29:45 -0500 Subject: [PATCH 10/10] fix crash 3 --- Code/Entities/PurpleBooster.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Code/Entities/PurpleBooster.cs b/Code/Entities/PurpleBooster.cs index 55bcc01..2e52b5a 100644 --- a/Code/Entities/PurpleBooster.cs +++ b/Code/Entities/PurpleBooster.cs @@ -467,7 +467,7 @@ public static IEnumerator PurpleDashingCoroutine() Vector2 origin = playerData.Get("boostTarget"); if(playerData.Get(QUALITYOFLIFEUPDATE) is bool a && a) { yield return null; - player.DashDir = lastAim; + player.DashDir = playerData.Get("lastAim"); } Vector2 earlyExitBoost = Vector2.Zero;