Recoil Can Be Controlled, But It's Hard
CSGO weapons follow mostly deterministic recoil patterns known as spray patterns. Consecutive bullets fired without releasing the trigger (known as a spray) will always follow this pattern as long as the shooter isn't moving (excluding a small amount of normally distributed randomness). The first spray in the video on the right shows the AK-47's spray pattern: up and then alternating between left and right. Each weapon in CSGO has its own spray pattern, as documented here.
Learning these spray patterns is a key skill in training an export CSGO human or bot. Spray control enables players to quickly land consecutive shots without releasing the trigger and waiting for recoil to dissipate. However, learning spray patterns requires a lot of memorization, since the game's main visual recoil indicator (the crosshair) doesn't match the actual recoil. The first spray in the video on the right shows that the crosshair partially follows the bullets' actual recoil pattern, moving up and side-to-side less than the actual bullet holes.
The relationship between actual and visual recoil patterns is:
- visual_recoil = mViewPunchAngle + mAimPunchAngle * weapon_recoil_scale * view_recoil_tracking
- actual_recoil = mAimPunchAngle * weapon_recoil_scale
The values in the above formulas are:
- mAimPunchAngle - A 2D vector computed by the game engine each frame indicating the raw recoil in yaw and pitch based on the number of bullets fired and the time between each bullet. (Technically it's a 3D vector, but the third component is always 0.)
- weapon_recoil_scale - A scalar constant set by the server each game to tune the amount of recoil. The standard value is 2.0.
- view_recoil_tracking - A scalar constant set by the server each game to tune the impact of actual recoil on visual recoil. The standard value is 0.45.
- mViewPunchAngle - A 2D vector computed by the game engine each frame adding additional, visual-only recoil. (Technically it's a 3D vector, but the third component is always 0.) Others claim that Valve added this extra recoil to provide immediate visual feedback when shooting, since there isn't a lot of actual recoil when firing the first few bullets for some guns.
I've confirmed that this relationship is correct using both prior work and experimental evidence. Others analyzing visual and actual recoil derived the same relationship as I did. The second spray in the above video provides experimental evidence for the relationship. I wrote a SourceMod plugin that removes visual recoil by subtracting mViewPunchAim + mAimPunchAngle * weapon_recoil_scale * view_recoil_tracking from the player's current crosshair position vector. Since I successfully removed visual recoil (the crosshair is still during the video's second spray), my understanding of the relationship is correct. Please note, this plugin requires disabling client-side prediction with cl_predict 0. Otherwise, the server-side SourceMod plugin will remove visual recoil but the client-side prediction will still apply some visual recoil while waiting for the server's commands.
Other Helpful Notes For Bot Designers
A player may also experience visual and actual recoil due to being shot without armor. This effect isn't part of a weapon's spray pattern. However, the same relationship between visual and actual recoil holds as the engine still implements the recoil using mAimPunchAngle and mViewPunchAngle.
Players always attempt to move at 450 units / second in any direction that they are currently holding the key for (like W, A, S, or D). The engine determines the actual velocity by running the physics simulation.
Request For Feedback
If you have questions or comments about this analysis, please email me at firstname.lastname@example.org.