События интерфейса ai-lib
Клиентские события, которые отправляет ai-lib, когда игрок отвечает в меню, диалоге ввода, выборе предметов, мини-игре или подсказке или отменяет полосу прогресса - для скриптов, которые сами вызывают экспорты ai-lib.
ai-lib рисует общий интерфейс игрока: меню, диалоги ввода, подсказки, полосу прогресса, мини-игры, уведомления. Когда игрок отвечает, ai-lib отправляет одно из этих клиентских локальных событий.
Большинство скриптов никогда их не слушает. menu, input, itemPicker, skillCheck, lockpick, onPromptPressed и progress из библиотеки (и те же имена в aiLib) открывают интерфейс, слушают ответ и возвращают его вам как результат. Слушайте сами, только когда вызываете экспорты ai-lib (OpenMenu, OpenInput, OpenMinigame) или OpenItemPicker из ai-core напрямую.
Каждый ответ несёт ресурс, который открыл интерфейс, и выбранный им id запроса. Проверяйте оба: каждый ресурс на клиенте слышит каждый ответ.
ai-lib:client:menuResult
Игрок выбрал пункт меню или закрыл меню. То же событие отвечает за выбор предметов ai-core и мини-игры ai-lib.
Сторона: клиент · Константа: MENU_EVENTS.menuResult
Аргументы
Prop
Type
Обработчик
import { resourceExport } from "@aicore-fivem/lib/client";
import { MENU_EVENTS } from "@aicore-fivem/shared";
const ui = resourceExport("ai-lib");
const me = GetCurrentResourceName();
let nextId = 0;
const waiting = new Map<number, (value: unknown) => void>();
on(MENU_EVENTS.menuResult, (resource: string, requestId: number, value: unknown) => {
if (resource !== me) return;
waiting.get(requestId)?.(value);
waiting.delete(requestId);
});
// menu() из библиотеки делает ровно это; показано здесь, чтобы объяснить событие.
export function pickColor(): Promise<string | null> {
const id = ++nextId;
return new Promise((resolve) => {
waiting.set(id, (value) => resolve(typeof value === "string" ? value : null));
ui.OpenMenu(id, {
title: "Color",
items: [
{ id: "red", label: "Red" },
{ id: "blue", label: "Blue" },
],
});
});
}ai-lib:client:menuHover
Указатель или фокус клавиатуры перешёл на пункт меню. Используйте для предпросмотра (показать цвет транспорта, пока игрок наводит на него). Меню остаётся открытым.
Сторона: клиент · Константа: MENU_EVENTS.menuHover · Библиотека: menu(request, { onHover })
Аргументы
Prop
Type
Обработчик
import { menu } from "@aicore-fivem/lib/client";
// Библиотека передаёт наведения своего меню в onHover.
export async function chooseColor(): Promise<string | null> {
return menu(
{ title: "Color", items: [{ id: "red", label: "Red" }, { id: "blue", label: "Blue" }] },
{ onHover: (item) => console.log(`previewing ${item}`) },
);
}ai-lib:client:menuToggle
Игрок переключил строку-переключатель (пункт с checked). Переключатель меняется на месте, и меню остаётся открытым.
Сторона: клиент · Константа: MENU_EVENTS.menuToggle · Библиотека: menu(request, { onToggle })
Аргументы
Prop
Type
Обработчик
import { menu } from "@aicore-fivem/lib/client";
let sounds = true;
export async function openSettings(): Promise<void> {
await menu(
{ title: "Settings", items: [{ id: "sounds", label: "Sounds", checked: sounds }] },
{ onToggle: (item, checked) => { if (item === "sounds") sounds = checked; } },
);
}ai-lib:client:inputResult
Игрок подтвердил или закрыл диалог ввода.
Сторона: клиент · Константа: MENU_EVENTS.inputResult · Библиотека: input(request)
Аргументы
Prop
Type
Обработчик
import { input } from "@aicore-fivem/lib/client";
// input() из библиотеки слушает ai-lib:client:inputResult за вас.
export async function askName(): Promise<string | null> {
const values = await input({
title: "Rename",
confirm: "Save",
fields: [{ name: "name", label: "Name", type: "text", maxLength: 32 }],
});
return values && typeof values.name === "string" ? values.name : null;
}ai-lib:client:promptPressed
Игрок нажал клавишу взаимодействия, пока подсказка была вверху списка. Реагировать должен только ресурс, который показал эту подсказку.
Сторона: клиент · Константа: LIB_UI.promptPressedEvent · Библиотека: onPromptPressed(handler)
Аргументы
Prop
Type
Обработчик
import { onPromptPressed, showPrompt } from "@aicore-fivem/lib/client";
showPrompt("atm", "Use ATM");
// onPromptPressed сам фильтрует по вашему ресурсу.
onPromptPressed((id) => {
if (id === "atm") console.log("open the ATM");
});ai-lib:client:cancelProgress
Игрок нажал клавишу отмены ai-lib, пока была видна полоса прогресса. progress из библиотеки с canCancel: true слушает это и завершает полосу с false.
Сторона: клиент · Константа: LIB_UI.cancelProgressEvent
Аргументы
Нет.
Обработчик
import { LIB_UI } from "@aicore-fivem/shared";
// Нужно, только если вы запускаете ShowProgress из ai-lib сами вместо progress() из библиотеки.
on(LIB_UI.cancelProgressEvent, () => console.log("player cancelled the bar"));Внутренние события ai-lib
Zones и Points из библиотеки передают свои проверки в ai-lib и получают ответ через эти события. Не отправляйте их; используйте Zones и Points.
| Событие | Константа | Аргументы |
|---|---|---|
ai-lib:client:zone | LIB_UI.zoneEvent | (owner: string, key: string, inside: boolean) игрок вошёл в зону или вышел из зоны, которую ai-lib проверяет для owner. |
ai-lib:client:modelPoint | LIB_UI.modelPointEvent | (owner: string, key: string, entity: number) изменился ближайший объект точки модели (0 = рядом нет). |
Сетевые события
Сетевые события, которые может слушать клиентский скрипт (канал данных игрока ai-core), и собственный сетевой трафик ai-core, который другие скрипты не должны вызывать.
State bag
Общие значения состояния, которые публикуют ai-core и скрипты ai-* - bag игроков, bag транспорта и ключи GlobalState - что хранит каждый, кто его пишет и как его читать и следить за ним.