Recoil Tracker
Records weapon recoils and analyzes player shot accuracy against them
Dependencies


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

  1. Equip the weapon you want to generate a recoil pattern for.
  2. Fully load the magazine. Do not use infiniteammo ConVar if you are an admin.
  3. Crouch and aim before shooting. Do not stand, do not shoot without aiming, and do not crouch without aiming.
  4. Hold down the trigger and fire without controlling the recoil. Let the weapon kick naturally.
  5. Shoot one full magazine. For better accuracy, shoot 2-3 full magazines.
  6. 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)
Starts recoil tracking for a player.
  • player - The player whose recoil should be tracked.
  • mode - Either Recording to capture a new pattern or Matching 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)
Stops a recoil tracking session for the given player.
  • player - The player whose recoil tracking should stop.
  • save - If true, the recorded pattern is saved. If false, the recording is discarded.
C#:
bool API_DoesRecoilPatternExist(string weaponShortName)
Checks if a saved recoil pattern exists for a given weapon.
  • weaponShortName - The short name of the weapon to check.
C#:
JObject API_GetRecoilPattern(string weaponShortName)
Retrieves the stored recoil pattern for a weapon.
  • 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)
Called when a player's shot is compared against a stored recoil pattern.
  • player - The player whose shot was analyzed.
  • matchData - A dictionary containing detailed information about the recoil match.
Breakdown of matchData:
KeyTypeDescription
WeaponShortNamestringThe short name of the weapon being used.
PatternCompletedbooltrue if the player has finished the entire recoil pattern, false otherwise.
CurrentShotIndexintThe index of the current shot in the stored recoil pattern.
CurrentDeviationfloatThe difference between the actual and expected recoil for the current shot.
AccuracyPercentfloatThe player's overall accuracy compared to the stored pattern (100% = perfect match).
ExpectedValuefloatThe expected recoil value for this shot, based on the stored pattern.
ActualValuefloatThe actual recorded recoil value for the player's shot.
IsHitbooltrue 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!");
    }
}
Author
VisEntities
License duration
Unlimited
Price
10.00 USD
First release
Last update

Ratings

0.00 star(s) 0 reviews

Parent plugin

Also by VisEntities

  • Bike Horn
    Bike Horn
    Adds horn functionality to motorbikes, sidecars, and pedal bikes
  • Countdown
    Countdown
    Allows starting timed countdowns with custom messages
  • Wet Guns Go Jam
    Wet Guns Go Jam
    Causes guns to jam when players are too wet
Back
Top
This plugin uses Oxide's permission system. Grant or revoke permissions using oxide.grant and oxide.revoke. You can assign them to individual players or groups using their Steam id or group name.
Chat commands start with a /, while console commands can be entered directly in the F1 console or server console. Use find <keyword> in console to search for available commands related to the plugin.
Settings are stored in the config file found under the config/ directory. You can edit this file manually, then reload the plugin to apply your changes.
Persistent data is saved in the data/ directory. This includes things like saved settings, usage stats, or player progress depending on the plugin. Deleting a data file will reset stored progress or customizations.
Language files are located in the lang/ folder. To translate messages, copy the en.json file into your target language folder (e.g. fr, de) and edit the values. Reload the plugin after changes to apply new messages.
This section lists public methods exposed by the plugin for use in other plugins. You can call these via the CallHook method. Make sure the plugin is loaded before calling its API to avoid null reference errors.
These are custom hooks that other plugins can listen for. Simply define a method with the same name and expected parameters in your plugin to handle the event. Hooks are triggered at key moments and are useful for extending or reacting to plugin behavior.
These hooks are injected into the game's code using Harmony. They let the plugin run code at key points in the game's internal logic. You can return values to block or modify behavior. Use with caution — these are powerful and can affect core mechanics.
Cart