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


This Rust plugin provides an API for recording and storing weapon recoil patterns, allowing other plugins—like Gamemode Aim Train or anti-cheat plugins such as Anti No Recoil—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.

Generating Recoil Patterns

  1. Equip the weapon you want to record.
  2. Load a full magazine. Do not use infiniteammo, even if you're an admin.
  3. Crouch and aim before shooting. Do not stand, hip-fire, or crouch without aiming.
  4. Hold down the trigger and let the weapon fire naturally. Do not move your mouse or control the recoil.
  5. Shoot at least one full magazine. For best results, fire 2–3 full mags in a row.
  6. When done, run the command:
    /rt.record save
    This saves the pattern to oxide/data/Recoils using the weapon's short 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
9.99 USD
First release
Last update

Ratings

0.00 star(s) 0 reviews

Child plugins

  • Anti No Recoil
    Anti No Recoil
    Analyzes player spray patterns and flags unusually accurate recoil control

Also by VisEntities

Back
Top
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. Parameters in < > are required, while [ ] are optional.
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.
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. Ensure 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