Предметы
Добавлять, забирать, считать и проверять предметы в любом инвентаре, регистрировать тайники, магазины скриптов и используемые предметы, читать определения предметов и переносимый вес.
Каждый вызов предметов идёт через ai-core, а не через собственные экспорты скрипта инвентаря. ai-core передаёт каждый вызов активному инвентарю: тому, что выбран в настройке панели Inventory script, или первому запущенному, когда выбрано автоматически (ai-inventory, ox_inventory, qb-inventory, tgiann-inventory и остальные из списка совместимости). Когда владелец сервера меняет инвентарь, ваш скрипт продолжает работать без изменений.
Что нужно знать:
- Инвентарь задаётся через
InventoryRef: серверный id игрока (число) для карманов этого игрока или текстовый id для всего остального (имя тайника, номер багажника). См. InventoryRef. - Имена предметов - это имена предметов в инвентаре (
water,bandage,WEAPON_PISTOL). - Метаданные - таблица дополнительных значений одной стопки (серийный номер, прочность). См. ItemMetadata.
- Пока ни один инвентарь не работает, каждый вызов отвечает своим «пустым» значением:
false,0, пустой список илиnull. - Тайники, магазины и используемые предметы, которые вы регистрируете, хранит ai-core и передаёт каждому инвентарю, который становится активным позже, в том числе после перезапуска инвентаря. Регистрируйте их один раз при старте скрипта.
AddItem
Выдаёт предметы в инвентарь.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.addItem
AddItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): booleanlocal ok = exports['ai-core']:AddItem(source, 'water', 2)Параметры
Prop
Type
Возвращает
boolean: true, когда инвентарь добавил предметы. false, когда они не помещаются, предмета нет в инвентаре, аргумент неверен (count меньше 1, пустое имя предмета) или ни один инвентарь не работает.
Пример
import { onClientCallback, resourceExport, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
const TAP = { x: 1206.4, y: -3110.2, z: 5.6 };
onClientCallback("myscript:fillBottle", { guards: [near(TAP, 2)], lock: true }, (source) => {
if (!core.RemoveItem(source, "empty_bottle")) return fail("NO_BOTTLE");
if (!core.AddItem(source, "water")) {
core.AddItem(source, "empty_bottle");
return fail("NO_SPACE");
}
return { ok: true };
});RemoveItem
Забирает предметы из инвентаря.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.removeItem
RemoveItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): booleanlocal ok = exports['ai-core']:RemoveItem(source, 'lockpick', 1)Параметры
Prop
Type
Возвращает
boolean: true, когда предметы забраны. false, когда в инвентаре их меньше (тогда не забирается ничего), аргумент неверен или ни один инвентарь не работает.
Пример
import { onClientCallback, minigameFor, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
onClientCallback("myscript:pickLock", { lock: true }, async (source) => {
if (!core.HasItem(source, "lockpick")) return fail("NO_LOCKPICK");
const result = await minigameFor(source, { game: "lockpick", minMs: 1500 });
if (result === "broken") core.RemoveItem(source, "lockpick");
return result === "won" ? { ok: true } : fail("LOCKPICK_FAILED");
});GetItemCount
Сколько предмета лежит в инвентаре.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.getItemCount
GetItemCount(inv: InventoryRef, item: string, metadata?: ItemMetadata): numberlocal count = exports['ai-core']:GetItemCount(source, 'fish')Параметры
Prop
Type
Возвращает
number: сумма по всем стопкам. 0, когда предмета нет, аргумент неверен или ни один инвентарь не работает.
Пример
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
// Скупщик рыбы показывает, сколько получит игрок.
onClientCallback("myscript:fishQuote", (source) => ({
ok: true,
price: core.GetItemCount(source, "fish") * 25,
}));HasItem
Есть ли в инвентаре хотя бы заданное количество предмета.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.hasItem
HasItem(inv: InventoryRef, item: string, count?: number): booleanlocal has = exports['ai-core']:HasItem(source, 'repairkit')Параметры
Prop
Type
Возвращает
boolean: true, когда в инвентаре count или больше. false, когда меньше, count меньше 1 или ни один инвентарь не работает.
Пример
import { onClientCallback, progressFor, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
import { Locale } from "common";
const core = resourceExport("ai-core");
onClientCallback("myscript:repair", { lock: true }, async (source) => {
if (!core.HasItem(source, "repairkit")) return fail("NO_KIT");
if (!(await progressFor(source, { label: Locale("REPAIRING"), duration: 8000 }))) return fail("CANCELLED");
if (!core.RemoveItem(source, "repairkit")) return fail("NO_KIT");
return { ok: true };
});Проверяйте снова по ответу RemoveItem после всего, что ждёт (полоса прогресса, мини-игра): игрок мог тем временем выбросить предмет.
CanCarryItem
Поместятся ли предметы в инвентарь (вес и слоты), без их добавления.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.canCarryItem
CanCarryItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata): booleanlocal fits = exports['ai-core']:CanCarryItem(source, 'water', 5)Параметры
Prop
Type
Возвращает
boolean: true, когда помещаются. false, когда нет, аргумент неверен или ни один инвентарь не работает.
Пример
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
onClientCallback("myscript:buyWater", { lock: true }, (source) => {
if (!core.CanCarryItem(source, "water", 5)) return fail("NO_SPACE");
if (!core.RemoveMoney(source, "cash", 50, "shop_water")) return fail("NOT_ENOUGH_MONEY");
core.AddItem(source, "water", 5);
return { ok: true };
});GetItems
Все стопки в инвентаре, с названиями.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.getItems
GetItems(inv: InventoryRef): InventoryStack[]local stacks = exports['ai-core']:GetItems(source) -- список таблицПараметры
Prop
Type
Возвращает
InventoryStack[]: по записи на каждую стопку с name, label, count, slot и metadata. См. InventoryStack. Пустой список для пустого или неизвестного инвентаря, неверного аргумента или когда ни один инвентарь не работает.
Пример
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
// Ломбард перечисляет все предметы игрока, которые он покупает.
const BUYS: Record<string, number> = { gold_ring: 120, rolex: 400 };
onClientCallback("myscript:pawnList", (source) => ({
ok: true,
rows: core.GetItems(source)
.filter((stack) => BUYS[stack.name] !== undefined)
.map((stack) => ({ slot: stack.slot, label: stack.label, count: stack.count, price: BUYS[stack.name] })),
}));ClearInventory
Полностью очищает инвентарь.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.clearInventory
ClearInventory(inv: InventoryRef): voidexports['ai-core']:ClearInventory(source)Параметры
Prop
Type
Возвращает
Ничего. Неверный аргумент или отсутствие работающего инвентаря ничего не делают.
Пример
import { addCommand, resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
addCommand("clearinv", { help: "Empties a player inventory", params: [{ name: "id", type: "playerId" }], restricted: true }, (_source, args) => {
core.ClearInventory(args.id);
});Это нельзя отменить. Держите это за админской командой или понятным игровым правилом (приём в тюрьму, который сначала сохраняет предметы).
RegisterStash
Создаёт тайник: ящик для хранения, который игроки открывают по его имени. ai-core хранит его и снова регистрирует в каждом инвентаре, который становится активным.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.registerStash
RegisterStash(name: string, label: string, slots: number, maxWeight: number, jobs?: string[]): voidexports['ai-core']:RegisterStash('police_evidence', 'Evidence', 100, 500000, { 'police' })Параметры
Prop
Type
Значения по умолчанию применяются, когда значение отсутствует или неверно.
Возвращает
Ничего. Без текстового name вызов ничего не делает. Повторная регистрация того же имени заменяет тайник.
Пример
import { onClientCallback, resourceExport, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
import { Locale } from "common";
const core = resourceExport("ai-core");
const LOCKER = { x: 474.9, y: -994.7, z: 26.3 };
// Один раз при старте; ai-core передаёт его инвентарям, которые стартуют позже.
core.RegisterStash("police_evidence", Locale("STASH_EVIDENCE"), 100, 500_000, ["police"]);
onClientCallback("myscript:openEvidence", { guards: [near(LOCKER, 2)] }, (source) => {
if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
return core.OpenInventory(source, "police_evidence") ? { ok: true } : fail("STASH_FAILED");
});OpenInventory
Открывает на экране игрока тайник, багажник или инвентарь другого игрока рядом с его собственным.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.openInventory
OpenInventory(source: number, inv: InventoryRef): booleanlocal opened = exports['ai-core']:OpenInventory(source, 'police_evidence')Параметры
Prop
Type
Возвращает
boolean: true, когда инвентарь открыл экран. false, когда не смог (неизвестный тайник, у игрока нет инвентаря), аргумент неверен или ни один инвентарь не работает.
Пример
import { onClientCallback, isNear, coordsOf, resourceExport } from "@aicore-fivem/lib/server";
import { fail, oneArg, readId } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
// Полиция обыскивает стоящего рядом игрока в наручниках.
onClientCallback("myscript:search", { args: oneArg(readId) }, (source, target) => {
if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
if (target === source || !isNear(target, coordsOf(source), 2)) return fail("TOO_FAR");
return core.OpenInventory(source, target) ? { ok: true } : fail("SEARCH_FAILED");
});Инвентарь здесь не проверяет ни расстояние, ни права. Проверьте работу, расстояние и состояние цели сами, прежде чем вызывать.
RegisterShop
Создаёт магазин скрипта: список предметов с ценами, который ваш скрипт открывает игроку (оружейная, торговый автомат). Инвентарь рисует магазин и принимает оплату по-своему (наличные, затем банк). ai-core хранит его и передаёт каждому инвентарю, который становится активным.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.registerShop
RegisterShop(name: string, label: string, items: ShopProduct[]): voidexports['ai-core']:RegisterShop('police_armoury', 'Armoury', { { name = 'bandage', price = 0 } })Параметры
Prop
Type
См. ShopProduct.
Возвращает
Ничего. Без текстового name или без единого допустимого товара вызов ничего не делает. Повторная регистрация того же имени заменяет магазин.
Пример
import { onClientCallback, resourceExport, near } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
import { Locale } from "common";
const core = resourceExport("ai-core");
const ARMOURY = { x: 482.6, y: -995.2, z: 30.7 };
core.RegisterShop("police_armoury", Locale("SHOP_ARMOURY"), [
{ name: "WEAPON_STUNGUN", price: 0 },
{ name: "bandage", price: 10 },
]);
onClientCallback("myscript:armoury", { guards: [near(ARMOURY, 2)] }, (source) => {
if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
return core.OpenShop(source, "police_armoury") ? { ok: true } : fail("SHOP_FAILED");
});OpenShop
Открывает на экране игрока магазин, зарегистрированный через RegisterShop.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.openShop
OpenShop(source: number, name: string): booleanlocal opened = exports['ai-core']:OpenShop(source, 'police_armoury')Параметры
Prop
Type
Возвращает
boolean: true, когда магазин открылся. false, когда магазина с таким именем нет, у активного инвентаря нет магазинов скриптов, он не смог открыть или ни один инвентарь не работает.
Пример
См. пример RegisterShop выше: зарегистрируйте один раз при старте, затем открывайте после собственных проверок работы и расстояния.
Как и OpenInventory, это не проверяет ни расстояние, ни доступ. Проверьте их сначала.
RegisterUsableItem
Делает предмет используемым: когда игрок использует его в инвентаре, выполняется ваша функция. ai-core хранит функцию, поэтому она работает с инвентарями, которые стартуют позже, и переживает перезапуск инвентаря.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.registerUsableItem
RegisterUsableItem(name: string, handler: UsableItemHandler): void
// UsableItemHandler = (source: number, item: UsedItem) => unknownexports['ai-core']:RegisterUsableItem('bandage', function(source, item) end)Параметры
Prop
Type
См. UsableItemHandler и UsedItem.
Возвращает
Ничего. Без текстового name или функции вызов ничего не делает. Второй вызов для того же предмета заменяет обработчик.
Что происходит с предметом после использования, зависит от инвентаря: инвентари, которые сами забирают использованный предмет (ai-inventory забирает количество consume предмета), оставляют его, когда ваш обработчик возвращает false; другие инвентари следуют своим настройкам предметов, поэтому там при необходимости забирайте предмет сами.
Пример
import { progressFor, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";
const core = resourceExport("ai-core");
core.RegisterUsableItem("bandage", (source) => {
// Обработчик должен ответить сразу; часть со временем выполняется отдельно.
void (async () => {
if (!(await progressFor(source, { label: Locale("BANDAGING"), duration: 4000 }))) return;
if (!core.RemoveItem(source, "bandage")) return;
emitNet("myscript:client:heal", source, 25); // ваш клиентский скрипт добавляет здоровье
})();
return false; // оставить: он забирается выше, когда полоса закончилась
});Использование также вызывает серверное событие ai-core:itemUsed (src, name, status), за которым следят эффекты предметов вроде голода и жажды. См. События и состояние.
GetItemDefinition
Один предмет так, как его определяет активный инвентарь: название, вес, складывается ли в стопку, картинка.
Сторона: сервер · Ожидание: нет · Библиотека: inventory.getItemDefinition
GetItemDefinition(name: string): ItemDefinition | nulllocal def = exports['ai-core']:GetItemDefinition('water') -- table или nilПараметры
Prop
Type
Возвращает
ItemDefinition | null: предмет с name, label, weight, unique, close, description и image, если у инвентаря она есть. См. ItemDefinition. null для неизвестного предмета, пустого имени или когда ни один инвентарь не работает.
Пример
import { notify, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";
const core = resourceExport("ai-core");
/** "You received 2x Water" with the inventory's own label. */
export function giveWithNotice(source: number, item: string, count: number): void {
if (!core.AddItem(source, item, count)) return;
const label = core.GetItemDefinition(item)?.label ?? item;
notify(source, Locale("NOTIFY_RECEIVED", count, label), "success");
}GetItemDefinitions
Все предметы, которые определяет активный инвентарь, с ключами по имени. Используйте редко (чтобы один раз построить список); для одного предмета используйте GetItemDefinition.
Сторона: сервер · Ожидание: нет · Библиотека: нет
GetItemDefinitions(): Record<string, ItemDefinition>local items = exports['ai-core']:GetItemDefinitions() -- таблица с ключами по имени предметаПараметры
Нет.
Возвращает
Record<string, ItemDefinition>: все предметы. Пустая таблица, пока ни один инвентарь не работает.
Пример
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
/** Warns at start about items in your config that the inventory does not know. */
export function checkItems(names: string[]): void {
const known = core.GetItemDefinitions();
for (const name of names) if (!known[name]) console.log(`unknown item: ${name}`);
}Выполняйте такую проверку после старта инвентаря: сразу после запуска сервера инвентарь может ещё не работать, и таблица будет пустой.
GetInventoryWeight
Что игрок несёт и может нести, по весу.
Сторона: сервер · Ожидание: нет · Библиотека: нет
GetInventoryWeight(source: number): { weight: number; maxWeight: number } | nulllocal w = exports['ai-core']:GetInventoryWeight(source) -- { weight, maxWeight } или nilПараметры
Prop
Type
Возвращает
{ weight, maxWeight } | null: переносимый вес и лимит в граммах. null, когда активный инвентарь их не сообщает, у игрока не загружен инвентарь или ни один инвентарь не работает.
Пример
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
onClientCallback("myscript:weight", (source) => {
const w = core.GetInventoryWeight(source);
return { ok: true, free: w ? w.maxWeight - w.weight : null };
});UseItem
Запускает обработчик, зарегистрированный для предмета, как будто игрок его использовал. Его вызывает мост ESX / QB в ai-core (из ESX.UseItem и CanUseItem в QB); у обычного скрипта нет причин это делать.
Сторона: сервер · Ожидание: нет · Библиотека: нет (только мост)
UseItem(source: number, name: string, item?: unknown): unknownlocal result = exports['ai-core']:UseItem(source, 'bandage', stack)Параметры
Prop
Type
Возвращает
unknown: то, что вернул обработчик. false, когда обработчик не зарегистрирован, аргументы неверны или обработчик бросил ошибку (она записывается в лог).
Пример
Без примера: его вызывают инвентари и мост. Чтобы реагировать на использование, зарегистрируйте предмет через RegisterUsableItem.
IsUsableItem
Зарегистрирован ли обработчик для предмета. Его использует мост ai-core.
Сторона: сервер · Ожидание: нет · Библиотека: нет (только мост)
IsUsableItem(name: string): booleanlocal usable = exports['ai-core']:IsUsableItem('bandage')Параметры
Prop
Type
Возвращает
boolean: true, когда какой-то ресурс зарегистрировал предмет через RegisterUsableItem. Иначе false.
Пример
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
/** Item tooltips show "Use" only for usable items. */
export function canUse(item: string): boolean {
return core.IsUsableItem(item);
}