AI Core
Dokumentacja APIAI Core: eksporty serwerowe

Przedmioty

Dodawaj, zabieraj, licz i sprawdzaj przedmioty w dowolnym ekwipunku, rejestruj schowki, sklepy skryptów i używalne przedmioty, odczytuj definicje przedmiotów i noszoną wagę.

Każde wywołanie przedmiotów przechodzi przez ai-core, nigdy przez własne eksporty skryptu ekwipunku. ai-core przekazuje każde wywołanie do aktywnego ekwipunku: tego, który wybiera ustawienie Inventory script w panelu, albo pierwszego działającego, gdy ustawione jest automatycznie (ai-inventory, ox_inventory, qb-inventory, tgiann-inventory i inne z listy zgodności). Gdy właściciel serwera zmienia ekwipunek, twój skrypt działa dalej bez zmian.

Co trzeba wiedzieć:

  • Ekwipunek jest nazywany przez InventoryRef: id serwera gracza (liczba) dla kieszeni tego gracza albo tekstowe id dla wszystkiego innego (nazwa schowka, tablica bagażnika). Zobacz InventoryRef.
  • Nazwy przedmiotów to nazwy przedmiotów w ekwipunku (water, bandage, WEAPON_PISTOL).
  • Metadane to tabela dodatkowych wartości na jednym stosie (numer seryjny, wytrzymałość). Zobacz ItemMetadata.
  • Dopóki nie działa żaden ekwipunek, każde wywołanie odpowiada swoją wartością "nic": false, 0, pustą listą lub null.
  • Schowki, sklepy i używalne przedmioty, które rejestrujesz, są trzymane przez ai-core i przekazywane każdemu ekwipunkowi, który stanie się aktywny później, także po restarcie ekwipunku. Rejestruj je raz, gdy twój skrypt startuje.

AddItem

Daje przedmioty do ekwipunku.

Strona: Serwer · Czeka: nie · Lib: inventory.addItem

Sygnatura
AddItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): boolean
Lua
local ok = exports['ai-core']:AddItem(source, 'water', 2)

Parametry

Prop

Type

Zwraca

boolean: true, gdy ekwipunek dodał przedmioty. false, gdy się nie mieszczą, przedmiot nie istnieje w ekwipunku, argument jest zły (count poniżej 1, pusta nazwa przedmiotu) albo nie działa żaden ekwipunek.

Przykład

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

Zabiera przedmioty z ekwipunku.

Strona: Serwer · Czeka: nie · Lib: inventory.removeItem

Sygnatura
RemoveItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata, slot?: number): boolean
Lua
local ok = exports['ai-core']:RemoveItem(source, 'lockpick', 1)

Parametry

Prop

Type

Zwraca

boolean: true, gdy przedmioty zostały zabrane. false, gdy ekwipunek ma ich mniej (wtedy nic nie jest zabierane), argument jest zły albo nie działa żaden ekwipunek.

Przykład

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

Ile sztuk przedmiotu ma ekwipunek.

Strona: Serwer · Czeka: nie · Lib: inventory.getItemCount

Sygnatura
GetItemCount(inv: InventoryRef, item: string, metadata?: ItemMetadata): number
Lua
local count = exports['ai-core']:GetItemCount(source, 'fish')

Parametry

Prop

Type

Zwraca

number: suma ze wszystkich stosów. 0, gdy nie ma żadnego, argument jest zły albo nie działa żaden ekwipunek.

Przykład

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

// Skupujący ryby pokazuje, ile gracz by dostał.
onClientCallback("myscript:fishQuote", (source) => ({
  ok: true,
  price: core.GetItemCount(source, "fish") * 25,
}));

HasItem

Czy ekwipunek ma co najmniej daną liczbę przedmiotu.

Strona: Serwer · Czeka: nie · Lib: inventory.hasItem

Sygnatura
HasItem(inv: InventoryRef, item: string, count?: number): boolean
Lua
local has = exports['ai-core']:HasItem(source, 'repairkit')

Parametry

Prop

Type

Zwraca

boolean: true, gdy ekwipunek ma count lub więcej. false, gdy ma mniej, count jest poniżej 1 albo nie działa żaden ekwipunek.

Przykład

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 };
});

Po wszystkim, co czeka (pasek postępu, minigra), sprawdź ponownie odpowiedzią RemoveItem: gracz mógł w międzyczasie wyrzucić przedmiot.

CanCarryItem

Czy przedmioty zmieściłyby się w ekwipunku (waga i sloty), bez ich dodawania.

Strona: Serwer · Czeka: nie · Lib: inventory.canCarryItem

Sygnatura
CanCarryItem(inv: InventoryRef, item: string, count?: number, metadata?: ItemMetadata): boolean
Lua
local fits = exports['ai-core']:CanCarryItem(source, 'water', 5)

Parametry

Prop

Type

Zwraca

boolean: true, gdy się mieszczą. false, gdy się nie mieszczą, argument jest zły albo nie działa żaden ekwipunek.

Przykład

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

Każdy stos w ekwipunku, z etykietami.

Strona: Serwer · Czeka: nie · Lib: inventory.getItems

Sygnatura
GetItems(inv: InventoryRef): InventoryStack[]
Lua
local stacks = exports['ai-core']:GetItems(source) -- lista tabel

Parametry

Prop

Type

Zwraca

InventoryStack[]: jeden wpis na stos z name, label, count, slot i metadata. Zobacz InventoryStack. Pusta lista dla pustego lub nieznanego ekwipunku, złego argumentu albo gdy nie działa żaden ekwipunek.

Przykład

import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";

const core = resourceExport("ai-core");

// Lombard wyświetla każdy przedmiot, który gracz nosi, a który lombard skupuje.
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

Całkowicie opróżnia ekwipunek.

Strona: Serwer · Czeka: nie · Lib: inventory.clearInventory

Sygnatura
ClearInventory(inv: InventoryRef): void
Lua
exports['ai-core']:ClearInventory(source)

Parametry

Prop

Type

Zwraca

Nic. Zły argument albo brak działającego ekwipunku nic nie robi.

Przykład

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);
});

Tego nie da się cofnąć. Trzymaj to za komendą administratora albo jasną regułą gry (przyjęcie do więzienia, które najpierw przechowuje przedmioty).

RegisterStash

Tworzy schowek: skrzynię, którą gracze otwierają po jej nazwie. ai-core trzyma go i rejestruje ponownie w każdym ekwipunku, który staje się aktywny.

Strona: Serwer · Czeka: nie · Lib: inventory.registerStash

Sygnatura
RegisterStash(name: string, label: string, slots: number, maxWeight: number, jobs?: string[]): void
Lua
exports['ai-core']:RegisterStash('police_evidence', 'Evidence', 100, 500000, { 'police' })

Parametry

Prop

Type

Wartości domyślne obowiązują, gdy wartości brakuje lub jest zła.

Zwraca

Nic. Bez tekstowego name wywołanie nic nie robi. Ponowne zarejestrowanie tej samej nazwy zastępuje schowek.

Przykład

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 };

// Raz przy starcie; ai-core przekazuje go ekwipunkom, które wystartują później.
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

Otwiera schowek, bagażnik lub ekwipunek innego gracza na ekranie gracza, obok jego własnego.

Strona: Serwer · Czeka: nie · Lib: inventory.openInventory

Sygnatura
OpenInventory(source: number, inv: InventoryRef): boolean
Lua
local opened = exports['ai-core']:OpenInventory(source, 'police_evidence')

Parametry

Prop

Type

Zwraca

boolean: true, gdy ekwipunek otworzył ekran. false, gdy nie mógł (nieznany schowek, gracz nie ma ekwipunku), argument jest zły albo nie działa żaden ekwipunek.

Przykład

import { onClientCallback, isNear, coordsOf, resourceExport } from "@aicore-fivem/lib/server";
import { fail, oneArg, readId } from "@aicore-fivem/lib/shared";

const core = resourceExport("ai-core");

// Policja przeszukuje skutego gracza, który stoi obok.
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");
});

Ekwipunek nie sprawdza tutaj ani zasięgu, ani uprawnień. Sam sprawdź pracę, odległość i stan celu, zanim to wywołasz.

RegisterShop

Tworzy sklep skryptu: listę przedmiotów z cenami, którą twój skrypt otwiera dla gracza (zbrojownia, automat). Ekwipunek rysuje sklep i pobiera płatność po swojemu (gotówka, potem bank). ai-core trzyma go i przekazuje każdemu ekwipunkowi, który staje się aktywny.

Strona: Serwer · Czeka: nie · Lib: inventory.registerShop

Sygnatura
RegisterShop(name: string, label: string, items: ShopProduct[]): void
Lua
exports['ai-core']:RegisterShop('police_armoury', 'Armoury', { { name = 'bandage', price = 0 } })

Parametry

Prop

Type

Zobacz ShopProduct.

Zwraca

Nic. Bez tekstowego name albo bez żadnego poprawnego produktu wywołanie nic nie robi. Ponowne zarejestrowanie tej samej nazwy zastępuje sklep.

Przykład

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

Otwiera na ekranie gracza sklep zarejestrowany przez RegisterShop.

Strona: Serwer · Czeka: nie · Lib: inventory.openShop

Sygnatura
OpenShop(source: number, name: string): boolean
Lua
local opened = exports['ai-core']:OpenShop(source, 'police_armoury')

Parametry

Prop

Type

Zwraca

boolean: true, gdy sklep się otworzył. false, gdy żaden sklep nie ma tej nazwy, aktywny ekwipunek nie ma sklepów skryptów, nie mógł go otworzyć albo nie działa żaden ekwipunek.

Przykład

Zobacz przykład RegisterShop powyżej: zarejestruj raz przy starcie, potem otwieraj po własnym sprawdzeniu pracy i odległości.

Tak jak OpenInventory, to nie sprawdza zasięgu ani dostępu. Sprawdź je najpierw.

RegisterUsableItem

Robi z przedmiotu przedmiot używalny: gdy gracz użyje go w ekwipunku, działa twoja funkcja. ai-core trzyma funkcję, więc działa z ekwipunkami, które wystartują później, i przetrwa restart ekwipunku.

Strona: Serwer · Czeka: nie · Lib: inventory.registerUsableItem

Sygnatura
RegisterUsableItem(name: string, handler: UsableItemHandler): void
// UsableItemHandler = (source: number, item: UsedItem) => unknown
Lua
exports['ai-core']:RegisterUsableItem('bandage', function(source, item) end)

Parametry

Prop

Type

Zobacz UsableItemHandler i UsedItem.

Zwraca

Nic. Bez tekstowego name albo funkcji wywołanie nic nie robi. Drugie wywołanie dla tego samego przedmiotu zastępuje handler.

To, co dzieje się z przedmiotem po użyciu, zależy od ekwipunku: ekwipunki, które same zabierają użyty przedmiot (ai-inventory zabiera ilość consume przedmiotu), zatrzymują go, gdy twój handler zwróci false; inne ekwipunki działają według własnych ustawień przedmiotu, więc tam w razie potrzeby usuń przedmiot sam.

Przykład

import { progressFor, resourceExport } from "@aicore-fivem/lib/server";
import { Locale } from "common";

const core = resourceExport("ai-core");

core.RegisterUsableItem("bandage", (source) => {
  // Handler musi odpowiedzieć od razu; część czasowa działa osobno.
  void (async () => {
    if (!(await progressFor(source, { label: Locale("BANDAGING"), duration: 4000 }))) return;
    if (!core.RemoveItem(source, "bandage")) return;
    emitNet("myscript:client:heal", source, 25); // twój skrypt kliencki dodaje zdrowie
  })();
  return false; // zatrzymaj go: zostaje usunięty powyżej, gdy pasek się skończy
});

Użycie wysyła też serwerowe zdarzenie ai-core:itemUsed (src, name, status), które śledzą efekty przedmiotów, takie jak głód i pragnienie. Zobacz Zdarzenia i stan.

GetItemDefinition

Jeden przedmiot tak, jak definiuje go aktywny ekwipunek: etykieta, waga, czy się łączy w stosy, obrazek.

Strona: Serwer · Czeka: nie · Lib: inventory.getItemDefinition

Sygnatura
GetItemDefinition(name: string): ItemDefinition | null
Lua
local def = exports['ai-core']:GetItemDefinition('water') -- table lub nil

Parametry

Prop

Type

Zwraca

ItemDefinition | null: przedmiot z name, label, weight, unique, close, description i image, gdy ekwipunek go ma. Zobacz ItemDefinition. null dla nieznanego przedmiotu, pustej nazwy albo gdy nie działa żaden ekwipunek.

Przykład

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

Każdy przedmiot zdefiniowany przez aktywny ekwipunek, z nazwą jako kluczem. Używaj tego rzadko (jednorazowe budowanie listy); dla jednego przedmiotu używaj GetItemDefinition.

Strona: Serwer · Czeka: nie · Lib: brak

Sygnatura
GetItemDefinitions(): Record<string, ItemDefinition>
Lua
local items = exports['ai-core']:GetItemDefinitions() -- tabela z nazwą przedmiotu jako kluczem

Parametry

Brak.

Zwraca

Record<string, ItemDefinition>: każdy przedmiot. Pusta tabela, dopóki nie działa żaden ekwipunek.

Przykład

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}`);
}

Uruchamiaj takie sprawdzenie po starcie ekwipunku: zaraz po starcie serwera ekwipunek może jeszcze nie działać, a tabela jest pusta.

GetInventoryWeight

Co gracz nosi i ile może unieść, według wagi.

Strona: Serwer · Czeka: nie · Lib: brak

Sygnatura
GetInventoryWeight(source: number): { weight: number; maxWeight: number } | null
Lua
local w = exports['ai-core']:GetInventoryWeight(source) -- { weight, maxWeight } lub nil

Parametry

Prop

Type

Zwraca

{ weight, maxWeight } | null: noszona waga i limit, w gramach. null, gdy aktywny ekwipunek ich nie podaje, gracz nie ma wczytanego ekwipunku albo nie działa żaden ekwipunek.

Przykład

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

Uruchamia handler zarejestrowany dla przedmiotu, tak jakby gracz go użył. Wywołuje to most ESX / QB w ai-core (z ESX.UseItem i CanUseItem z QB); zwykły skrypt nie ma powodu tego robić.

Strona: Serwer · Czeka: nie · Lib: brak (tylko most)

Sygnatura
UseItem(source: number, name: string, item?: unknown): unknown
Lua
local result = exports['ai-core']:UseItem(source, 'bandage', stack)

Parametry

Prop

Type

Zwraca

unknown: to, co zwrócił handler. false, gdy żaden handler nie jest zarejestrowany, argumenty są złe albo handler rzucił wyjątek (zapisane w logu).

Przykład

Bez przykładu: wywołują to ekwipunki i most. Aby zareagować na użycie, zarejestruj przedmiot przez RegisterUsableItem.

IsUsableItem

Czy dla przedmiotu jest zarejestrowany handler. Używa tego most ai-core.

Strona: Serwer · Czeka: nie · Lib: brak (tylko most)

Sygnatura
IsUsableItem(name: string): boolean
Lua
local usable = exports['ai-core']:IsUsableItem('bandage')

Parametry

Prop

Type

Zwraca

boolean: true, gdy jakiś zasób zarejestrował przedmiot przez RegisterUsableItem. W przeciwnym razie false.

Przykład

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);
}

Na tej stronie