AI Core
Referência da APILib: cliente

UI compartilhada

notify, progress, menu, input, prompts, skillCheck, lockpick e itemPicker - a UI do jogador que o ai-lib desenha para todo recurso.

O ai-lib desenha uma UI compartilhada para todo recurso: cards de notificação, a barra de progresso, os prompts "aperte E", menus, diálogos de entrada e minigames. Seu script só os pede, então todo script do servidor tem a mesma cara e você não escreve NUI para eles. O seletor de itens é desenhado pelo ai-core.

Os textos que você passa são mostrados como estão: traduza-os antes (Locale("KEY") em TypeScript, t('KEY') em Lua).

Notificações

notify

Mostra um card de notificação na tela deste jogador.

Lado: Cliente · Espera: não

Signature
notify(text: string, kind?: NotificationKind, duration?: number): void
Lua
aiLib.notify(text, kind, duration)

Parâmetros

Prop

Type

O tipo de kind é NotificationKind. Para notificar um jogador a partir do servidor, use o notify(source, text, kind) do servidor.

Retorno

void.

Exemplo

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

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

notify(Locale("WELCOME"));
notify(Locale("NO_MONEY"), "error");
notify(Locale("SAVED"), "success", 2000);

Barra de progresso

progress

Executa uma ação cronometrada com a barra de progresso do ai-lib e uma animação ou cenário opcional, e espera até ela terminar. Ela termina antes (cancelada) quando o jogador morre, entra em um veículo, aperta a tecla de cancelar do ai-lib (padrão Backspace, só com canCancel), ou o seu script chama cancelProgress(). Um progresso por recurso por vez.

Lado: Cliente · Espera: sim (Promise em TypeScript, pausa a thread em Lua)

Signature
progress(options: ProgressOptions): Promise<boolean>
Lua
local finished = aiLib.progress(options) -- boolean, chame dentro de uma thread

Parâmetros

Prop

Type

ProgressOptions

Prop

Type

Retorno

Promise<boolean>: true quando a barra terminou; false quando foi cancelada, ou na hora quando outro progresso do seu recurso ainda está rodando. Lua retorna o mesmo boolean.

Exemplo

import { callAction, createLocale, nearestVehicle, notify, progress } from "@aicore-fivem/lib/client";

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

export async function repair(): Promise<void> {
  const vehicle = nearestVehicle(4, { notOwn: true });
  if (!vehicle) return notify(Locale("NO_VEHICLE"), "error");
  const [x = 0, y = 0, z = 0] = GetEntityCoords(vehicle, false);
  const done = await progress({
    label: Locale("REPAIRING"),
    duration: 8000,
    face: { x, y, z },
    anim: { dict: "mini@repair", clip: "fixing_a_player" },
    canCancel: true,
    disable: { move: true, combat: true },
  });
  if (!done) return notify(Locale("CANCELLED"), "error");
  await callAction("mymech:repair", [NetworkGetNetworkIdFromEntity(vehicle)], { fallback: "REPAIR_FAILED" });
}

O resultado é a palavra do cliente: um trapaceiro pode pular a barra. Quando o servidor paga pela ação (itens, dinheiro, um conserto), rode a barra a partir do servidor com progressFor(source, options) (Entrada do cliente): ela só responde true quando passou tempo suficiente no servidor também.

cancelProgress

Cancela o progresso em andamento do seu recurso, quer o jogador possa cancelá-lo ou não. A chamada de progress então resolve false. Nada acontece quando nenhum progresso está rodando.

Lado: Cliente · Espera: não

Signature
cancelProgress(): void
Lua
aiLib.progress.cancel()

Retorno

void.

Exemplo

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

// O servidor diz que o alvo foi roubado por outra pessoa.
onServerEvent("myrob:taken", () => cancelProgress());

isProgressRunning

Se um progresso do seu recurso está rodando agora.

Lado: Cliente · Espera: não

Signature
isProgressRunning(): boolean
Lua
local running = aiLib.progress.isRunning()

Retorno

boolean: true enquanto a barra do seu recurso roda. As barras de outros recursos não contam.

Exemplo

import { isProgressRunning, menu } from "@aicore-fivem/lib/client";

export async function openMenu(): Promise<void> {
  if (isProgressRunning()) return; // ocupado
  await menu({ title: "Actions", items: [{ id: "a", label: "Action" }] });
}

Mostra o menu do ai-lib e espera a escolha do jogador. As setas movem, Enter escolhe. Itens com checked são linhas de interruptor que mudam no lugar sem fechar o menu. Em um submenu (back: true), um Escape curto resolve MENU_BACK para que você possa abrir o menu anterior; segurar Escape fecha.

Lado: Cliente · Espera: sim (Promise em TypeScript, pausa a thread em Lua)

Signature
menu(request: MenuRequest, listeners?: ((item: string) => void) | MenuListeners): Promise<string | null>
Lua
local picked = aiLib.menu.show(request, listeners) -- string ou nil, chame dentro de uma thread

Parâmetros

Prop

Type

Prop

Type

Prop

Type

Os tipos são MenuRequest e MenuItem.

Prop

Type

Retorno

Promise<string | null>: o id do item escolhido; "__back" (MENU_BACK de @aicore-fivem/shared) depois de um Escape curto em um submenu; null quando o jogador fechou o menu. Lua retorna o mesmo, nil para fechado.

Exemplo

import { callAction, createLocale, menu } from "@aicore-fivem/lib/client";
import { MENU_BACK } from "@aicore-fivem/shared";

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

export async function vehicleMenu(vehicle: number): Promise<void> {
  const pick = await menu({
    title: Locale("VEHICLE"),
    items: [
      { id: "doors", label: Locale("DOORS"), icon: "door-open" },
      { id: "engine", label: Locale("ENGINE"), icon: "power-off", checked: engineOn },
    ],
  }, {
    onToggle: (item, checked) => {
      if (item !== "engine") return;
      engineOn = checked;
      SetVehicleEngineOn(vehicle, checked, false, true);
    },
  });
  if (pick === "doors") await doorsMenu(vehicle);
}

async function doorsMenu(vehicle: number): Promise<void> {
  const pick = await menu({
    title: Locale("DOORS"),
    back: true,
    items: [0, 1, 2, 3].map((door) => ({ id: String(door), label: Locale("DOOR", door + 1) })),
  });
  if (pick === MENU_BACK) return vehicleMenu(vehicle);
  if (pick !== null) SetVehicleDoorOpen(vehicle, Number(pick), false, false);
}

O id escolhido vem do cliente do jogador: o servidor precisa verificar se é uma escolha válida.

input

Mostra o diálogo de entrada do ai-lib e espera os valores. Cada campo é uma caixa de número ou uma caixa de texto.

Lado: Cliente · Espera: sim (Promise em TypeScript, pausa a thread em Lua)

Signature
input(request: InputRequest): Promise<Record<string, string | number> | null>
Lua
local values = aiLib.input(request) -- table ou nil, chame dentro de uma thread

Parâmetros

Prop

Type

InputRequest

Prop

Type

InputField: number

Prop

Type

InputField: text

Prop

Type

Os tipos são InputRequest e InputField.

Retorno

Promise<Record<string, string | number> | null>: os valores digitados por name de campo quando o jogador confirmou; null quando ele fechou o diálogo. Valores que não são nem string nem número ficam de fora. Lua retorna a tabela ou nil.

Exemplo

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

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

export async function sendBill(target: number): Promise<void> {
  const values = await input({
    title: Locale("BILL"),
    confirm: Locale("SEND"),
    fields: [
      { name: "amount", label: Locale("AMOUNT"), type: "number", min: 1, max: 100000 },
      { name: "reason", label: Locale("REASON"), type: "text", maxLength: 80 },
    ],
  });
  if (!values) return;
  await callAction("mybill:send", [target, values.amount, values.reason], { fallback: "BILL_FAILED" });
}

min, max e maxLength só orientam o jogador. O servidor precisa verificar cada valor de novo (readInt, readText no handler do servidor).

itemPicker

Ferramentas de admin: mostra o seletor de itens do ai-core. Ele lista todos os itens do inventário ativo com imagem e uma busca; os cliques preenchem uma lista à direita (1 por clique, 10 com Ctrl, 100 com Shift) que para no limite de peso do alvo. A lista de itens só é enviada aos admins.

Lado: Cliente · Espera: sim (Promise em TypeScript, pausa a thread em Lua)

Signature
itemPicker(request: ItemPickerRequest): Promise<PickedItem[] | null>
Lua
local list = aiLib.itemPicker(request) -- table ou nil, chame dentro de uma thread

Parâmetros

Prop

Type

ItemPickerRequest

Prop

Type

Retorno

Promise<PickedItem[] | null>: a lista que o admin pegou, cada linha { name: string; count: number } (count um número inteiro acima de 0); null quando o seletor foi fechado. Lua retorna a lista ou nil. Os tipos são ItemPickerRequest e PickedItem.

Exemplo

import { callAction, itemPicker } from "@aicore-fivem/lib/client";

export async function giveItems(target: number): Promise<void> {
  const list = await itemPicker({ title: "Give items", target });
  if (!list || list.length === 0) return;
  await callAction("myadmin:give", [target, list], { fallback: "GIVE_FAILED" });
}

O handler do seu servidor é que dá os itens: verifique se quem chama é admin (guard isAdmin) e verifique de novo cada nome e quantidade. O seletor nunca dá nada sozinho.

Prompts à mão

Os pontos mostram e escondem prompts para você. Use estes só para um prompt que não está ligado a um lugar.

showPrompt

Mostra (ou muda o texto de) um dos prompts do seu recurso: a caixa "aperte E" à direita da tela. Com at, o prompt flutua sobre um ponto do mundo ou um local de uma entidade.

Lado: Cliente · Espera: não

Signature
showPrompt(id: string, text: string, at?: PromptAnchor): void
Lua
aiLib.showPrompt(id, text) -- sem âncora no mundo em Lua

Parâmetros

Prop

Type

Retorno

void.

Exemplo

Veja onPromptPressed.

hidePrompt

Esconde um dos prompts do seu recurso. Um id que não está sendo mostrado não faz nada.

Lado: Cliente · Espera: não

Signature
hidePrompt(id: string): void
Lua
aiLib.hidePrompt(id)

Parâmetros

Prop

Type

Retorno

void.

onPromptPressed

Roda um handler quando o jogador aperta a tecla de interação (padrão E) enquanto um dos prompts do seu recurso é o de cima.

Lado: Cliente · Espera: não

Signature
onPromptPressed(handler: (id: string) => void): void
Lua
aiLib.onPromptPressed(function(id) end)

Parâmetros

Prop

Type

Retorno

void.

Exemplo

import { createLocale, hidePrompt, onCache, onPromptPressed, showPrompt } from "@aicore-fivem/lib/client";

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

// "Aperte E para expulsar" enquanto está no banco do passageiro.
onCache("seat", (seat) => {
  if (seat === 0) showPrompt("eject", Locale("EJECT"));
  else hidePrompt("eject");
});

onPromptPressed((id) => {
  if (id !== "eject") return;
  TaskLeaveVehicle(PlayerPedId(), GetVehiclePedIsIn(PlayerPedId(), false), 4160);
});

Minigames

skillCheck

O skill check do ai-lib: uma agulha dá uma volta em um anel por etapa, e o jogador aperta a tecla mostrada enquanto ela está no arco verde. Ele tem o formato comum de skill check do FiveM ("easy" | "medium" | "hard" ou { areaSize, speedMultiplier }), então código escrito para o skill check do ox_lib funciona igual.

Lado: Cliente · Espera: sim (Promise em TypeScript, pausa a thread em Lua)

Signature
skillCheck(difficulty: SkillDifficulty | SkillDifficulty[], keys?: string[]): Promise<boolean>
Lua
local passed = aiLib.skillCheck(difficulty, keys) -- boolean, chame dentro de uma thread

Parâmetros

Prop

Type

SkillDifficulty

SkillDifficulty é um de:

Prop

Type

Retorno

Promise<boolean>: true quando todas as etapas foram acertadas; false em um erro, uma tecla errada ou Escape.

Exemplo

import { callAction, skillCheck } from "@aicore-fivem/lib/client";

export async function hotwire(netId: number): Promise<void> {
  const passed = await skillCheck(["easy", "easy", "medium", { areaSize: 30, speedMultiplier: 1.5 }], ["w", "a", "s", "d"]);
  await callAction("mykeys:hotwire", [netId, passed], { fallback: "HOTWIRE_FAILED" });
}

O resultado é a palavra do cliente. Quando o minigame paga (um carro, um roubo), jogue-o a partir do servidor com minigameFor(source, { game: "skillCheck", ... }), que também recusa uma vitória mais rápida que uma jogada real (Entrada do cliente).

lockpick

O lockpick do ai-lib: o jogador move a gazua com A / D (ou as setas) e segura W para girar a fechadura. A fechadura gira mais quanto mais perto a gazua está do ponto certo escondido; forçá-la desgasta a gazua.

Lado: Cliente · Espera: sim (Promise em TypeScript, pausa a thread em Lua)

Signature
lockpick(options?: LockpickOptions): Promise<LockpickResult>
Lua
local result = aiLib.lockpick(options) -- 'opened' | 'broken' | 'cancelled', chame dentro de uma thread

Parâmetros

Prop

Type

LockpickOptions

Prop

Type

Retorno

Promise<LockpickResult> (LockpickResult): "opened" quando todos os pinos giraram; "broken" quando a última gazua quebrou (tire o item de lockpick); "cancelled" quando o jogador apertou Escape.

Exemplo

import { callAction, lockpick } from "@aicore-fivem/lib/client";

export async function pickDoor(doorId: string): Promise<void> {
  const result = await lockpick({ difficulty: "hard", pins: 3, picks: 2 });
  if (result === "cancelled") return;
  await callAction("mydoors:picked", [doorId, result], { fallback: "PICK_FAILED" });
}

Nesta página