ai-vehicles for developers
Server exports, state bags and events of ai-vehicles, and the qbx_vehicles API it answers.
ai-vehicles has server exports only. They are all synchronous (no Promise, no waiting in Lua), except SpawnVehicle, which answers through a callback. Types are in @aicore-fivem/shared (vehicles.ts).
import { resourceExport } from "@aicore-fivem/lib/server";
const vehicles = resourceExport("ai-vehicles");local vehicles = exports['ai-vehicles']To give, take or check keys, store a vehicle in a garage or read fuel, use the lib's layers (vehicleKeys, garages, fuel): they work with whichever key, garage or fuel script the server runs. Call ai-vehicles directly only for ownership itself.
Types
VehicleOwner
Who owns a vehicle.
Prop
Type
OwnedVehicle
What GetVehicle and GetVehicles return.
Prop
Type
Server exports
CreateVehicle
Registers a new owned vehicle and parks it. Use it when a player gets a vehicle (a purchase, a reward, an admin gift). It does not spawn the car: take it out with SpawnVehicle or let the player pick it up at a garage.
Side: Server · Waits: no
CreateVehicle(owner: VehicleOwner, model: string, garage: string | null, props?: VehicleProps): { id: number; plate: string } | nulllocal created = exports['ai-vehicles']:CreateVehicle(owner, model, garage, props) -- { id = number, plate = string } or nilParameters
Prop
Type
Returns
{ id, plate } of the new vehicle. null when owner is not a valid owner or model is not text.
Example
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
const vehicles = resourceExport("ai-vehicles");
// Gives the player a Sultan, parked at the Motel Parking garage.
export function giveSultan(source: number): string | null {
const character = core.GetCharacter(source);
if (!character) return null;
const created = vehicles.CreateVehicle(
{ type: "character", id: String(character.id) },
"sultan",
"pillbox",
);
return created?.plate ?? null;
}GetVehicle
Finds one owned vehicle by its id or plate.
Side: Server · Waits: no
GetVehicle(ref: number | string): OwnedVehicle | nulllocal vehicle = exports['ai-vehicles']:GetVehicle(ref) -- table or nilParameters
Prop
Type
Returns
The OwnedVehicle, or null when no vehicle in memory has that id or plate (also when it belongs to an offline character).
Example
const vehicle = vehicles.GetVehicle("AI00001A");
if (vehicle) console.log(vehicle.model, vehicle.state, vehicle.fuel);GetVehicles
Every vehicle of one owner.
Side: Server · Waits: no
GetVehicles(owner: VehicleOwner): OwnedVehicle[]local list = exports['ai-vehicles']:GetVehicles(owner) -- arrayParameters
Prop
Type
Returns
An array of OwnedVehicle. Empty for an invalid owner, an owner without vehicles, or an offline character.
Example
const fleet = vehicles.GetVehicles({ type: "job", id: "police" });
const parked = fleet.filter((v) => v.state === "garage").length;
console.log(`police: ${parked} of ${fleet.length} cars parked`);IsOwnedPlate
Whether a plate belongs to an owned vehicle in memory.
Side: Server · Waits: no
IsOwnedPlate(plate: string): booleanlocal owned = exports['ai-vehicles']:IsOwnedPlate(plate)Returns
true when an owned vehicle has this plate. false for an unknown plate, a non-text value, or a vehicle of an offline character.
GetVehicleIdByEntity
The ai-vehicles id of a spawned owned vehicle.
Side: Server · Waits: no
GetVehicleIdByEntity(entity: number): number | nulllocal id = exports['ai-vehicles']:GetVehicleIdByEntity(entity)Parameters
Prop
Type
Returns
The vehicle id, or null when the entity is not an owned vehicle spawned by ai-vehicles.
GetEntity
The entity of a spawned owned vehicle.
Side: Server · Waits: no
GetEntity(id: number): number | nulllocal entity = exports['ai-vehicles']:GetEntity(id)Returns
The server entity handle, or null when the vehicle is not out or its entity no longer exists.
GetPlateOwners
Every owned vehicle in memory as [plate, ownerType, ownerId]. A script that must check many plates (a key system) reads this once at its start, then follows the ai-vehicles:owners event, instead of calling an export for every check.
Side: Server · Waits: no
GetPlateOwners(): Array<[plate: string, type: VehicleOwnerType, id: string]>local owners = exports['ai-vehicles']:GetPlateOwners() -- { { plate, type, id }, ... }Returns
An array of triples. Empty when no vehicle is in memory.
SaveVehicle
Saves the condition and look of a vehicle: fuel, damage, state, garage, and props (colors, extras, dirt). The stored tuning (mods, neon) never changes here, so a look read from a player's client cannot save a mod menu's work. Use SaveTuning for tuning.
Side: Server · Waits: no
SaveVehicle(id: number, change: { props?: VehicleProps; fuel?: number; engine?: number; body?: number; state?: VehicleState; garage?: string | null }): voidexports['ai-vehicles']:SaveVehicle(id, change)Parameters
Prop
Type
change
Prop
Type
Returns
Nothing. An unknown id does nothing.
Example
// A repair job finished: full engine and body.
vehicles.SaveVehicle(vehicleId, { engine: 1000, body: 1000 });SaveTuning
Saves full props, tuning included (mods, neon). Meant for tuning shops only: AI Core's own tuning shop, ai-mechanic, is the only ai-* script that calls it.
Side: Server · Waits: no
SaveTuning(id: number, props: VehicleProps): voidexports['ai-vehicles']:SaveTuning(id, props)Returns
Nothing. Invalid props are ignored. The plate inside the props is always replaced with the vehicle's own.
Never pass props that came straight from a player's client without checking them on the server: whatever you save here is the car's tuning from now on.
StoreVehicle
Parks a vehicle: deletes its entity if it is out and sets its state and garage.
Side: Server · Waits: no
StoreVehicle(id: number, garage: string | null, state?: VehicleState): voidexports['ai-vehicles']:StoreVehicle(id, garage, state)Parameters
Prop
Type
Returns
Nothing. It does not save the condition first: call SaveVehicle before it when the damage and fuel should be kept. To park through whatever garage script the server runs, use the lib's garages.store instead.
SetOwner
Gives a vehicle to another owner (a sale between players, a car moved into a job fleet).
Side: Server · Waits: no
SetOwner(id: number, owner: VehicleOwner): voidexports['ai-vehicles']:SetOwner(id, owner)Returns
Nothing. An invalid owner or unknown id does nothing. The keys of the old owner are not taken: remove them through the lib's vehicleKeys.remove if needed.
Example
vehicles.SetOwner(vehicleId, { type: "job", id: "mechanic" });DeleteVehicle
Deletes an owned vehicle for good: its entity if it is out, and its database row.
Side: Server · Waits: no
DeleteVehicle(id: number): voidexports['ai-vehicles']:DeleteVehicle(id)Returns
Nothing.
This cannot be undone. The vehicle, its look and its tuning are gone.
SpawnVehicle
Creates the entity of an owned vehicle in the world with its look, plate, fuel and state bags, and gives the keys to asker through the active key system. The vehicle's state becomes out.
Side: Server · Waits: no (the result arrives in cb)
SpawnVehicle(id: number, at: { x: number; y: number; z: number; heading: number }, asker: number, cb: (netId: number | null) => void, purpose?: KeyPurpose, setup?: VehicleSetup): voidexports['ai-vehicles']:SpawnVehicle(id, at, asker, function(netId) end, purpose, setup)Parameters
Prop
Type
Returns
Nothing. cb gets the network id, or null when the vehicle does not exist, is already out, is being spawned right now, or the game could not create it.
Example
import { resourceExport } from "@aicore-fivem/lib/server";
const vehicles = resourceExport("ai-vehicles");
export function bringOut(source: number, vehicleId: number): void {
const ped = GetPlayerPed(String(source));
const [x, y, z] = GetEntityCoords(ped);
const heading = GetEntityHeading(ped);
vehicles.SpawnVehicle(vehicleId, { x: x + 3, y, z, heading }, source, (netId) => {
if (netId === null) console.log(`vehicle ${vehicleId} could not come out`);
});
}A vehicle that is already out is refused (cb(null)). If its entity later disappears while it is out, it moves to the impound state.
Events
ai-vehicles:owners
Fires when vehicles enter ai-vehicles' memory or change owner, and when plates leave memory. One batch per server tick. Read GetPlateOwners once at start, then apply these batches to keep a plate-to-owner copy. The name is VEHICLES_EVENTS.owners in @aicore-fivem/shared.
Side: Server (local event, not sent to clients)
Prop
Type
import { resourceExport } from "@aicore-fivem/lib/server";
import { VEHICLES_EVENTS } from "@aicore-fivem/shared";
const owners = new Map<string, string>();
for (const [plate, type, id] of resourceExport("ai-vehicles").GetPlateOwners())
owners.set(plate, `${type}:${id}`);
on(VEHICLES_EVENTS.owners, (puts: [string, string, string][], removes: string[]) => {
for (const [plate, type, id] of puts) owners.set(plate, `${type}:${id}`);
for (const plate of removes) owners.delete(plate);
});State bags
ai-vehicles sets these on every owned vehicle it spawns. Names are in VEHICLE_BAGS (@aicore-fivem/shared).
| Bag | Type | Meaning |
|---|---|---|
ai:owned | true | The entity is an owned vehicle. |
ai:vid | number | Its id in ai-vehicles. |
ai:props | VehicleProps | The saved look. ai-core's client that owns the entity applies it. |
ai:setup | VehicleSetup | A spawn look for a vehicle without props, applied once. |
fuel | number | Fuel 0-100. The fuel script keeps it from then on. |
local vehicle = GetVehiclePedIsIn(PlayerPedId(), false)
if Entity(vehicle).state['ai:owned'] then
print('owned vehicle', Entity(vehicle).state['ai:vid'])
endqbx_vehicles API
ai-vehicles provides qbx_vehicles, so these calls reach it. Shapes follow Qbox: state is 0 out, 1 garage, 2 impound.
| Export | What it does |
|---|---|
GetPlayerVehicles(filters: { citizenid?, garage? }) | Vehicles of an online character, optionally only one garage. Returns { id, citizenid, modelName, garage, state, depotPrice, props }[]. |
GetPlayerVehicle(id: number) | One vehicle in the same shape, or nil. |
CreatePlayerVehicle(request: { model, citizenid, garage?, props? }) | Creates a vehicle for an online character. Returns the id, or nil, { code, message } (bad_request, not_found). |
SetPlayerVehicleOwner(id: number, citizenid: string) | New owner (online). true when it worked. |
DeletePlayerVehicles(idType: "plate" | "vehicleId", idValue) | Deletes one vehicle. true when found. |
GetVehicleIdByPlate(plate: string) | The id, or nil. |
DoesPlayerVehiclePlateExist(plate: string) | true when the plate is owned. |
SaveVehicle(entity: number, options: { props?, state?, garage? }) | Saves a spawned vehicle, tuning included. Takes AI Core's props or the ox_lib / qb-core props shape. Props of another model than the entity are refused (state and garage still save). |
GetPlayerVehicle returns props in AI Core's VehicleProps shape, not ox_lib's. depotPrice is always 0.