BUNNYHOPPING
It’s recommended to bind the mouse wheel (either up or down) to jump.
bind mwheeldown +jump
bind mwheelup +jump
Bunnyhop
Bunnyhopping is the name given to multiple jumps done consecutively. If done correctly, you’ll spend most of your time in the air where gaining speed is easier and no friction takes part.
- 1. Start running and jump.
- 2. While in the air, make one or more air-strafes.
- 3. In the exact moment you touch the ground, jump again.
- 4. Repeat
2
and3
. Timing is the key.
Although the step’s sound when bhopping gets chosen randomly, it sounds differently based on how many frames you spent on ground. Step’s sound effect is called twice: when you touch the ground and when you perform a jump. Therefore, if you jump in the same frame you touched the ground the engine will play two sounds in the same frame making only the second one audible because the first one will be overlapped by it. In the other hand, if you spend two or more frames between landing and jumping, the engine will play both sounds with two or more frames interval.
Physics
Before starting, here are a few things you need to know:
- When you perform a jump using mouse wheel it executes both
+jump
and-jump
commands within one frame. - When client sends
+jump
command, engine setsIN_JUMP
bit tocmd->buttons
variable and when client sends-jump
engine removesIN_JUMP
bit. - FOG is abbreviation for ‘frames on ground’.
velocity.z
is a player’s vertical speed.
Unlike HL1 and KZmod where you can roll mouse wheel like a crazy without any
consequences, in order to achieve decent bunnyhop in CS 1.6 you need to do it
with a certain speed. When you scroll jump being on the ground, engine checks
if you already had IN_JUMP
button in previous frame and if so, it won’t allow
you to jump as long as your previous frame has IN_JUMP
button. That’s the
reason why we can’t autobhop just by holding spacebar.
A common scroll distribution looks like:
Groundflag | Command(s) | Comments |
---|---|---|
0 | +jump;-jump | Jump could be done if player were on the ground. |
0 | ||
0 | +jump;-jump | Jump could be done if player were on the ground. |
1 | +jump;-jump | Player just hit the ground but at this point engine does not allow him to jump because he had IN_JUMP in previous frame. |
1 | ||
1 | +jump;-jump | Everything is ok, executing jump code. |
0 | ||
0 | +jump;-jump | Jump could be done if player were on the ground. |
Only because player scrolled too fast, it led him to bhop with 3 FOG which in most cases will ruin your run.
Meanwhile, an ideal scroll distribution looks like:
Groundflag | Command(s) | Comments |
---|---|---|
0 | +jump;-jump | Jump could be done if player were on the ground. |
0 | ||
0 | +jump;-jump | Jump could be done if player were on the ground. |
0 | ||
1 | +jump;-jump | Everything is ok, executing jump code. |
0 | ||
0 | +jump;-jump | Jump could be done if player were on the ground. |
But even with scroll distribution like that we are not safe from failing bhop
because of some factors.
1. PM_PreventMegaBunnyJumping():
After passing all of PM_Jump()
checks there remains only
PM_PreventMegaBunnyJumping()
. This function decides whether to reduce your
XYZ speed or not.
First it calculates maximum speed cap for equipped weapon:
maxscaledspeed = BUNNYJUMP_MAX_SPEED_FACTOR * pmove->maxspeed
If you have Knife or USP in hands, it can be translated to:
maxscaledspeed = 1.2 * 250
Then it checks if our XYZ speed (variable speed
) is more than maxscaledspeed
and if so, it scales our velocity
vector by:
(maxscaledspeed / speed) * 0.8
Some examples:
ex 1.
We have USP in hands,
velocity.x
= 286.132, velocity.y
= -11.622, velocity.z
= 0.0.
maxscaledspeed = 1.2 * 250 = 300.0
speed = squareroot(velocity.x² + velocity.y² + velocity.z²) = 286.367
Since speed < maxscaledspeed
, speed
remains the same.
ex2.
We have Scout in hands,
velocity.x
= -54.337, velocity.y
= 311.328, velocity.z
= 0.0.
maxscaledspeed = 1.2 * 260 = 312.0
speed = squareroot(velocity.x² + velocity.y² + velocity.z²) = 316.034
We now have speed > maxscaledspeed
therefore the whole velocity
vector will
be scaled by:
(maxscaledspeed / speed) * 0.8
We then proceed to calculate final speed
:
velocity.x = -54.337 * 0.789 = -42.914
velocity.y = 311.328 * 0.789 = 245.883
velocity.z = 0.0 * 0.789 = 0.0
speed = squareroot(-42.914² + 245.883² + 0.0²) = 249.599
So, our speed
went from 316.034 to 249.599 after
PM_PreventMegaBunnyJumping()
function call.
Most of you have experienced situations where speed
was cropped even though it
was less than 300.0, there’s an explanation for this. At the point of
PM_PreventMegaBunnyJumping()
call, engine doesn’t know yet that we are on the
ground and apply gravity via PM_AddCorrectGravity()
reducing our velocity.z
in 4.0 as if we were in the air:
ent_gravity * pmove->movevars->gravity * 0.5 * pmove->frametime)
It adds 4.0 back to velocity.z
later though.
So although your XY speed was less than 300.0, your XYZ speed wasn’t. This
means that in examples above our velocity.z
should have been -4.0 instead of
0.0 if we wanted to get accurate results. All in all, in order to prevent
PM_PreventMegaBunnyJumping()
affecting speed
your XY speed should be
roughly ≈299.97 or less when jumping. Just a little less than the 300.0
mentioned everywhere.
2. PM_Friction()
and PM_WalkMove():
As you already could understand, we can still get 2 FOG perfect bhops. On such
occasions, both PM_Friction()
and PM_WalkMove()
will strike.
fuser2
is a jump modificator that slows us down after performing a jump. After this, engine sets its value to 1315.789428 and each frame afterwards decreases it by current ‘msec’ value. If your FPS is 100 then your msec is 10, this means that to completely get rid of slowdown effect you need to wait 1.315 seconds.
PM_Friction()
is a common ground friction function that reduces our speed on
each frame we are on the ground (This does not apply for 1 FOG bhops):
squareroot(velocity.x^2 + velocity.y^2) * 4 * 0.01
PM_WalkMove()
checks if fuser2
value is bigger than 0.0 and if so, both
velocity.x
and velocity.y
will be multiplied by:
(100.0 - pmove->fuser2 * 0.001 * 19.0) * 0.01
As an example. here we have 1 FOG bhop with 300.0 speed and 60.022 speed loss
because of PM_PreventMegaBunnyJumping()
, let’s calculate how much speed in
theory we could save if it was 2 FOG bhop.
Frame | Groundflag | Command(s) | Velocity.x | Velocity.y | Velocity.z | HSpeed |
---|---|---|---|---|---|---|
107 | 1 | +jump;-jump | 300.0 | 0.0 | -4.0 | 300.0 |
108 | 0 | 239.978 | 0.0 | 0.0 | 239.979 |
PM_Friction()
: Using the formula we know it gives us a 12.0 speed loss.
squareroot(300.0^2 + 0.0^2) * 4 * 0.01 = 12.0
PM_WalkMove()
: Let’s say before this jump we had other jump that lasted 67
frames, just a normal non-stand-up bhop. At this point our fuser2
value
is 645.789 (1315.789 - 67 * 10). Now, taking into account that the speed is now
288.0 (300.0 - 12.0) and utilizing the formula, we can also know that
PM_WalkMove()
will make us lose 35.34 speed.
(288 - 288 * 0.877) = 35.34
It sums up to 47.34 speed loss in total. We can clearly say that in a case with ≈300 speed it’s better to have 2 FOG bhop and lose ≈47 speed instead of doing 1 FOG bhop and losing ≈60 speed. Of course, bhops with as low speed loss as possible are known as ideal or perfect bhops.
Stand-up Bunnyhop
Stand-up bunnyhops are done just like regular bhops but performing a stand-up
before jumping.
Doing this kind of bhop means it will take you longer to reach the ground
because now you must fall the crouch distance too. This effectively gives you
more airtime before jumping again, allowing you to avoid some of stamina’s
related slowdown, making your next jump a little higher (and thus further)
than a regular bhop.
- 1. Start running and jump.
- 2. While in air, make one or more air-strafes.
- 3. Duck in air, a few moments before touching the ground.
- 4. Unduck just when you are reaching the ground (less than 18 units left), doing a stand-up.
- 5. In the exact moment you touch the ground, jump again.
- 6. Repeat
2
,3
,4
and5
. Timing is the key.
You could, and should, alternate between stand-up and regular bhops according to
your needs.
Regular ones are faster, while stand-ups gets you a little higher/further.