Garage - Car key
Wire the Vale valet app to your garage and car key scripts.
The Vale app lists a player's vehicles and has a valet bring one to them. Both halves need pointing at whatever garage and key scripts you run.
Car keys
GiveKeyCar in gksphone/client/settings.lua hands over the key once a vehicle is delivered. Seven key systems are already covered: qb-vehiclekeys, qs-vehiclekeys, cd_garage, wasabi_carlock, jaksam-vehicles-keys, mk_vehiclekeys and Renewed-Vehiclekeys.
For anything else, add a branch before the final else:
function GiveKeyCar(callback_vehicle)
local plate = GetVehicleNumberPlateText(callback_vehicle)
if GetResourceState('qb-vehiclekeys') == 'started' then
TriggerEvent("vehiclekeys:client:SetOwner", plate)
-- ... the other six ...
elseif GetResourceState('my_keys') == 'started' then
exports['my_keys']:GiveKey(plate)
else
print("No compatible vehicle key system found to give keys.")
end
endSetFuel sits right below it and works the same way — LegacyFuel, ps-fuel, Renewed-Fuel, cdn-fuel, lc_fuel, ox_fuel and qs-fuelstations are covered.
Garage
Everything else lives in your framework's file under gksphone/server/framework/ — esx.lua, qb.lua, standalone.lua. Edit only the one you use.
Database columns
At the top of that file. The defaults differ per framework because the schemas do:
| Setting | ESX default | QB default | Is |
|---|---|---|---|
Config.GarageDBColumn | "parking" | "garage" | Column holding the garage name |
Config.GarageDefaultName | "SanAndreasAvenue" | "pillboxgarage" | Garage a vehicle returns to |
Config.GarageStored | "stored = 1" | "state = 1" | SQL fragment meaning "in the garage" |
Match these to your garage script's own table, not to the framework default, if it uses something else.
Three functions to adapt
Each already carries branches for six garage scripts — esx_garage, qb-garages, cd_garage, jg-advancedgarages, loaf_garage and qs-advancedgarages. Add yours alongside.
| Function | Job |
|---|---|
GetCharacterAllVehicles(identifier, appname) | List the player's vehicles and mark each one Out, Impounded or On The Street |
GetVehicle(identifier, plate) | Decide whether a vehicle can be fetched. Return "carimpounded" or "carnotingarage" to refuse |
VehicleUpdate(plate, ...) | Mark the vehicle as out once the valet delivers it |
Reading the state:
function GetCharacterAllVehicles(identifier, appname)
if GetResourceState("qb-garages") == "started" then
if vehicle.state == 2 then
vehData.garage = "Impounded"
elseif vehicle.state == 0 then
vehData.garage = "Out"
end
elseif GetResourceState("loaf_garage") == "started" then
if vehicle.state == 0 then
vehData.garage = "On The Street"
elseif vehicle.state == 2 then
vehData.garage = "Impounded"
end
end
endRefusing a fetch:
function GetVehicle(identifier, plate)
if GetResourceState("qb-garages") == "started" then
if ret.state == 2 then return "carimpounded" end
if ret.state == 0 then return "carnotingarage" end
end
endWriting back after delivery:
function VehicleUpdate(plate, app, data)
if GetResourceState("qb-garages") == "started" then
MySQL.Async.execute('UPDATE player_vehicles SET `state` = @state WHERE `plate` = @plate', {
['@plate'] = plate,
['@state'] = 0,
})
end
endVehicleUpdate takes (plate) in esx.lua and (plate, app, data) in qb.lua. Keep whichever signature your file already has.

