AI Core
Référence de l’APIÉvénements et état

Événements serveur

Chaque événement local côté serveur que déclenche ai-core - personnages, argent, métiers, service, gangs, métadonnées, définitions, objets, morts - avec arguments et écouteurs en TypeScript et en Lua.

ai-core déclenche ces événements sur le serveur avec TriggerEvent (locaux : les autres ressources serveur les entendent, les clients jamais). Le miroir online de la lib et les ponts ESX / QB / vRP reposent dessus ; c’est donc le moyen le moins coûteux de suivre les joueurs : aucun appel d’export, aucune interrogation en boucle.

Le handler de chaque événement s’exécute de façon synchrone pendant qu’ai-core est au milieu du changement : gardez les handlers courts et n’attendez jamais à l’intérieur. Si vous devez attendre (une écriture en base de données), lancez-la sans bloquer.

ai-core:playerLoaded

Le personnage d’un joueur a été chargé et ses données envoyées à son client. Se déclenche une fois par chargement de personnage, aussi après un changement de personnage. Avec le choix d’apparition activé, il se déclenche avant que le joueur choisisse où apparaître ; ai-core:playerSpawned suit le choix.

Côté : Serveur · Constante : CORE.playerLoadedEvent

Arguments

Prop

Type

Écouteur

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

Les personnages déjà chargés avant le démarrage de votre ressource ne le déclenchent jamais pour vous. Utilisez onCharacter({ loaded }) de la lib (aiLib.onCharacter en Lua), qui les rejoue.

ai-core:playerSpawned

Le personnage chargé a été placé dans le monde. Se déclenche juste après ai-core:playerLoaded, ou après que le joueur a choisi un point d’apparition quand le serveur le laisse choisir. Utilisez-le pour ce qui a besoin du ped dans le monde (un message de bienvenue, une téléportation).

Côté : Serveur · Constante : CORE.playerSpawnedEvent

Arguments

Prop

Type

Écouteur

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

Un personnage est libéré : le joueur a quitté le serveur, ou est revenu à l’écran des personnages. Se déclenche avant qu’ai-core abandonne le personnage, si bien que les exports d’ai-core répondent encore pour lui dans votre handler. Nettoyez ici tout ce que vous gardez par joueur.

Côté : Serveur · Constante : CORE.playerUnloadedEvent

Arguments

Prop

Type

Écouteur

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

Avec reason = "switch", le même id serveur peut charger un autre personnage un instant plus tard. Indexez vos données par personnage avec charId ou effacez-les ici ; ne supposez jamais qu’un id serveur garde un seul personnage.

ai-core:moneyChanged

Le solde d’un compte d’un personnage chargé a changé. Se déclenche après l’application du changement, une fois par changement, seulement quand le solde a vraiment bougé.

Côté : Serveur · Constante : CORE.moneyChangedEvent

Arguments

Prop

Type

Écouteur

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

// Signale au staff les gros paiements en liquide.
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

La liste des métiers d’un personnage chargé a changé : un métier ajouté ou retiré, ou un grade modifié.

Côté : Serveur · Constante : CORE.jobsChangedEvent

Arguments

Prop

Type

Écouteur

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 personnage chargé a pris son service dans un métier, ou l’a quitté. Un joueur est en service dans au plus un métier à la fois.

Côté : Serveur · Constante : CORE.dutyChangedEvent

Arguments

Prop

Type

Écouteur

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

Pour savoir combien de joueurs sont en service dans un métier, lisez la clé GlobalState ai:duty:<job> (voir State bags) au lieu de compter ces événements vous-même.

ai-core:gangsChanged

La liste des gangs d’un personnage chargé a changé : un gang ajouté ou retiré, ou un grade modifié.

Côté : Serveur · Constante : CORE.gangsChangedEvent

Arguments

Prop

Type

Écouteur

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 personnage chargé a changé le gang pour lequel il agit, ou n’agit plus pour aucun.

Côté : Serveur · Constante : CORE.activeGangChangedEvent

Arguments

Prop

Type

Écouteur

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

Une valeur de métadonnées d’un personnage chargé a changé. Les métadonnées sont un sac libre de clés / valeurs stocké avec le personnage ; les ponts ESX / QB y gardent les métadonnées de framework (hunger, thirst, stress, isdead...).

Côté : Serveur · Constante : CORE.metaChangedEvent

Arguments

Prop

Type

Écouteur

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

Un métier ou un gang a été ajouté, modifié ou supprimé dans le panneau d’administration. Se déclenche une fois par métier ou gang modifié.

Côté : Serveur · Constante : CORE.definitionsChangedEvent

Arguments

Prop

Type

Écouteur

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

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

// Oublie un libellé en cache quand le panneau modifie ce métier.
on(CORE.definitionsChangedEvent, (file: "jobs" | "gangs", name: string) => {
  if (file === "jobs") labelCache.delete(name);
});

ai-core:characterScreen

L’écran des personnages d’un joueur se charge (après la connexion, ou après y être revenu). ai-core lit lui-même les apparences des cartes ; un script de vêtements écoute pour dessiner les portraits des cartes.

Côté : Serveur · Constante : CORE.characterScreenEvent

Arguments

Prop

Type

Écouteur

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

L’inventaire derrière la couche d’inventaire d’ai-core a changé : l’inventaire choisi a démarré ou s’est arrêté, ou le propriétaire en a choisi un autre dans le panneau. Oubliez tout ce que vous aviez mis en cache depuis l’ancien inventaire (libellés d’objets, définitions).

Côté : Serveur · Constante : CORE.inventoryChangedEvent

Arguments

Prop

Type

Écouteur

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; // relire depuis le nouvel inventaire à la prochaine utilisation
  console.log(`inventory is now ${resource ?? "none"}`);
});

ai-core:itemUsed

Un joueur a utilisé un objet. Transporte les besoins que donne l’objet (faim, soif, stress), pour qu’un HUD ou un script de besoins les applique sans connaître l’inventaire. ai-hud l’écoute.

Côté : Serveur · Constante : CORE.itemUsedEvent

Arguments

Prop

Type

Écouteur

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

Aujourd’hui, seul ai-inventory signale les utilisations d’objets à ai-core : avec un autre inventaire, cet événement ne se déclenche pas. Écoutez cet événement, et non l’événement d’utilisation propre à un inventaire, pour que votre script fonctionne quand ai-inventory est l’inventaire et continue de fonctionner quand d’autres seront ajoutés.

ai-core:playerDied

Un joueur avec un personnage chargé est mort. ai-core le tient du propre rapport de mort de ped de FXServer (FXServer 38039 ou plus récent), si bien qu’aucun client n’est cru sur parole.

Côté : Serveur · Constante : CORE.playerDiedEvent

Arguments

Prop

Type

Écouteur

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

Il s’agit de la mort dans le jeu, pas de l’état « à terre » du script de mort : un script de mort peut garder en vie un joueur à terre pour l’animer. Pour savoir si un joueur est à terre, utilisez medical de la lib serveur ou les exports médicaux serveur d’ai-core.

ai-core:vrp:config

Le propriétaire du serveur a modifié la correspondance vRP dans le panneau d’ai-core (onglet "vRP scripts"). Le pont vRP d’ai-core l’écoute ; vous n’en avez besoin que si vous lisez vous-même la correspondance vRP.

Côté : Serveur · Constante : VRP.configEvent

Arguments

Prop

Type

Écouteur

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

Événements des autres scripts ai-*

Ceux-ci sont déclenchés par des scripts ai-*, pas par ai-core, mais beaucoup de ressources les écoutent. Leur référence complète se trouve sur la page développeur de chaque script.

ai-vehicles:owners

Les propriétaires des véhicules possédés en mémoire ont changé (un personnage chargé avec son garage, un véhicule acheté, vendu ou supprimé). Se déclenche au plus une fois par tick serveur avec tous les changements de ce tick. Les scripts de clés l’utilisent pour garder une table plaque vers propriétaire sans interroger ai-vehicles à chaque fois.

Côté : Serveur · Constante : VEHICLES_EVENTS.owners

Arguments

Prop

Type

Écouteur

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

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

// Partir de la liste complète, puis suivre les changements.
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 déclenche l’événement FiveM classique chatMessage avant de livrer le message d’un joueur. Appeler CancelEvent() dans votre handler supprime le message.

Côté : Serveur · Constante : aucune (le nom propre à FiveM)

Arguments

Prop

Type

Écouteur

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

Sur cette page