### Check CDF Plugin Readiness with CDFFunctions.IsPluginReady() Source: https://context7.com/policing-redefined/commondataframework/llms.txt Consuming plugins should wait for CDF to fully initialize and load its settings and postal codes before making any CDF calls that depend on configuration values. This example demonstrates waiting up to 30 seconds for CDF to become ready. ```csharp using CommonDataFramework.API; using LSPD_First_Response.Mod.API; using Rage; public class MyPlugin : Plugin { public override void Initialize() { LSPDFRFunctions.OnOnDutyStateChanged += OnDutyChanged; } public override void Finally() { } private static void OnDutyChanged(bool onDuty) { if (!onDuty) return; GameFiber.StartNew(() => { // Wait up to 30 seconds for CDF to finish loading its settings and postal codes. bool ready = GameFiber.WaitUntil(CDFFunctions.IsPluginReady, 30000); if (!ready) { Game.LogTrivial("[MyPlugin] CDF did not become ready in time. Falling back to defaults."); return; } Game.LogTrivial("[MyPlugin] CDF is ready. Proceeding with startup."); // ... rest of startup logic }); } } ``` -------------------------------- ### Retrieve or Create Ped Data with PedDataController.GetPedData() Source: https://context7.com/policing-redefined/commondataframework/llms.txt This extension method on Rage.Ped retrieves an existing PedData record or creates a new one if none exists. It returns null for non-human or non-existent peds without a cached record. The example shows how to access and modify ped data, including citations and license status. ```csharp using CommonDataFramework.Modules.PedDatabase; using CommonDataFramework.Modules; using Rage; [ConsoleCommand] private static void Command_CheckNearestPed() { Ped[] nearby = Game.LocalPlayer.Character.GetNearbyPeds(1); if (nearby.Length == 0) { Game.LogTrivial("No nearby ped found."); return; } PedData data = nearby[0].GetPedData(); if (data == null) { Game.LogTrivial("Could not retrieve ped data (non-human or non-existent ped)."); return; } Game.LogTrivial($"Name : {data.FullName}"); Game.LogTrivial($"DOB : {data.Birthday:MM/dd/yyyy} ({data.ToNameAndDOBString()})"); Game.LogTrivial($"Gender : {data.Gender}"); Game.LogTrivial($"Wanted : {data.Wanted}"); Game.LogTrivial($"Parole : {data.IsOnParole} | Probation: {data.IsOnProbation}"); Game.LogTrivial($"Citations : {data.Citations} | Times Stopped: {data.TimesStopped}"); Game.LogTrivial($"Address : {data.Address}"); // e.g. "1047 Grove Street" // Driver's license Game.LogTrivial($"DL State : {data.DriversLicenseState}"); if (data.DriversLicenseExpiration.HasValue) Game.LogTrivial($"DL Expiry : {data.DriversLicenseExpiration.Value:MM/dd/yyyy}"); // Modify the ped — changes sync back via LSPDFR Persona data.Citations += 1; data.DriversLicenseState = ELicenseState.Suspended; // DriversLicenseExpiration is automatically updated to a past date } ``` -------------------------------- ### Initialize and Handle OnDuty State Source: https://github.com/policing-redefined/commondataframework/blob/main/README.md This snippet shows how to initialize the CDF plugin and subscribe to the OnDuty state changes. It includes a crucial wait for CDF to be ready before accessing its features. ```cs using CommonDataFramework.API; using CommonDataFramework.Modules; using CommonDataFramework.Modules.PedDatabase; using CommonDataFramework.Modules.VehicleDatabase; using LSPD_First_Response.Mod.API; using Rage; using Rage.Attributes; public class EntryPoint : Plugin { internal static bool OnDutyState; public override void Initialize() { LSPDFRFunctions.OnOnDutyStateChanged += OnOnDutyStateChanged; Game.AddConsoleCommands(); } public override void Finally() { LSPDFRFunctions.OnOnDutyStateChanged -= OnOnDutyStateChanged; } // Example of getting ped data: [ConsoleCommand] internal static void Command_LogClosestPed(bool changeHuntingPermit) { Ped[] peds = Game.LocalPlayer.Character.GetNearbyPeds(1); if (peds.Length == 0) { Game.LogTrivial("Could not find any nearby ped."); return; } Ped ped = peds[0]; PedData pedData = ped.GetPedData(); Game.LogTrivial($"Ped name: {pedData.FullName}."); // Example of giving the ped a hunting permit: if (changeHuntingPermit && pedData.HuntingPermit.Status != EDocumentStatus.Valid) { pedData.HuntingPermit.Status = EDocumentStatus.Valid; Game.LogTrivial($"Hunting permit expiration: {pedData.HuntingPermit.ExpirationDate:MM/dd/yyyy}"); } } // Example of getting vehicle data: [ConsoleCommand] internal static void Command_LogClosestVehicle(bool changeRegistration) { Vehicle[] vehicles = Game.LocalPlayer.Character.GetNearbyVehicles(1); if (vehicles.Length == 0) { Game.LogTrivial("Could not find any nearby vehicle."); return; } Vehicle vehicle = vehicles[0]; VehicleData vehicleData = vehicle.GetVehicleData(); Game.LogTrivial($"Vehicle VIN: {vehicleData.Vin}."); Game.LogTrivial($"Vehicle Owner: {vehicleData.Owner.FullName} (Type: {vehicleData.OwnerType})."); // .Owner -> PedData // Example of setting a vehicle's registration as expired: if (changeRegistration && vehicleData.Registration.Status != EDocumentStatus.Expired) { vehicleData.Registration.Status = EDocumentStatus.Expired; Game.LogTrivial($"Vehicle registration expired on: {vehicleData.Registration.ExpirationDate:MM/dd/yyyy}"); } } private static void OnOnDutyStateChanged(bool onDuty) { OnDutyState = onDuty; // CDF might take some time until it fully read the users .xml and .ini file on startup. // This means that if you try to access CDF stuff before it was marked as ready, it will have to fall back to default values. // One way of solving this: GameFiber.WaitUntil(CDFFunctions.IsPluginReady, 30000); // The fiber will wait until CDF loaded fully. // ...rest of your startup code that includes CDF usage. // Alternatively, if you don't care about the default values or you are not using CDF right on startup, you can simply skip this. } } ``` -------------------------------- ### CDFFunctions.IsPluginReady() Source: https://context7.com/policing-redefined/commondataframework/llms.txt Checks if the Common Data Framework (CDF) has fully initialized, including loading its settings and postal codes. Consuming plugins should wait for this to return true before making any CDF calls that depend on configuration values, as initialization involves asynchronous file loading. ```APIDOC ## CDFFunctions.IsPluginReady() ### Description Checks whether CDF has fully initialized and its settings and postal codes are loaded. Consuming plugins should wait for this to return `true` before making any CDF calls that depend on configuration values. ### Usage Example ```csharp // Wait up to 30 seconds for CDF to finish loading its settings and postal codes. bool ready = GameFiber.WaitUntil(CDFFunctions.IsPluginReady, 30000); if (!ready) { Game.LogTrivial("[MyPlugin] CDF did not become ready in time. Falling back to defaults."); return; } Game.LogTrivial("[MyPlugin] CDF is ready. Proceeding with startup."); // ... rest of startup logic ``` ``` -------------------------------- ### Check and Modify Ped Permits Source: https://context7.com/policing-redefined/commondataframework/llms.txt Demonstrates how to check the status and expiration dates of a ped's hunting, fishing, and weapon permits. Shows how to manually grant a valid hunting permit and revoke a fishing permit, with automatic expiration date updates. ```csharp using CommonDataFramework.Modules.PedDatabase; using CommonDataFramework.Modules; using Rage; [ConsoleCommand] private static void Command_CheckPermits() { Ped[] nearby = Game.LocalPlayer.Character.GetNearbyPeds(1); if (nearby.Length == 0) return; PedData data = nearby[0].GetPedData(); if (data == null) return; // --- Hunting Permit --- Game.LogTrivial($"Hunting Permit : {data.HuntingPermit.Status}"); if (data.HuntingPermit.ExpirationDate.HasValue) Game.LogTrivial($" Expires : {data.HuntingPermit.ExpirationDate.Value:MM/dd/yyyy}"); // --- Fishing Permit --- Game.LogTrivial($"Fishing Permit : {data.FishingPermit.Status}"); // --- Weapon Permit --- Game.LogTrivial($"Weapon Permit : {data.WeaponPermit.Status} (Type: {data.WeaponPermit.PermitType})"); // PermitType is either EWeaponPermitType.CcwPermit or EWeaponPermitType.FflPermit // Manually grant a valid hunting permit; ExpirationDate auto-set ~4 years from now if (data.HuntingPermit.Status != EDocumentStatus.Valid) { data.HuntingPermit.Status = EDocumentStatus.Valid; Game.LogTrivial($"Granted hunting permit. New expiry: {data.HuntingPermit.ExpirationDate.Value:MM/dd/yyyy}"); } // Revoke fishing permit data.FishingPermit.Status = EDocumentStatus.Revoked; Game.LogTrivial($"Fishing permit revoked. Expired: {data.FishingPermit.ExpirationDate.Value:MM/dd/yyyy}"); } ``` -------------------------------- ### Retrieve and Log Vehicle Data Source: https://context7.com/policing-redefined/commondataframework/llms.txt Retrieves data for the nearest vehicle and logs its details. It also demonstrates how to modify the registration status. ```csharp using CommonDataFramework.Modules.VehicleDatabase; using CommonDataFramework.Modules; using Rage; [ConsoleCommand] private static void Command_CheckNearestVehicle() { Vehicle[] nearby = Game.LocalPlayer.Character.GetNearbyVehicles(1); if (nearby.Length == 0) { Game.LogTrivial("No nearby vehicle found."); return; } VehicleData data = nearby[0].GetVehicleData(); if (data == null) { Game.LogTrivial("Could not retrieve vehicle data."); return; } Game.LogTrivial($"Make : {data.Make} | Model: {data.Model}"); Game.LogTrivial($"Color : {data.PrimaryColor} / {data.SecondaryColor}"); Game.LogTrivial($"Color (GTA) : {data.PrimaryColorSpecific} / {data.SecondaryColorSpecific}"); Game.LogTrivial($"Stolen : {data.IsStolen}"); Game.LogTrivial($"VIN : {data.Vin.Number} (Status: {data.Vin.Status})"); Game.LogTrivial($"Registration : {data.Registration.Status} Expires: {data.Registration.ExpirationDate:MM/dd/yyyy}"); Game.LogTrivial($"Insurance : {data.Insurance.Status} Expires: {data.Insurance.ExpirationDate:MM/dd/yyyy}"); Game.LogTrivial($"Owner : {data.Owner.FullName} (Type: {data.OwnerType})"); Game.LogTrivial($"Owner HasPed : {data.Owner.HasRealPed}"); // Mark the vehicle's registration as expired data.Registration.Status = EDocumentStatus.Expired; Game.LogTrivial($"Registration set to Expired. New expiry: {data.Registration.ExpirationDate.Value:MM/dd/yyyy}"); } ``` -------------------------------- ### Configure CDF Vehicle and Ped Probabilities with Settings.ini Source: https://context7.com/policing-redefined/commondataframework/llms.txt This INI file allows end-users to configure weighted probabilities for various vehicle and ped attributes used by the Common Data Framework. Values are integers representing relative weights and should be adjusted according to the specified sums (e.g., registration/insurance/VIN groups should sum to 100). ```ini ; CommonDataFramework/Settings.ini [Vehicle] ; Probability (0-100) that a newly queried vehicle is already stolen VehicleStolenChance=8 ; Registration status weights (should sum to 100) VehicleRegValidChance=65 VehicleRegExpiredChance=20 VehicleRegRevokedChance=5 VehicleUnregisteredChance=10 ; Insurance status weights (should sum to 100) VehicleInsValidChance=55 VehicleInsExpiredChance=25 VehicleInsRevokedChance=5 VehicleUninsuredChance=15 ; VIN status weights (should sum to 100) VehicleVinValidChance=90 VehicleVinScratchedChance=10 ; Vehicle owner type weights (should sum to 100) VehicleOwnerDriver=30 VehicleOwnerPassenger=25 VehicleOwnerFamily=25 VehicleOwnerRandom=20 [Ped] ; Probability (0-100) for a ped to be on probation PedProbationChance=25 ; Probability (0-100) for a ped NOT on probation to also be on parole PedParoleChance=30 [Postals] ; Name of the postal code XML set to load (filename without extension) ; Leave empty to auto-select the first available set PostalsSet= ``` -------------------------------- ### Display and Update Ped Address Source: https://context7.com/policing-redefined/commondataframework/llms.txt Shows how to retrieve and display a ped's address details, including postal number, street name, zone, and world position. Demonstrates updating the ped's address to the player's current position. ```csharp using CommonDataFramework.Modules.PedDatabase; using CommonDataFramework.Modules.PedResidence; using CommonDataFramework.Modules.Postals; using Rage; [ConsoleCommand] private static void Command_ShowPedAddress() { Ped[] nearby = Game.LocalPlayer.Character.GetNearbyPeds(1); if (nearby.Length == 0) return; PedData data = nearby[0].GetPedData(); if (data == null) return; PedAddress addr = data.Address; Game.LogTrivial($"Full Address : {addr}"); // e.g. "1047 Grove Street" Game.LogTrivial($"Postal Number : {addr.AddressPostal.Number}"); Game.LogTrivial($"Street : {addr.StreetName}"); Game.LogTrivial($"Zone : {addr.Zone?.RealAreaName}"); Game.LogTrivial($"Position : {addr.Position}"); // Override address to a specific world position data.Address = new PedAddress(Game.LocalPlayer.Character.Position); Game.LogTrivial($"Address updated to player position: {data.Address}"); } ``` -------------------------------- ### Issue and Manage Vehicle BOLO Source: https://context7.com/policing-redefined/commondataframework/llms.txt Demonstrates how to issue a BOLO for a vehicle, check its active status, and manually deactivate or remove it. Ensure the `VehicleBOLO` class and related methods are available in your project. ```csharp using System; using CommonDataFramework.Modules.VehicleDatabase; using Rage; [ConsoleCommand] private static void Command_IssueBOLO() { Vehicle[] nearby = Game.LocalPlayer.Character.GetNearbyVehicles(1); if (nearby.Length == 0) return; VehicleData data = nearby[0].GetVehicleData(); if (data == null) return; // Issue a BOLO valid for the next 24 hours VehicleBOLO bolo = new VehicleBOLO( reason: "Suspect vehicle — armed robbery", issued: DateTime.Now, expires: DateTime.Now.AddHours(24), issuedBy: "LSPD Dispatch" ); data.AddBOLO(bolo); Game.LogTrivial($"BOLO issued. Active: {bolo.IsActive} | Expires: {bolo.Expires:g}"); Game.LogTrivial($"Vehicle has BOLOs: {data.HasAnyBOLOs}"); // Enumerate all active BOLOs foreach (VehicleBOLO b in data.GetAllBOLOs()) { Game.LogTrivial($" [{(b.IsActive ? "ACTIVE" : "INACTIVE")}] {b.Reason} by {b.IssuedBy} until {b.Expires:g}"); } // Deactivate the BOLO manually bolo.SetIsActive(false); Game.LogTrivial($"BOLO manually deactivated. Active: {bolo.IsActive}"); // Remove from vehicle data.RemoveBOLO(bolo); Game.LogTrivial($"Vehicle has BOLOs after removal: {data.HasAnyBOLOs}"); } ``` -------------------------------- ### VehicleBOLO Management Source: https://context7.com/policing-redefined/commondataframework/llms.txt Demonstrates how to issue, manage, and remove a Be-On-the-Lookout (BOLO) entry for a vehicle. This includes adding a BOLO with specific details, checking its active status, and removing it. ```APIDOC ## `VehicleBOLO` A Be-On-the-Lookout entry that can be attached to any `VehicleData`. A BOLO has a reason, issuing agency, start/end datetime, and an active flag. `IsActive` returns `true` only when the BOLO is within its valid date range and has not been manually deactivated. ### Usage Example ```csharp using System; using CommonDataFramework.Modules.VehicleDatabase; using Rage; [ConsoleCommand] private static void Command_IssueBOLO() { Vehicle[] nearby = Game.LocalPlayer.Character.GetNearbyVehicles(1); if (nearby.Length == 0) return; VehicleData data = nearby[0].GetVehicleData(); if (data == null) return; // Issue a BOLO valid for the next 24 hours VehicleBOLO bolo = new VehicleBOLO( reason: "Suspect vehicle — armed robbery", issued: DateTime.Now, expires: DateTime.Now.AddHours(24), issuedBy: "LSPD Dispatch" ); data.AddBOLO(bolo); Game.LogTrivial($"BOLO issued. Active: {bolo.IsActive} | Expires: {bolo.Expires:g}"); Game.LogTrivial($"Vehicle has BOLOs: {data.HasAnyBOLOs}"); // Enumerate all active BOLOs foreach (VehicleBOLO b in data.GetAllBOLOs()) { Game.LogTrivial($" [{(b.IsActive ? "ACTIVE" : "INACTIVE")}] {b.Reason} by {b.IssuedBy} until {b.Expires:g}"); } // Deactivate the BOLO manually bolo.SetIsActive(false); Game.LogTrivial($"BOLO manually deactivated. Active: {bolo.IsActive}"); // Remove from vehicle data.RemoveBOLO(bolo); Game.LogTrivial($"Vehicle has BOLOs after removal: {data.HasAnyBOLOs}"); } ``` ``` -------------------------------- ### PedDataController.GetPedData(this Ped ped) Source: https://context7.com/policing-redefined/commondataframework/llms.txt An extension method on `Rage.Ped` that retrieves the `PedData` record for a ped from the CDF database. If no record exists, it creates and stores a new one. It returns `null` for non-human or non-existent peds without a cached record. Data is automatically pruned every 15 minutes and records are retained for at least one extra prune cycle after a ped despawns. ```APIDOC ## PedDataController.GetPedData(this Ped ped) ### Description Extension method on `Rage.Ped` that retrieves the existing `PedData` record for a ped from the CDF database, or creates and stores a new one if none exists. Returns `null` for non-human peds or non-existent peds with no cached record. The database is automatically pruned every 15 minutes; records are kept for at least one extra prune cycle after a ped despawns. ### Usage Example ```csharp PedData data = nearby[0].GetPedData(); if (data == null) { Game.LogTrivial("Could not retrieve ped data (non-human or non-existent ped)."); return; } Game.LogTrivial($"Name : {data.FullName}"); // ... other data fields // Modify the ped data data.Citations += 1; data.DriversLicenseState = ELicenseState.Suspended; ``` ### Parameters #### Path Parameters - **ped** (Ped) - Required - The ped for which to retrieve data. ``` -------------------------------- ### Postal Code Lookups Source: https://context7.com/policing-redefined/commondataframework/llms.txt Provides functionality to look up postal codes and find the nearest postal code to a given location. This uses user-supplied XML files loaded on startup and selected via `Settings.ini`. ```APIDOC ## `PostalCodeController` — Postal Lookups CDF loads user-supplied postal code XML files on startup and exposes them for address generation and nearest-code lookups. The active set is selected by name via `Settings.ini`. `GetPostalCode` and `GetNearestPostalCode` can be called from any plugin referencing CDF. ### Usage Example ```csharp using CommonDataFramework.Modules.Postals; using Rage; [ConsoleCommand] private static void Command_NearestPostal() { Vector3 playerPos = Game.LocalPlayer.Character.Position; // Simple string code for display in a CAD / computer plugin string code = PostalCodeController.GetPostalCode(playerPos); Game.LogTrivial($"Nearest postal code (string): {code}"); // Full nearest-postal object with distance NearestPostalCode nearest = PostalCodeController.GetNearestPostalCode(playerPos); if (nearest != null) { Game.LogTrivial($"Postal number : {nearest.Code.Number}"); Game.LogTrivial($"Distance : {nearest.Distance:F1} units"); Game.LogTrivial($"Position : X={nearest.Code.X} Y={nearest.Code.Y}"); } // Inspect the active set PostalCodeSet active = PostalCodeController.ActivePostalCodeSet; if (active != null) Game.LogTrivial($"Active postal set: {active.Name} ({active.Codes.Count} entries)"); } ``` ``` -------------------------------- ### Perform Postal Code Lookups Source: https://context7.com/policing-redefined/commondataframework/llms.txt Retrieves postal codes and nearest postal code information using `PostalCodeController`. This requires CDF to have loaded postal code XML files and the active set to be selected in `Settings.ini`. ```csharp using CommonDataFramework.Modules.Postals; using Rage; [ConsoleCommand] private static void Command_NearestPostal() { Vector3 playerPos = Game.LocalPlayer.Character.Position; // Simple string code for display in a CAD / computer plugin string code = PostalCodeController.GetPostalCode(playerPos); Game.LogTrivial($"Nearest postal code (string): {code}"); // Full nearest-postal object with distance NearestPostalCode nearest = PostalCodeController.GetNearestPostalCode(playerPos); if (nearest != null) { Game.LogTrivial($"Postal number : {nearest.Code.Number}"); Game.LogTrivial($"Distance : {nearest.Distance:F1} units"); Game.LogTrivial($"Position : X={nearest.Code.X} Y={nearest.Code.Y}"); } // Inspect the active set PostalCodeSet active = PostalCodeController.ActivePostalCodeSet; if (active != null) Game.LogTrivial($"Active postal set: {active.Name} ({active.Codes.Count} entries)"); } ``` -------------------------------- ### Handle Ped and Vehicle Data Removal Events Source: https://context7.com/policing-redefined/commondataframework/llms.txt Subscribes to `CDFEvents.OnPedDataRemoved` and `CDFEvents.OnVehicleDataRemoved` to perform cleanup when data records are pruned. Ensure your plugin implements `IPlugin` and handles duty state changes correctly. ```csharp using CommonDataFramework.API; using CommonDataFramework.Modules.PedDatabase; using CommonDataFramework.Modules.VehicleDatabase; using LSPD_First_Response.Mod.API; using Rage; public class MyPlugin : Plugin { public override void Initialize() { LSPDFRFunctions.OnOnDutyStateChanged += OnDutyChanged; } public override void Finally() { CDFEvents.OnPedDataRemoved -= HandlePedDataRemoved; CDFEvents.OnVehicleDataRemoved -= HandleVehicleDataRemoved; } private static void OnDutyChanged(bool onDuty) { if (onDuty) { CDFEvents.OnPedDataRemoved += HandlePedDataRemoved; CDFEvents.OnVehicleDataRemoved += HandleVehicleDataRemoved; } else { CDFEvents.OnPedDataRemoved -= HandlePedDataRemoved; CDFEvents.OnVehicleDataRemoved -= HandleVehicleDataRemoved; } } private static void HandlePedDataRemoved(Ped ped, PedData pedData) { // ped may no longer exist at this point; pedData still contains all cached values Game.LogTrivial($"[MyPlugin] Ped record removed: {pedData.FullName} (Citations: {pedData.Citations})"); // Clean up any secondary references your plugin holds to this PedData } private static void HandleVehicleDataRemoved(Vehicle vehicle, VehicleData vehicleData) { Game.LogTrivial($"[MyPlugin] Vehicle record removed: {vehicleData.Make} {vehicleData.Model} VIN: {vehicleData.Vin.Number}"); // Clean up secondary references } } ``` -------------------------------- ### CDF Data Removal Events Source: https://context7.com/policing-redefined/commondataframework/llms.txt Subscribes to static events that are fired when Common Data Framework (CDF) removes PedData or VehicleData records. This is useful for plugins that need to perform cleanup of their own secondary references to these data objects. ```APIDOC ## `CDFEvents.OnPedDataRemoved` / `CDFEvents.OnVehicleDataRemoved` Static events fired when CDF removes a `PedData` or `VehicleData` record from its database during a prune cycle. Useful for cleanup in plugins that maintain their own secondary references to CDF data objects. Note: these events are NOT fired when the entire database is cleared on duty-end. ### Usage Example ```csharp using CommonDataFramework.API; using CommonDataFramework.Modules.PedDatabase; using CommonDataFramework.Modules.VehicleDatabase; using LSPD_First_Response.Mod.API; using Rage; public class MyPlugin : Plugin { public override void Initialize() { LSPDFRFunctions.OnOnDutyStateChanged += OnDutyChanged; } public override void Finally() { CDFEvents.OnPedDataRemoved -= HandlePedDataRemoved; CDFEvents.OnVehicleDataRemoved -= HandleVehicleDataRemoved; } private static void OnDutyChanged(bool onDuty) { if (onDuty) { CDFEvents.OnPedDataRemoved += HandlePedDataRemoved; CDFEvents.OnVehicleDataRemoved += HandleVehicleDataRemoved; } else { CDFEvents.OnPedDataRemoved -= HandlePedDataRemoved; CDFEvents.OnVehicleDataRemoved -= HandleVehicleDataRemoved; } } private static void HandlePedDataRemoved(Ped ped, PedData pedData) { // ped may no longer exist at this point; pedData still contains all cached values Game.LogTrivial($"[MyPlugin] Ped record removed: {pedData.FullName} (Citations: {pedData.Citations})"); // Clean up any secondary references your plugin holds to this PedData } private static void HandleVehicleDataRemoved(Vehicle vehicle, VehicleData vehicleData) { Game.LogTrivial($"[MyPlugin] Vehicle record removed: {vehicleData.Make} {vehicleData.Model} VIN: {vehicleData.Vin.Number}"); // Clean up secondary references } } ``` ``` -------------------------------- ### Transfer Vehicle Ownership Source: https://context7.com/policing-redefined/commondataframework/llms.txt Demonstrates transferring vehicle ownership to a nearby ped or forcing a specific owner type. Requires nearby vehicles and peds. ```csharp using CommonDataFramework.Modules.VehicleDatabase; using CommonDataFramework.Modules.PedDatabase; using Rage; [ConsoleCommand] private static void Command_TransferOwnership() { Vehicle[] nearbyVehicles = Game.LocalPlayer.Character.GetNearbyVehicles(1); Ped[] nearbyPeds = Game.LocalPlayer.Character.GetNearbyPeds(1); if (nearbyVehicles.Length == 0 || nearbyPeds.Length == 0) return; VehicleData vehData = nearbyVehicles[0].GetVehicleData(); PedData pedData = nearbyPeds[0].GetPedData(); if (vehData == null || pedData == null) return; Game.LogTrivial($"Current Owner : {vehData.Owner.FullName} (Type: {vehData.OwnerType})"); // Transfer ownership to the nearest ped bool success = vehData.TrySetOwner(pedData); Game.LogTrivial(success ? $ ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.