Layers through ai-core
medical, appearance, gestures, seatbelt, fuel, mdt, radial, world and inventory - client calls that reach whatever death, clothing, emote, belt, fuel, MDT, radial, weather or inventory script the server runs.
These objects never talk to a specific script. They ask ai-core, and ai-core forwards to whichever script the server runs for that job: ai-death or another death script, ai-appearance or tgiann-clothing, any supported emote or radial script. Your script keeps working when the owner swaps one. How the layers work is on Layers and the bridge.
When no script of that kind runs, the calls answer false, null or the game's own value, as each entry says.
medical
medical.isDead
Whether the local player is down (dead or in last stand), in whatever death script runs. Death scripts keep a downed ped alive to animate it, so IsEntityDead alone misses them. A memory read after the first call.
Side: Client · Waits: no
medical.isDead(): booleanNo Lua twin: call exports['ai-core']:IsDead() and listen to the local event ai-core:client:dead (dead).
Returns
boolean: true when ai-core's medical layer says the player is down, or the ped is dead for the game.
Example
import { medical, notify } from "@aicore-fivem/lib/client";
RegisterCommand(
"phone",
() => {
if (medical.isDead()) return notify("You cannot use the phone now", "error");
SetNuiFocus(true, true);
},
false,
);medical.onChange
Runs a handler when the local player goes down or gets up.
Side: Client · Waits: no
medical.onChange(fn: (dead: boolean) => void): voidNo Lua twin: AddEventHandler('ai-core:client:dead', function(dead) end).
Parameters
Prop
Type
Returns
void.
Example
import { medical, Points } from "@aicore-fivem/lib/client";
const points = new Points();
medical.onChange(() => points.refresh()); // points whose canShow reads medical.isDead()appearance
Looks on peds through ai-core's appearance layer, whatever clothing script runs.
appearance.apply
Puts a stored look on a ped of the look's model. Get the look on the server with appearance.get(charId), create the ped with look.model, then apply. On the player's own ped it changes their clothes.
Side: Client · Waits: no
appearance.apply(ped: number, look: CharacterAppearance): booleanlocal ok = aiLib.appearance.apply(ped, look)Parameters
Prop
Type
The type is CharacterAppearance.
Returns
boolean: false when the ped is gone, the model differs, or no clothing script runs.
Example
import { appearance, LocalPed, triggerServerCallback } from "@aicore-fivem/lib/client";
import type { CharacterAppearance } from "@aicore-fivem/shared";
// A sleeping copy of a character, dressed like them.
export async function showSleeper(charId: number): Promise<void> {
const look = (await triggerServerCallback("mysleep:look", [charId]).catch(() => null)) as CharacterAppearance | null;
if (!look) return;
new LocalPed({
model: look.model,
coords: { x: 151.2, y: -1004.6, z: 29.4, heading: 90 },
onSpawn: (ped) => appearance.apply(ped, look),
});
}Check what the server sends before you cast it. A ped created with another model than look.model cannot take the look: apply answers false.
appearance.read
The look a ped wears now.
Side: Client · Waits: no
appearance.read(ped: number): CharacterAppearance | nulllocal look = aiLib.appearance.read(ped) -- table or nilParameters
Prop
Type
Returns
CharacterAppearance | null: the look, or null (nil in Lua) when the clothing script cannot tell or none runs.
Example
import { appearance, cache } from "@aicore-fivem/lib/client";
const before = appearance.read(cache.ped); // put it back later with appearance.applyappearance.openMenu
Opens the clothing script's clothing shop, barber or saved outfits for the player.
Side: Client · Waits: no
appearance.openMenu(menu: ClothingMenu): booleanlocal ok = aiLib.appearance.openMenu(menu)Parameters
Prop
Type
The type is ClothingMenu.
Returns
boolean: false when the clothing script has no such menu or none runs.
Example
import { appearance, Points } from "@aicore-fivem/lib/client";
const points = new Points();
points.add("barber", {
coords: { x: -814.3, y: -183.8, z: 37.6 },
label: "Barber",
onPressed: () => appearance.openMenu("barber"),
});appearance.wearOutfit
Puts a job outfit (a uniform) on the player until reloadSkin. It is not saved: a reconnect or reloadSkin gives the player's own clothes back. Only the listed pieces change.
Side: Client · Waits: no
appearance.wearOutfit(outfit: JobOutfit): booleanlocal ok = aiLib.appearance.wearOutfit(outfit)Parameters
Prop
Type
The types are JobOutfit and OutfitPiece.
Returns
boolean: false when it cannot (no clothing script, a model it does not support).
Example
import { appearance } from "@aicore-fivem/lib/client";
appearance.wearOutfit({
components: [
{ id: 11, collection: "", index: 55, texture: 0 },
{ id: 4, collection: "", index: 35, texture: 0 },
],
props: [{ id: 0, collection: "", index: -1, texture: 0 }],
});appearance.reloadSkin
Puts the player's saved look back on (takes a job outfit off).
Side: Client · Waits: no
appearance.reloadSkin(): booleanlocal ok = aiLib.appearance.reloadSkin()Returns
boolean: false without a clothing script.
Example
import { appearance } from "@aicore-fivem/lib/client";
RegisterCommand("offduty", () => appearance.reloadSkin(), false);gestures
Hands up, pointing and emotes of whatever emote script runs, through ai-core.
gestures.isHandsUp
Whether the local player has the hands up.
Side: Client · Waits: no
gestures.isHandsUp(): booleanlocal up = aiLib.gestures.isHandsUp()Returns
boolean: true while the hands are up in the running emote script.
Example
import { gestures, onServerCallback } from "@aicore-fivem/lib/client";
// The server asks before a robbery whether the victim surrendered.
onServerCallback("myrob:surrendered", () => gestures.isHandsUp());gestures.isPointing
Whether the local player is pointing.
Side: Client · Waits: no
gestures.isPointing(): booleanlocal pointing = aiLib.gestures.isPointing()Returns
boolean: true while pointing.
Example
if (gestures.isPointing()) return; // do not start an emote over pointinggestures.provider
The emote script that answers hands up and pointing.
Side: Client · Waits: no
gestures.provider(): string | nulllocal name = aiLib.gestures.provider()Returns
string | null: its resource name, or null (nil) when none runs.
Example
console.log(`hands up from ${gestures.provider() ?? "nothing"}`);gestures.playEmote
Plays an emote by its command name (what players type after e) in the running emote script.
Side: Client · Waits: no
gestures.playEmote(name: string): booleanlocal ok = aiLib.gestures.playEmote(name)Parameters
Prop
Type
Returns
boolean: false without an emote script.
Example
import { gestures } from "@aicore-fivem/lib/client";
RegisterCommand("hi", () => gestures.playEmote("wave"), false);gestures.cancelEmote
Stops the emote the player plays (cuffed, knocked down).
Side: Client · Waits: no
gestures.cancelEmote(): booleanlocal ok = aiLib.gestures.cancelEmote()Returns
boolean: false without an emote script.
Example
onServerEvent("mypolice:cuffed", () => gestures.cancelEmote());gestures.emoteProvider
The emote script that plays emotes (it may differ from the one answering hands up).
Side: Client · Waits: no
gestures.emoteProvider(): string | nulllocal name = aiLib.gestures.emoteProvider()Returns
string | null: its resource name, or null (nil) when none runs.
Example
if (gestures.emoteProvider() === null) console.log("no emote script: skipping the emote");seatbelt
The local player's seat belt through ai-core, whatever seat belt script runs.
seatbelt.isOn
Whether the belt is on. Ask on demand, not every frame.
Side: Client · Waits: no
seatbelt.isOn(): boolean | nulllocal worn = aiLib.seatbelt.isOn() -- boolean or nilReturns
boolean | null: true or false; null (nil) when no seat belt script answers.
Example
import { cache, notify, onCache, seatbelt } from "@aicore-fivem/lib/client";
onCache("vehicle", (vehicle) => {
if (vehicle !== false && seatbelt.isOn() === false) notify("Buckle up", "warning");
});seatbelt.onChange
Runs a handler when the belt changes. Only seat belt scripts that report changes trigger it.
Side: Client · Waits: no
seatbelt.onChange(fn: (worn: boolean | null) => void): voidaiLib.seatbelt.onChange(function(worn) end)Parameters
Prop
Type
Returns
void.
Example
seatbelt.onChange((worn) => SendNUIMessage({ action: "belt", data: worn === true }));seatbelt.provider
The seat belt script that answers.
Side: Client · Waits: no
seatbelt.provider(): string | nulllocal name = aiLib.seatbelt.provider()Returns
string | null: its resource name, or null (nil) when none answers.
Example
if (seatbelt.provider() === null) console.log("no seat belt script runs");fuel
fuel.get
A vehicle's fuel level. The server keeps a fuel state bag for every vehicle whatever fuel script runs, so this is a memory read; without that bag it is the game's tank level.
Side: Client · Waits: no
fuel.get(vehicle: number): numberNo Lua twin: read Entity(vehicle).state.fuel. Setting fuel is server-only (fuel.set on Vehicles).
Parameters
Prop
Type
Returns
number: 0-100.
Example
import { cache, every, fuel } from "@aicore-fivem/lib/client";
every(1000, () => {
if (cache.vehicle !== false) SendNUIMessage({ action: "fuel", data: Math.round(fuel.get(cache.vehicle)) });
});mdt
mdt.open
Opens the active police MDT for the local player. The MDT checks the job itself.
Side: Client · Waits: no
mdt.open(): booleanlocal ok = aiLib.mdt.open()Returns
boolean: false when no MDT runs or it cannot be opened from outside.
Example
import { mdt, notify } from "@aicore-fivem/lib/client";
RegisterCommand("mdt", () => {
if (!mdt.open()) notify("No MDT available", "error");
}, false);radial
Items on whichever radial menu runs (ai-radialmenu, or another through ai-core's radial layer). ai-core keeps them across radial restarts and drops them when your resource stops: add once at start.
radial.add
Adds an item to the wheel, or replaces the item with the same id.
Side: Client · Waits: no
radial.add(item: RadialItem): voidaiLib.radial.add(item)Parameters
Prop
Type
RadialItem
Prop
Type
The type is RadialItem.
Returns
void.
Example
import { cache, createLocale, hasJob, radial } from "@aicore-fivem/lib/client";
import { RADIAL_VEHICLE } from "@aicore-fivem/shared";
const Locale = createLocale<typeof import("../../locales/en.json")>();
radial.add({
id: "myscript:engine",
label: Locale("ENGINE"),
icon: "power-off",
parent: RADIAL_VEHICLE,
keepOpen: true,
canShow: () => cache.seat === -1,
onPressed: () => {
if (cache.vehicle === false) return;
SetVehicleEngineOn(cache.vehicle, !GetIsVehicleEngineRunning(cache.vehicle), false, true);
},
});
radial.add({
id: "myscript:police",
label: Locale("POLICE"),
icon: "shield-halved",
canShow: () => hasJob(["police"]),
items: [
{ id: "myscript:cuff", label: Locale("CUFF"), icon: "handcuffs", onPressed: () => emitNet("mypolice:cuff") },
],
});radial.remove
Removes one of your items. An unknown id does nothing.
Side: Client · Waits: no
radial.remove(id: string): voidaiLib.radial.remove(id)Parameters
Prop
Type
Returns
void.
Example
radial.remove("myscript:engine");radial.refresh
Reads every canShow of an open wheel again. Call it after something they read changed while the wheel may be open.
Side: Client · Waits: no
radial.refresh(): voidaiLib.radial.refresh()Returns
void.
Example
onMembershipChange(() => radial.refresh());world
The weather and time sync of whatever weather script runs, paused while a reason holds.
world.pauseSync
Pauses the weather and time sync for a reason: inside an interior, during a scene, or while your script sets its own weather.
Side: Client · Waits: no
world.pauseSync(reason: string): voidaiLib.world.pauseSync(reason)Parameters
Prop
Type
Returns
void.
Example
import { world } from "@aicore-fivem/lib/client";
export function enterApartment(): void {
world.pauseSync("apartment");
NetworkOverrideClockTime(12, 0, 0);
SetWeatherTypeNowPersist("EXTRASUNNY");
}
export function leaveApartment(): void {
world.resumeSync("apartment");
}world.resumeSync
Removes one pause reason; the sync runs again when no reason is left.
Side: Client · Waits: no
world.resumeSync(reason: string): voidaiLib.world.resumeSync(reason)Parameters
Prop
Type
Returns
void. See the world.pauseSync example.
inventory
The local player's inventory through ai-core's inventory layer: the inventory the server picked answers. Giving and taking items is server-only (Items).
inventory.openInventory
Opens the player's own inventory screen.
Side: Client · Waits: no
inventory.openInventory(): voidaiLib.inventory.openInventory()Returns
void.
Example
import { inventory } from "@aicore-fivem/lib/client";
RegisterCommand("bag", () => inventory.openInventory(), false);inventory.hasItem
Whether the player holds at least count of an item. Use it in canShow so the player only sees what they can do; the server checks again.
Side: Client · Waits: no
inventory.hasItem(item: string, count?: number): booleanlocal has = aiLib.inventory.hasItem(item, count)Parameters
Prop
Type
Returns
boolean: true when the player has enough.
Example
import { inventory, Points } from "@aicore-fivem/lib/client";
const points = new Points();
points.addVehicle("lockpick", {
label: "Lockpick",
icon: "unlock",
canShow: (vehicle) => GetVehicleDoorLockStatus(vehicle) >= 2 && inventory.hasItem("lockpick"),
onPressed: (vehicle) => emitNet("mykeys:lockpick", NetworkGetNetworkIdFromEntity(vehicle)),
});inventory.currentWeapon
The weapon item in the player's hand: its name, label and picture.
Side: Client · Waits: no
inventory.currentWeapon(): HeldWeapon | nulllocal weapon = aiLib.inventory.currentWeapon() -- table or nilReturns
HeldWeapon { name: string; label: string; image?: string } (name like WEAPON_PISTOL, image a nui:// url when the inventory has one), or null (nil) when the hand is empty.
Example
import { inventory, onCache } from "@aicore-fivem/lib/client";
// Read it when the weapon changes, never every frame.
onCache("weapon", () => SendNUIMessage({ action: "weapon", data: inventory.currentWeapon() }));