-
Notifications
You must be signed in to change notification settings - Fork 28
Holdable Movement
Madeline can pick up a Holdable if:
- Her hitbox overlaps the holdable's pink hitbox (Theo has a higher depth than Madeline, so he moves before the hitbox overlap is checked)
- She is not tired (flashing red, which occurs when stamina < 20)
- She is in StNormal, StLaunch or StDash
- Pickups from StNormal and StLaunch require Madeline to not be crouched, but from StDash allows being crouched if Madeline is able to uncrouch
Picking up a Holdable uncrouches Madeline, sets her minHoldTimer
to 21 frames, and sets her state to StPickup. This state stores Madeline's jump timer and previous speed, temporarily sets her speed to 0, and plays the pickup animation, which lasts for 12 frames. On the 13th frame, if Madeline is still in StPickup (which she might not be), the state then:
- restores Madeline's jump timer and speed
- sets Madeline's vertical speed to a maximum of 0
- sets Madeline's state to StNormal -- this happens after input checking, so Madeline won't be able to perform any actions until the next frame
While Madeline is carrying a holdable and her minHoldTimer
(set by the pickup animation) is 0, releasing grab will make her release the holdable as follows:
- if down is held on the same frame, Madeline will drop the holdable. This does not affect Madeline's speed and gives the holdable 0 speed on both axes. Gravity will then take affect, causing the holdable to fall straight down.
- if down is not held, Madeline will throw the holdable to the side she is facing. This gives Madeline 80 speed away from that side and gives the holdable 6 frames of
noGravityTimer
(which functions like Madeline'svarJumpTimer
) and a release force of -0.4 vertically and 1 towards the side to which it was thrown.
Releasing a holdable also sets its cannotHoldTimer
to its cannotHoldDelay
. Madeline cannot pick up a holdable with a positive cannotHoldTimer
, but she can still pick up any other holdable whose timer has expired.
Vanilla Celeste only has two types of holdables, jellyfish and Theo. Modded holdables have typically chosen one of these types and copied most of its behavior, which has resulted in the two main categories of holdables, "light" and "heavy".
For all characteristics truly inherent to one of these categories, vanilla and modded holdables use the fields Holdable.SlowFall
and Holdable.SlowRun
to choose a set of characteristics. SlowFall
affects far more behavior than SlowRun
, so its value is the focus of these categories. They are defined as follows:
Category | SlowFall | SlowRun |
---|---|---|
Light (jellyfish) | true | false |
Heavy (Theo) | false | true |
In addition, these are instance fields, not static fields, so holdables of the same type can theoretically have different values for these fields, but this never occurs in vanilla.
While Madeline is carrying a holdable whose SlowRun
is true, her horizontal speed soft cap is reduced to 70. This is the only effect of this field.
The behavior in this section only occurs if the related holdable's SlowFall
is true.
When Madeline picks up the holdable, the game checks if it should trigger a jelly bump. If not, if Madeline has any upwards speed, that speed is set to -105 if it was not already lower (faster upwards).
While Madeline is carrying the holdable, the friction and acceleration applied to her are halved, and while airborne, her horizontal speed soft cap is increased to 108.
If Madeline walljumps while carrying the holdable, regardless of whether her input was neutral, she is given forceMoveX
away from the wall for 16 frames.
Each frame, Madeline's maxFall
approaches:
Wind \ Vertical Input | Neutral | Down | Up |
---|---|---|---|
No upwards wind | 40 | 120 | 24 |
Upwards wind | 0 | 120 | -32 |
The above effect considers wind to be upwards if its vertical component is less than 0, no matter how small.
When Madeline picks up a holdable whose SlowFall
is true, on the 13th frame of the pickup animation, if Madeline's gliderBoostTimer
is at least 0.16 (10 frames) and her gliderBoostDir
's Y component is upwards, a "jelly bump" will be triggered, which sets Madeline's vertical speed to 240 * gliderBoostDir
's Y component unless her speed was already lower (faster upwards).
gliderBoostDir source |
Direction's Y component | Resulting Y speed |
---|---|---|
Dash |
DashDir 's Y component |
varies |
Hyper | ~-0.555 | ~-133.337 |
Super | ~-0.707 | ~-169.706 |
Wallbounce | -1 | -240 |
Each of the above actions also sets gliderBoostTimer
to 0.55 (33 frames), so if Madeline picks up a light holdable within 23 frames, a jelly bump will be triggered. However, gliderBoostTimer
is reset to 0 by:
- jumping, climbjumping, or walljumping
- colliding with a solid
- entering a dream block
- using a red booster (
RedDashBegin
sets the timer to 0.55 but setsDashDir
to 0, andRedDashUpdate
sets the timer to 0.05 which is too low to trigger a jelly bump) - hitting a spring
-
Player.Bounce
(bouncing on Oshiro, snowballs, seekers, iceballs, pufferfish, or deadly pits in assist mode)
The two vanilla holdable types have many characteristics related directly to each instance of those classes, rather than to the "category" imposed by Holdable.SlowFall
. This section aims to cover characteristics that are commonly attributed to "light" or "heavy" holdables despite their independence from that field.
The classes' constructors set each instance's Hold.cannotHoldDelay
to 6 frames for Theo and 18 frames for jellyfish.
TheoCrystal.Update
causes Theo to open Theo gates, kill Madeline when he dies, prevent screen transitions while leaving him behind, approach 200 vertical speed, and have horizontal friction of 5.833 speed/frame (halved while moving upwards) and vertical friction of 13.333 speed/frame (halved while vertical speed is between -30 and 30). Theo has additional event methods used to bounce from spinners and interact with seekers.
Glider.Update
causes jellyfish to be destroyed by seeker barriers, be affected by wind, approach vertical speeds of 30 without upwards wind and 0 with upwards wind, and have horizontal friction of 0.666 speed/frame and vertical friction of 3.333 speed/frame (halved while vertical speed is between -30 and 30).
When thrown, each holdable calculates its speed by multiplying its release force by a specific number. Despite the factor for Theo being twice that for jellyfish, the arcs are similar since jellyfish experience much less friction.
Type | Factor | Resulting Speed |
---|---|---|
Theo | 200 | 200, -80 |
Jellyfish | 100 | 100, -40 |
If Madeline is holding down while touching the ground, she will crouch, which drops the holdable she was carrying. Crouchjumps also drop the holdable.
If the holdable's SlowFall
is true, holding down while picking up the holdable as Madeline is grounded or while carrying it as Madeline is airborne will set a holdCannotDuck
flag which prevents initiating a crouch, but touching the ground while not holding down removes the flag. If holdCannotDuck
is false, it's still possible to fastfall on the ground with a jellyfish by holding an angle of 120° or 240°, since jellyfish use a different threshold for fastfalling than Madeline does for crouching.
In some situations, it may be possible to set Madeline's state during the pickup animation. Due to how Player.PickupCoroutine
is written, doing this will not prevent Madeline from carrying the holdable, but it also won't perform any of the actions normally performed when the pickup animation ends (see Picking up). Most notably, this means Madeline will not regain the speed she had before the pickup.
Anything that sets Madeline's state can theoretically be used to cancel the pickup animation. Some interactions commonly used to achieve this are:
- demodashing under some state-setting hitbox and starting the pickup at a position where Madeline will uncrouch into that hitbox (often sideways springs or seekers)
- jumping, moving into an upwards spring, then starting the pickup while inside the spring
Example Video
SpringCancel.mp4
Note
There are several other terms that refer to this interaction, including:
- "Extra Ball tech", after the room in Strawberry Jam's Pinball Purgatory which popularized it
- "freeze frame ungrab", since many early uses of the interaction triggered it by using pufferfish or bumpers to enter StLaunch, which allow the interaction to be more easily triggered RTA by releasing the grab button during the freeze frames from those entities
- "grabless grab", following the silly naming convention started by dashless dashes
StNormal is the only state that prevents Madeline from dashing, climbjumping, and grabbing a wall while carrying a holdable, even though those actions can be initiated from other states. StNormal is also the only state from which player inputs can directly cause Madeline to release a holdable. It seems the approach used in development to prevent holdables from being carried in other states was to find each section of code that puts Madeline in another state and add code to that section that first forces her to drop her holdable. However, only the following methods of reaching other states have that addition:
- entering fling birds or Badeline orbs
- entering a booster (custom maps may disable this, allowing Madeline to carry things while in boosters)
- being put in a return bubble
- interacting with binoculars
"Hands-free holding" is the term applied to carrying a holdable in a state other than StNormal, which can be accomplished by setting Madeline's state in any way not explicitly prevented above. It's often used to perform one of the actions that StNormal prevents while carrying a holdable, but that isn't necessary for a strat to be said to use hands-free holding.
Not all of the actions restricted by StNormal can be performed from all states. If a vanilla state (other than StNormal) is not present in the table below, none of the actions can be performed from that state.
State | Dash | Climbjump | Grab Wall |
---|---|---|---|
StClimb | ✅ | ✅ | N/A |
StDash | N/A | ✅ | ❌ |
StSwim | ✅ | ❌ | ✅ |
StBoost | ✅ | ❌ | ❌ |
StRedDash | ✅ | ✅ | ❌ |
StHitSquash | ✅ | ✅ | ✅ |
StLaunch | ✅ | ❌ | ❌ |
StDreamDash | ❌ | ❌ | ✅ |
StStarFly | ✅ | ❌ | ✅ |
StLaunch is a special case for hands-free holding because holding grab in that state will cause Madeline to pick up the holdable she is already carrying. If Madeline's state is set to StLaunch on one frame, the player must release grab on the next frame to start hands-free holding.
Unlike StNormal and StDash, StLaunch does not check whether Madeline is already carrying a holdable when determining if she should be able to pick up a holdable. If a different holdable has a higher actualDepth
than the one Madeline is currently carrying while she is in StLaunch, pressing grab will cause her to pick up that other holdable. This sets Madeline's Holding
to the new holdable, but it does not release the old holdable, which has several interesting effects:
- the old holdable doesn't lose its
Persistent
tag, so screen transitioning will not unload it. Re-entering the room will still spawn another copy, so this can be used to duplicate holdables - the old holdable hovers in place in the air (it still has a
Holder
so itsUpdate
function doesn't apply gravity, and Madeline'sUpdateCarry
only updates the currentHolding
which is no longer the old holdable) - the game will crash the frame after Madeline is set to
null
, e.g. by dying, if any currently loaded holdable still has her as itsHolder
but she doesn't have it as herHolding
These effects are instance-dependent, so modded holdables may have additional effects when they become the "old holdable" in holdable persistence.
Since Madeline can not usually climbjump or dash with Theo or Jellies during long climbs, she must drop or throw them away to climb up big vertical sections.
basic high stamina cost
-------------------------------
26,J,G 1,D,J
1,D,J 4,K,G
26,K,G or 1,J,G
1,D,K 24,J,G
... ...
are both very common. "Optimal" climbs depend on the situation a lot. Turning the high stamina cost into a half stamina climb, for example, also works quite well.
With large amounts of speed, Madeline starts moving faster than she can throw objects, and because you can neither dash nor climbjump/cornerboost, your movement is usually limited to regular jumping and releasing the holdable.
Carrying speed past obstacles involves throwing the holdable forward and then dashing and/or climbjumping to pick it back up. Timing can vary quite a bit and depend on the situation.
Example Video
Large.Speed.mp4
Throwing a holdable gives Madeline 80 horizontal speed away from where she threw it. The term "backboost" usually refers to intentionally turning around to throw a jellyfish in the direction opposite Madeline's current speed, to get the speed from throwing added rather than subtracted.
Example Video and Inputs
Backboost.mp4
11,R,G
1,L
19,R,D,X
Picking up a Holdable will cancel a dash. It is common to perform a short grounded Ultra into a Holdable to get a 1.2x speedboost, then pick up the holdable to cancel StDash. Cancelling the state is desirable because the dash naturally ending would reset Madeline's horizontal speed to 160.
Example Video and Inputs
UltraCancel.example.mp4
15,R,D,X
1,R,J
5,R,D,X
13,R,G
12,R,J,G
If Madeline has any amount of upwards speed when she picks up a SlowFall
holdable, that speed is increased to -105 (unless it was already faster or a jelly bump was triggered). If Madeline then drops that holdable as soon as her minHoldTimer
expires, she will still have a small amount of upwards speed, at which point she can pick up a second SlowFall
holdable and get her vertical speed set to -105 again. This can be repeated indefinitely, alternating which holdable is grabbed, to slowly gain infinite height.
Since StPickup sets Madeline's speed to 0 but restores her previous speed afterwards, picking up a holdable allows Madeline to touch ground, getting coyote time and refilling stamina and dashes, while maintaining the upwards trajectory from some prior movement. Some holdable-related tech terms are based on the usage of this interaction for some benefit.
In the context of holdable movement, this term refers to performing a hyper, picking up a holdable and touching the ground during the pickup animation. It's often followed by a jump from coyote time just after StPickup ends, in which case it's usually referred to as a "0-frame bunnyhop" no matter how many frames come between StPickup ending and Madeline jumping.
This can be performed in many circumstances if Madeline starts the hyper from the bottom eighth of the pixel touching the ground, as the -52.5 speed on the first frame of the hyper will not be enough move her to the next pixel up. It can also be performed regardless of vertical subpixel if, during the pickup animation, either a floor moves under Madeline or a force such as moving solids or wind pushes Madeline to ground.
Example Video
low.subpixel.hyper.mp4
With the exception of 0f bunnyhops, many methods of getting coyote time then moving upwards from the ground Madeline jumped from are known as "double jumps".
The example below uses jump timer abuse to get upwards speed after touching the ground. A standard jump from the higher position reached using jump timer abuse gains enough height for Madeline to down-diagonal dash and not land an ultra until the dash ends, allowing her to keep the speed.
Example Video and Inputs
DoubleJump.mp4
# start with a hyper bhop for speed
6,R,Z
1,R,J
7,R
1,R,J
# quickly after the jump, grounded ultra to touch the ground again and gain speed
8,R,D,J,X
# pick up Theo, and hold jump so that JTA will be used for height after the animation ends
13,R,J,G
# crouch to drop Theo before `minHoldTimer` expires, and keep holding jump to gain height using JTA
4,R,D,J
# after moving upwards, start another jump from coyote time -- this is the "double jump"
12,R,K
# now she's high enough to downright and not collide with the ground until it ends
15,R,D,X
1,R,J
# grounded ultra cancel for more speed
5,R,D,X
13,R,G
Entering a dream block requires Madeline to be DashAttacking
, which picking up a holdable does not disable. Dashing sets Madeline's dashAttackTimer
to 18f and the pickup animation is 13f long. The earliest Madeline can pick up the holdable while having speed from the dash is two frames after pressing dash, leaving at most three frames during which Madeline can be moving and carrying a holdable while DashAttacking
(and so can enter a dream block while carrying a holdable). Doing this is typically referred to as "dream smuggling" even when it's part of a map's intended route.
Smuggling holdables downwards is much harder, because grabbing a throwable resets downwards speed to 0 and being directly above a solid sets gravity to 0 (which does not leave enough time to accelerate and collide with it normally). The easier way is to already be hands-free holding, allowing you to dash whilst holding the throwable. It is also possible if a top corner is exposed, by grabbing the throwable off the edge, gaining some downwards speed then moving onto the block to collide with it.
When smuggling a Holdable through a dreamblock, you can dreamgrab while carrying a holdable and dash and demohyper while not letting go of Theo or any other holdable.