@@ -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
0 commit comments