Pulse Phone docs
Connecting your own garage script
The Garage app lists a character's vehicles and shows where each one is: which garage it is stored in, which lot has impounded it and what that lot charges, and whether the phone knows where a car that is out has got to. It reads this from the garage script the server runs.
Supported out of the box
The phone recognises these scripts on its own when their resource is started:
| Script | Provider name |
|---|---|
| qb-garages | qb-garages |
| qbx_garages | qbx_garages |
| jg-advancedgarages | jg-advancedgarages |
| cd_garage | cd_garage |
| okokGarage | okokGarage |
| esx_garage (2.x and the older version) | esx_garage |
| esx_advancedgarage | esx_advancedgarage |
| none of these: the framework's own vehicle table | framework-table |
To force one, set it in config/config.lua:
Config.Providers = {
garage = 'jg-advancedgarages', -- or 'auto' (the default), or 'none' to switch the connection off
}Valet delivery is switched off while jg-advancedgarages or cd_garage runs, because those
scripts keep "parked" in a column of their own. A car delivered by the phone would still be
listed in their garage, so it could be taken out twice.
Garage positions when your script has none
If your script's config does not give a garage a position, put the position in
Config.Garage.garages (config/apps.lua) under the same id your script stores in the
vehicle row. Put impound lots in Config.Garage.impounds. The phone uses these for the
Directions button.
Writing a provider for an in-house script
Add a file to bridge/server/ (the manifest loads every .lua there), for example
garage_mygarage.lua:
local RESOURCE = 'my-garage'
local P = { KnowsImpounds = true, Script = RESOURCE }
-- Is the script running? Return false and a reason otherwise; the reason shows in the console.
function P.Available()
return GarageKit.Ready(RESOURCE)
end
function P.Describe() return 'my-garage (player_vehicles state, garage)' end
-- The character's vehicles: cb(list) or cb({}, reason).
function P.ListVehicles(src, cb)
GarageKit.Rows(src, function(rows, reason)
if not rows then return cb({}, reason) end
local out = {}
for _, r in ipairs(rows) do
local v = GarageKit.Condition(r) -- fuel / engine / body, 0-100, or nil
v.plate = r.plate
v.model = GarageKit.Model(r)
if tonumber(r.state) == 1 then
v.stored = true
v.garage = r.garage
v.garageLabel = 'Pillbox Garage'
v.place = { name = 'Pillbox Garage', x = 213.9, y = -808.4, z = 31.0 }
end
out[#out + 1] = v
end
cb(out)
end)
end
-- Optional: where a garage id is, for Directions. Return a place, or nil and a reason.
function P.GetGarageLocation(id)
return nil, 'my-garage has no positions'
end
-- The number is a priority: a higher number wins when several providers are available.
Bridge.Register('garage', RESOURCE, P, 20)GarageKit.Rows returns every column of the character's rows in the framework's vehicle
table (player_vehicles for QBCore and Qbox, owned_vehicles for ESX). A column your script
does not have is simply nil.
The vehicle fields
Leave out anything your script does not record. The phone never fills a gap with a guess; it says what it does not know.
| Field | Meaning |
|---|---|
plate, model |
required |
nickname |
the name the player gave the car |
fuel, engine, body |
0-100 (GarageKit.Condition(row) reads the usual columns) |
stored |
true when it is in a garage |
garage, garageLabel |
the garage's id and the name to show |
impounded |
true when the police impounded it |
depot |
true when it is out but a depot holds it (a car left out at a restart) |
fee |
what the lot charges to release it |
impoundReason, impoundBy |
why it was impounded and by whom, when the script records them |
releaseAt |
when it may be collected, in milliseconds |
place |
{ name, x, y, z }: the one garage or lot the car is at |
lots |
a list of places when any of several lots can release it; the phone picks the nearest one that takes the vehicle's class (a place may carry classes = { 0, 1, ... }) |
lotLabel |
the lot's name when its position is unknown |
anyGarage |
true when the car can be taken out at any garage in lots |
lastSeen |
{ x, y, z }: where the script last recorded a car that is out |
Helpers
| Helper | Returns |
|---|---|
GarageKit.Ready(resource) |
true, or false and a reason (not started, no SQL, no vehicle table) |
GarageKit.Rows(src, cb) |
the character's rows, cb(rows, reason, tableName) |
GarageKit.Model(row), GarageKit.Condition(row) |
the model and the condition from a row |
GarageKit.Point(v) |
{ x, y, z } from a vector, a table, an array or cd_garage's x_1 form, or nil |
GarageKit.Place(name, entry) |
a place from a config entry, looking in the usual position fields |
GarageKit.Export(resource, fn, ...) |
an export's result, guarded, or nil and a reason |
GarageKit.Config(resource, { 'config.lua' }) |
the script's config read in a sandbox, or nil |
GarageKit.Str, GarageKit.Num, GarageKit.Fee, GarageKit.Json |
safe conversions from a column |
Restart the phone after adding the file. The phone's startup line in the console (and the
phone:diag command) names the garage provider it chose. A script that is running but could
not be connected is named there with the reason.