AI Core
Referencia de la APIEventos y estado

Eventos de servidor

Cada evento local de servidor que dispara ai-core - personajes, dinero, trabajos, servicio, bandas, metadatos, definiciones, objetos, muertes - con sus argumentos y listeners en TypeScript y Lua.

ai-core dispara estos eventos en el servidor con TriggerEvent (locales: los oyen los demás recursos de servidor, los clientes nunca). El espejo online de la lib y los puentes de ESX / QB / vRP se basan en ellos, así que son la forma más barata de seguir a los jugadores: ni llamadas a exports ni consultas periódicas.

El handler de cada evento se ejecuta de forma síncrona mientras ai-core está en mitad del cambio: mantén los handlers cortos y nunca esperes dentro de ellos. Si necesitas esperar (una escritura en la base de datos), iníciala sin bloquear.

ai-core:playerLoaded

Se cargó el personaje de un jugador y sus datos se enviaron a su cliente. Se dispara una vez por carga de personaje, también tras un cambio de personaje. Con la elección de aparición activada, se dispara antes de que el jugador elija dónde aparecer; ai-core:playerSpawned sigue a la elección.

Lado: Servidor · Constante: CORE.playerLoadedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE, type CharacterInfo } from "@aicore-fivem/shared";

on(CORE.playerLoadedEvent, (src: number, character: CharacterInfo) => {
  console.log(`#${character.id} ${character.firstname} ${character.lastname} loaded (src ${src})`);
});

Los personajes que ya estaban cargados antes de que se iniciara tu recurso nunca te disparan esto. Usa el onCharacter({ loaded }) de la lib (aiLib.onCharacter en Lua), que vuelve a pasártelos.

ai-core:playerSpawned

Se puso al personaje cargado en el mundo. Se dispara justo después de ai-core:playerLoaded, o después de que el jugador elija un punto de aparición cuando el servidor le deja elegir. Úsalo para cosas que necesitan el ped en el mundo (un mensaje de bienvenida, un teletransporte).

Lado: Servidor · Constante: CORE.playerSpawnedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { notify } from "@aicore-fivem/lib/server";
import { CORE } from "@aicore-fivem/shared";
import { Locale } from "common";

on(CORE.playerSpawnedEvent, (src: number, _charId: number) => {
  notify(src, Locale("WELCOME_BACK"), "info");
});

ai-core:playerUnloaded

Se está soltando a un personaje: el jugador salió del servidor o volvió a la pantalla de personajes. Se dispara antes de que ai-core descarte el personaje, así que los exports de ai-core siguen respondiendo por él dentro de tu handler. Limpia aquí todo lo que guardes por jugador.

Lado: Servidor · Constante: CORE.playerUnloadedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

const activeJobs = new Map<number, string>();

on(CORE.playerUnloadedEvent, (src: number, _charId: number, reason: "dropped" | "switch") => {
  activeJobs.delete(src);
  console.log(`${src} unloaded (${reason})`);
});

Con reason = "switch" el mismo id de servidor puede cargar otro personaje un momento después. Guarda tus datos por personaje con charId como clave o bórralos aquí; nunca supongas que un id de servidor conserva un mismo personaje.

ai-core:moneyChanged

Cambió el saldo de una cuenta de un personaje cargado. Se dispara después de aplicar el cambio, una vez por cambio, solo cuando el saldo se movió de verdad.

Lado: Servidor · Constante: CORE.moneyChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

// Marca los pagos grandes en efectivo para el staff.
on(CORE.moneyChangedEvent, (src: number, account: string, balance: number, delta: number, reason: string) => {
  if (account === "cash" && delta >= 100_000)
    console.log(`${src} got $${delta} cash (${reason}), now $${balance}`);
});

ai-core:jobsChanged

Cambió la lista de trabajos que tiene un personaje cargado: se añadió o quitó un trabajo, o cambió un rango.

Lado: Servidor · Constante: CORE.jobsChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE, type JobMembership } from "@aicore-fivem/shared";

on(CORE.jobsChangedEvent, (src: number, jobs: JobMembership[]) => {
  const police = jobs.find((m) => m.job === "police");
  console.log(police ? `${src} is police grade ${police.grade}` : `${src} is not police`);
});

ai-core:dutyChanged

Un personaje cargado entró de servicio en un trabajo, o salió de servicio. Un jugador está de servicio en como mucho un trabajo a la vez.

Lado: Servidor · Constante: CORE.dutyChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.dutyChangedEvent, (src: number, job: string | null) => {
  console.log(job ? `${src} on duty: ${job}` : `${src} off duty`);
});

Para saber cuántos jugadores están de servicio en un trabajo, lee el GlobalState ai:duty:<job> (consulta State bags) en lugar de contar tú estos eventos.

ai-core:gangsChanged

Cambió la lista de bandas a las que pertenece un personaje cargado: se añadió o quitó una banda, o cambió un rango.

Lado: Servidor · Constante: CORE.gangsChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE, type GangMembership } from "@aicore-fivem/shared";

on(CORE.gangsChangedEvent, (src: number, gangs: GangMembership[]) => {
  console.log(`${src} is in ${gangs.length} gang(s)`);
});

ai-core:activeGangChanged

Un personaje cargado cambió la banda para la que actúa, o ya no actúa para ninguna.

Lado: Servidor · Constante: CORE.activeGangChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.activeGangChangedEvent, (src: number, gang: string | null) => {
  console.log(`${src} now acts for ${gang ?? "no gang"}`);
});

ai-core:metaChanged

Cambió un valor de metadatos de un personaje cargado. Los metadatos son una bolsa libre de clave / valor guardada con el personaje; los puentes de ESX / QB guardan ahí los metadatos de framework (hambre, sed, estrés, isdead...).

Lado: Servidor · Constante: CORE.metaChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.metaChangedEvent, (src: number, key: string, value: unknown) => {
  if (key === "stress" && typeof value === "number" && value >= 90)
    console.log(`${src} is very stressed`);
});

ai-core:definitionsChanged

Se añadió, cambió o borró un trabajo o una banda en el panel de administración. Se dispara una vez por cada trabajo o banda que cambió.

Lado: Servidor · Constante: CORE.definitionsChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

const labelCache = new Map<string, string>();

// Descarta una etiqueta en caché cuando el panel cambia ese trabajo.
on(CORE.definitionsChangedEvent, (file: "jobs" | "gangs", name: string) => {
  if (file === "jobs") labelCache.delete(name);
});

ai-core:characterScreen

La pantalla de personajes de un jugador está cargando (tras entrar, o tras volver a ella). ai-core lee por sí mismo los aspectos de las tarjetas; un script de ropa lo escucha para dibujar los retratos de las tarjetas.

Lado: Servidor · Constante: CORE.characterScreenEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.characterScreenEvent, (src: number, charIds: number[]) => {
  console.log(`${src} sees ${charIds.length} character card(s)`);
});

ai-core:inventoryChanged

Cambió el inventario que hay detrás de la capa de inventario de ai-core: el inventario elegido se inició o se detuvo, o el dueño eligió otro en el panel. Descarta todo lo que tuvieras en caché del inventario anterior (etiquetas de objetos, definiciones).

Lado: Servidor · Constante: CORE.inventoryChangedEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { CORE } from "@aicore-fivem/shared";

let itemLabels: Record<string, string> | null = null;

on(CORE.inventoryChangedEvent, (resource: string | null) => {
  itemLabels = null; // se vuelve a leer del nuevo inventario en el próximo uso
  console.log(`inventory is now ${resource ?? "none"}`);
});

ai-core:itemUsed

Un jugador usó un objeto. Lleva las necesidades que da el objeto (hambre, sed, estrés), para que un HUD o un script de necesidades las aplique sin conocer el inventario. ai-hud lo escucha.

Lado: Servidor · Constante: CORE.itemUsedEvent

Argumentos

Prop

Type

Oyente

resource/server/needs.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.itemUsedEvent, (src: number, name: string, status: Record<string, number> | null) => {
  if (!status) return;
  for (const [need, amount] of Object.entries(status))
    console.log(`${src} used ${name}: ${need} ${amount > 0 ? "+" : ""}${amount}`);
});

Hoy solo ai-inventory informa a ai-core de los usos de objetos: con otro inventario este evento no se dispara. Escucha este evento, no el evento de uso propio de un inventario, para que tu script funcione cuando ai-inventory es el inventario y siga funcionando cuando se añadan otros.

ai-core:playerDied

Murió un jugador con un personaje cargado. ai-core lo toma del propio aviso de muerte de ped de FXServer (FXServer 38039 o más nuevo), así que no se confía en ningún cliente.

Lado: Servidor · Constante: CORE.playerDiedEvent

Argumentos

Prop

Type

Oyente

resource/server/killfeed.ts
import { CORE } from "@aicore-fivem/shared";

on(CORE.playerDiedEvent, (src: number, killer: number | null, weaponHash: number) => {
  if (killer !== null && killer !== src)
    console.log(`${GetPlayerName(String(killer))} killed ${GetPlayerName(String(src))} (weapon ${weaponHash})`);
});

Esta es la muerte del juego, no el estado de "caído" del script de muerte: un script de muerte puede mantener vivo a un jugador caído para animarlo. Para saber "si este jugador está caído", usa el medical de la lib de servidor o los exports médicos de servidor de ai-core.

ai-core:vrp:config

El dueño del servidor cambió el mapeo de vRP en el panel de ai-core (pestaña "vRP scripts"). El puente de vRP de ai-core lo escucha; solo lo necesitas si lees tú el mapeo de vRP.

Lado: Servidor · Constante: VRP.configEvent

Argumentos

Prop

Type

Oyente

resource/server/index.ts
import { VRP, type VrpConfig } from "@aicore-fivem/shared";

on(VRP.configEvent, (config: VrpConfig) => {
  console.log(`${config.permissions.length} vRP permission rule(s)`);
});

Eventos de otros scripts ai-*

Estos los disparan scripts ai-*, no ai-core, pero muchos recursos los escuchan. Su referencia completa está en la página para desarrolladores de cada script.

ai-vehicles:owners

Cambiaron los dueños de los vehículos en propiedad que hay en memoria (se cargó un personaje con su garaje, se compró, vendió o borró un vehículo). Se dispara como mucho una vez por tick del servidor con todos los cambios de ese tick. Los scripts de llaves lo usan para mantener un mapa de matrícula a dueño sin preguntar a ai-vehicles cada vez.

Lado: Servidor · Constante: VEHICLES_EVENTS.owners

Argumentos

Prop

Type

Oyente

resource/server/owners.ts
import { resourceExport } from "@aicore-fivem/lib/server";
import { VEHICLES_EVENTS } from "@aicore-fivem/shared";

const owners = new Map<string, string>();

// Empieza con la lista completa y después sigue los cambios.
for (const [plate, type, id] of resourceExport("ai-vehicles").GetPlateOwners()) owners.set(plate, `${type}:${id}`);

on(VEHICLES_EVENTS.owners, (puts: Array<[string, string, string]>, removes: string[]) => {
  for (const [plate, type, id] of puts) owners.set(plate, `${type}:${id}`);
  for (const plate of removes) owners.delete(plate);
});

chatMessage

ai-chat dispara el clásico evento chatMessage de FiveM antes de entregar el mensaje de un jugador. Llamar a CancelEvent() en tu handler descarta el mensaje.

Lado: Servidor · Constante: ninguna (el propio nombre de FiveM)

Argumentos

Prop

Type

Oyente

resource/server/filter.ts
on("chatMessage", (source: number, _author: string, text: string) => {
  if (text.toLowerCase().includes("discord.gg")) {
    CancelEvent();
    console.log(`blocked an invite link from ${source}`);
  }
});

En esta página