AI Core

Vehicles

spawnVehicle, vehicleType, randomPlate, nearest vehicles, entities from client net ids, vehicleKeys, fuel and garages.

TypeScript
import { spawnVehicle, vehicleKeys, fuel, garages, vehicleFromNet } from "@aicore-fivem/lib/server";

Spawning

spawnVehicle

Creates a networked vehicle on the server and sets it up in one call: plate, fuel, look, lock, routing bucket, keys for the right purpose, a driver and passengers. Use it for every script vehicle (job vehicles, rentals, garage vehicles, admin spawns).

Side: Server · Waits: yes (Promise in TypeScript, yields the thread in Lua)

Signature
spawnVehicle(options: SpawnVehicleOptions): Promise<number | null>
Lua
local vehicle = aiLib.spawnVehicle(options) -- entity or nil, call inside a thread

Parameters

Prop

Type

SpawnVehicleOptions

Prop

Type

Returns

Promise<number | null>: the vehicle entity handle. null when the model does not exist (the asker client said so), the entity was not created within 5 seconds, or the type is unknown.

Example

import { onClientCallback, spawnVehicle, hasCharacter, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";

const DEPOT = { x: 895.4, y: -179.3, z: 74.7 };

onClientCallback(
  "my-taxi:start",
  async (source) => {
    const vehicle = await spawnVehicle({
      model: "taxi",
      coords: { x: 899.1, y: -180.6, z: 73.8, heading: 238 },
      asker: source,
      keysTo: source,
      purpose: "job",
      driver: source,
      fuel: 100,
      setup: { dirt: 0 },
    });
    if (!vehicle) return fail("SPAWN_FAILED");
    return { ok: true, netId: NetworkGetNetworkIdFromEntity(vehicle) };
  },
  { guards: [hasCharacter(), near(DEPOT, 5)], lock: true },
);

The keys wait (up to 3 seconds) until the server reads the plate: before the owner client's first sync, the server reads an empty plate. Seated players are put in again for up to 2 seconds until they sit. In TypeScript a model's type from one client serves only that player until a second player's client gives the same answer; the Lua twin keeps the first answer it gets.

vehicleType

The spawn type of a model, asked from a player's client. Use it to check a model exists before you take money.

Side: Server · Waits: yes (Promise)

Signature
vehicleType(model: string, asker: number): Promise<string | null>

No Lua twin: aiLib.spawnVehicle with asker checks it and returns nil for an unknown model.

Prop

Type

Returns

Promise<string | null>: automobile, bike, boat, heli, plane, submarine, trailer or train; null when the game has no such vehicle or the client gave no valid answer. An answer is kept for everyone once two different players' clients agreed on it, so one modified client can only break its own spawns.

Example

import { onClientCallback, vehicleType } from "@aicore-fivem/lib/server";
import { fail, oneArg, readText } from "@aicore-fivem/lib/shared";

onClientCallback("my-dealer:buy", { args: oneArg((v) => readText(v, 32)), lock: true }, async (source, model) => {
  if (!(await vehicleType(model, source))) return fail("UNKNOWN_MODEL");
  // take the money, then spawnVehicle(...)
  return { ok: true };
});

randomPlate

A random plate like the game's own (two digits, three letters, three digits), or your prefix followed by digits.

Side: Server · Waits: no

Signature
randomPlate(prefix?: string): string

No Lua twin (aiLib.spawnVehicle sets a random plate when you pass none).

Prop

Type

Returns an 8-character plate (42ABC123, or TAXI1234 for randomPlate("TAXI")). It is not checked for uniqueness: check your own table before you store it.

const plate = randomPlate("RENT");

Finding vehicles

nearestVehicleTo

The closest vehicle within metres of a player that passes your filter. The vehicle the player sits in wins first.

Side: Server · Waits: no

Signature
nearestVehicleTo(source: number, metres: number, filter?: (vehicle: number) => boolean): number
Lua
local vehicle = aiLib.nearestVehicleTo(source, metres, filter) -- entity or 0

Prop

Type

Returns the vehicle entity, or 0 when none.

const vehicle = nearestVehicleTo(source, 5);
if (!vehicle) return fail("NO_VEHICLE");

It walks every vehicle on the server: use it for commands and actions (rate-limited), never in a tick.

nearestVehicleAt

The closest vehicle within metres of a point. Use it to check a spawn spot is free.

Side: Server · Waits: no

Signature
nearestVehicleAt(point: { x: number; y: number; z: number }, metres: number, filter?: (vehicle: number) => boolean): number

No Lua twin.

Returns the vehicle entity, or 0 when none. Walks every vehicle, like nearestVehicleTo.

const SPOT = { x: 899.1, y: -180.6, z: 73.8 };
if (nearestVehicleAt(SPOT, 3)) return fail("SPOT_BLOCKED");

Entities from client input

A client sends a network id, never an entity handle. These turn a net id into the live server entity and check it, so you never call NetworkGetEntityFromNetworkId + DoesEntityExist + GetEntityType by hand.

entityFromNet

The live entity behind a client's network id.

Side: Server · Waits: no

Signature
entityFromNet(netId: unknown, type?: 1 | 2 | 3): number

No Lua twin (Lua has vehicleFromNet).

Prop

Type

Returns the entity, or 0 when the value is not a positive whole number, not networked, gone, or of another type.

const prop = entityFromNet(rawNetId, 3);
if (!prop) return fail("NOT_FOUND");

pedFromNet

entityFromNet(netId, 1): the live ped, or 0.

Side: Server · Waits: no

Signature
pedFromNet(netId: unknown): number

No Lua twin.

const ped = pedFromNet(rawNetId);

vehicleFromNet

entityFromNet(netId, 2): the live vehicle, or 0.

Side: Server · Waits: no

Signature
vehicleFromNet(netId: unknown): number
Lua
local vehicle = aiLib.vehicleFromNet(netId) -- entity or 0
const vehicle = vehicleFromNet(rawNetId);
if (!vehicle) return fail("NO_VEHICLE");

vehicleNearPlayer

The vehicle behind a client's network id, but only when the player is near it (or in its driver seat).

Side: Server · Waits: no

Signature
vehicleNearPlayer(source: number, netId: unknown, options?: { metres?: number; driver?: boolean }): number
Lua
local vehicle = aiLib.vehicleNearPlayer(source, netId, options) -- entity or 0

Prop

Type

Returns the vehicle, or 0 when the id is bad, the vehicle is gone, or the player is too far / not the driver.

onClientCallback("my-tow:hook", { args: oneArg(readId), lock: true }, (source, netId) => {
  const vehicle = vehicleNearPlayer(source, netId, { metres: 6 });
  if (!vehicle) return fail("TOO_FAR");
  return { ok: true };
});

Keys

vehicleKeys goes through ai-core's key layer: the key script the server runs (ai-vehiclekeys, or another the owner picks) answers. A vehicle is a server entity handle or a plate.

vehicleKeys.give

Gives a player the keys of a vehicle.

Side: Server · Waits: no

Signature
vehicleKeys.give(source: number, vehicle: number | string, purpose?: KeyPurpose): void
Lua
aiLib.vehicleKeys.give(source, vehicle, purpose)

Prop

Type

Returns void.

vehicleKeys.give(source, vehicle, "rental");

vehicleKeys.remove

Takes a player's keys of a vehicle.

Side: Server · Waits: no

Signature
vehicleKeys.remove(source: number, vehicle: number | string): void
Lua
aiLib.vehicleKeys.remove(source, vehicle)

Returns void.

vehicleKeys.remove(source, "RENT1234");

vehicleKeys.has

Whether a player holds the keys.

Side: Server · Waits: no

Signature
vehicleKeys.has(source: number, vehicle: number | string): boolean
Lua
local has = aiLib.vehicleKeys.has(source, vehicle)

Returns boolean. true also when the key script cannot tell or none runs, so do not use it as the only lock on something valuable.

if (!vehicleKeys.has(source, vehicle)) return fail("NO_KEYS");

Fuel

fuel reads and sets a vehicle's fuel (0 to 100) through ai-core's fuel layer, whatever fuel script runs. No Lua twin on the server: call ai-core's exports GetVehicleFuel / SetVehicleFuel.

fuel.get

Side: Server · Waits: no

Signature
fuel.get(vehicle: number): number | null

Returns the level of a server vehicle entity (0 to 100), or null when it has none.

const level = fuel.get(vehicle) ?? 0;

fuel.set

Side: Server · Waits: no

Signature
fuel.set(vehicle: number, level: number): boolean

Prop

Type

Returns true when set, false for a wrong vehicle.

fuel.set(vehicle, 100);

fuel.provider

Side: Server · Waits: no

Signature
fuel.provider(): string | null

Returns the resource name of the fuel script that answers (ai-fuel, ox_fuel, LegacyFuel...), or null when none runs.

console.log(`fuel through ${fuel.provider() ?? "nothing"}`);

Garages

garages goes through ai-core's garage layer, whatever garage script runs; each script answers only what it exposes. No Lua twin.

garages.impound

Sends a vehicle to the impound, or opens the garage script's impound form for by.

Side: Server · Waits: no

Signature
garages.impound(vehicle: number, by?: number): boolean

Prop

Type

Returns true when the garage script took it. false when nothing took it: delete the vehicle yourself.

if (!garages.impound(vehicle, source)) DeleteEntity(vehicle);

garages.store

Stores a vehicle in a garage.

Side: Server · Waits: no

Signature
garages.store(vehicle: number, garage?: string | null, by?: number): boolean

Prop

Type

Returns true when stored, false when nothing took it.

if (!garages.store(vehicle, "legion", source)) return fail("STORE_FAILED");

garages.open

Opens the garage menu of the garage script for a player.

Side: Server · Waits: no

Signature
garages.open(source: number, garage?: string | null): boolean

Returns true when opened, false when the script has no such menu.

garages.open(source, "pillbox");

garages.stored

A player's vehicles in garages or the impound.

Side: Server · Waits: yes (Promise)

Signature
garages.stored(source: number): Promise<GaragedVehicle[] | null>

Returns GaragedVehicle[] (plate, model, garage, impounded), or null when the script cannot tell or ai-core is stopped.

const list = await garages.stored(source);
const impounded = list?.filter((v) => v.impounded).length ?? 0;

garages.provider

Side: Server · Waits: no

Signature
garages.provider(): string | null

Returns the garage script that answers, or null when none runs.

if (!garages.provider()) console.warn("no garage script runs");

On this page