# Configuration > Configuration reference for ML Vehicle Persistence Category: VEHICLE PERSISTENCE · Source: https://miciomods.it/docs/ml-vehicle-persistence-configuration · Last updated: 2026-07-28 ## Overview - `shared/config.lua`: persistence behavior, world streaming, world-vehicle claiming, decay, cleanup, GPS items, admin panel - `server/config_server.lua`: Discord webhooks and log provider - `open/server.lua`: ownership, garage and impound hooks Most values are also editable live from the admin panel, where they are stored as overrides and survive restarts. ## General **shared/config.lua** ```lua Config.Debug = false Config.locale = 'en' Config.PersistThroughRestart = true Config.MaxVehiclesPerPlayer = 5 Config.PersistDestroyed = false ``` - `Debug`: Prints gate decisions and lifecycle events to the server console - `locale`: Active language. Files live in `locales/` - `PersistThroughRestart`: Respawn every persisted vehicle in its saved spot after a server restart - `MaxVehiclesPerPlayer`: Maximum parked vehicles persisted per owner. `0` = unlimited. When the limit is hit, the owner's oldest parked vehicle stops being persistent - `PersistDestroyed`: `true` brings a wreck back as a wreck (burnt body, dead engine, burst tyres) on respawn and after a restart. `false` drops a destroyed vehicle from persistence for good ## World Streaming **shared/config.lua** ```lua Config.SpawnDistance = 250.0 Config.ScanInterval = 5 Config.SpawnStaggerMs = 150 ``` Persisted vehicles are held in memory and only spawned into the world when a player comes close, then despawned once everyone leaves. This is what allows hundreds of saved vehicles without filling the world with entities. - `SpawnDistance`: Distance in meters at which a saved vehicle is spawned. Despawn happens 60 meters beyond this - `ScanInterval`: Seconds between world scans. Lower is snappier for spawns and position updates, higher is lighter on the server - `SpawnStaggerMs`: Delay in milliseconds between two vehicle spawns inside a scan, to spread the load ## External Deletes **shared/config.lua** ```lua Config.RespawnOnExternalDelete = false ``` - `RespawnOnExternalDelete`: What happens when another resource deletes a persisted vehicle (an admin `/dv`, a garage, a cleanup script). `false` treats it as a real removal and drops the vehicle from persistence, so a plain `/dv` deletes the car like every other script expects. `true` brings it back on its saved spot, so a saved car can never be lost > **WARNING:** Using true > > With `true`, intentional deletes only stick if the deleting resource is routed through the script. Add `shared_script '@ml_vehicle_persistence/deletehook.lua'` as the **first** script line in the `fxmanifest.lua` of every resource that deletes vehicles (admin menu, garage), or call the `PurgeVehicle` export. Otherwise every `/dv` respawns the vehicle. ## Vehicle Types **shared/config.lua** ```lua Config.PersistTypes = { automobile = true, bike = true, bicycle = true, quadbike = true, amphibious_automobile = true, amphibious_quadbike = true, submarinecar = true, boat = true, heli = true, blimp = true, plane = true, submarine = false, trailer = true, } ``` - Only categories set to `true` are persisted. The key is the server-side vehicle archetype **shared/config.lua** ```lua Config.BlacklistedModels = { -- 'police', 'ambulance', } Config.BlacklistedPlates = { -- 'MECH', 'RENT', } ``` - `BlacklistedModels`: Spawn names that never persist, even when player-owned - `BlacklistedPlates`: Plate fragments that never persist. Partial match, case-insensitive, made for job and rental prefixes ## Notifications **shared/config.lua** ```lua Config.Notifications = { onParked = false, onLimitWarning = true, onLimitReached = true, } ``` - `onParked`: Popup on every park confirming the vehicle will stay - `onLimitWarning`: Warn the owner when only one parking slot is left - `onLimitReached`: Warn the owner when the oldest vehicle drops out of persistence ## World Vehicles **shared/config.lua** ```lua Config.WorldVehicles = { enabled = true, countTowardLimit = true, notifyOnClaim = true, } ``` - `enabled`: Any unowned vehicle becomes persistent when first driven; the first driver becomes its owner - `countTowardLimit`: Claimed vehicles count toward `Config.MaxVehiclesPerPlayer` - `notifyOnClaim`: Tell the player the vehicle is now theirs > **TIP:** Opt a vehicle out > > Scripts that spawn temporary vehicles (missions, rentals) exclude them with `exports.ml_vehicle_persistence:DoNotSave(plateOrNetId, reason)`. ## Decay **shared/config.lua** ```lua Config.Decay = { enabled = false, graceDays = 2, bodyPerDay = 40.0, enginePerDay = 40.0, healthFloor = 150.0, } ``` - `enabled`: Parked vehicles lose health while untouched. Applied when the record is loaded at restart - `graceDays`: Days without a save before decay starts - `bodyPerDay`: Body health lost per day after the grace period - `enginePerDay`: Engine health lost per day after the grace period - `healthFloor`: Decay never drops health below this value. A vehicle already saved below the floor is left alone ## Orphaned Vehicles **shared/config.lua** ```lua Config.OrphanedVehicles = { enabled = true, thresholdDays = 7, action = 'impound', impoundLot = 'impound', feePerDay = 100, maxFee = 1500, } ``` - `enabled`: Clean up vehicles whose owner has not been seen for `thresholdDays` - `thresholdDays`: Days of owner absence before a vehicle is orphaned - `action`: `'impound'` routes owned vehicles through `OpenServer.ImpoundVehicle`; `'delete'` removes them. Claimed vehicles are always deleted, since they have no garage record - `impoundLot`: Impound lot name passed to the hook - `feePerDay`: Fee charged per orphaned day - `maxFee`: Maximum impound fee ## Cleanup **shared/config.lua** ```lua Config.Cleanup = { enabled = false, engineBelow = nil, underZ = nil, clearZones = { -- { coords = vector3(0.0, 0.0, 0.0), radius = 20.0 }, }, safeZones = { -- { coords = vector3(0.0, 0.0, 0.0), radius = 20.0 }, }, keepPlates = { -- 'STAFF', }, keepModels = { -- 'adder', }, schedule = { -- { hour = 4, minute = 0 }, -- { day = 3, hour = 16, minute = 0 }, }, runOnStart = false, } ``` Housekeeping sweep that drops persisted vehicles a server would rather not keep. Rules are read from the saved record, so a burnt-out or out-of-bounds vehicle is pruned even when nobody has it streamed. - `enabled`: Master switch for the sweep - `engineBelow`: Prune vehicles whose engine dropped to or under this value. A dead engine sits around `0`, a blown-up one goes deeply negative. `nil` keeps every vehicle - `underZ`: Prune vehicles that ended up under this height, for cars dropped through the map or sunk. `nil` to skip - `clearZones`: Any vehicle sitting inside one of these circles is pruned - `safeZones`: Sanctuaries. A vehicle inside one is never pruned, whatever the other rules say - `keepPlates`: Plate fragments immune to the sweep. Partial match, case-insensitive - `keepModels`: Spawn names the sweep never touches - `schedule`: When to run, on the server clock. `day` is optional (`0` = Sunday through `6` = Saturday) - `runOnStart`: Run one pass a few seconds after the resource boots The sweep can also be triggered from another resource with the `RunCleanup` export. ## GPS Item **shared/config.lua** ```lua Config.GpsItem = 'vehicle_gps' ``` - `GpsItem`: Usable item that lists the owner's persisted and garaged vehicles and sets a waypoint. Set to `false` to disable ## GPS Scanner **shared/config.lua** ```lua Config.GpsScanner = { enabled = true, scannerItem = 'gps_scanner', moduleItem = 'gps_module', range = 8.0, tamperTime = 6000, installTime = 5000, scanSeconds = 20, consumeScannerOnTamper = false, screen = true, anim = { dict = 'cellphone@', name = 'cellphone_text_read_base', weapon = 'weapon_digiscanner', bone = 28422, offset = vector3(0.0, 0.0, 0.0), rot = vector3(0.0, 0.0, 0.0) }, workAnim = { dict = 'anim@amb@clubhouse@tutorial@bkr_tut_ig3@', name = 'machinic_loop_mechandplayer' }, beep = { name = 'IDLE_BEEP', set = 'EPSILONISM_04_SOUNDSET', range = 5.0 }, } ``` A thief sweeps around a vehicle with the scanner item; the closer they get, the faster it beeps. Holding the scan rips the GPS out, and the owner's GPS item then freezes on the last known position with a tampered badge until a new module is installed on the recovered vehicle. - `enabled`: Master switch for the scanner and tamper feature - `scannerItem`: Reusable detector and remover carried by the thief - `moduleItem`: Consumed by the owner to reinstall a removed GPS - `range`: Meters at which the scanner picks a vehicle up - `tamperTime`: Milliseconds held next to the vehicle to rip the GPS out - `installTime`: Milliseconds held to install a new module - `scanSeconds`: How long one scanner use stays active - `consumeScannerOnTamper`: Also burn one scanner item per removal - `screen`: Draw the live proximity bars on the device screen - `anim`: Device held in hand while sweeping. `weapon` takes the device model straight from that weapon, so it does not break if the prop name changes. `bone` is the attach bone - `workAnim`: Animation played while ripping the GPS out or bolting a new module in - `beep`: Scanner sound. Heard by anyone within `range` meters, so bystanders notice the sweep > **INFO:** Reinstalling > > Only the vehicle's owner can install a module. The GPS stays frozen until they do. ## Admin Panel **shared/config.lua** ```lua Config.AdminAcePermission = nil Config.Admin = { command = 'vpadmin', theme = 'default', minimizeKey = 'F9', } ``` - `AdminAcePermission`: Optional dedicated ACE node. `nil` grants access to any `ml_bridge` admin - `Admin.command`: Command that opens the panel - `Admin.theme`: Panel theme: `'default'`, `'wasteland'`, `'cyberpunk'`, `'noir'`, `'fantasy'` - `Admin.minimizeKey`: Key that hides and restores the panel (F1-F12 or a single letter/digit) ## Commands **shared/config.lua** ```lua Config.Commands = { list = 'vpcount', remove = 'vpremove', clear = 'vpclear', save = 'vpsave', } ``` - `list`: Print the persisted-vehicle count and the full list in the server console - `remove`: `/vpremove ` drops one vehicle from persistence - `clear`: `/vpclear` wipes every persisted vehicle. `/vpclear ` only clears persisted vehicles within that many meters of the admin - `save`: Force-save all tracked vehicles to the database Set any command name to `false` to disable it. All four also run from the server console and RCON, where the admin panel is not reachable. ## Logging **server/config_server.lua** ```lua Config.DiscordWebhook = { Default = 'INSERT_WEBHOOK_LINK_HERE', Parked = 'INSERT_WEBHOOK_LINK_HERE', Claimed = 'INSERT_WEBHOOK_LINK_HERE', Removed = 'INSERT_WEBHOOK_LINK_HERE', Destroyed = 'INSERT_WEBHOOK_LINK_HERE', Impounded = 'INSERT_WEBHOOK_LINK_HERE', Restored = 'INSERT_WEBHOOK_LINK_HERE', SpawnFailed = 'INSERT_WEBHOOK_LINK_HERE', GpsTampered = 'INSERT_WEBHOOK_LINK_HERE', GpsInstalled = 'INSERT_WEBHOOK_LINK_HERE', AdminAction = 'INSERT_WEBHOOK_LINK_HERE', } Config.LogProvider = 'discord' ``` - Each action has its own webhook. Unset actions fall back to `Default` - `LogProvider`: `'discord'`, `'fivemanage'`, `'ox_lib'`, `'both'`, or `'all'` Set any webhook to `false` to disable that log entirely.