Custom · origen_parking
The custom/ folder lets you integrate any framework, key system or fuel system without touching the core. All files here survive updates.
custom/
├── sv_framework.lua — server-side: identifier, permissions, money, notifications, garages
├── sv_keys.lua — server-side: give keys, set lock state
├── cl_framework.lua — client-side: identifier, notifications, player loaded event
├── cl_keys.lua — client-side: read lock state
└── cl_fuel.lua — client-side: get/set fuel levelsv_framework.lua
Framework.GetIdentifier(source) → string | nil
Returns the unique identifier of a player (citizenid / license). Called on every park/retrieve action.
function Framework.GetIdentifier(source)
-- Config.Framework == 'custom'
return nil -- replace with your own logic
endFramework.GetVehicleOwner(plate) → string | nil
Returns the owner identifier for a given plate from the framework's vehicle table.
function Framework.GetVehicleOwner(plate)
-- Config.Framework == 'custom'
return nil
endFramework.SetVehicleStorageState(plate, stored)
Marks a vehicle as stored (stored = true) or out (stored = false) in the framework's vehicle table.
function Framework.SetVehicleStorageState(plate, stored)
-- Config.Framework == 'custom'
endFramework.HasAdminPermission(source, permission) → boolean
Called on all admin callbacks. Permission systems checked in order:
origen_admin—exports['origen_admin']:HasPermission(src, permission)ace—IsPlayerAceAllowed(src, Config.AdminAceNode)qbx/qb— checksPlayerData.groupforgod,superadmin,adminesx— checksxPlayer.getGroup()forsuperadmin,admincustom— implement below
function Framework.HasAdminPermission(source, permission)
-- Config.AdminSystem == 'custom'
return false
endFramework.Notify(source, message, ntype)
Send a notification to a player. ntype: 'info' | 'success' | 'error'
function Framework.Notify(source, message, ntype)
-- Config.NotifySystem == 'custom'
endFramework.GetGarages() → table[]
Returns a list of garages for the admin panel. Each entry: { id, name, label }.
function Framework.GetGarages()
-- Config.GarageIntegration == 'custom'
return {}
endFramework.GetMoney(source) → number
Returns the cash balance of a player. Used by the parking cost system.
function Framework.GetMoney(source)
-- Config.Framework == 'custom'
return 0
endFramework.RemoveMoney(source, amount) → boolean
Deducts cash from a player. Returns true on success.
function Framework.RemoveMoney(source, amount)
-- Config.Framework == 'custom'
return false
endFramework.GetVehicleState(plate) → number | nil
Returns the stored state of a vehicle from the framework's table (1 = out, 0 = stored, or nil if not found).
function Framework.GetVehicleState(plate)
-- Config.Framework == 'custom'
return nil
endKey system integration
The parking system talks to your key system through two bridge files — custom/sv_keys.lua (give keys + set lock) and custom/cl_keys.lua (read lock state). Which path runs is driven by Config.KeySystem:
Config.KeySystem | Behaviour |
|---|---|
qbx_vehiclekeys | GiveKeys + SetLockState via qbx exports, native fallback. |
qb-vehiclekeys | GiveKeys via qb export, lock applied with the native + state bag. |
qs-vehiclekeys | GiveKeys + setLocked via qs exports, native fallback. |
rk-keys | addKey via rk export, native lock. |
none | No keys given, vehicles spawn unlocked. |
custom | You implement the bridge in sv_keys.lua / cl_keys.lua. |
Regardless of Config.KeySystem, the recommended way to drive park/unpark from your key system is the explicit client hooks below. They are deterministic and run the full eligibility checks — no guessing.
Connecting any key system (recommended)
Call these client exports from your key system whenever the player locks or unlocks a vehicle. The parking system handles the rest (eligibility checks, server park/unpark). Both accept a vehicle entity handle and are safe no-ops when the vehicle is not eligible.
exports['origen_parking']:onVehicleLocked(vehicle) -- park this vehicle
exports['origen_parking']:onVehicleUnlocked(vehicle) -- unpark this vehicleWiring from a lock/unlock event (most qb / esx key systems fire one):
AddEventHandler('my_keys:client:vehicleLocked', function(veh)
exports['origen_parking']:onVehicleLocked(veh)
end)
AddEventHandler('my_keys:client:vehicleUnlocked', function(veh)
exports['origen_parking']:onVehicleUnlocked(veh)
end)Wiring from the door-lock state bag (qbx_vehiclekeys and similar publish doorslockstate):
AddStateBagChangeHandler('doorslockstate', nil, function(bagName, _, value)
local veh = GetEntityFromStateBagName(bagName)
if veh == 0 then return end
if value and value >= 2 then
exports['origen_parking']:onVehicleLocked(veh)
else
exports['origen_parking']:onVehicleUnlocked(veh)
end
end)Native-only key systems lock the car server-side, so the entity owner's client cannot always observe the lock via the native poller. For those systems the explicit hooks above are the only reliable trigger — prefer them over Config.AutomaticParking.
sv_keys.lua
Keys.GiveKeys(source, entity, plate)
Give vehicle keys to a player on spawn. Runs only when Config.GiveKeysOnSpawn = true. Each branch checks the key resource is started and wraps the export in pcall, so a missing key system never breaks spawning.
| Parameter | Type | Description |
|---|---|---|
source | number | Player server id receiving the keys. |
entity | number | Vehicle entity handle (may be 0 if not yet spawned — use plate). |
plate | string | Vehicle number plate. |
Handled out of the box: qbx_vehiclekeys, qb-vehiclekeys, qs-vehiclekeys, rk-keys. For custom, add your own export call:
function Keys.GiveKeys(source, entity, plate)
-- Config.KeySystem == 'custom'
-- exports['my_key_resource']:GiveKey(source, plate)
endKeys.SetLock(entity, locked)
Lock or unlock a vehicle entity server-side. Runs only when Config.LockVehiclesOnSpawn = true. locked = true → locked (state 2), false → unlocked (state 1). Every branch falls back to the native + state bag so other players see the parked vehicle as locked.
| Parameter | Type | Description |
|---|---|---|
entity | number | Vehicle entity handle. |
locked | boolean | true to lock, false to unlock. |
function Keys.SetLock(entity, locked)
-- Config.KeySystem == 'custom' / 'none' / 'rk-keys' → native fallback:
SetVehicleDoorsLocked(entity, locked and 2 or 1)
Entity(entity).state.doorslockstate = locked and 2 or 1
endcl_framework.lua
Framework.GetLocalIdentifier() → string | nil
Returns the local player's unique identifier client-side.
function Framework.GetLocalIdentifier()
-- Config.Framework == 'custom'
return nil
endFramework.NotifyClient(message, notifyType)
Show a notification to the local player. notifyType: 'info' | 'success' | 'error'
function Framework.NotifyClient(message, notifyType)
-- Config.NotifySystem == 'custom'
endFramework.OnPlayerLoaded(callback)
Register a callback that fires when the player's data is ready. Used for initial sync.
function Framework.OnPlayerLoaded(callback)
-- Config.Framework == 'custom'
CreateThread(function() Wait(0); callback() end)
endcl_keys.lua
Keys.IsLocked(vehicle) → boolean
Returns true if the vehicle is currently locked. Used only by the optional automatic-parking poller (Config.AutomaticParking) to detect when the player locks their car after exiting. It checks both the native lock status and the doorslockstate state bag — never early-returning on an unlocked state bag, so a stale bag can't hide a real native lock.
| Parameter | Type | Description |
|---|---|---|
vehicle | number | Vehicle entity handle. |
function Keys.IsLocked(vehicle)
-- Native lock: 0=None 1=Unlocked 2=Locked 3=LockedForPlayer 4=StuckForPlayer
if GetVehicleDoorLockStatus(vehicle) >= 2 then return true end
local stateBagLock = Entity(vehicle).state.doorslockstate
if stateBagLock ~= nil and stateBagLock >= 2 then return true end
return false
endIf automatic detection is unreliable on your key system, skip the poller and use the explicit hooks (onVehicleLocked / onVehicleUnlocked) documented in Key system integration above.
cl_fuel.lua
Fuel.Get(vehicle) → number
Returns the current fuel level (0–100) of a vehicle.
Auto-detection order: ox_fuel → LegacyFuel → ps-fuel → cdn-fuel → native.
function Fuel.Get(vehicle)
-- Config.FuelSystem == 'custom'
return GetVehicleFuelLevel(vehicle)
endFuel.Set(vehicle, level)
Sets the fuel level (0–100) of a vehicle. Always calls SetVehicleFuelLevel as base, then the active system on top.
function Fuel.Set(vehicle, level)
-- Config.FuelSystem == 'custom'
SetVehicleFuelLevel(vehicle, level + 0.0)
end