- Dependencies
- Gamemode Aim Train (Required)
This plugin provides an API for recording and storing weapon recoil patterns, allowing other plugins—like Gamemode Aim Train or anti-cheat plugins—to analyze player shots and determine how accurately they follow a weapon's expected recoil. It doesn't do anything on its own but serves as a foundation for tracking recoil mechanics, assisting with aim training, or detecting unnatural shot patterns.
Permissions
recoiltracker.record
- Allows a player to start, stop, and save recoil recordings.
Commands
rt.record start
- Starts recording a player’s recoil pattern.rt.record save
- Saves the recorded recoil pattern for future use.rt.record cancel
- Cancels an active recoil recording without saving.
Quick Start
- Equip the weapon you want to generate a recoil pattern for.
- Fully load the magazine. Do not use
infiniteammo
ConVar if you are an admin. - Crouch and aim before shooting. Do not stand, do not shoot without aiming, and do not crouch without aiming.
- Hold down the trigger and fire without controlling the recoil. Let the weapon kick naturally.
- Shoot one full magazine. For better accuracy, shoot 2-3 full magazines.
- Run the save command to store the recoil pattern. It will be saved in the data folder with the weapon's name.
Stored Data
JSON:
{
"RecoilPatterns": {
"rifle.ak": {
"Weapon": "rifle.ak",
"Attachments": ["weapon.mod.silencer", "weapon.mod.lasersight"],
"RecoilPoints": [0, -5, -10, -15, -20, -25, -30]
},
"smg.mp5": {
"Weapon": "smg.mp5",
"Attachments": [],
"RecoilPoints": [0, -2, -4, -6, -8, -10, -12]
}
}
}
Localization
JSON:
{
"Usage": "Usage:\nrt.record start - Begin recording recoil pattern\nrt.record save - Save current recording\nrt.record cancel - Discard current recording",
"NoPermission": "You do not have permission to use this command.",
"UsageStart": "Usage: rt.record start",
"UsageSave": "Usage: rt.record save",
"UsageCancel": "Usage: rt.record cancel",
"AlreadyRecording": "You already have an active recording!",
"RecordStarted": "Recoil recording started. Perform your shots to record the pattern.",
"NoActiveToSave": "No active recording to save!",
"RecordSaved": "Recoil pattern successfully saved!",
"NoActiveToCancel": "No active recording to cancel!",
"RecordCancelled": "Active recording cancelled.",
"UnknownSubcommand": "Unknown subcommand '{0}'. Valid commands: start, save, cancel"
}
Developer API
C#:
void API_StartRecoilTracking(BasePlayer player, string mode, float tolerance = 5f)
player
- The player whose recoil should be tracked.mode
- EitherRecording
to capture a new pattern orMatching
to compare the player's shots to an existing pattern.tolerance
- The maximum allowed deviation when checking if a shot follows a recorded pattern.
C#:
void API_StopRecoilTracking(BasePlayer player, bool save)
player
- The player whose recoil tracking should stop.save
- Iftrue
, the recorded pattern is saved. Iffalse
, the recording is discarded.
C#:
bool API_DoesRecoilPatternExist(string weaponShortName)
weaponShortName
- The short name of the weapon to check.
C#:
JObject API_GetRecoilPattern(string weaponShortName)
weaponShortName
- The short name of the weapon whose pattern should be retrieved.- The returned JObject contains:
Weapon
(string) - The weapon name.Attachments
(List<string>) - Any attachments present when the pattern was recorded.Recoil Points
(List<float>) - A list of recorded recoil values.
Developer Hooks
C#:
void OnRecoilMatchResult(BasePlayer player, Dictionary<string, object> matchData)
player
- The player whose shot was analyzed.matchData
- A dictionary containing detailed information about the recoil match.
matchData
:Key | Type | Description |
---|---|---|
WeaponShortName | string | The short name of the weapon being used. |
PatternCompleted | bool | true if the player has finished the entire recoil pattern, false otherwise. |
CurrentShotIndex | int | The index of the current shot in the stored recoil pattern. |
CurrentDeviation | float | The difference between the actual and expected recoil for the current shot. |
AccuracyPercent | float | The player's overall accuracy compared to the stored pattern (100% = perfect match). |
ExpectedValue | float | The expected recoil value for this shot, based on the stored pattern. |
ActualValue | float | The actual recorded recoil value for the player's shot. |
IsHit | bool | true if the shot was within the allowed tolerance, false if it deviated too much. |
Example usage in plugins:
C#:
void OnRecoilMatchResult(BasePlayer player, Dictionary<string, object> matchData)
{
string weapon = matchData["WeaponShortName"].ToString();
float accuracy = Convert.ToSingle(matchData["AccuracyPercent"]);
bool isHit = Convert.ToBoolean(matchData["IsHit"]);
Puts($"{player.displayName} fired a {weapon}. Accuracy: {accuracy}% - Hit: {isHit}");
// If accuracy drops below 50%, warn the player
if (accuracy < 50f)
{
SendReply(player, "Your recoil control needs improvement!");
}
}