AI Core
Referencia de la APIAI Core: exports de servidor

Dinero y cuentas

Lee y cambia los saldos de un jugador y las cuentas de trabajos y bandas, mueve dinero entre dos cuentas en una sola transacción, lee los tipos de cuenta.

Cada personaje tiene un saldo por tipo de cuenta. Los tipos vienen de la lista Accounts del panel de administración; un servidor nuevo tiene cash, bank, black_money y crypto. Cada trabajo y cada banda tiene también una cuenta de cada tipo (el dinero de la sociedad), que empieza vacía.

Cómo funciona el dinero en ai-core:

  • Las cantidades son números enteros (dólares, sin céntimos). Una fracción, NaN o un número fuera del rango de enteros seguros de JavaScript se rechaza.
  • Un cambio se aplica al momento en memoria y se escribe en la base de datos en unos 50 ms, junto con una fila del registro de movimientos (ai_core_transactions). El registro guarda el reason que pasas; sin él guarda el nombre del recurso que llamó.
  • Un saldo no puede bajar de 0 salvo que su tipo de cuenta tenga activado Can go below zero (puede bajar de cero) en el panel.
  • Cada cambio en la cuenta de un jugador dispara el evento de servidor ai-core:moneyChanged (src, account, balance, delta, reason) y llega al propio juego del jugador. Consulta Eventos y estado.

GetMoney

El saldo de un jugador en una cuenta.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
GetMoney(src: number, account: string): number | null
Lua
local balance = exports['ai-core']:GetMoney(source, 'bank') -- number o nil

Parámetros

Prop

Type

Devuelve

number | null: el saldo. null cuando el jugador no tiene un personaje cargado o el tipo de cuenta no existe.

Ejemplo

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

Añade dinero a la cuenta de un jugador. Úsalo para recompensas, sueldos que paga tu script o ingresos de ventas.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
AddMoney(src: number, account: string, amount: number, reason?: string): boolean
Lua
local ok = exports['ai-core']:AddMoney(source, 'cash', 250, 'fishing_sale')

Parámetros

Prop

Type

Devuelve

boolean: true cuando se añadió el dinero. false cuando el jugador no tiene un personaje cargado, el tipo de cuenta no existe o amount no es un número entero mayor que 0.

Ejemplo

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

Para mover dinero de una cuenta a otra (un jugador que paga a un trabajo, una transferencia bancaria), usa TransferMoney, no un par RemoveMoney + AddMoney: una transferencia es una sola transacción en la base de datos, un par son dos cambios separados.

RemoveMoney

Quita dinero de la cuenta de un jugador. Úsalo para cobrar algo.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
RemoveMoney(src: number, account: string, amount: number, reason?: string): boolean
Lua
local paid = exports['ai-core']:RemoveMoney(source, 'bank', 500, 'license_fee')

Parámetros

Prop

Type

Devuelve

boolean: true cuando se quitó el dinero. false cuando el saldo es demasiado bajo (y el tipo de cuenta no permite saldos negativos), el jugador no tiene un personaje cargado, el tipo de cuenta no existe o amount no es un número entero mayor que 0. Con false no cambió nada.

Ejemplo

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

Comprueba lo que puede fallar antes de quitar el dinero (espacio en el inventario, existencias), o devuelve el dinero con AddMoney cuando falle el paso siguiente.

SetMoney

Pone el saldo de un jugador a un valor exacto. Úsalo para herramientas de admin; las funciones del juego deberían añadir y quitar.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
SetMoney(src: number, account: string, amount: number, reason?: string): boolean
Lua
local ok = exports['ai-core']:SetMoney(source, 'cash', 0, 'admin_reset')

Parámetros

Prop

Type

Devuelve

boolean: true cuando el saldo es ahora amount (también cuando ya lo era). false cuando el jugador no tiene un personaje cargado, el tipo de cuenta no existe, amount no es un número entero o es menor que 0 en una cuenta que no lo permite.

Ejemplo

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

El saldo de la cuenta de un trabajo o una banda (dinero de la sociedad).

Lado: Servidor · Espera: no · Lib: ninguna (banking.societyBalance pregunta a la capa de banca, que puede leer de un script de banca en su lugar)

Firma
GetSharedMoney(ownerType: "job" | "gang", ownerId: string, account: string): number | null
Lua
local balance = exports['ai-core']:GetSharedMoney('job', 'police', 'bank') -- number o nil

Parámetros

Prop

Type

Devuelve

number | null: el saldo. null cuando el trabajo, la banda o el tipo de cuenta no existen (o sus cuentas aún no están cargadas).

Ejemplo

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

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

// Un menú de jefe muestra el dinero del trabajo; solo los miembros del trabajo pueden pedirlo.
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 };
});

Cuando el ajuste del panel Job and gang accounts está en The script's own accounts, las cuentas bank de los trabajos y bandas viven en ese script: entonces este export lee el saldo del script. Consulta Banca.

AddSharedMoney

Añade dinero a la cuenta de un trabajo o una banda.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
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')

Parámetros

Prop

Type

Devuelve

boolean: true cuando se añadió el dinero. false cuando el trabajo, la banda o la cuenta no existen o amount no es un número entero mayor que 0.

Ejemplo

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

Cuando un jugador paga al trabajo, usa TransferMoney de la cuenta del jugador a la del trabajo: una transacción, ambas filas del registro.

RemoveSharedMoney

Quita dinero de la cuenta de un trabajo o una banda.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
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')

Parámetros

Prop

Type

Devuelve

boolean: true cuando se quitó el dinero. false cuando el saldo es demasiado bajo (y no se permiten saldos negativos), el trabajo, la banda o la cuenta no existen o amount no es un número entero mayor que 0.

Ejemplo

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

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

// Un trabajo encarga suministros desde su propia cuenta.
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

Mueve dinero de una cuenta a otra en una sola transacción de la base de datos con ambas filas del registro. Cada lado puede ser la cuenta de un jugador cargado o la cuenta de un trabajo o una banda. Úsalo para cada pago entre dos cuentas: un jugador que paga a un negocio, una transferencia bancaria, un ingreso en la sociedad.

Lado: Servidor · Espera: no · Lib: money.transfer

Firma
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)

Parámetros

Prop

Type

MoneyRef es { source, account } para la cuenta de un jugador cargado, o { owner, id, account } para la cuenta de un trabajo o una banda. Consulta MoneyRef.

Devuelve

boolean: true cuando from pagó amount + fee y to recibió amount. false cuando falta una cuenta (jugador no cargado, trabajo desconocido, tipo de cuenta desconocido), ambos lados son la misma cuenta, from no puede pagar amount + fee, amount no es un número entero mayor que 0 o fee no es un número entero de 0 o más. Con false no cambió nada.

Ejemplo

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

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

// Un ingreso en cajero en la cuenta de la propia banda del jugador, con una comisión del 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");
  },
);

Ambos lados disparan su cambio habitual (el lado de un jugador dispara ai-core:moneyChanged). Dos jugadores pueden ser los dos lados: { source: a, account: "bank" } a { source: b, account: "bank" }.

GetAccountTypes

Cada tipo de cuenta de la lista Accounts del panel, con su etiqueta, su cantidad inicial y si puede quedar en negativo. Úsalo para construir un menú de cuentas o para comprobar un nombre.

Lado: Servidor · Espera: no · Lib: ninguna

Firma
GetAccountTypes(): Record<string, AccountTypeDefinition>
Lua
local types = exports['ai-core']:GetAccountTypes() -- tabla con el nombre de la cuenta como clave

Parámetros

Ninguno.

Devuelve

Record<string, AccountTypeDefinition>: una copia con el nombre de la cuenta como clave (cash, bank...). Cada valor tiene label (lo que ven los jugadores), start (lo que recibe un personaje nuevo) y allowNegative. Consulta AccountTypeDefinition.

Ejemplo

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

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

// La pantalla de la cartera lista cada cuenta con su etiqueta y su saldo.
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 };
});

En esta página