Общий интерфейс
notify, progress, menu, input, подсказки, skillCheck, lockpick и itemPicker - интерфейс игрока, который ai-lib рисует для каждого ресурса.
ai-lib рисует один общий интерфейс для всех ресурсов: карточки уведомлений, полосу прогресса, подсказки «нажмите E», меню, диалоги ввода и мини-игры. Ваш скрипт только запрашивает их, поэтому все скрипты на сервере выглядят одинаково, а вы не пишете для них NUI. Выбор предметов рисует ai-core.
Переданные вами тексты показываются как есть: сначала переведите их (Locale("KEY") в TypeScript, t('KEY') в Lua).
Уведомления
notify
Показывает карточку уведомления на экране этого игрока.
Сторона: Клиент · Ждёт: нет
notify(text: string, kind?: NotificationKind, duration?: number): voidaiLib.notify(text, kind, duration)Параметры
Prop
Type
Тип вида: NotificationKind. Чтобы уведомить игрока с сервера, используйте серверный notify(source, text, kind).
Возвращает
void.
Пример
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);Полоса прогресса
progress
Выполняет действие с таймером с полосой прогресса ai-lib и необязательной анимацией или сценарием и ждёт его окончания. Оно заканчивается досрочно (отменяется), когда игрок умирает, садится в транспорт, нажимает клавишу отмены ai-lib (по умолчанию Backspace, только с canCancel) или ваш скрипт вызывает cancelProgress(). Одновременно одна полоса прогресса на ресурс.
Сторона: Клиент · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
progress(options: ProgressOptions): Promise<boolean>local finished = aiLib.progress(options) -- boolean, вызывайте внутри потокаПараметры
Prop
Type
ProgressOptions
Prop
Type
Возвращает
Promise<boolean>: true, если полоса дошла до конца; false, если она отменена, или сразу, если ещё идёт другая полоса вашего ресурса. Lua возвращает то же булево значение.
Пример
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" });
}Результат это слово клиента: читер может пропустить полосу. Когда сервер платит за действие (предметы, деньги, ремонт), запускайте полосу с сервера через progressFor(source, options) (Ввод от клиента): он отвечает true, только если достаточно времени прошло и на сервере.
cancelProgress
Отменяет идущую полосу прогресса вашего ресурса, независимо от того, может ли её отменить игрок. Вызов progress тогда выполняется с false. Ничего не происходит, если полоса не идёт.
Сторона: Клиент · Ждёт: нет
cancelProgress(): voidaiLib.progress.cancel()Возвращает
void.
Пример
import { cancelProgress, onServerEvent } from "@aicore-fivem/lib/client";
// Сервер сообщает, что цель ограбил кто-то другой.
onServerEvent("myrob:taken", () => cancelProgress());isProgressRunning
Идёт ли сейчас полоса прогресса вашего ресурса.
Сторона: Клиент · Ждёт: нет
isProgressRunning(): booleanlocal running = aiLib.progress.isRunning()Возвращает
boolean: true, пока идёт полоса вашего ресурса. Полосы других ресурсов не учитываются.
Пример
import { isProgressRunning, menu } from "@aicore-fivem/lib/client";
export async function openMenu(): Promise<void> {
if (isProgressRunning()) return; // занято
await menu({ title: "Actions", items: [{ id: "a", label: "Action" }] });
}Меню и диалоги
menu
Показывает меню ai-lib и ждёт выбора игрока. Стрелки перемещают, Enter выбирает. Пункты с checked это строки-переключатели, которые переключаются на месте, не закрывая меню. В подменю (back: true) короткое нажатие Escape выполняется с MENU_BACK, чтобы вы могли открыть предыдущее меню; удержание Escape закрывает.
Сторона: Клиент · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
menu(request: MenuRequest, listeners?: ((item: string) => void) | MenuListeners): Promise<string | null>local picked = aiLib.menu.show(request, listeners) -- string или nil, вызывайте внутри потокаПараметры
Prop
Type
MenuRequest
Prop
Type
MenuItem
Prop
Type
Типы: MenuRequest и MenuItem.
MenuListeners
Prop
Type
Возвращает
Promise<string | null>: id выбранного пункта; "__back" (MENU_BACK из @aicore-fivem/shared) после короткого Escape в подменю; null, когда игрок закрыл меню. Lua возвращает то же, nil при закрытии.
Пример
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);
}Выбранный id приходит с клиента игрока: сервер должен проверить, что это допустимый выбор.
input
Показывает диалог ввода ai-lib и ждёт значений. Каждое поле это числовое или текстовое поле.
Сторона: Клиент · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
input(request: InputRequest): Promise<Record<string, string | number> | null>local values = aiLib.input(request) -- таблица или nil, вызывайте внутри потокаПараметры
Prop
Type
InputRequest
Prop
Type
InputField: number
Prop
Type
InputField: text
Prop
Type
Типы: InputRequest и InputField.
Возвращает
Promise<Record<string, string | number> | null>: введённые значения по name поля, если игрок подтвердил; null, если закрыл диалог. Значения, которые не являются ни строкой, ни числом, пропускаются. Lua возвращает таблицу или nil.
Пример
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 и maxLength лишь направляют игрока. Сервер должен снова проверить каждое значение (readInt, readText в серверном обработчике).
itemPicker
Инструменты администратора: показывает выбор предметов ai-core. Он перечисляет все предметы активного инвентаря с картинкой и поиском; клики заполняют список справа (1 за клик, 10 с Ctrl, 100 с Shift), который останавливается на пределе веса получателя. Список предметов отправляется только администраторам.
Сторона: Клиент · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
itemPicker(request: ItemPickerRequest): Promise<PickedItem[] | null>local list = aiLib.itemPicker(request) -- таблица или nil, вызывайте внутри потокаПараметры
Prop
Type
ItemPickerRequest
Prop
Type
Возвращает
Promise<PickedItem[] | null>: список, который взял администратор, каждая строка { name: string; count: number } (count это целое число больше 0); null, если выбор закрыли. Lua возвращает список или nil. Типы: ItemPickerRequest и PickedItem.
Пример
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" });
}Предметы выдаёт ваш серверный обработчик: проверьте, что вызывающий является администратором (guard-условие isAdmin), и снова проверьте каждое название и количество. Сам выбор никогда ничего не выдаёт.
Подсказки вручную
Точки показывают и скрывают подсказки за вас. Используйте эти функции только для подсказки, которая не привязана к месту.
showPrompt
Показывает одну из подсказок вашего ресурса (или меняет её текст): окно «нажмите E» справа на экране. С at подсказка вместо этого парит над точкой в мире или местом на сущности.
Сторона: Клиент · Ждёт: нет
showPrompt(id: string, text: string, at?: PromptAnchor): voidaiLib.showPrompt(id, text) -- в Lua нет привязки к мируПараметры
Prop
Type
Возвращает
void.
Пример
См. onPromptPressed.
hidePrompt
Скрывает одну из подсказок вашего ресурса. Id, который не показан, ничего не делает.
Сторона: Клиент · Ждёт: нет
hidePrompt(id: string): voidaiLib.hidePrompt(id)Параметры
Prop
Type
Возвращает
void.
onPromptPressed
Запускает обработчик, когда игрок нажимает клавишу взаимодействия (по умолчанию E), пока сверху находится одна из подсказок вашего ресурса.
Сторона: Клиент · Ждёт: нет
onPromptPressed(handler: (id: string) => void): voidaiLib.onPromptPressed(function(id) end)Параметры
Prop
Type
Возвращает
void.
Пример
import { createLocale, hidePrompt, onCache, onPromptPressed, showPrompt } from "@aicore-fivem/lib/client";
const Locale = createLocale<typeof import("../../locales/en.json")>();
// «Нажмите E, чтобы высадить», пока сидите на пассажирском месте.
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);
});Мини-игры
skillCheck
Проверка навыка ai-lib: стрелка проходит по кольцу один раз за этап, и игрок нажимает показанную клавишу, пока она на зелёной дуге. У неё распространённая в FiveM форма проверки навыка ("easy" | "medium" | "hard" или { areaSize, speedMultiplier }), поэтому код, написанный для проверки навыка ox_lib, работает так же.
Сторона: Клиент · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
skillCheck(difficulty: SkillDifficulty | SkillDifficulty[], keys?: string[]): Promise<boolean>local passed = aiLib.skillCheck(difficulty, keys) -- boolean, вызывайте внутри потокаПараметры
Prop
Type
SkillDifficulty
SkillDifficulty это одно из:
Prop
Type
Возвращает
Promise<boolean>: true, если пройдены все этапы; false при промахе, неверной клавише или Escape.
Пример
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" });
}Результат это слово клиента. Когда мини-игра приносит выгоду (машина, ограбление), запускайте её с сервера через minigameFor(source, { game: "skillCheck", ... }), который также отклоняет победу быстрее реальной игры (Ввод от клиента).
lockpick
Взлом отмычкой ai-lib: игрок двигает отмычку клавишами A / D (или стрелками) и удерживает W, чтобы повернуть замок. Замок поворачивается тем дальше, чем ближе отмычка к скрытой зоне срабатывания; если давить силой, отмычка изнашивается.
Сторона: Клиент · Ждёт: да (Promise в TypeScript, в Lua приостанавливает поток)
lockpick(options?: LockpickOptions): Promise<LockpickResult>local result = aiLib.lockpick(options) -- 'opened' | 'broken' | 'cancelled', вызывайте внутри потокаПараметры
Prop
Type
LockpickOptions
Prop
Type
Возвращает
Promise<LockpickResult> (LockpickResult): "opened", если повернулись все штифты; "broken", если сломалась последняя отмычка (заберите предмет отмычки); "cancelled", если игрок нажал Escape.
Пример
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" });
}Педы, блипы и пропы
LocalPed, Blips, createBlip, attachProp, PreviewVehicle и player.holdAnim - локальные NPC, блипы на карте, пропы в руках, витринный транспорт и удерживаемые анимации.
Экраны и управление
NuiScreen, hud, keyHints и controls - ваш собственный полноэкранный NUI, скрытие всех HUD, строки подсказок клавиш и отключённые элементы управления.