Skip to content

mi-garage

A React NUI garage. Players store and retrieve owned vehicles at garage points, officers run a police impound lot, and owners transfer, locate, and (for staff) administer vehicles. Vehicle mods and health persist across restarts.

Install

ensure mi-garage

Depends on ox_lib and oxmysql. It ships server/migrate.lua, so its tables auto-create on first boot, no manual SQL import.

Config

Owner-editable settings live in shared/config/*.lua.

shared/config/settings.lua:

platePattern    = 'MI 1111',       -- random-plate mask: 1 = digit, A = letter, . = either
defaultDistance = 10.0,
defaultGarage   = 'luxgarage',     -- where givecar vehicles land when no garage is given

realtimeHealth  = true,            -- persist live vehicle health/props (also gates the persistence exports)

-- external vehicle-keys resource that gets addKey(plate) on take-out / admin spawn. Guarded,
-- so if it is not started the vehicle still spawns. Point it at your keys resource, or false to disable.
keysResource = 'mi-keys',

-- staff permission tiers (highest to lowest); the short ace names permissions.cfg grants.
permTiers = { 'admin', 'mod', 'support', 'partner' },

insurance = {
    default   = 350,
    onRecover = function(veh)
        SetVehicleEngineHealth(veh, 500.0)
        SetVehicleBodyHealth(veh, 500.0)
    end,
},

police = {
    holdMinutes = 60,          -- fallback hold (minutes) when a script seizes without naming one
    releaseFine = 2500,        -- fallback release fine when a seizure did not set its own
    -- /seize popup bounds. The officer picks hold and fine per seizure; the server clamps
    -- to these and never trusts the raw input.
    seize = {
        presets        = { 15, 30, 60, 180, 720 }, -- one-tap hold durations, in minutes
        minMinutes     = 5,
        maxMinutes     = 10080,    -- 7 days
        defaultMinutes = 60,
        defaultFine    = 2500,
        maxFine        = 50000,
    },
    jobs = { police = 0 },     -- jobs (name -> min grade) allowed at the Police Impound lot
},

transfer = { fee = 500, perClass = {}, cooldown = 5 },

fuel = {
    get = function(veh) return Entity(veh).state.fuel end,
    set = function(veh, v) Entity(veh).state.fuel = v end,
},

classes = { all = {...}, car = {...}, air = {15,16}, sea = {14}, rig = {...}, emergency = {18,19} },

-- per-member cap in a gang garage; first hit wins: entry.slots, limits[garageKey],
-- limits[gangName], then gangSlotDefault. One worked example, add your own gangs.
gangSlotLimits  = { godfathers = 10 },
gangSlotDefault = 2,

shared/config/garages.lua defines every garage location (label, type, coords, spawns, blip).

shared/config/rentals.lua is the job motor pool. A garage entry with type = 'rental' hands out fleet vehicles instead of the player's own: a rental never touches player_vehicles, it exists only while it is out, and returning it refunds refund of the deposit. The fleet a player sees is picked by their job, so one rental point can serve several services.

account        = 'bank',      -- account the deposit is taken from and refunded to
platePattern   = 'RENT1111',
refund         = 0.75,        -- share of the deposit paid back on return
maxActive      = 1,           -- vehicles one player may have on rent at once
returnAnywhere = true,        -- false = a rental must go back to the point it came from

jobs = {
    police = {
        label = 'Police motor pool',
        vehicles = {          -- grade is the MINIMUM job grade that may take the vehicle
            { model = 'police',  label = 'Cruiser',     deposit = 500, grade = 0 },
            { model = 'police2', label = 'Interceptor', deposit = 750, grade = 1 },
        },
    },
},

UI colours are in shared/config/theme.lua (winter_blue by default; presets obsidian_rouge, winter_blue, monochrome, twilight_amber, ultramarine_navy).

Exports

The persistence exports (EnablePersistence, DisablePersistence, GetPlayerVehicle, GetVehicleIdByPlate, SaveVehicle) register only when realtime health is enabled.

Export Signature What it does
giveVehicle giveVehicle(target, model, garage?, plate?) stores a vehicle for a player (server id or citizenid); returns the plate or false
randomPlate randomPlate(pattern?) returns a unique random plate for the given mask
policeImpound policeImpound(plate, minutes?) impounds a vehicle with a timed hold
getAllGarages getAllGarages() returns a list of every configured garage
SaveVehicle SaveVehicle(vehicle, options?) writes a spawned vehicle's props and state back to the database
GetPlayerVehicle GetPlayerVehicle(vehicleId, filters?) returns an owned vehicle row by id
GetVehicleIdByPlate GetVehicleIdByPlate(plate) returns the vehicleId for a plate
EnablePersistence EnablePersistence(vehicle) marks a vehicle to respawn when deleted
DisablePersistence DisablePersistence(vehicle) stops a vehicle from respawning
isRentalPlate isRentalPlate(plate) returns true if the plate is a live rental (for keys, insurance, dispatch)
getGarages (client) getGarages() returns the garages config table
showGarageZone (client) showGarageZone(data) creates an external [E] garage zone; returns its zoneId
carSeizureDOJ (client) carSeizureDOJ(data, slot) runs the DOJ (grade 9+) vehicle-seizure form flow

Commands

Command Access Does
/givecar <cid> <model> [plate] [garage] group.admin grant a vehicle to a player (id or citizenid)
/impoundveh <plate> [minutes] group.admin police-impound a vehicle for a timed hold
/resetimpound group.admin clear the depot price on impounded stored vehicles
/vehdata [serverid] group.support open the admin vehicle panel for a player
/toggleRealtimeHealth group.admin toggle realtime vehicle health persistence
/seize police job seize the vehicle you are in (or the nearest within 5m) and set its impound hold and fine

Statebags

mi-garage publishes vehicle and player state so persistence, inventory, and staff tools can react without an export call.

Statebag Scope Set when Read by
vehicleid vehicle Set on a stored vehicle when it is spawned or saved, carrying its database row id. mi-garage (persistence); ox_inventory (qbx bridge, to key the vehicle's trunk and glovebox stash)
persisted vehicle Set when a spawned vehicle is registered for realtime-health persistence, cleared when it is disabled. mi-garage (respawns a persisted vehicle if it is deleted); also toggled by mi_core's EnablePersistence/DisablePersistence
Garage player Set to the current garage key when the player enters a garage zone (client), cleared on exit. mi-garage server (authorizes store and retrieve at the player's current garage) and its NUI
realtimeHealth global (GlobalState) Set at boot from Config.realtimeHealth, flipped by /toggleRealtimeHealth. mi-garage client and server (gates realtime health persistence and the persistence exports)

See the state reference for the core statebags and GlobalState.