Skip to content

Commit 2d2dc09

Browse files
authored
Merge pull request #43 from swoolcock/swoolcock/gravityhelper-support
Gravity Helper support + other fixes
2 parents 56d8aa7 + 5a5dc7d commit 2d2dc09

9 files changed

+171
-32
lines changed

Code/Entities/BowlPuffer.cs

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using Celeste.Mod.Entities;
2+
using Celeste.Mod.VortexHelper.Misc;
23
using Microsoft.Xna.Framework;
34
using Monocle;
45
using System;
@@ -341,7 +342,7 @@ private void OnRelease(Vector2 force)
341342

342343
#endregion
343344

344-
#region Explosiong
345+
#region Explosion
345346

346347
private void Explode(bool playsound = true)
347348
{
@@ -764,6 +765,21 @@ public override void Render()
764765
{
765766
this.puffer.Scale = this.scale * (1f + this.inflateWiggler.Value * 0.4f);
766767
this.puffer.FlipX = false;
768+
769+
// gravity helper forces a scale change on the default Sprite
770+
if (Get<Sprite>() is { } sprite) sprite.Scale.Y = Math.Abs(sprite.Scale.Y);
771+
772+
// invert sprites if required
773+
var inverted = GravityHelperInterop.IsActorInverted(this);
774+
if (inverted)
775+
{
776+
this.puffer.Y *= -1;
777+
this.pufferBowlTop.Y *= -1;
778+
this.pufferBowlBottom.Y *= -1;
779+
this.pufferBowlTop.Scale.Y *= -1;
780+
this.pufferBowlBottom.Scale.Y *= -1;
781+
this.puffer.Scale.Y *= -1;
782+
}
767783

768784
Vector2 position = this.Position;
769785
this.Position.Y -= 6.0f;
@@ -792,6 +808,16 @@ public override void Render()
792808
Draw.Point(p, Color.Lerp(Color.OrangeRed, Color.LawnGreen, a / (float) Math.PI));
793809
}
794810
}
811+
812+
if (inverted)
813+
{
814+
this.puffer.Y *= -1;
815+
this.pufferBowlTop.Y *= -1;
816+
this.pufferBowlBottom.Y *= -1;
817+
this.pufferBowlTop.Scale.Y *= -1;
818+
this.pufferBowlBottom.Scale.Y *= -1;
819+
this.puffer.Scale.Y *= -1;
820+
}
795821
}
796822

797823
public static void InitializeParticles()

Code/Entities/FloorBooster.cs

+36-13
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ private enum DisableMode
3232

3333
public bool IceMode;
3434
public bool NoRefillsOnIce;
35+
public bool Ceiling;
3536

3637
private DisableMode disableMode;
3738

@@ -41,9 +42,12 @@ private enum DisableMode
4142
public int MoveSpeed;
4243

4344
public FloorBooster(EntityData data, Vector2 offset)
44-
: this(data.Position + offset, data.Width, data.Bool("left"), data.Int("speed"), data.Bool("iceMode"), data.Bool("noRefillOnIce"), data.Bool("notAttached")) { }
45+
: this(data.Position + offset, data.Width, data.Bool("left"), data.Int("speed"), data.Bool("iceMode"), data.Bool("noRefillOnIce"), data.Bool("notAttached"), data.Bool("ceiling")) { }
4546

4647
public FloorBooster(Vector2 position, int width, bool left, int speed, bool iceMode, bool noRefillOnIce, bool notAttached)
48+
: this(position, width, left, speed, iceMode, noRefillOnIce, notAttached, false) { }
49+
50+
public FloorBooster(Vector2 position, int width, bool left, int speed, bool iceMode, bool noRefillOnIce, bool notAttached, bool ceiling)
4751
: base(position)
4852
{
4953
this.Tag = Tags.TransitionUpdate;
@@ -54,8 +58,9 @@ public FloorBooster(Vector2 position, int width, bool left, int speed, bool iceM
5458
this.IceMode = iceMode;
5559
this.MoveSpeed = (int) Calc.Max(0, speed);
5660
this.Facing = left ? Facings.Left : Facings.Right;
61+
this.Ceiling = ceiling;
5762

58-
this.Collider = new Hitbox(width, 3, 0, 5);
63+
this.Collider = new Hitbox(width, 3, 0, ceiling ? 0 : 5);
5964
if (!this.notCoreMode)
6065
Add(new CoreModeListener(OnChangeMode));
6166

@@ -74,7 +79,7 @@ public FloorBooster(Vector2 position, int width, bool left, int speed, bool iceM
7479
});
7580
}
7681

77-
this.tiles = BuildSprite(left);
82+
this.tiles = BuildSprite(left, ceiling);
7883
}
7984

8085
public void SetColor(Color color)
@@ -109,7 +114,7 @@ private void OnDisable()
109114
this.Visible = false;
110115
}
111116

112-
private List<Sprite> BuildSprite(bool left)
117+
private List<Sprite> BuildSprite(bool left, bool ceiling)
113118
{
114119
var list = new List<Sprite>();
115120
for (int i = 0; i < this.Width; i += 8)
@@ -128,6 +133,8 @@ private List<Sprite> BuildSprite(bool left)
128133
Sprite sprite = VortexHelperModule.FloorBoosterSpriteBank.Create("FloorBooster" + id);
129134
if (!left)
130135
sprite.FlipX = true;
136+
if (ceiling)
137+
sprite.FlipY = true;
131138

132139
sprite.Position = new Vector2(i, 0);
133140
list.Add(sprite);
@@ -151,11 +158,11 @@ private void OnChangeMode(Session.CoreModes mode)
151158
this.idleSfx.Play(SFX.env_loc_09_conveyer_idle);
152159
}
153160

154-
private bool IsRiding(JumpThru jumpThru) => CollideCheckOutside(jumpThru, this.Position + Vector2.UnitY);
161+
private bool IsRiding(JumpThru jumpThru) => CollideCheckOutside(jumpThru, this.Position + (this.Ceiling ? -Vector2.UnitY : Vector2.UnitY));
155162

156163
private bool IsRiding(Solid solid)
157164
{
158-
if (CollideCheckOutside(solid, this.Position + Vector2.UnitY))
165+
if (CollideCheckOutside(solid, this.Position + (this.Ceiling ? -Vector2.UnitY : Vector2.UnitY)))
159166
{
160167
this.disableMode = (solid is CassetteBlock or SwitchBlock) ? DisableMode.ColorFade : DisableMode.Disappear;
161168
return true;
@@ -192,8 +199,10 @@ public override void Update()
192199
bool isUsed = false;
193200
base.Update();
194201

195-
if (player is not null && CollideCheck(player) && player.OnGround() && player.Bottom <= this.Bottom)
196-
isUsed = true;
202+
var matchGravity = this.Ceiling == GravityHelperInterop.IsPlayerInverted();
203+
204+
if (matchGravity && player is not null && CollideCheck(player) && player.OnGround())
205+
isUsed = this.Ceiling ? player.Top >= this.Top : player.Bottom <= this.Bottom;
197206

198207
PlayActivateSfx(this.IceMode || !isUsed);
199208
}
@@ -224,7 +233,7 @@ private void PositionSfx(Player entity)
224233
return;
225234

226235
this.idleSfx.Position = Calc.ClosestPointOnLine(this.Position, this.Position + new Vector2(this.Width, 0f), entity.Center) - this.Position;
227-
this.idleSfx.Position.Y += 7;
236+
if (!this.Ceiling) this.idleSfx.Position.Y += 7;
228237
this.activateSfx.Position = this.idleSfx.Position;
229238
this.idleSfx.UpdateSfxPosition(); this.activateSfx.UpdateSfxPosition();
230239
}
@@ -258,13 +267,18 @@ private static bool Player_RefillDash(On.Celeste.Player.orig_RefillDash orig, Pl
258267
if (level.Transitioning)
259268
return orig(self);
260269

270+
var playerInverted = GravityHelperInterop.IsPlayerInverted();
271+
261272
foreach (FloorBooster entity in self.Scene.Tracker.GetEntities<FloorBooster>())
262273
{
263274
if (!entity.IceMode)
264275
continue;
265276

277+
if (entity.Ceiling != playerInverted)
278+
continue;
279+
266280
if (self.CollideCheck(entity) && self.OnGround()
267-
&& self.Bottom <= entity.Bottom
281+
&& (entity.Ceiling ? self.Top >= entity.Top : self.Bottom <= entity.Bottom)
268282
&& entity.NoRefillsOnIce)
269283
return false;
270284
}
@@ -289,8 +303,9 @@ private static int Player_NormalUpdate(On.Celeste.Player.orig_NormalUpdate orig,
289303
playerData.Set("lastFloorBooster", null);
290304

291305
FloorBooster lastFloorBooster = playerData.Get<FloorBooster>("lastFloorBooster");
306+
var playerInverted = GravityHelperInterop.IsPlayerInverted();
292307

293-
if (lastFloorBooster is not null && !self.CollideCheck(lastFloorBooster))
308+
if (lastFloorBooster is not null && (lastFloorBooster.Ceiling != playerInverted || !self.CollideCheck(lastFloorBooster)))
294309
{
295310
Vector2 vec = Vector2.UnitX
296311
* playerData.Get<float>("floorBoosterSpeed")
@@ -310,8 +325,11 @@ private static int Player_NormalUpdate(On.Celeste.Player.orig_NormalUpdate orig,
310325
{
311326
if (entity.IceMode)
312327
continue;
328+
329+
if (entity.Ceiling != playerInverted)
330+
continue;
313331

314-
if (self.CollideCheck(entity) && self.OnGround() && self.StateMachine != Player.StClimb && self.Bottom <= entity.Bottom)
332+
if (self.CollideCheck(entity) && self.OnGround() && self.StateMachine != Player.StClimb && (entity.Ceiling ? self.Top >= entity.Top : self.Bottom <= entity.Bottom))
315333
{
316334
if (!touchedFloorBooster)
317335
{
@@ -349,14 +367,19 @@ private static float GetPlayerFriction()
349367
{
350368
if (!Util.TryGetPlayer(out Player player))
351369
return 1.0f;
370+
371+
var playerInverted = GravityHelperInterop.IsPlayerInverted();
352372

353373
foreach (FloorBooster entity in player.Scene.Tracker.GetEntities<FloorBooster>())
354374
{
355375
if (!entity.IceMode)
356376
continue;
377+
378+
if (entity.Ceiling != playerInverted)
379+
continue;
357380

358381
if (player.CollideCheck(entity) && player.OnGround() && player.StateMachine != Player.StClimb
359-
&& player.Bottom <= entity.Bottom)
382+
&& (entity.Ceiling ? player.Top >= entity.Top : player.Bottom <= entity.Bottom))
360383
return player.SceneAs<Level>().CoreMode is Session.CoreModes.Cold ? 0.4f : 0.2f;
361384
}
362385

Code/Entities/PurpleBooster.cs

+21-6
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,8 @@ public override void Update()
254254
{
255255
base.Update();
256256

257+
var inverted = GravityHelperInterop.IsPlayerInverted();
258+
257259
this.actualLinkPercent = Calc.Approach(this.actualLinkPercent, this.linkPercent, 5f * Engine.DeltaTime);
258260

259261
if (this.cannotUseTimer > 0f)
@@ -271,7 +273,10 @@ public override void Update()
271273
Vector2 target = Vector2.Zero;
272274
Player entity = this.Scene.Tracker.GetEntity<Player>();
273275
if (entity is not null && CollideCheck(entity))
274-
target = entity.Center + Booster.playerOffset - this.Position;
276+
{
277+
var playerOffset = new Vector2(Booster.playerOffset.X, inverted ? -Booster.playerOffset.Y : Booster.playerOffset.Y);
278+
target = entity.Center + playerOffset - this.Position;
279+
}
275280
this.sprite.Position = Calc.Approach(this.sprite.Position, target, 80f * Engine.DeltaTime);
276281
}
277282

@@ -377,8 +382,10 @@ public static int PurpleBoostUpdate(Player player)
377382
Vector2 value = Input.Aim.Value * 3f;
378383
Vector2 vector = Calc.Approach(player.ExactPosition, boostTarget - player.Collider.Center + value, 80f * Engine.DeltaTime);
379384

385+
GravityHelperInterop.BeginOverride();
380386
player.MoveToX(vector.X, null);
381387
player.MoveToY(vector.Y, null);
388+
GravityHelperInterop.EndOverride();
382389

383390
if (Vector2.DistanceSquared(player.Center, boostTarget) >= 275f)
384391
{
@@ -403,9 +410,11 @@ public static int PurpleBoostUpdate(Player player)
403410

404411
public static void PurpleBoostEnd(Player player)
405412
{
413+
GravityHelperInterop.BeginOverride();
406414
Vector2 vector = (player.boostTarget - player.Collider.Center).Floor();
407415
player.MoveToX(vector.X, null);
408416
player.MoveToY(vector.Y, null);
417+
GravityHelperInterop.EndOverride();
409418
}
410419

411420
public static IEnumerator PurpleBoostCoroutine(Player player)
@@ -414,12 +423,12 @@ public static IEnumerator PurpleBoostCoroutine(Player player)
414423
player.StateMachine.State = VortexHelperModule.PurpleBoosterDashState;
415424
}
416425

417-
// Arc Motion
426+
// Arc Motion
418427
public static void PurpleDashingBegin(Player player)
419428
{
420429
Celeste.Freeze(0.05f); // this freeze makes fastbubbling much more lenient
421430
DynamicData playerData = DynamicData.For(player);
422-
player.DashDir = Input.GetAimVector(player.Facing);
431+
player.DashDir = GravityHelperInterop.InvertIfRequired(Input.GetAimVector(player.Facing));
423432
playerData.Set(POSSIBLE_EARLY_DASHSPEED, Vector2.Zero);
424433

425434
foreach (PurpleBooster b in player.Scene.Tracker.GetEntities<PurpleBooster>())
@@ -469,22 +478,24 @@ public static IEnumerator PurpleDashingCoroutine(Player player)
469478
Vector2 origin = player.boostTarget;
470479
if(VortexHelperModule.SessionProperties.BoosterQoL) {
471480
yield return null;
472-
player.DashDir = player.lastAim;
481+
player.DashDir = GravityHelperInterop.InvertIfRequired(player.lastAim);
473482
}
474483

475484
Vector2 earlyExitBoost = Vector2.Zero;
476485
while (t < 1f)
477486
{
478487
t = Calc.Approach(t, 1.0f, Engine.DeltaTime * 1.5f);
479-
Vector2 vec = origin + Vector2.UnitY * 6f + player.DashDir * 60f * (float) Math.Sin(t * Math.PI);
488+
float offset = GravityHelperInterop.IsPlayerInverted() ? -6f : 6f;
489+
Vector2 vec = origin + Vector2.UnitY * offset + player.DashDir * 60f * (float) Math.Sin(t * Math.PI);
480490

481491
if(VortexHelperModule.SessionProperties.BoosterQoL)
482492
{
483493
if(t == 1f)
484494
{
485495
// frame 0: mimics speed at launch exit exactly, Input.MoveX.Value == -Math.Sign(player.DashDir) ? 300 : 250
486496
earlyExitBoost = 250f * -player.DashDir;
487-
Vector2 aim = Input.GetAimVector(player.Facing).EightWayNormal().Sign();
497+
Vector2 aim = GravityHelperInterop.InvertIfRequired(Input.GetAimVector(player.Facing));
498+
aim = aim.EightWayNormal().Sign();
488499
if (aim.X == Math.Sign(earlyExitBoost.X)) earlyExitBoost.X *= 1.2f;
489500
if (aim.Y == Math.Sign(earlyExitBoost.Y)) earlyExitBoost.Y *= 1.2f;
490501
} else if(t > 0.93f)
@@ -505,7 +516,9 @@ public static IEnumerator PurpleDashingCoroutine(Player player)
505516
player.StateMachine.State = Player.StNormal;
506517
yield break;
507518
}
519+
GravityHelperInterop.BeginOverride();
508520
player.MoveToX(vec.X); player.MoveToY(vec.Y);
521+
GravityHelperInterop.EndOverride();
509522
yield return null;
510523
}
511524

@@ -531,6 +544,8 @@ public static void PurpleBoosterExplodeLaunch(Player player, Vector2 from, Vecto
531544
level.Shake(0.15f);
532545

533546
Vector2 vector = (player.Center - from).SafeNormalize(-Vector2.UnitY);
547+
vector = GravityHelperInterop.InvertIfRequired(vector);
548+
534549
if (Math.Abs(vector.X) < 1f && Math.Abs(vector.Y) < 1f)
535550
vector *= 1.1f;
536551

Code/Misc/GravityHelperInterop.cs

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
using Microsoft.Xna.Framework;
2+
using MonoMod.ModInterop;
3+
using System;
4+
5+
namespace Celeste.Mod.VortexHelper.Misc;
6+
7+
internal static class GravityHelperInterop
8+
{
9+
[ModImportName("GravityHelper")]
10+
internal static class Imports
11+
{
12+
public static Func<bool> IsPlayerInverted;
13+
public static Func<Actor, bool> IsActorInverted;
14+
public static Action BeginOverride;
15+
public static Action EndOverride;
16+
}
17+
18+
public static bool IsPlayerInverted() => Imports.IsPlayerInverted?.Invoke() ?? false;
19+
public static bool IsActorInverted(Actor actor) => Imports.IsActorInverted?.Invoke(actor) ?? false;
20+
public static void BeginOverride() => Imports.BeginOverride?.Invoke();
21+
public static void EndOverride() => Imports.EndOverride?.Invoke();
22+
public static Vector2 InvertIfRequired(Vector2 v) => IsPlayerInverted() ? new Vector2(v.X, -v.Y) : v;
23+
}

Code/VortexHelperModule.cs

+3
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using Celeste.Mod.VortexHelper.Misc;
33
using Microsoft.Xna.Framework;
44
using Monocle;
5+
using MonoMod.ModInterop;
56
using System;
67
using System.Reflection;
78

@@ -69,6 +70,8 @@ public override void Load()
6970
MiscHooks.Hook();
7071

7172
Util.LoadDelegates();
73+
74+
typeof(GravityHelperInterop.Imports).ModInterop();
7275
}
7376

7477
public override void Unload()

Loenn/entities/bowl_puffer.lua

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ bowlPuffer.placements = {
2929
}
3030

3131
bowlPuffer.texture = "objects/VortexHelper/pufferBowl/idle00"
32-
bowlPuffer.offset = {32, 35}
32+
bowlPuffer.offset = {0, 3}
3333

3434
function bowlPuffer.selection(room, entity)
3535
return utils.rectangle((entity.x or 0) - 11, (entity.y or 0) - 11, 21, 19)

0 commit comments

Comments
 (0)