AI Core
Справочник APIAI Core: серверные экспорты

Деньги и счета

Читать и менять балансы игрока, счета работ и банд, перемещать деньги между двумя счетами одной транзакцией, читать типы счетов.

У каждого персонажа есть по одному балансу на каждый тип счёта. Типы берутся из списка Accounts в админ-панели; на новом сервере есть cash, bank, black_money и crypto. У каждой работы и банды тоже есть по одному счёту каждого типа (деньги организации), который изначально пуст.

Как работают деньги в ai-core:

  • Суммы - целые числа (доллары, без центов). Дробь, NaN или число за пределами безопасного диапазона целых в JavaScript отклоняются.
  • Изменение сразу применяется в памяти и записывается в базу данных примерно в течение 50 мс вместе со строкой журнала операций (ai_core_transactions). Журнал хранит переданный вами reason; без него он хранит имя вызвавшего ресурса.
  • Баланс не может опуститься ниже 0, если у его типа счёта в панели не включено Can go below zero.
  • Каждое изменение счёта игрока вызывает серверное событие ai-core:moneyChanged (src, account, balance, delta, reason) и доходит до игры самого игрока. См. События и состояние.

GetMoney

Баланс игрока на одном счёте.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetMoney(src: number, account: string): number | null
Lua
local balance = exports['ai-core']:GetMoney(source, 'bank') -- number или nil

Параметры

Prop

Type

Возвращает

number | null: баланс. null, когда у игрока нет загруженного персонажа или тип счёта не существует.

Пример

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

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

onClientCallback("myscript:balance", (source) => {
  const bank = core.GetMoney(source, "bank");
  if (bank === null) return fail("NO_CHARACTER");
  return { ok: true, bank };
});

AddMoney

Добавляет деньги на счёт игрока. Используйте для наград, зарплат, которые платит ваш скрипт, или дохода от продаж.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
AddMoney(src: number, account: string, amount: number, reason?: string): boolean
Lua
local ok = exports['ai-core']:AddMoney(source, 'cash', 250, 'fishing_sale')

Параметры

Prop

Type

Возвращает

boolean: true, когда деньги добавлены. false, когда у игрока нет загруженного персонажа, тип счёта не существует или amount не целое число больше 0.

Пример

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

const core = resourceExport("ai-core");
const BUYER = { x: -1845.2, y: -1197.4, z: 14.3 };

onClientCallback("myscript:sellFish", { guards: [near(BUYER, 3)], lock: true }, (source) => {
  const fish = inventory.getItemCount(source, "fish");
  if (fish < 1) return fail("NO_FISH");
  if (!inventory.removeItem(source, "fish", fish)) return fail("SELL_FAILED");
  core.AddMoney(source, "cash", fish * 25, "fishing_sale");
  return { ok: true };
});

Чтобы переместить деньги с одного счёта на другой (игрок платит работе, банковский перевод), используйте TransferMoney, а не пару RemoveMoney + AddMoney: перевод - это одна транзакция в базе данных, а пара - два отдельных изменения.

RemoveMoney

Забирает деньги со счёта игрока. Используйте, чтобы взять плату за что-либо.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
RemoveMoney(src: number, account: string, amount: number, reason?: string): boolean
Lua
local paid = exports['ai-core']:RemoveMoney(source, 'bank', 500, 'license_fee')

Параметры

Prop

Type

Возвращает

boolean: true, когда деньги забраны. false, когда баланса не хватает (а тип счёта не разрешает отрицательный баланс), у игрока нет загруженного персонажа, тип счёта не существует или amount не целое число больше 0. При false ничего не изменилось.

Пример

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

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

onClientCallback("myscript:buyLicense", { lock: true }, (source) => {
  if (!inventory.canCarryItem(source, "driver_license")) return fail("NO_SPACE");
  if (!core.RemoveMoney(source, "bank", PRICE, "license_fee")) return fail("NOT_ENOUGH_MONEY");
  inventory.addItem(source, "driver_license");
  return { ok: true };
});

Проверьте то, что может не получиться, до того как забрать деньги (место в инвентаре, наличие товара), или верните деньги через AddMoney, когда следующий шаг не удался.

SetMoney

Устанавливает баланс игрока в точное значение. Используйте для админских инструментов; игровые функции должны добавлять и забирать.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
SetMoney(src: number, account: string, amount: number, reason?: string): boolean
Lua
local ok = exports['ai-core']:SetMoney(source, 'cash', 0, 'admin_reset')

Параметры

Prop

Type

Возвращает

boolean: true, когда баланс теперь равен amount (и тогда, когда уже был). false, когда у игрока нет загруженного персонажа, тип счёта не существует, amount не целое число или он ниже 0 на счёте, который этого не разрешает.

Пример

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

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

addCommand("setcash", {
  help: "Sets a player cash",
  params: [{ name: "id", type: "playerId" }, { name: "amount", type: "number" }],
  restricted: true,
}, (_source, args) => {
  console.log(core.SetMoney(args.id, "cash", args.amount, "admin_set") ? "done" : "refused");
});

GetSharedMoney

Баланс счёта работы или банды (деньги организации).

Сторона: сервер · Ожидание: нет · Библиотека: нет (banking.societyBalance спрашивает банковский слой, который может читать банковский скрипт)

Сигнатура
GetSharedMoney(ownerType: "job" | "gang", ownerId: string, account: string): number | null
Lua
local balance = exports['ai-core']:GetSharedMoney('job', 'police', 'bank') -- number или nil

Параметры

Prop

Type

Возвращает

number | null: баланс. null, когда работа, банда или тип счёта не существует (или её счета ещё не загружены).

Пример

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

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

// Меню босса показывает деньги работы; спрашивать могут только сотрудники этой работы.
onClientCallback("myscript:societyBalance", (source) => {
  const job = online.dutyJob(source);
  if (!job) return fail("NOT_ON_DUTY");
  return { ok: true, balance: core.GetSharedMoney("job", job, "bank") ?? 0 };
});

Когда в настройке панели Job and gang accounts выбрано The script's own accounts, счета bank работ и банд живут в этом скрипте: тогда этот экспорт читает баланс скрипта. См. Банк.

AddSharedMoney

Добавляет деньги на счёт работы или банды.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
AddSharedMoney(
  ownerType: "job" | "gang",
  ownerId: string,
  account: string,
  amount: number,
  reason?: string,
): boolean
Lua
local ok = exports['ai-core']:AddSharedMoney('job', 'mechanic', 'bank', 300, 'repair_fee')

Параметры

Prop

Type

Возвращает

boolean: true, когда деньги добавлены. false, когда работа, банда или счёт не существует или amount не целое число больше 0.

Пример

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

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

/** A sale made by an NPC customer goes into the restaurant's account. */
export function restaurantSale(job: string, price: number): void {
  if (!core.AddSharedMoney("job", job, "bank", price, "npc_sale"))
    console.log(`job ${job} has no bank account`);
}

Когда игрок платит работе, используйте TransferMoney со счёта игрока на счёт работы: одна транзакция, обе строки журнала.

RemoveSharedMoney

Забирает деньги со счёта работы или банды.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
RemoveSharedMoney(
  ownerType: "job" | "gang",
  ownerId: string,
  account: string,
  amount: number,
  reason?: string,
): boolean
Lua
local ok = exports['ai-core']:RemoveSharedMoney('job', 'police', 'bank', 2000, 'equipment')

Параметры

Prop

Type

Возвращает

boolean: true, когда деньги забраны. false, когда баланса не хватает (а отрицательный баланс не разрешён), работа, банда или счёт не существует или amount не целое число больше 0.

Пример

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

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

// Работа заказывает материалы со своего счёта.
onClientCallback("myscript:orderSupplies", { lock: true }, (source) => {
  const job = online.dutyJob(source);
  if (!job) return fail("NOT_ON_DUTY");
  if (!core.RemoveSharedMoney("job", job, "bank", 1500, "supplies")) return fail("SOCIETY_NO_MONEY");
  return { ok: true };
});

TransferMoney

Перемещает деньги с одного счёта на другой одной транзакцией в базе данных с обеими строками журнала. Каждая сторона может быть счётом загруженного игрока или счётом работы или банды. Используйте для каждого платежа между двумя счетами: игрок платит бизнесу, банковский перевод, взнос в организацию.

Сторона: сервер · Ожидание: нет · Библиотека: money.transfer

Сигнатура
TransferMoney(from: MoneyRef, to: MoneyRef, amount: number, reason?: string, fee?: number): boolean
Lua
local ok = exports['ai-core']:TransferMoney(
  { source = source, account = 'bank' },
  { owner = 'job', id = 'mechanic', account = 'bank' },
  750, 'repair', 0)

Параметры

Prop

Type

MoneyRef - это { source, account } для счёта загруженного игрока или { owner, id, account } для счёта работы или банды. См. MoneyRef.

Возвращает

boolean: true, когда from заплатил amount + fee, а to получил amount. false, когда счёт отсутствует (игрок не загружен, неизвестная работа, неизвестный тип счёта), обе стороны - один и тот же счёт, from не может заплатить amount + fee, amount не целое число больше 0 или fee не целое число от 0. При false ничего не изменилось.

Пример

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

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

// Взнос через банкомат на счёт собственной банды игрока, с комиссией 2%.
onClientCallback(
  "myscript:gangDeposit",
  { args: ([amount]) => { const n = readInt(amount, 1, 1_000_000); return n === null ? null : [n]; }, lock: true },
  (source, amount) => {
    const gang = core.GetActiveGang(source);
    if (!gang) return fail("NO_GANG");
    const fee = Math.ceil(amount * 0.02);
    const ok = core.TransferMoney(
      { source, account: "bank" },
      { owner: "gang", id: gang, account: "bank" },
      amount, "gang_deposit", fee,
    );
    return ok ? { ok: true } : fail("NOT_ENOUGH_MONEY");
  },
);

Обе стороны вызывают своё обычное событие изменения (сторона игрока вызывает ai-core:moneyChanged). Обеими сторонами могут быть два игрока: { source: a, account: "bank" } в { source: b, account: "bank" }.

GetAccountTypes

Все типы счетов из списка Accounts в панели, с подписью, начальной суммой и тем, может ли баланс уходить в минус. Используйте, чтобы построить меню счетов или проверить имя.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetAccountTypes(): Record<string, AccountTypeDefinition>
Lua
local types = exports['ai-core']:GetAccountTypes() -- таблица с ключами по имени счёта

Параметры

Нет.

Возвращает

Record<string, AccountTypeDefinition>: копия с ключами по имени счёта (cash, bank...). У каждого значения есть label (видят игроки), start (что получает новый персонаж) и allowNegative. См. AccountTypeDefinition.

Пример

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

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

// Экран кошелька показывает каждый счёт с подписью и балансом.
onClientCallback("myscript:wallet", (source) => {
  const rows = Object.entries(core.GetAccountTypes()).map(([name, type]) => ({
    name,
    label: type.label,
    balance: core.GetMoney(source, name) ?? 0,
  }));
  return { ok: true, rows };
});

На этой странице