# BurnsCommon > A shared utility library for LSPDFR/RagePluginHook plugins. Provides common functionality so you don't have to rewrite the same code in every plugin. ## Overview BurnsCommon centralizes common systems such as logging, dependency validation, update checking, configuration helpers, audio utilities, and UI components into a single lightweight framework. Instead of every plugin re-implementing the same boilerplate code, developers can rely on BurnsCommon for consistent, reliable behavior. ## Namespaces | Namespace | Class | Purpose | |-----------|-------|---------| | BurnsCommon | BurnsCommonAPI | Version info and initialization | | BurnsCommon.Core | Logger | Consistent log formatting | | BurnsCommon.Core | DependencyChecker | Validate RPH/LSPDFR versions and required files | | BurnsCommon.Core | UpdateChecker | Check for plugin updates from a remote API | | BurnsCommon.Core | ConfigHelper | INI file utilities and value clamping | | BurnsCommon.Core | KeybindManager | Configurable keybinds with modifier keys | | BurnsCommon.Core | NotificationQueue | Rate-limited GTA V notifications | | BurnsCommon.Core | LocalizationManager | Multi-language support for plugins | | BurnsCommon.Helpers | VehicleHelper | Vehicle class, police/emergency checks, spawn utilities | | BurnsCommon.Helpers | PedHelper | Armed checks, relationship groups, ped actions | | BurnsCommon.Helpers | WorldHelper | Nearby entities, safe spawn points, zone/street names | | BurnsCommon.Callouts | CalloutBase | Base class for LSPDFR callouts with auto-cleanup | | BurnsCommon.Audio | AudioHelper | Play WAV/MP3 files asynchronously | | BurnsCommon.UI | Popup | In-game dialog boxes with choices | ## Installation ### For Users 1. Copy BurnsCommon.dll to your GTA V root folder (same location as GTA5.exe) 2. That's it — plugins that need it will automatically use it ### For Plugin Developers 1. In Visual Studio: Right-click your project → Add → Reference 2. Browse to BurnsCommon.dll and click OK ## Getting Started After adding the reference, initialize BurnsCommon in your plugin's Initialize() method: ```csharp using BurnsCommon; using BurnsCommon.Core; public class MyPlugin : Plugin { public override void Initialize() { // Initialize BurnsCommon (logs that your plugin is using it) BurnsCommonAPI.Initialize("MyPlugin"); // Check dependencies before doing anything else if (!DependencyChecker.Check( pluginName: "MyPlugin", minRphVersion: 1.98f, minLspdfrVersion: new Version("0.4.9"))) { // Dependencies not met - the checker already showed an error return; } // Your plugin code here... } } ``` ## Logger Namespace: BurnsCommon.Core The Logger class provides consistent, prefixed log formatting. Create one with your plugin's name and use it throughout your code. ```csharp using BurnsCommon.Core; // Create a logger with your plugin's prefix var log = new Logger("[MyPlugin]"); log.Info("Plugin loaded successfully"); log.Warning("Config value out of range, using default"); log.Error("Failed to load file", exception); ``` Output in RagePluginHook.log: ``` [MyPlugin] Plugin loaded successfully [MyPlugin] [WARN] Config value out of range, using default [MyPlugin] [ERROR] Failed to load file ``` Methods: - Info(message) — Log an informational message - Warning(message) — Log a warning (prefixed with [WARN]) - Error(message, exception?) — Log an error with optional exception details ## Dependency Checker Namespace: BurnsCommon.Core Validates that the required versions of RagePluginHook, LSPDFR, and any required files are present before your plugin runs. Shows the user a clear error notification if something is missing. ```csharp using BurnsCommon.Core; bool success = DependencyChecker.Check( pluginName: "MyPlugin", minBurnsCommonVersion: new Version("1.0.0"), // Optional minRphVersion: 1.98f, // Optional minLspdfrVersion: new Version("0.4.9"), // Optional requiredFiles: new[] { // Optional "Plugins/LSPDFR/MyPlugin.ini", "Plugins/LSPDFR/MyPlugin/sounds/alert.wav" } ); if (!success) { // Error notification already shown to user // Unload your plugin gracefully return; } ``` Methods: - Check(pluginName, minBurnsCommonVersion?, minRphVersion?, minLspdfrVersion?, requiredFiles?) — Validates all dependencies. Returns false if any check fails. Automatically displays error notifications. ## Update Checker Namespace: BurnsCommon.Core Checks a remote API for newer versions of your plugin and notifies the user if an update is available. Runs in the background. ```csharp using BurnsCommon.Core; var updateChecker = new UpdateChecker( pluginName: "MyPlugin", currentVersion: "1.0.0", apiUrl: "https://api.example.com/myplugin/version" ); // Runs in background, shows notification if update available updateChecker.CheckAsync(); ``` The API endpoint should return JSON like: {"version": "1.2.0"} Methods: - UpdateChecker(pluginName, currentVersion, apiUrl) — Create an update checker instance - CheckAsync() — Asynchronously checks for updates and notifies the user ## Config Helper Namespace: BurnsCommon.Core Utilities for reading INI configuration files with automatic value clamping. Prevents invalid config values from crashing your plugin. ```csharp using BurnsCommon.Core; using Rage; string iniPath = ConfigHelper.GetIniPath("MyPlugin"); // Returns: "Plugins/LSPDFR/MyPlugin.ini" var ini = new InitializationFile(iniPath); // Read with automatic clamping int scanRadius = ConfigHelper.ReadInt(ini, "Settings", "ScanRadius", defaultValue: 50, min: 10, max: 200); float volume = ConfigHelper.ReadFloat(ini, "Audio", "Volume", defaultValue: 0.8f, min: 0f, max: 1f); ``` Methods: - GetIniPath(pluginName) — Returns the standard INI path: "Plugins/LSPDFR/{pluginName}.ini" - ReadInt(ini, section, key, defaultValue, min, max) — Reads an integer from INI, clamped between min and max - ReadFloat(ini, section, key, defaultValue, min, max) — Reads a float from INI, clamped between min and max ## Keybind Manager Namespace: BurnsCommon.Core Provides configurable keybinds with modifier key support. Keybinds can be set programmatically or loaded from an INI file so users can customize them. ```csharp using BurnsCommon.Core; using System.Windows.Forms; var keybinds = new KeybindManager("MyPlugin"); // Register keybinds with optional modifiers keybinds.Register("OpenMenu", Keys.F8); keybinds.Register("QuickAction", Keys.E, ModifierKeys.Ctrl); keybinds.Register("ToggleMode", Keys.T, ModifierKeys.Ctrl | ModifierKeys.Shift); // Load from INI file (overrides defaults with user config) var ini = new InitializationFile("Plugins/LSPDFR/MyPlugin.ini"); keybinds.LoadFromIni(ini, section: "Keybinds"); // Check in your main loop if (keybinds.IsPressed("OpenMenu")) { // Key was just pressed this frame } if (keybinds.IsHeld("QuickAction")) { // Key is currently held down } // Get display string for UI string display = keybinds.GetDisplayString("ToggleMode"); Game.DisplayNotification($"Press ~b~{display}~s~ to toggle mode."); ``` INI file format: ```ini [Keybinds] OpenMenu=F8 OpenMenuCtrl=false OpenMenuShift=false OpenMenuAlt=false QuickAction=E QuickActionCtrl=true ``` Methods: - Register(name, key, modifiers?) — Register a keybind with optional modifier keys - LoadFromIni(ini, section) — Load user-customized keybinds from an INI file - IsPressed(name) — Returns true if the key was just pressed this frame - IsHeld(name) — Returns true if the key is currently held down - GetDisplayString(name) — Returns a human-readable string like "Ctrl+Shift+T" ## Notification Queue Namespace: BurnsCommon.Core Rate-limited GTA V notifications that prevent notification spam. Uses the standard GTA V notification system. ```csharp using BurnsCommon.Core; var notify = new NotificationQueue(minIntervalSeconds: 1.5f); // Simple notification notify.Show("~g~Suspect detained."); // With picture/icon (police department style) notify.Enqueue("~b~Dispatch", "~y~Traffic Stop", "Backup is en route.", "web_lossantospolicedept", "web_lossantospolicedept"); // Immediate notification (bypasses queue) notify.ShowImmediate("~b~Dispatch", "~y~Alert", "Officer needs assistance.", "web_lossantospolicedept", "web_lossantospolicedept"); // Clear pending notifications notify.Clear(); ``` Common texture dictionaries: - "web_lossantospolicedept" — Police department logo - "mphud" with "mp_player_ready" — Multiplayer ready icon Methods: - NotificationQueue(minIntervalSeconds) — Create a rate-limited notification queue - Show(message) — Show a simple text notification - Enqueue(title, subtitle, message, txdDict, txdName) — Queue a notification with a picture/icon - ShowImmediate(title, subtitle, message, txdDict, txdName) — Show immediately, bypassing the queue - Clear() — Clear all pending notifications ## Localization Manager Namespace: BurnsCommon.Core Multi-language support for plugins. Register strings with keys, add translations, and the manager handles language selection including auto-detection from the system locale. ```csharp using BurnsCommon.Core; var lang = new LocalizationManager("MyPlugin"); lang.Register("greeting", "Welcome, Officer."); lang.Register("suspect_fled", "The suspect has fled the scene."); lang.Register("backup_eta", "Backup arriving in {0} seconds."); // Add translations lang.AddTranslation("de", "greeting", "Willkommen, Officer."); lang.AddTranslation("es", "greeting", "Bienvenido, Oficial."); // Or load translations from an INI file lang.LoadFromIni("Plugins/LSPDFR/MyPlugin/lang.ini"); // Auto-detect system language lang.AutoDetectLanguage(); // Or set manually lang.CurrentLanguage = "de"; // Use translations Game.DisplayNotification(lang.Get("greeting")); Game.DisplayNotification(lang["suspect_fled"]); // Shorthand Game.DisplayNotification(lang.GetFormatted("backup_eta", 30)); ``` Language INI file format: ```ini [en] greeting=Welcome, Officer. suspect_fled=The suspect has fled the scene. [de] greeting=Willkommen, Officer. [es] greeting=Bienvenido, Oficial. ``` Methods: - Register(key, englishText) — Register a default (English) string - AddTranslation(languageCode, key, text) — Add a translation for a specific language - LoadFromIni(path) — Load all translations from an INI file - AutoDetectLanguage() — Set language based on system locale - Get(key) / this[key] — Get the translated string for the current language - GetFormatted(key, args) — Get a translated string with format arguments - GetAvailableLanguages() — Returns an array of available language codes ## Vehicle Helper Namespace: BurnsCommon.Helpers Utility methods for working with GTA V vehicles: classification, police/emergency checks, occupant queries, and spawn helpers. ```csharp using BurnsCommon.Helpers; VehicleClass vClass = VehicleHelper.GetVehicleClass(vehicle); bool isPolice = VehicleHelper.IsPoliceVehicle(vehicle); bool isEmergency = VehicleHelper.IsEmergencyVehicle(vehicle); bool isBike = VehicleHelper.IsTwoWheeler(vehicle); bool isStolen = VehicleHelper.IsStolen(vehicle); Vehicle playerCar = VehicleHelper.GetPlayerVehicle(); Vehicle[] nearby = VehicleHelper.GetNearbyVehicles( Game.LocalPlayer.Character.Position, 50f); bool hasDriver = VehicleHelper.HasDriver(vehicle); Ped[] occupants = VehicleHelper.GetOccupants(vehicle); VehicleHelper.MakePersistent(vehicle); VehicleHelper.RepairAndClean(vehicle); ``` Methods: - GetVehicleClass(vehicle) — Returns the vehicle class enum - IsPoliceVehicle(vehicle) — Check if the vehicle is a police vehicle - IsEmergencyVehicle(vehicle) — Check if the vehicle is an emergency vehicle - IsTwoWheeler(vehicle) — Check if motorcycle or bicycle - IsStolen(vehicle) — Check if flagged as stolen - GetPlayerVehicle() — Get player's current vehicle (null if on foot) - GetNearbyVehicles(position, radius) — Get all vehicles within radius - HasDriver(vehicle) — Check if vehicle has a driver - GetOccupants(vehicle) — Get all peds in the vehicle - MakePersistent(vehicle) — Prevent despawning - RepairAndClean(vehicle) — Fully repair and clean ## Ped Helper Namespace: BurnsCommon.Helpers Utility methods for working with GTA V peds (characters): weapon checks, status queries, proximity searches, and action commands. ```csharp using BurnsCommon.Helpers; bool armed = PedHelper.IsArmed(suspect); bool hasGun = PedHelper.HasFirearm(suspect); bool isCop = PedHelper.IsCop(ped); bool isDead = PedHelper.IsDead(ped); bool inCar = PedHelper.IsInVehicle(ped); bool wanted = PedHelper.IsWanted(Game.LocalPlayer.Character); Vehicle car = PedHelper.GetVehicle(suspect); Ped[] nearbyPeds = PedHelper.GetNearbyPeds(position, 100f, excludePlayer: true); Ped closest = PedHelper.GetClosestPed(position, maxRadius: 50f); PedHelper.Flee(suspect, Game.LocalPlayer.Character.Position); PedHelper.Surrender(suspect); PedHelper.GiveWeapon(suspect, "WEAPON_PISTOL", ammo: 50, equip: true); PedHelper.MakePersistent(suspect); ``` Methods: - IsArmed(ped) — Check if ped has any weapon - HasFirearm(ped) — Check if ped has a firearm - IsCop(ped) — Check if law enforcement - IsDead(ped) — Check if dead - IsInVehicle(ped) — Check if inside a vehicle - IsWanted(ped) — Check if has wanted level - GetVehicle(ped) — Get current vehicle (null if on foot) - GetNearbyPeds(position, radius, excludePlayer?) — Get peds within radius - GetClosestPed(position, maxRadius) — Get closest ped - Flee(ped, fromPosition) — Make ped run away - Surrender(ped) — Make ped put hands up - GiveWeapon(ped, weaponName, ammo, equip?) — Give weapon with ammo - MakePersistent(ped) — Prevent despawning ## World Helper Namespace: BurnsCommon.Helpers Utility methods for the game world: location info, safe spawn points, terrain checks, distance calculations, and time queries. ```csharp using BurnsCommon.Helpers; Vector3 playerPos = WorldHelper.PlayerPosition; string zone = WorldHelper.GetZoneName(position); string street = WorldHelper.GetStreetName(position); Vector3 safeSpawn = WorldHelper.GetSafeSpawnPoint( playerPos, minDistance: 20f, maxDistance: 50f); Vector3 roadSpawn = WorldHelper.GetRandomRoadPosition(playerPos, radius: 100f); float groundZ = WorldHelper.GetGroundZ(position); bool onRoad = WorldHelper.IsPositionOnRoad(position); bool inWater = WorldHelper.IsPositionInWater(position); float dist = WorldHelper.GetDistance(pos1, pos2); float heading = WorldHelper.GetHeadingTowards(from, to); bool isNight = WorldHelper.IsNightTime(); string gameTime = WorldHelper.GetGameTimeString(); // "14:30" Blip blip = WorldHelper.CreateBlip( position, color: Color.Red, name: "Suspect"); ``` Methods: - PlayerPosition — Get player's current position - GetZoneName(position) — Get zone/area name - GetStreetName(position) — Get street name - GetSafeSpawnPoint(position, minDistance, maxDistance) — Find safe road spawn point - GetRandomRoadPosition(position, radius) — Random road position nearby - GetGroundZ(position) — Get ground height - IsPositionOnRoad(position) — Check if on road - IsPositionInWater(position) — Check if in water - GetDistance(pos1, pos2) — Distance between two positions - GetHeadingTowards(from, to) — Heading angle between positions - IsNightTime() — Check if night in game - GetGameTimeString() — In-game time as "HH:MM" - CreateBlip(position, color, name) — Create named map blip ## Callout Base Namespace: BurnsCommon.Callouts A base class for LSPDFR callouts that provides automatic entity cleanup, error handling, and logging. Inherit from CalloutBase instead of the standard LSPDFR Callout class. ```csharp using BurnsCommon.Callouts; using Rage; using LSPD_First_Response.Mod.Callouts; using System.Drawing; [CalloutInfo("Robbery In Progress", CalloutProbability.Medium)] public class RobberyCallout : CalloutBase { private Ped _suspect; private Vehicle _suspectVehicle; private Blip _suspectBlip; protected override string CalloutName => "Robbery In Progress"; protected override bool Setup() { CalloutPosition = WorldHelper.GetSafeSpawnPoint( WorldHelper.PlayerPosition, 100f, 250f); CalloutMessage = "Robbery In Progress"; return true; } protected override void OnAccepted() { _suspect = SpawnPed("a_m_y_stbla_02", CalloutPosition); _suspectVehicle = SpawnVehicle("sultan", CalloutPosition); _suspectBlip = CreateBlip(_suspect, Color.Red, "Suspect"); PedHelper.GiveWeapon(_suspect, "WEAPON_PISTOL"); ShowDispatch("Reports of a robbery. Suspect is armed."); } protected override void OnProcess() { if (PedHelper.IsDead(_suspect)) { ShowDispatch("Suspect is down. Code 4."); EndCallout(); } } protected override void OnCleanup() { Log.Info("Robbery callout cleaned up"); } } ``` Key benefits: - Auto-cleanup: All entities/blips via SpawnPed(), SpawnVehicle(), CreateBlip() are automatically dismissed when callout ends - Error handling: Exceptions in OnProcess() are caught and logged instead of crashing - Built-in logger: Log.Info(), Log.Warning(), Log.Error() available in every callout - Dispatch helper: ShowDispatch("message") sends formatted police dispatch notification Methods: - CalloutName (override) — Set display name for logs and dispatch - Setup() (override) — Set spawn point and callout message, return true to show - OnAccepted() (override) — Spawn entities and set up scene - OnProcess() (override) — Called every tick while active - OnCleanup() (override) — Optional extra cleanup - SpawnPed(model, position) — Spawn with auto-cleanup - SpawnVehicle(model, position) — Spawn with auto-cleanup - CreateBlip(entity, color, name) — Blip with auto-cleanup - ShowDispatch(message) — Formatted dispatch notification - EndCallout() — End callout and trigger cleanup ## Audio Helper Namespace: BurnsCommon.Audio Play WAV and MP3 audio files asynchronously. ```csharp using BurnsCommon.Audio; AudioHelper.PlayAsync( "Plugins/LSPDFR/MyPlugin/sounds/alert.wav", "[MyPlugin]"); AudioHelper.PlayAsync( "Plugins/LSPDFR/MyPlugin/sounds/music.mp3", "[MyPlugin]"); AudioHelper.StopAll(); ``` Methods: - PlayAsync(filePath, logPrefix) — Play audio file asynchronously - StopAll() — Stop all currently playing audio ## Popup Dialogs Namespace: BurnsCommon.UI In-game dialog boxes with support for messages, yes/no confirmations, and multiple choice. ```csharp using BurnsCommon.UI; // Simple message Popup.Message("Notice", "The suspect has been detained."); // Yes/No confirmation Popup.Confirm("Pursuit", "Call for backup?", onYes: () => Game.LogTrivial("Backup requested"), onNo: () => Game.LogTrivial("Going solo") ); // Multiple choice var popup = new Popup( title: "Select Action", text: "What would you like to do?", answers: new List { "Arrest", "Release", "Question" }, pauseGame: false, callback: p => { switch (p.IndexOfGivenAnswer) { case 0: /* Arrest */ break; case 1: /* Release */ break; case 2: /* Question */ break; } } ); popup.Display(); ``` Methods: - Popup.Message(title, text) — Simple informational dialog - Popup.Confirm(title, text, onYes, onNo) — Yes/no confirmation with callbacks - new Popup(title, text, answers, pauseGame, callback) — Multiple choice dialog - Display() — Show the popup to the player ## Complete Example Plugin ```csharp using System; using Rage; using BurnsCommon; using BurnsCommon.Core; [assembly: Rage.Attributes.Plugin("ExamplePlugin", Description = "Example using BurnsCommon")] public class ExamplePlugin : Plugin { private Logger _log; public override void Initialize() { _log = new Logger("[ExamplePlugin]"); BurnsCommonAPI.Initialize("ExamplePlugin"); if (!DependencyChecker.Check("ExamplePlugin", minRphVersion: 1.98f)) { _log.Error("Dependencies not met, unloading"); return; } new UpdateChecker("ExamplePlugin", "1.0.0", "https://api.example.com/version").CheckAsync(); _log.Info("Plugin loaded successfully"); Game.DisplayNotification("~g~ExamplePlugin~s~ loaded successfully!"); } public override void Finally() { _log.Info("Plugin unloaded"); } } ``` ## Distribution When distributing your plugin: 1. Include BurnsCommon.dll with your plugin download, OR 2. Tell users to install BurnsCommon separately 3. The DependencyChecker will warn users if BurnsCommon is missing or outdated ## Links - Download: https://adamburns.co/mods/burns-common - Documentation: https://adamburns.co/mods/burns-common/docs - All Mods: https://adamburns.co/mods