Last server records
Pro Nub

HighJump physics

Posted by Kpoluk 13 May 2023 in 11:30
In the article about strafe physics we were diggind a bit into PM_Friction function which was responsible for the slowdown of a player. Then we considered the friction variable as simply the value of the cvar sv_friction (4 by default). In fact, everything is much more interesting here:


From the point of view of interaction with the map, it can be said that the player is a parallelepiped, which is defined by two points - player_mins and player_maxs. These points defines hull i. e. the "shell" of the player. Two states of hull will be important for us - when the player is standing and when he is sitting (the variable pmove-> usehull is responsible for the state choise). As can be seen from the code, in the horizontal plane the player model is a square of 32 by 32 units, while the height is 72 standing units and 36 units sitting.

When moving on the ground, each frame PM_Friction performs the so-called trace. Trace usually means that the engine draws a line from one point to another to find out if it has crossed something along the way. If there is an intersection, then the trace can tell what kind of object it was on the way, and also at what distance. In our case, the trace is a bit more complicated, since PM_PlayerTrace function takes into account the size of the player in the direction of the trace.

The initial point is 16 units in the direction of the current velocity at the foot level (which is for standing player below its origin position by 36 units, and for a sitting player - by 18 units). The end point is lower than the initial one by 34 units. To this we must add half the height i. e. again, 36 or 18 units.


Consequently, if we run to the edge of the block, then the engine will check if it is not higher than 70 units, and if we move sitting - 52 units. If it is higher, then the friction variable is multiplied by pmove->movevars->edgefriction which is the value of cvar edgefriction. By default, it is 2, so the friction will be twice as strong. If edgefriction 1 is used, any hj will turn into ordinary lj, and if it's 0 than the friction at the edge of the block will completely disappear (so if we release all the buttons, we will simply slide off the block).

Since the trace takes place in 16 units from the player in the direction of his velocity, we would want to keep the velocity vector durings prestrafe as parallel as possible to the edge of the block. Such a technique for performing hj on blocks has been known for a long time, but in practice it is very difficult to perform it. A classic example is the 245 block performed by Risible Ripple (you can download the demo here) who was able to jump the block with a distance of several units less than distance considered as the smallest possible for this block. This was not the first demo using this trick, but since it supposed to be a new world record, it has reverberated through kz community and was even declared illegal. In the end it was accepted, and physics concepts of the game were revised. Now I suggest you to look at the animation, built on the data from this demo. Blue line conventionally denotes the edge of the block, red - the velocity vector, white - the view direction, green - the vector wishdir from the articles about strafe and lj physics. The prestrafe on the ground is marked orange, the strafes in the air are yellow, playback is slowed down 20 times:

GIF 6.07MB

Note that the first strafe takes more frames cause player needs more time to turn his mouse. Here's the same 245 block by max3semne for comparison (you can download it here), done with a regular technique:

GIF 6.18MB

There is also another trick, which is often used on extreme maps. If hj block is in contact with the wall, then during prestrafe you can try to keep the velocity vector directed towards the wall as long as possible. At this time, the end of our 16 units vector will be either above the block or inside the wall (if it is not too thin). In any case, the trace will cross something, and there will be no additional slowdown. Of course, the form of a block or other circumstances may prevent you from using this technique, but it also happens that this is the only way to pass the map.

Next time we'll talk about bhop and a special parameter fuser2, introduced by developers in CS 1.6.