Interface partagée
notify, progress, menu, input, invites, skillCheck, lockpick et itemPicker : l’interface joueur qu’ai-lib dessine pour chaque ressource.
ai-lib dessine une interface partagée pour chaque ressource : cartes de notification, barre de progression, invites « appuyez sur E », menus, boîtes de saisie et mini-jeux. Votre script ne fait que les demander, si bien que tous les scripts du serveur ont le même aspect et que vous n’écrivez aucune NUI pour ces éléments. Le sélecteur d’objets est dessiné par ai-core.
Les textes que vous passez sont affichés tels quels : traduisez-les d’abord (Locale("KEY") en TypeScript, t('KEY') en Lua).
Notifications
notify
Affiche une carte de notification sur l’écran de ce joueur.
Côté : client · Attend : non
notify(text: string, kind?: NotificationKind, duration?: number): voidaiLib.notify(text, kind, duration)Paramètres
Prop
Type
Le type du genre est NotificationKind. Pour notifier un joueur depuis le serveur, utilisez le notify(source, text, kind) serveur.
Retour
void.
Exemple
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);Barre de progression
progress
Exécute une action minutée avec la barre de progression d’ai-lib et une animation ou un scénario facultatif, et attend qu’elle se termine. Elle se termine plus tôt (annulée) quand le joueur meurt, monte dans un véhicule, appuie sur la touche d’annulation d’ai-lib (Backspace par défaut, uniquement avec canCancel), ou quand votre script appelle cancelProgress(). Une seule progression par ressource à la fois.
Côté : client · Attend : oui (Promise en TypeScript, cède la main (yield) du thread en Lua)
progress(options: ProgressOptions): Promise<boolean>local finished = aiLib.progress(options) -- booléen, à appeler dans un threadParamètres
Prop
Type
ProgressOptions
Prop
Type
Retour
Promise<boolean> : true quand la barre est arrivée au bout ; false quand elle a été annulée, ou immédiatement quand une autre progression de votre ressource est encore en cours. Lua renvoie le même booléen.
Exemple
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" });
}Le résultat n’est que la parole du client : un tricheur peut sauter la barre. Quand le serveur paie pour l’action (objets, argent, réparation), lancez la barre depuis le serveur avec progressFor(source, options) (Entrées client) : elle ne répond true que lorsque suffisamment de temps s’est aussi écoulé sur le serveur.
cancelProgress
Annule la progression en cours de votre ressource, que le joueur ait le droit de l’annuler ou non. L’appel progress se résout alors à false. Rien ne se passe quand aucune progression n’est en cours.
Côté : client · Attend : non
cancelProgress(): voidaiLib.progress.cancel()Retour
void.
Exemple
import { cancelProgress, onServerEvent } from "@aicore-fivem/lib/client";
// Le serveur indique que la cible a été braquée par quelqu’un d’autre.
onServerEvent("myrob:taken", () => cancelProgress());isProgressRunning
Indique si une progression de votre ressource est en cours.
Côté : client · Attend : non
isProgressRunning(): booleanlocal running = aiLib.progress.isRunning()Retour
boolean : true tant que la barre de votre ressource tourne. Les barres des autres ressources ne comptent pas.
Exemple
import { isProgressRunning, menu } from "@aicore-fivem/lib/client";
export async function openMenu(): Promise<void> {
if (isProgressRunning()) return; // occupé
await menu({ title: "Actions", items: [{ id: "a", label: "Action" }] });
}Menus et boîtes de dialogue
menu
Affiche le menu d’ai-lib et attend le choix du joueur. Les flèches déplacent, Entrée choisit. Les éléments avec checked sont des lignes à interrupteur qui basculent sur place sans fermer le menu. Dans un sous-menu (back: true), un appui bref sur Échap résout MENU_BACK pour que vous puissiez ouvrir le menu précédent ; maintenir Échap ferme.
Côté : client · Attend : oui (Promise en TypeScript, cède la main (yield) du thread en Lua)
menu(request: MenuRequest, listeners?: ((item: string) => void) | MenuListeners): Promise<string | null>local picked = aiLib.menu.show(request, listeners) -- chaîne ou nil, à appeler dans un threadParamètres
Prop
Type
MenuRequest
Prop
Type
MenuItem
Prop
Type
Les types sont MenuRequest et MenuItem.
MenuListeners
Prop
Type
Retour
Promise<string | null> : l’id de l’élément choisi ; "__back" (MENU_BACK depuis @aicore-fivem/shared) après un appui bref sur Échap dans un sous-menu ; null quand le joueur a fermé le menu. Lua renvoie la même chose, nil en cas de fermeture.
Exemple
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);
}L’id choisi vient du client du joueur : le serveur doit vérifier qu’il s’agit d’un choix valide.
input
Affiche la boîte de saisie d’ai-lib et attend les valeurs. Chaque champ est une zone numérique ou une zone de texte.
Côté : client · Attend : oui (Promise en TypeScript, cède la main (yield) du thread en Lua)
input(request: InputRequest): Promise<Record<string, string | number> | null>local values = aiLib.input(request) -- table ou nil, à appeler dans un threadParamètres
Prop
Type
InputRequest
Prop
Type
InputField: number
Prop
Type
InputField: text
Prop
Type
Les types sont InputRequest et InputField.
Retour
Promise<Record<string, string | number> | null> : les valeurs saisies, indexées par le name du champ, quand le joueur a confirmé ; null quand il a fermé la boîte de dialogue. Les valeurs qui ne sont ni une chaîne ni un nombre sont omises. Lua renvoie la table ou nil.
Exemple
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 et maxLength ne font que guider le joueur. Le serveur doit revérifier chaque valeur (readInt, readText dans le gestionnaire serveur).
itemPicker
Outils d’administration : affiche le sélecteur d’objets d’ai-core. Il liste chaque objet de l’inventaire actif avec son image et une recherche ; les clics remplissent une liste à droite (1 par clic, 10 avec Ctrl, 100 avec Maj) qui s’arrête à la limite de poids de la cible. La liste des objets n’est envoyée qu’aux administrateurs.
Côté : client · Attend : oui (Promise en TypeScript, cède la main (yield) du thread en Lua)
itemPicker(request: ItemPickerRequest): Promise<PickedItem[] | null>local list = aiLib.itemPicker(request) -- table ou nil, à appeler dans un threadParamètres
Prop
Type
ItemPickerRequest
Prop
Type
Retour
Promise<PickedItem[] | null> : la liste prise par l’administrateur, chaque ligne { name: string; count: number } (count un nombre entier supérieur à 0) ; null quand le sélecteur a été fermé. Lua renvoie la liste ou nil. Les types sont ItemPickerRequest et PickedItem.
Exemple
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" });
}C’est votre gestionnaire serveur qui donne les objets : vérifiez que l’appelant est administrateur (garde isAdmin) et revérifiez chaque nom et chaque quantité. Le sélecteur ne donne jamais rien de lui-même.
Invites à la main
Les points affichent et masquent les invites pour vous. N’utilisez ces fonctions que pour une invite qui n’est pas liée à un lieu.
showPrompt
Affiche l’une des invites de votre ressource (ou en change le texte) : la boîte « appuyez sur E » à droite de l’écran. Avec at, l’invite flotte plutôt au-dessus d’un point du monde ou d’un emplacement sur une entité.
Côté : client · Attend : non
showPrompt(id: string, text: string, at?: PromptAnchor): voidaiLib.showPrompt(id, text) -- pas d’ancrage dans le monde en LuaParamètres
Prop
Type
Retour
void.
Exemple
Voir onPromptPressed.
hidePrompt
Masque l’une des invites de votre ressource. Un id qui n’est pas affiché ne fait rien.
Côté : client · Attend : non
hidePrompt(id: string): voidaiLib.hidePrompt(id)Paramètres
Prop
Type
Retour
void.
onPromptPressed
Exécute un gestionnaire quand le joueur appuie sur la touche d’interaction (E par défaut) alors que l’une des invites de votre ressource est celle du dessus.
Côté : client · Attend : non
onPromptPressed(handler: (id: string) => void): voidaiLib.onPromptPressed(function(id) end)Paramètres
Prop
Type
Retour
void.
Exemple
import { createLocale, hidePrompt, onCache, onPromptPressed, showPrompt } from "@aicore-fivem/lib/client";
const Locale = createLocale<typeof import("../../locales/en.json")>();
// « Appuyez sur E pour éjecter » quand le joueur est sur le siège passager.
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);
});Mini-jeux
skillCheck
Le test d’adresse d’ai-lib : une aiguille fait le tour d’un anneau une fois par étape, et le joueur appuie sur la touche affichée quand elle se trouve sur l’arc vert. Il a la forme courante des tests d’adresse FiveM ("easy" | "medium" | "hard" ou { areaSize, speedMultiplier }), si bien que le code écrit pour le test d’adresse d’ox_lib fonctionne de la même manière.
Côté : client · Attend : oui (Promise en TypeScript, cède la main (yield) du thread en Lua)
skillCheck(difficulty: SkillDifficulty | SkillDifficulty[], keys?: string[]): Promise<boolean>local passed = aiLib.skillCheck(difficulty, keys) -- booléen, à appeler dans un threadParamètres
Prop
Type
SkillDifficulty
SkillDifficulty est l’un de :
Prop
Type
Retour
Promise<boolean> : true quand chaque étape a été réussie ; false en cas d’échec, de mauvaise touche ou d’Échap.
Exemple
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" });
}Le résultat n’est que la parole du client. Quand le mini-jeu rapporte quelque chose (une voiture, un braquage), lancez-le depuis le serveur avec minigameFor(source, { game: "skillCheck", ... }), qui refuse aussi une victoire plus rapide qu’une vraie partie (Entrées client).
lockpick
Le crochetage d’ai-lib : le joueur déplace le crochet avec A / D (ou les flèches) et maintient W pour tourner la serrure. La serrure tourne d’autant plus loin que le crochet est proche du point idéal caché ; forcer use le crochet.
Côté : client · Attend : oui (Promise en TypeScript, cède la main (yield) du thread en Lua)
lockpick(options?: LockpickOptions): Promise<LockpickResult>local result = aiLib.lockpick(options) -- 'opened' | 'broken' | 'cancelled', à appeler dans un threadParamètres
Prop
Type
LockpickOptions
Prop
Type
Retour
Promise<LockpickResult> (LockpickResult) : "opened" quand chaque goupille a tourné ; "broken" quand le dernier crochet a cassé (retirez l’objet crochet) ; "cancelled" quand le joueur a appuyé sur Échap.
Exemple
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" });
}Peds, blips et props
LocalPed, Blips, createBlip, attachProp, PreviewVehicle et player.holdAnim : PNJ locaux, blips sur la carte, props tenus en main, véhicules de showroom et animations maintenues.
Écrans et contrôles
NuiScreen, hud, keyHints et controls : votre propre NUI plein écran, masquer tous les HUD, les lignes d’aide des touches et les contrôles désactivés.