esx_garage
Configure esx_garage 2.0 for ESX Legacy: garages, impound lots, job access, settings, server exports like registerGarage and impoundVehicle, and fixes.
esx_garage is the ESX Legacy garage and impound system. Players park owned vehicles at garages, take them out again through a React UI, favorite, rename or transfer them, and pay a fee to recover vehicles from an impound lot. Version 2.0 replaced the old marker-based config completely, so configs from older versions do not work.
Overview
| Resource | esx_garage (version 2.0.0) |
| Side | client + server, NUI (web/dist) |
| Dependencies | esx_lib, es_extended, oxmysql |
| Optional | esx_hud (mileage shown in the UI) |
| Data | owned_vehicles plus columns parking, pound, custom_name, is_favorite, last_used, mileage; table esx_garage_migrations |
Features in-game:
- Garages with an entry point (opens the menu), an optional store point and an optional NPC.
- Impound lots with a per-lot fee. The fee is taken from cash first, then from the bank.
- Paginated vehicle list with search and filters (stored, impounded, favorite).
- Rename and favorite vehicles, transfer a stored vehicle to a player within 10 m.
- Optional "give keys" hook for a key script.
Vehicle state
stored | parking | pound | Meaning |
|---|---|---|---|
1 | garage id or NULL | NULL | Parked in a garage |
1 | NULL | impound id | Impounded |
0 | NULL | NULL | Out in the world |
A vehicle that is out (stored = 0) but whose entity no longer exists can only be recovered at an impound, never at a garage. Before respawning it the server deletes every live entity with that plate, so it cannot be duplicated.
Installation
Database
Nothing to do on an existing server: on start the resource adds missing columns and indexes, converts legacy stored = 2 rows to the new impound state and records version 1.16.0 in esx_garage_migrations. For a fresh or manual install you can import esx_garage.sql; every statement is guarded, so it is safe to run again.
Ensure the resource
ensure oxmysql
ensure esx_lib
ensure es_extended
ensure esx_garageConfiguration
Config.Settings
| Key | Default | Description |
|---|---|---|
interactionDistance | 3.0 | Distance to a garage or impound point to interact. |
restrictToGarage | false | Only allow retrieval at the garage stored in parking. NULL or removed garages count as "any garage". |
defaultImpoundFee | 400 | Fee for impound lots without their own cost. |
vehicleKeys | false | Shows the give keys button and enables the esx_garage:giveKeys callback. |
storeMarkerOnlyInVehicle | true | Only draw the store marker while sitting in a vehicle. |
showMarker | true | Draw ground markers at the points. |
vehiclesPerPage | 30 | Default page size of the vehicle list. |
maxVehiclesPerMenu | 100 | Largest page size a client may request (hard capped at 100). |
Config.Locale defaults to GetConvar('esx:locale', 'en').
Config.Garages
A list of garages. Defaults: vespucci_boulevard and san_andreas_avenue.
| Field | Type | Description |
|---|---|---|
id | string | Unique id, stored in owned_vehicles.parking. Do not rename it once used. |
label | string | Display name and blip label. |
type | 'public' | 'job' | 'gang' | 'impound' | Passed to the UI. Access is not derived from it; use access. |
entryPoint | vector3 | Opens the menu. |
storePoint | vector3? | Where vehicles are parked. |
spawns | vector4[] | Spawn positions; at least one. |
blip | { sprite, scale, color }? | Map blip. |
ped | { model, z?, heading?, snapToGround? }? | Optional NPC. |
access | { jobs?, authorize? }? | jobs maps job name to minimum grade. authorize(source, garage) is a server-side function that returns true to allow. |
logo | string? | Image URL shown in the menu header. |
color | string? | Hex accent color for the menu. |
pound | string? | Linked impound id. |
Config.Garages[#Config.Garages + 1] = {
id = 'mrpd',
label = 'Mission Row PD',
type = 'job',
entryPoint = vec3(454.6, -1017.4, 28.4),
storePoint = vec3(447.6, -1021.5, 28.5),
spawns = { vec4(438.4, -1018.3, 27.7, 90.0) },
blip = { sprite = 357, scale = 0.8, color = 38 },
access = { jobs = { police = 0 } },
pound = 'los_santos',
}Config.Impounds
Defaults: los_santos, paleto_bay, sandy_shores, each with cost = 3000. The first entry is the default lot for automatic impounds.
| Field | Type | Description |
|---|---|---|
id | string | Unique id, stored in owned_vehicles.pound. |
label | string | Display name. |
getOutPoint | vector3 | Opens the impound menu. |
spawns | vector4[] | Spawn positions. |
blip | { sprite, scale, color }? | Map blip. |
ped | table? | Optional NPC. |
cost | integer? | Fee; falls back to defaultImpoundFee. |
Server exports
registerGarage
exports.esx_garage:registerGarage(garage)Adds or replaces a garage at runtime and refreshes all clients. Throws (via assert) if id, entryPoint or spawns are missing or invalid. Use it for property or gang garages created by other resources.
exports.esx_garage:registerGarage({
id = 'apartment_12',
label = 'Apartment 12',
type = 'public',
entryPoint = vec3(-796.1, 304.4, 85.7),
spawns = { vec4(-791.6, 300.3, 85.4, 180.0) },
access = {
authorize = function(source)
return exports.my_housing:isTenant(source, 12)
end,
},
})registerGarages
exports.esx_garage:registerGarages(list)Calls registerGarage for every entry in list.
unregisterGarage
exports.esx_garage:unregisterGarage(id)Removes a garage by id and refreshes clients. Vehicles parked there remain available at any garage.
getGarages / getImpounds
local garages = exports.esx_garage:getGarages()
local impounds = exports.esx_garage:getImpounds()Return arrays of all registered garages and impound lots (including runtime registrations).
impoundVehicle
local ok = exports.esx_garage:impoundVehicle(plate, lotId)| Name | Type | Description |
|---|---|---|
plate | string | Plate of an owned vehicle. |
lotId | string? | Impound id. Unknown or nil falls back to the first lot. |
Deletes the live vehicle if it exists and marks it impounded. Returns true when the database row is in the impound afterwards. Typical use: a police or tow job command.
ESX.RegisterCommand('impound', 'admin', function(xPlayer, args)
local ok = exports.esx_garage:impoundVehicle(args.plate, 'los_santos')
xPlayer.showNotification(ok and 'Vehicle impounded' or 'Impound failed')
end, false, {
help = 'Impound a vehicle by plate',
arguments = { { name = 'plate', help = 'Plate', type = 'string' } },
})Server events (hooks)
Local server events you can listen to with AddEventHandler. They cannot be triggered by clients.
| Event | Arguments | Fired when |
|---|---|---|
esx_garage:vehicleTransferred | source, targetId, plate, fromIdentifier, toIdentifier | A player transferred ownership of a vehicle. |
esx_garage:giveKeys | source, plate | A player pressed "give keys" (only with vehicleKeys = true). |
AddEventHandler('esx_garage:giveKeys', function(source, plate)
exports.my_keys:giveKey(source, plate)
end)Callbacks
The UI talks to the server through these callbacks. Each is rate limited (1 to 1.5 s) and checks ownership, distance and garage access on the server, so they are safe against spoofed clients. They return { success = boolean, error = string? }.
| Callback | Purpose |
|---|---|
esx_garage:getGarages | Garages the player can access, plus all impounds. |
esx_garage:getVehicles | Paginated vehicle list. |
esx_garage:retrieveVehicle | Take a vehicle out (charges the impound fee). |
esx_garage:storeVehicle | Park the current vehicle. |
esx_garage:toggleFavorite | Toggle favorite. |
esx_garage:renameVehicle | Set custom_name. |
esx_garage:transferVehicle | Give a stored vehicle to a player within 10 m. |
esx_garage:giveKeys | Fire the esx_garage:giveKeys hook. |
The client event esx_garage:refresh rebuilds blips and points; it is also triggered on esx:playerLoaded and esx:setJob.
Integration tips
- Vehicles bought in esx_vehicleshop land in
owned_vehiclesand show up automatically. - The garage list does not filter by the vehicle
typecolumn, so boats and aircraft appear in every garage. Use separate garages withaccessif that matters. - Despawning an owned vehicle with another script sends it to the default impound. Store it through esx_garage or call
impoundVehiclewith the right lot. - The
maxVehiclesfield from the type annotations is not enforced by the current code.
Common issues
- Old config does not load: v2 uses
Config.Settings,Config.Garagesas a list withid/entryPoint/spawns, andConfig.ImpoundswithgetOutPoint.Config.DrawDistance,Config.Markersand the oldEntryPoint/SpawnPointkeys are gone. no_moneyat the impound: the player has neither enough cash nor enough bank money for the fee.wrong_garage:restrictToGarageis on and the vehicle is parked elsewhere.model_mismatchorplate_mismatchwhen storing: the vehicle entity does not match the owned record (for example after a plate change by another script).- Every vehicle impounded after restart: expected, see the FAQ below.
Related
Frequently asked questions
Independent documentation
Last updated on
esx_drugs
esx_drugs lets players harvest cannabis, process it into marijuana and sell it for black money in ESX Legacy. Config, items, events and anti-exploit checks.
esx_hud
esx_hud is the default ESX Legacy HUD with status bars, money, job, speedometer, indicators and saved mileage. Config keys, exports and events.