AI Core

Screens and controls

NuiScreen, hud, keyHints and controls - your own full-screen NUI, hiding every HUD, key help lines and disabled controls.

Helpers for scripts with their own NUI page or tool mode: open a full-screen page with focus and hidden HUDs, list the keys of a tool on the HUD, and block controls without writing a per-frame loop.

NuiScreen

new NuiScreen

Your resource's full-screen NUI page in one object. open takes the focus, hides every HUD (through hud) and sends the open message; close gives the focus back, shows the HUDs, sends { action: "close" } to the page and runs your onClose. The page's own close NUI callback closes it too. Create one per resource, at the top of the file.

Side: Client · Waits: no

Signature
new NuiScreen<M extends NuiPageMessage = NuiPageMessage>(name: string, options?: NuiScreenOptions)

No Lua twin: Lua resources call SetNuiFocus, aiLib.hud.hide / show and RegisterNUICallback('close', ...) themselves.

Parameters

Prop

Type

NuiScreenOptions

Prop

Type

NuiPageMessage

What open and send take: { action: string; data?: unknown }. Pass your own union type as M to type every message.

Members

Prop

Type

Example

resource/client/index.ts
import { callAction, NuiScreen, ScriptCamera } from "@aicore-fivem/lib/client";
import { readText } from "@aicore-fivem/lib/shared";

type Message =
  | { action: "open"; data: { items: string[] } }
  | { action: "result"; data: boolean };

const camera = new ScriptCamera();
const screen = new NuiScreen<Message>("shop", {
  onClose: () => camera.stop(500),
});

export function openShop(items: string[]): void {
  camera.start({ x: 26.5, y: -1345.0, z: 30.2 }, { pointAt: { x: 25.7, y: -1347.3, z: 29.5 } }, 500);
  screen.open({ action: "open", data: { items } });
}

// The page calls fetch(`https://${GetParentResourceName()}/buy`, { body: JSON.stringify("water") }).
screen.on(
  "buy",
  (data) => readText(data, 32),
  async (item) => {
    const reply = await callAction("myshop:buy", [item], { fallback: "BUY_FAILED" });
    return { ok: reply !== null };
  },
);

Use NuiScreen for full-screen pages. Overlays that keep the HUD on screen (a chat box, a radial wheel, a target eye) keep their own focus code.

hud

HUDs (ai-hud and the other HUD scripts ai-core supports) through ai-core. A full-screen UI hides them on open and shows them on close. Reasons are counted per resource, so two screens open at once keep the HUDs hidden until both close. While any reason holds, ai-core hides every HUD and the minimap.

hud.hide

Hides every HUD for a reason, until hud.show with the same reason.

Side: Client · Waits: no

Signature
hud.hide(reason: string): void
Lua
aiLib.hud.hide(reason)

Parameters

Prop

Type

Returns

void.

Example

import { hud } from "@aicore-fivem/lib/client";

RegisterCommand(
  "cinema",
  () => {
    if (hud.visible) hud.hide("cinema");
    else hud.show("cinema");
  },
  false,
);

hud.show

Removes one hide reason. The HUDs come back when no reason of any resource is left.

Side: Client · Waits: no

Signature
hud.show(reason: string): void
Lua
aiLib.hud.show(reason)

Parameters

Prop

Type

Returns

void. See the hud.hide example.

hud.visible

Whether HUDs show now (no full-screen UI open).

Side: Client · Waits: no

Signature
hud.visible: boolean // read-only property
Lua
local visible = aiLib.hud.visible() -- a function in Lua

Returns

boolean: true when no hide reason of any resource holds.

hud.onChange

Runs a handler whenever HUDs show or hide. A HUD script uses it to hide itself.

Side: Client · Waits: no

Signature
hud.onChange(fn: (visible: boolean) => void): void

No Lua twin: listen to the local event ai-core:client:hudVisible (visible).

Parameters

Prop

Type

Returns

void.

Example

import { hud } from "@aicore-fivem/lib/client";

hud.onChange((visible) => SendNUIMessage({ action: "visible", data: visible }));

keyHints

Key help lines a script shows for a while (an admin noclip's keys, a minigame's controls), listed by the HUD on the left next to the ones keybinds declare with hint. Hints of a stopped resource disappear by themselves.

keyHints.show

Shows a key hint, or changes the one with the same id.

Side: Client · Waits: no

Signature
keyHints.show(id: string, hint: KeyHintRequest): void
Lua
aiLib.keyHints.show(id, hint)

Parameters

Prop

Type

KeyHintRequest

Prop

Type

The type is KeyHintRequest.

Returns

void.

Example

import { createLocale, keyHints } from "@aicore-fivem/lib/client";

const Locale = createLocale<typeof import("../../locales/en.json")>();

export function startPlacing(): void {
  keyHints.show("rotate", { label: Locale("ROTATE"), key: "Q / E", icon: "rotate" });
  keyHints.show("place", { label: Locale("PLACE"), keybind: "myscript_place", icon: "check" });
}

export function stopPlacing(): void {
  keyHints.hide("rotate");
  keyHints.hide("place");
}

keyHints.hide

Removes one of your key hints. An unknown id does nothing.

Side: Client · Waits: no

Signature
keyHints.hide(id: string): void
Lua
aiLib.keyHints.hide(id)

Parameters

Prop

Type

Returns

void. See the keyHints.show example.

controls

Disabled controls of your resource, with one per-frame job for all of them. Each reason (cuffed, menu, placing) adds its controls and removes them when it ends; the job runs only while any reason is active. Never write your own setTick with DisableControlAction.

controls.disable

Disables a list of controls every frame until controls.enable(reason). Calling it again with the same reason replaces that reason's list.

Side: Client · Waits: no

Signature
controls.disable(reason: string, controls: readonly number[], group?: number): void
Lua
aiLib.controls.disable(reason, controls, group)

Parameters

Prop

Type

Returns

void.

Example

import { controls, onServerEvent } from "@aicore-fivem/lib/client";

const CUFFED = [21, 22, 23, 24, 25, 37, 44, 140, 141, 142, 143, 257, 263, 264];

onServerEvent(
  "mypolice:cuffed",
  { args: ([on]) => (typeof on === "boolean" ? [on] : null) },
  (on) => (on ? controls.disable("cuffed", CUFFED) : controls.enable("cuffed")),
);

controls.disableAll

Disables every control (input groups 0, 1 and 2) every frame until controls.enable(reason), except the ones you keep. Use it for a noclip or a free camera, and read the disabled keys with IsDisabledControlPressed.

Side: Client · Waits: no

Signature
controls.disableAll(reason: string, except?: readonly number[]): void
Lua
aiLib.controls.disableAll(reason, except)

Parameters

Prop

Type

Returns

void.

Example

import { controls, every } from "@aicore-fivem/lib/client";

const fly = every(0, () => {
  if (IsDisabledControlPressed(0, 32)) console.log("forward");
}, { active: false, name: "noclip" });

export function noclip(on: boolean): void {
  if (on) controls.disableAll("noclip", [1, 2, 249]);
  else controls.enable("noclip");
  fly.set(on);
}

controls.enable

Ends one reason: its controls work again unless another reason still disables them. An unknown reason does nothing.

Side: Client · Waits: no

Signature
controls.enable(reason: string): void
Lua
aiLib.controls.enable(reason)

Parameters

Prop

Type

Returns

void. See the examples above.

controls.isDisabled

Whether a reason of your resource is active now.

Side: Client · Waits: no

Signature
controls.isDisabled(reason: string): boolean

No Lua twin.

Parameters

Prop

Type

Returns

boolean: true while that reason holds.

Example

import { controls } from "@aicore-fivem/lib/client";

if (controls.isDisabled("cuffed")) console.log("the player is cuffed");

On this page