[TF2] Classic Movement
- Important notes
- Demo videos
This Sourcemod plugin brings back movement as it was in Quake or Half Life 1 based games. It feels and behaves almost exactly like the original.
- (Proper) Strafe jumps
- Jumping while being fully crouched
- Double ducking
- Small speedboosts when changing direction
- Whatever movement results by combining any of these above
You can find the AlliedModders thread here.
Download classicmovement.smx or compile it yourself and move it into your
The configuration file is located at
cfg/sourcemod/plugin.classicmovement.cfg. It will be autogenerated when the plugin is loaded for the first time.
The following convars exist:
|classicmovement_version||1.0.0||Contains the plugin version (is a constant and can't be changed).|
|cm_enabled||1||Enable/Disable the plugin.|
|cm_speedo||0||Show speedometer by default.|
|cm_duckjump||1||Allow jumping while being fully crouched.|
|cm_doubleduck||1||Allow double ducking. Might make snipers become unemployed (see here).|
|cm_speedcap||-1||The maximum speed players can reach. -1 for unlimited.|
|cm_use_nice_hud||1||Whether or not to use a prettier speedometer display.|
|cm_hud_color||"255 255 0"||Speedometer HUD color. Whitespace separated red, green, blue values.
Works only if
|cm_allow_autohop||1||Allow users to jump automatically by holding jump. Useful for manual hopping aswell.
See also Jumping.
|cm_frametime||0.009||Frametime (in seconds) to simulate a higher tickrate. 0 to disable. Negative values or values higher than 0.015 have no effect.
See also Interpolation.
|sm_speed [on|off]||Show speedometer|
|sm_autohop [on|off]||Toggle autohop (on/off)|
|sm_fov <number|reset>||Set FOV to a custom value.
Passing "reset" rather than a number will reset the FOV (after respawn).
These settings are stored across sessions.
The default settings aim to replicate the default behaviour from Half Life 1 (and Quake).
For tweaking, only these 3 variables are useful:
Higher values allow sharper turns without losing speed. Default is
CS bhop servers usually use a value of
100it's nearly impossible to lose speed by turning too fast.
The interpolation rate (see here for an explanation). Default is
0.01interpolates (one time) every second frame.
0.0075interpolates (one time) every frame. Higher values than
0.01are pretty much useless. Smaller values than
0.0075will cause multiple interpolation frames per actual frame.
The smaller the frametime the easier it is to gain speed by airstrafing and the less speed you will lose on sharp turns. If you want to achieve the latter, you should rather use
sv_airaccelerate. The default value (
0.009) resembles airstrafing at tickrate 100 (even though tickrate 100 actually has a frametime of
0.01) and should be fine in most cases. If you're unsure, leave it as it is.
If you want to tweak this variable anyway, you'll have to try around a bit to find out what's best for you. Sometimes even small changes make a noticable difference, e.g.
Controls if players are restricted to a certain amount of ducks while in midair (2 afaik). It's enabled by default.
Setting this to
0disables any restrictions.
Plays well with
cm_doubleduckand allows a certain degree of duckrolling. It's also commonly used on jump maps.
Personally, I'm using
cm_tickrate 0.009 and
tf_clamp_airducks 0 on my server.
TF2 servers are locked at a tickrate of 66.66666. For bunnyhopping you need at least 100, though, otherwise it's nearly impossible to properly gain speed. Instead you're mostly losing speed.
This plugins comes with an interpolation algorithm, that simulates higher tickrates by simulating one (or more) movement frame(s) per actual frame. It makes airstrafing way smoother and behave almost exactly like it was in Quake/Half Life. Note that interpolation only happens during airtime. There's no need to interpolate on ground.
Here is a video that compares bunnyhopping with and without interpolation enabled.
The following table shows the game frames of a 66.66666 and 100 tickrate server.
As you see, during 2 frames at a 66.6666 tickrate, the engine processes 3 frames at a 100 tickrate. That means, there is 1 "skipped" frame.
What this plugin does is, it uses an internal frame counter that only increases during airtime by a value depending on the virtual frametime defined by
This way the plugin can detect "skipped" frames and interpolate them by simply subdividing the movement of that frame by 2 (or more) and simulate an extra frame (or more) using that subdivision.
Note that it does not process a whole game frame. It only runs a shorter, replicated version of the engine's movement code to calculate the speed like the engine would have done it.
You can set the virtual frametime using the
It can be calculates like this:
For optimal results, you should use a tickrate greater or equal 100.
For example, for tickrate 100 you would use:
Note that it doesn't feel 100% like a real server at this tickrate. Sometimes you have to tweak the frametime a bit to get closer to the original.
For example, a frametime of
0.009 feels more like tickrate 100 than the actual frametime of
To deactivate this functionality (why would you?) set
Frametimes higher than
0.015 (66.66666) don't make sense because that's the same frametime the server runs at. Doing this anyway or setting a negative frametime will disable interpolation.
TF2 has a ground speedcap at 520 that can't be modified. No matter what speed you have, as soon as you land on ground, your speed will be capped to 520.
To avoid this, the plugin remembers your previous speed and simulates friction for each frame you're on the ground. As soon as you jump it will reset your speed to the calculated value. This effectively bypasses the 520-speedcap and allows proper mousewheel hopping above speeds of 520.
Double ducking & Duckspam
Double ducking works as expected, but could be exploited to annoy the hell out of snipers by spamming
+duck while walking. This will make you twitch over the ground making it way harder to headshot you.
If you are a server owner, you should be aware of this and decide if you really want to have double ducking enabled.
Double ducking can be disabled using
Tickrate issues (& solutions)
TF2 servers are locked at a tickrate of 66.66666 FPS. This is ok for normal gameplay, but awful for everything else.
Wallstrafing depends on acceleration and friction, which in turn depend on the tickrate. For example, at tickrate
100 you can gain speed up to
489 with a base speed of
320 (Spy). With tickrate
66.66666, you can only get a maximum of
There is no workaround for this. It's also not that important, as it's not a game breaker.
Airstrafing with 66 FPS is awful because the frame intervals are too big to properly gain speed. You have to turn very slowly, otherwise you're mostly losing speed. This is what makes existing bunnyhop plugins feel "not right".
This plugin has an interpolation mechanism to simulate higher tickrates, which makes airstrafing way smoother.
See here for an explanation of how it works and how to use it.
The default settings try to replicate a tickrate 100 server.
The engine interprets jump key input (
+jump) only as jump if there was no jump input in the frame before. This prevents autohopping (jumping by holding down the jump key).
That means, when spamming
+jump commands (which you usually do when using the mouse wheel to jump) they will count only as jump if there's at least 1 frame in between without a jump command. Otherwise the engine will simply ignore these commands, as it's interpreted as "holding jump".
On a tickrate >=100 server it's almost guaranteed that there are no more than 2 consecutive
+jump-frames. On a tickrate 66 server though, it's very likely that you get 3-5 in a row.
This makes manual hopping in TF2 annoying as hell, because your jumps get regularily "eaten up" and you loose a lot of speed.
Cells containing a
+ symbolize a frame with jump input, cells with a
As you see, at the 66 tickrate, all jump commands are right behind each other, and the engine will only count the first one as actual jump. If you're still in the air at that point, you'll obviously not jump.
Let's say you hit the ground in the next frame. Even though there's a jump command, it gets ignored because there was already one in the last frame and the engine interprets it as "holding jump key". That means, you are at the ground for at least 3 frames, which makes you loose a ton of speed.
In comparison, at tickrate 100 there's always a frame in between without
+jump. That means your ground time is at most 1 frame.
Keep in mind that this is only an example that demonstrates the problem. The actual results depend on your mouse, how much you scroll and of course timing.
If you want to hop by holding down the jump key, that's already your solution. Simply enable autohopping.
If you want to hop using the mouse wheel, keep autohopping enabled and use the mouse wheel rather than holding down jump. This will not make you do frame perfect jumps, but still treats consecutive
+jumps as actual jumps. It almost feels like hopping at tickrate 100 (or higher).
Autohopping can be activated by setting the
cm_allow_autohop variable to
1. It is already enabled by default.
Duckspam/Duckroll suffers from the same problem as explained in the Jumping section. It works to a certain degree, but obviously not as good as you would expect it from a tickrate 100 server.
Unlike autohopping, there's no "duckroll key" that automatically interprets consecutive
+ducks as double ducking.
There's no workaround for this. Setting
0 makes it better though (see also Tweaking).
There's also no real usage for this kind of movement in TF2, so it shouldn't be that much of a problem. One use case would be to get up stairs/slopes without loosing speed, but this only works with very high framerates anyway.
The following videos demonstrate the features of this plugin in comparison to the original Half-Life.
- (Maybe) Reuse
+useas Duckroll/Duckspam key
- Jump Pads might not set speed for some reason
- FOV might get reset by other stuff (until respawn or re-entering !fov command)