Kartik Scripts

Job Owned Vehicles

A job vehicle belongs to the job itself, not to a person. It never shows up in anyone's personal garage, it cannot be transferred or given sub-owners, and while restrictToJobGarages is on, it can only be parked and taken out at a garage of type job that the owning job owns.

The behaviour settings below live in shared/job_vehicles.lua. The spawn list, owned job vehicles and the registered keeper are managed in game from /garageadmin → Job Fleet, see Job Fleet & Category Management.

How ownership is stored

The owning job's name goes in its own column on the vehicle table (job by default, Config.JobOwnedVehicles.column). It is created automatically if your table does not already have one, ESX's owned_vehicles already ships it.

The owner column (citizenid on QB/Qbox, owner on ESX) still holds a real citizen id, called the registered keeper, because those schemas put a foreign key on it. The keeper gains nothing from this: every personal-ownership query excludes rows that have a job set, so the vehicle is not theirs in any sense the script recognises. It exists to satisfy the constraint and to record who bought it.

A vehicle whose owner column holds job:<name> is also read as job-owned, for servers where another resource writes ownership that way. This resource never writes that form.

Configuration

Config.JobOwnedVehicles = {
    enabled = true,
    column = "job",                 -- column holding the owning job's name
    ownerPrefix = "job:",           -- also read as job ownership, never written
    restrictToJobGarages = true,    -- job garages only
    minGrade = { police = 2 },      -- minimum grade to take one out
    requireOnDuty = false,          -- must be clocked in
    chargeFees = false,             -- charge the usual retrieval/parking fees
    bossOnlyManage = true,          -- only a boss may move or remove
}

Selling to a job from a dealership

PurchaseJobVehicle is the entry point for a shop. Call it after you have taken payment, this resource never touches anyone's money.

local ok, plate = exports['kartik-garages']:PurchaseJobVehicle({
    job    = 'police',          -- required, the job that will own it
    model  = 'police3',         -- required, spawn name
    plate  = nil,               -- optional, a free plate is generated
    buyer  = Player.citizenid,  -- optional, becomes the registered keeper
    garage = nil,               -- optional, defaults to the job's own garage
    props  = props,             -- optional, table or json string
    price  = 45000,             -- optional, for the log and the event only
})

if not ok then
    print(plate) -- holds the reason on failure
end

If holding an export reference is awkward, trigger the server-only event instead. It is not a net event, so nothing a player sends can forge a sale:

TriggerEvent('kartik-garages:server:purchaseJobVehicle', {
    job = 'police', model = 'police3', buyer = Player.citizenid,
})

Either way, a completed sale fires an event you can listen for:

AddEventHandler('kartik-garages:server:jobVehiclePurchased', function(sale)
    -- sale = { job, jobLabel, plate, model, garage, buyer, price }
end)

The registered keeper

buyer is used when you pass one. Otherwise the fallback keeper is resolved in this order:

  1. Registered Keeper in /garageadmin → Job Fleet, stored in the database, survives restarts.
  2. Config.JobOwnedVehicles.keeperCitizenId, if an older config still sets it.

With neither set, a call that names no buyer fails with A registered keeper Citizen ID is required.

The keeper must be a character that really exists. An invented id is rejected both when it is set and when a vehicle is filed.

Managing a fleet in game

A boss of the job gets a Fleet button in the garage menu at their own job garages. It lists every vehicle the job owns and lets them move a stored vehicle between the job's garages or delete one from the fleet.

Set bossOnlyManage = false to let any member of the job manage it. Admins manage every job's fleet from /garageadmin → Job Fleet → Owned Vehicles, which is also the only place a vehicle can be added: sit in it and click Add the vehicle I'm sitting in.

Every panel action is re-checked on the server; the button only decides what gets drawn.

The /addjobcar, /deljobcar and /jobkeeper commands have been removed. Everything they did is in /garageadmin → Job Fleet.

Exports

See Server Exports for the full list.

On this page