5. Ducking and jumping¶
Ducking and jumping are some of the fundamental player actions. Understanding the intricacies associated with these actions is vital to writing an effecting TAS and troubleshooting issues that might arise along the way.
5.1. Ducking¶
Ducking is one of the most important actions in playing Half-Life. And yet, it has some of the more misunderstood behaviours. Ducking can be performed with the use of the duck key, which issues +duck. The subsequent behaviour depends on whether the player is onground, and how long the duck key is held before releasing.
Fig. 5.1. Depiction of standing and ducking hulls (also known as axis-aligned bounding boxes) of the player entity. The hulls are drawn to scale and projected orthographically.¶
There are three ducking states in Half-Life, namely standing, in-duck, and ducked. The standing state is simply the player’s default state, when the duck key is not held. In this state, the player bounding box is set to be 72 units tall. The in-duck state refers to the transitional state between the standing and ducked states. Lastly, the ducked state is when the player is fully ducked, with a bounding box of 36 units height. The standing and ducked states are relatively straightforward, but what happens in the in-duck state is less obvious and potentially misleading.
Fig. 5.2. Illustration of how bounding box varies over time when the duck key is pressed, held, and released, while the player is on the ground. Notice that while in the in-duck state, the bounding box stays unchanged, despite the camera seemingly moving downwards.¶
Suppose the player presses the duck key. Suppose also the player is onground. The ducking state will instantly transition from standing to in-duck. As a result, the game will start a countdown of 0.4 seconds. Meanwhile, the game will begin to slowly animate the player vertical view offset downwards. This can be observed in-game as the camera position seemingly easing downwards when ducking. However, this is misleading: the player hull size has not changed thus far, and the height remains at 72 units throughout. Only when the 0.4 seconds time is up the game will set the ducking state to ducked and instantaneously set the hull height to 36 units. And only in the following frame does the FSU values (see Forwardmove, sidemove, and upmove) get scaled down by a factor of 0.333:
As long as the duck key is still being held, the ducking state will remain unchanged no matter what situation the player is in, and no matter how long. (Note that the factor of 0.333 is exact and actually used in the SDK. This is not an approximation made by this documentation.)
Fig. 5.3. Illustration of how bounding box varies over time when the duck key is pressed, held, and released, while the player is in the air. Notice that the centre of bounding boxes does not move after ducking or unducking, assuming the player has not moved in the meantime due to gravity.¶
On the other hand, if the player is not onground (in the air), then the game will skip the in-duck state entirely, and transition immediately to the ducked state. This means that changing hull size is instantaneously as long as the player is in the air. This allows for very quick responses when navigating around narrow terrains. For example, the player can duck in the air to immediately dodge an obstructing object. Again, the FSU values will only get scaled down in the following frame.
Fig. 5.4. Illustration of how bounding box varies over time when the duck key is pressed, held, and released before the in-duck state is over, while the player is on the ground. Note that the -duck need not be issued at
Now let us backtrack and assume the player is onground. What if the player releases the duck key before the 0.4 seconds is up? The game will attempt to unduck. If the player is onground, the game will consider the location 18 units above the current player position, and the game will begin player tracing from the current position to 18 units above, taking the player hull size into account (72 units height in this case). If the area 18 units above the player is clear, then the unducking process is considered successful, and the player position will be instantaneously set to 18 units above the ground. This is peculiar behaviour forms the foundation of ducktapping (see Ducktapping).
5.1.1. Duckbug¶
The duckbug is one of the many ways of cancelling fall damage. Duckbug requires a slope, but otherwise works like a combination of jumpbug (see Jumpbug) and edgebug. Similar to the jumpbug, the player must unduck to go from being in the air to onground within a frame, though no jump is required. And similar to the edgebug, the player must be able to exit the onground layer of the slope before the end of the frame by “sliding off” the ground.
Fig. 5.5. Illustration of a player (represented by the bounding box) performing a duckbug. This figure is not drawn to scale. The length of
Referring to Fig. 5.5., the player begins at frame -duck is issued in this frame, the player switches to the standing bounding box. The bottom of the bounding box at PM_UnDuck, and cancelling the vertical velocity. At the end of frame
There is a minimum horizontal speed required to exit the 2 units onground layer. The horizontal displacement in one frame, represented by the length
must be satisfied for duckbug to work at all. Observe that the greater the slope angle
In addition to the horizontal speed, the frame rate must not be too high or too low. This is unlike jumpbug, where higher frame rates are generally better, and unlike edgebug, where lower frame rates are usually preferred. With duckbug, a frame rate too high makes it difficult to exit the 2 units onground layer, because the minimum required horizontal speed would too high. A frame rate too low makes it difficult to unduck onto the ground. In practice, we probably should pick a frame rate that is as high as possible while ensuring the inequality above is met. In most situations, there is not much leeway in altering the horizontal speed prior to a duckbug, therefore the frame rate is the most important control input.
5.1.2. Ducktapping¶
Suppose a player is onground and the duckstate is in-duck or ducked. When the player then unducks, PM_UnDuck will be called. This function will try to move the player origin up by 18 units, and will succeed in doing so provided sufficient space above the player. Suppose the player is in the ducked state. Then this upward displacement makes sense, as one can check that the difference in vertical player position (measured at the centre point of the hull in use) using the ducked and standing hulls when resting on the same ground level is exactly 18 units. If the function did not forcibly displace the player in such a way, the player would be stuck to the ground with 18 units buried below it. Interestingly, the behaviour of PM_UnDuck does not distinguish between in-duck and ducked states, and it does not “notice” that the standing hull is used in the in-duck state. This results in the player incorrectly being displaced 18 units upwards when unducked in the in-duck state, while using the standing hull throughout. This lies the basis for ducktapping, where the player holds the duck key to get into the in-duck state from the standing state, and then releasing the duck key while the player is still in the in-duck state, preferably as soon as possible. The player will be teleported to 18 units in the air, and air movement physics will take over.
Ducktapping is an alternative to jumping in minimising or eliminating the effect of ground friction (see Ground friction) on the player’s horizontal speed. Ducktapping is especially critical in the presence of the bunnyhop cap (see Bunnyhop cap). Nonetheless, even without the bunnyhop cap, ducktapping can be useful in altering the player vertical position some time later to a more desirable location. For example, a tight vent may be hard to get in by a series of pure jumps because the player may not be in the right vertical position at the mouth of the vent. By doing ducktaps in place of jumping at appropriate points, however, the player vertical position may be manipulated to level with the vent, making entrance much easier. The downside of ducktapping, at least in its standard form, is that there is always one frame where the player is onground, and therefore subjected to ground friction. This may be eliminated in newer Half-Life engines by setting the frame rate to a very high value on landing, thereby causing the player frame rate (see Frame rate) to be zero, or
When ducktapping, the vertical velocity remains unchanged and is usually zero, since the player needs to be on the ground in the prior frame which would set the vertical velocity to zero. Therefore, the time it takes for the player to fall back onto the ground by entering the 2 units onground layer can be found by solving
or
Assuming the entity gravity is 1 and the value of sv_gravity is 800, then we have
5.2. Jumping¶
When the jump bit is set by issuing the +jump command and the player is onground, the player will jump. To be precise, the act of jumping refers to setting the vertical velocity to
The unsimplified expression
The time it takes for the player to fall back onto the ground by entering the 2 units onground layer can be found by solving
or
Assuming the entity gravity is 1 and the value of sv_gravity is 800, then we have
The physics for jumping under water has been described in Sharking.
5.2.1. Bunnyhop cap¶
Denote sv_maxspeed. Keep in mind that it is not always the case that
Consider player velocity vectors in the 3D space,
5.2.2. Jumping up to a slope¶
When there is a sloped plane above the player and the player is able to jump and collide with it, it will result in a respectable horizontal speed boost. This technique works both on the ground and underwater, though the effect is more pronounced and continuous underwater. This technique has been implemented in Half-Life speedruns, especially in the Residue Processing chapter. The horizontal speed tends towards a maximum that depends on the angle of inclination of the plane above. We will consider the underwater case here.
Fig. 5.6. +jump has been issued, but before water movement physics. The height of +jump is issued underwater, as explained in Sharking. Each of
Refer to Fig. 5.6. underwater and ignore water friction for simplicity. Suppose +jump is held down. In the first +jump will cause the vertical velocity to be set to the length of
Observe that
In practice, water inflicts some friction in each frame, causing the actual
The analysis presented here is also roughly applicable to the case of jumping off the ground onto a ceiling. Though, it takes time for the player to land on the ground and make another jump again, so the horizontal acceleration is much lower than that underwater.
5.2.3. Jumpbug¶
Note
TODO: explain what onground, position categorisation means
Fall damage is computed after the player movement functions based on the condition that, within a frame, the player is not onground (i.e. in the air) after the very first position categorisation in PM_PlayerMove and that the player is onground after the final position categorisation in the same function. It is possible for the player position to change momentarily to something else between the two. For example, the player could be in the air before and after, but onground some point in the middle. This is the loophole that allows jumpbug to work.
Fig. 5.7. Illustration of a player (represented by the bounding box) performing a jumpbug. This figure is not drawn to scale.¶
Assuming the player is in the air at the first position categorisation and falling towards the ground. The exact vertical velocity does not matter as long as it is negative or below 180. Observe that there is a position categorisation step at the end of PM_UnDuck, which is only called by PM_Duck when the player attempts to unduck. Suppose the player duck state is ducked in the air, and crucially, would become onground after unducking due to the position categorisation in PM_UnDuck. This condition will be met if the player position (i.e. the position of the centre point of the player’s bounding box) is between 36 to 38 units above the ground when the unducking is done, and the vertical velocity is below 180. [1] If these conditions are met, and if the player now unducks, the player will be considered onground at the end of PM_UnDuck. As a result, the subsequent player physics will be run with that assumption.
As explained in Jumping, a player is allowed to jump only if the player is onground at the moment when PM_Jump is called. Therefore, if the player is onground after PM_UnDuck, the player will be allowed to jump, regardless of what happened before unducking! By jumping, the vertical velocity will be set to the positive value given in Jumping. Since this value is larger than the 180 ups limit for being onground, the final position categorisation (occurs after PM_WalkMove or PM_AirMove) will consider the player to be in the air again. As a result, the game sees the player as being in the air before and after, and thus the fall damage will be completely bypassed.
The criteria for jumpbug is extremely stringent. There is a mere 2 units window for jumpbug to work. Therefore, the frame rate plays a significant role in enabling jumpbug. The higher the frame rate, the smaller the difference between player positions before and after a frame, and therefore more likely to hit the 2 units window. The exact frame rate needed depends on the height and initial falling speed.
5.2.3.1. Effect of bunnyhop cap¶
It is very important to note that, jumpbug may trigger the bunnyhop cap as well (see Bunnyhop cap). In fact, jumpbug is significantly prone to triggering it, because the bunnyhop cap considers the 3D velocity vector and not just in the horizontal directions. For example, suppose the player is moving with velocity PM_Jump returns, the vertical speed is set to that given in Jumping. Notice that, despite the horizontal speed being less than the cap, it is still scaled down due to the very high vertical speed. The conclusion is that jumpbug should be avoided as far as possible when the bunnyhop cap is a significant concern, and alternative methods of avoiding fall damage, such as the edgebug or duckbug (Duckbug) should be used instead.
5.2.4. Duckjump¶
5.3. Fast stair climbing¶
Stairs are not exactly ubiquitous in Half-Life, though they are still fairly common, and mastering how to climb stairs as fast as possible is an essential to every speedrunner. When walking up to a step, the game checks if the step has height less than or equal to sv_stepsize, which has a default value of 18. If this is indeed the case, instead of getting blocked by the step, the player would simply “teleport” up by the step size and continue moving forward as though the step was not there. However, this ability to simply “walk up” to a step does not work when the player is in the air. If the player flies into stairs without jumping or ducking, the motion will be stopped entirely.
Although it has roots in the Counter Strike and Adrenaline Gamer jump maps, quadrazid popularised the trick of ducking and unducking repeatedly to climb stairs in Half-Life. This has been referred to by various names, including duckspamming, duckrolling, ducklooping, and doubleducking. We will call it fast stair climbing for less ambiguity. When the ducking frequency is set to the right value, which may be achieved by the rudimentary method of changing frame rates, the player will magically be able to climb stairs fluently as though the they were a simple slope. Fundamentally, the mechanism that allows this trick to work is ducktapping (see Ducktapping). Ducktapping from step to step is fast because it does not add vertical speed, unlike jumping.
However, there still are restrictions on how fast one could travel horizontally when implementing this trick. When ducktapping from a step, it takes time for gravity to pull the player down and land on the next step. If the horizontal speed is too high, the player might crash into a step further ahead and stopping the horizontal motion as a result. This section is devoted to better understand these speed limits.
5.3.1. Preliminaries¶
Referring to Fig. 5.8. and borrowing architectural terminology, we will define a step to be a riser (vertical wall) of rise height
Fig. 5.8. A schematic drawing of a stair.¶
As described in ducking physics, tapping the duck key causes the player to teleport 18 units upward. However, if we consider the player position at the feet rather than the bounding box centre, and the player ducks in the air, the player effectively teleports 36 units upward. The height of this teleportation may be denoted as
Ducktapping yields a parabolic trajectory if the player also moves forward with nonzero speed
The climbing action roughly refers to how the trajectory emerges that is also dependent on all the variables that define
This change in
- constant action
Δ 𝜙 = 0 - leading action
Δ 𝜙 > 0 - trailing action
Δ 𝜙 < 0 - colliding action
collision with a riser,
is undefinedΔ 𝜙
If leading or trailing action is attainable on some values of
To compute the window sizes, we first note that the player trajectory may be given by the following equation of motion, relative to the edge of the current step:
Denote
To solve these systems, for each
5.3.2. Single-action climbing¶
The simplest climbing strategy may be called the single-action climbing. This refers to stair climbing by the same type of climbing action.
The constant action is the simplest climbing action. It preserves
The constant action, however, does not yield the highest
This, of course, assumes
The trailing action can also be chosen as the sole action for climbing if the speed limit is higher than that of the other actions. Similar to using leading action as the action of choice, the decrease in
The required speed can be computed similarly.
5.3.3. Mixed-action climbing¶
Rather than using the same action throughout the climb, it may be possible to use both leading and trailing actions on different values of
Suppose the
Footnotes