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.

Everything on this page is configured in shared/job_vehicles.lua.

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
    keeperCitizenId = nil,          -- fallback registered keeper
    bossOnlyManage = true,          -- only a boss may add 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. /jobkeeper <citizenid>: set in game, stored in the database, survives restarts.
  2. Config.JobOwnedVehicles.keeperCitizenId.

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 can manage any job's fleet through the commands below.

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

Commands

CommandDescription
/addjobcar [job]Files the vehicle you are sitting in under a job, yours by default
/deljobcar <plate>Deletes a job vehicle
/jobkeeper [citizenid | clear]Shows or sets the fallback registered keeper

Exports

See Server Exports for the full list.

On this page