AI Core
API-ReferenzAI Core: Server-Exports

Jobs und Gangs

Jobs, Gangs, Ränge und Dienst eines Charakters lesen und ändern, Spieler im Dienst zählen, Prime Time, Job- und Gang-Definitionen lesen.

Ein Charakter kann mehrere Jobs und mehrere Gangs haben (bis zu den Panel-Werten Most jobs per character und Most gangs per character). Höchstens ein Job ist gleichzeitig im Dienst, und nur dieser Job zahlt ein Gehalt. Höchstens eine Gang ist aktiv. Jobs und Gangs mit ihren Rängen werden im Admin-Panel definiert (Bereiche Jobs und Gangs).

Ein Rang ist eine Position in der Rangliste des Jobs, gezählt ab 0: Rang 0 ist die erste Zeile im Panel, Rang 1 die zweite und so weiter.

Jede Änderung löst ein Server-Event aus (ai-core:jobsChanged, ai-core:dutyChanged, ai-core:gangsChanged, ai-core:activeGangChanged) und erreicht das eigene Spiel des Spielers. Ressourcen, die die Jobs vieler Spieler brauchen, folgen diesen Events über den online-Spiegel der Lib, statt die Exports unten für jeden Spieler aufzurufen. Siehe Events und Zustand.

GetJobs

Jede Job-Mitgliedschaft des Charakters eines Spielers.

Seite: Server · Wartet: nein · Lib: online.jobs(source) liest dasselbe aus dem Spiegel der Lib

Signature
GetJobs(src: number): JobMembership[] | null
Lua
local jobs = exports['ai-core']:GetJobs(source) -- Liste von { job, grade } oder nil

Parameter

Prop

Type

Rückgabe

JobMembership[] | null: ein { job, grade } pro Job (JobMembership). Eine leere Liste, wenn der Charakter keinen Job hat (der Arbeitslosen-Job des Panels wird nie gespeichert). null, wenn der Spieler keinen geladenen Charakter hat.

Beispiel

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

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

// Ein Jobcenter-Bildschirm listet die Jobs des Spielers mit ihren Labels.
onClientCallback("myscript:myJobs", (source) => {
  const jobs = core.GetJobs(source);
  if (!jobs) return fail("NO_CHARACTER");
  return {
    ok: true,
    jobs: jobs.map(({ job, grade }) => ({
      job,
      label: core.GetJobDefinition(job)?.label ?? job,
      grade,
    })),
  };
});

GetCurrentJob

Der eine Job, den andere Skripte als „den“ Job des Spielers behandeln sollen: der Job im Dienst, sonst der letzte Job, für den der Spieler im Dienst war, sonst der erste Job, sonst der Arbeitslosen-Job des Panels. ESX- und QB-Skripte sehen diesen Job über die Brücke.

Seite: Server · Wartet: nein · Lib: keine

Signature
GetCurrentJob(src: number): JobMembership | null
Lua
local job = exports['ai-core']:GetCurrentJob(source) -- { job, grade } oder nil

Parameter

Prop

Type

Rückgabe

JobMembership | null: { job, grade }. Für einen Charakter ohne Job ist es der Arbeitslosen-Job (Panel-Einstellung, standardmäßig unemployed) mit Rang 0. null nur, wenn der Spieler keinen geladenen Charakter hat.

Beispiel

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

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

addCommand("job", { help: "Shows a player job", params: [{ name: "id", type: "playerId" }], restricted: true }, (_source, args) => {
  const job = core.GetCurrentJob(args.id);
  if (job) console.log(`${job.job} grade ${job.grade}`);
});

GetDutyJob

Der Job, für den der Spieler gerade im Dienst ist. Nutze es für jede Prüfung der Art „nur Polizei im Dienst darf das“.

Seite: Server · Wartet: nein · Lib: online.dutyJob(source) liest dasselbe aus dem Spiegel der Lib

Signature
GetDutyJob(src: number): string | null
Lua
local job = exports['ai-core']:GetDutyJob(source) -- Jobname oder nil

Parameter

Prop

Type

Rückgabe

string | null: der Jobname. null, wenn der Spieler nicht im Dienst ist oder keinen geladenen Charakter hat.

Beispiel

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

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

onClientCallback("myscript:openArmory", (source) => {
  if (core.GetDutyJob(source) !== "police") return fail("NOT_POLICE");
  return { ok: true };
});

SetDuty

Setzt einen Spieler für einen seiner Jobs in den Dienst (und für jeden anderen außer Dienst) oder außer Dienst.

Seite: Server · Wartet: nein · Lib: keine

Signature
SetDuty(src: number, job: string | null): boolean
Lua
local ok = exports['ai-core']:SetDuty(source, 'police') -- nil = außer Dienst

Parameter

Prop

Type

Rückgabe

boolean: true, wenn der Spieler jetzt für job im Dienst ist (oder bei null außer Dienst), auch wenn sich nichts ändern musste. false, wenn der Spieler job nicht hat oder keinen geladenen Charakter hat.

Beispiel

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

const core = resourceExport("ai-core");
const LOCKER_ROOM = { x: 452.3, y: -993.2, z: 30.7 };

// Ein Dienstschalter im Umkleideraum der Wache.
onClientCallback("myscript:toggleDuty", { guards: [near(LOCKER_ROOM, 3)] }, (source) => {
  const onDuty = core.GetDutyJob(source) === "police";
  return core.SetDuty(source, onDuty ? null : "police") ? { ok: true, onDuty: !onDuty } : fail("NOT_POLICE");
});

Der Dienst wird nicht gespeichert: Ein Spieler, der beitritt, ist außer Dienst, es sei denn, die Panel-Einstellung Keep duty after rejoining (Dienst nach erneutem Beitritt behalten) ist aktiv.

SetJob

Gibt einem Spieler einen Job oder ändert den Rang eines Jobs, den er bereits hat.

Seite: Server · Wartet: nein · Lib: keine

Signature
SetJob(src: number, job: string, grade: number): boolean
Lua
local ok = exports['ai-core']:SetJob(source, 'mechanic', 0)

Parameter

Prop

Type

Rückgabe

boolean: true, wenn der Charakter jetzt job mit grade hat. false, wenn der Job nicht existiert, der Rang nicht existiert (keine ganze Zahl, unter 0 oder nach dem letzten Rang), der Charakter bereits so viele Jobs hat, wie Most jobs per character erlaubt, oder der Spieler keinen geladenen Charakter hat.

Wenn die Panel-Einstellung Several jobs per character (mehrere Jobs pro Charakter) aus ist, ersetzt ein neuer Job den anderen Job des Charakters.

Beispiel

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

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

// Ein Jobcenter: Jeder darf einen Job, den das Panel listet, mit Rang 0 annehmen.
onClientCallback(
  "myscript:takeJob",
  { args: ([job]) => { const name = readText(job, 32); return name ? [name] : null; } },
  (source, job) => {
    if (!core.GetJobDefinition(job)?.listed) return fail("JOB_NOT_LISTED");
    return core.SetJob(source, job, 0) ? { ok: true } : fail("JOB_LIMIT");
  },
);

RemoveJob

Nimmt einem Spieler einen Job weg. Ein Spieler, der für diesen Job im Dienst ist, geht zuerst außer Dienst.

Seite: Server · Wartet: nein · Lib: keine

Signature
RemoveJob(src: number, job: string): boolean
Lua
local ok = exports['ai-core']:RemoveJob(source, 'mechanic')

Parameter

Prop

Type

Rückgabe

boolean: true, wenn der Job entfernt wurde. false, wenn der Charakter ihn nicht hat oder der Spieler keinen geladenen Charakter hat.

Beispiel

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

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

onClientCallback(
  "myscript:quitJob",
  { args: ([job]) => { const name = readText(job, 32); return name ? [name] : null; } },
  (source, job) => (core.RemoveJob(source, job) ? { ok: true } : fail("NOT_MEMBER")),
);

GetOnDutyCount

Wie viele Spieler gerade für einen Job im Dienst sind. Nutze es für Regeln wie „braucht 2 Polizisten online“.

Seite: Server · Wartet: nein · Lib: keine (online.countOnDuty(jobs) zählt mehrere Jobs aus dem Spiegel der Lib)

Signature
GetOnDutyCount(job: string): number
Lua
local officers = exports['ai-core']:GetOnDutyCount('police')

Parameter

Prop

Type

Rückgabe

number: Spieler im Dienst für job. 0 für niemanden oder einen unbekannten Job. Dieselbe Zahl steht für Client-Skripte im GlobalState ai:duty:<job>.

Beispiel

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

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

onClientCallback("myscript:startRobbery", { lock: true }, (source) => {
  if (core.GetOnDutyCount("police") < POLICE_NEEDED) return fail("NOT_ENOUGH_POLICE");
  // ... den Überfall starten
  return { ok: true };
});

IsPrimeTime

Ob gerade Prime Time für einen Job ist. Die Prime-Time-Stunden kommen aus der Quelle, die das Panel wählt: ein Skript, das eigene Stunden führt (tgiann-policealert), solange es läuft, sonst die eigenen Stunden von ai-core (das eigene Zeitfenster des Jobs oder das Standardfenster). Nutze es für Regeln, die sich mit den Stoßzeiten ändern, etwa einen Überfall, der mehr bringt.

Seite: Server · Wartet: nein · Lib: isPrimeTime(job?)

Signature
IsPrimeTime(job?: string): boolean
Lua
local prime = exports['ai-core']:IsPrimeTime('police')

Parameter

Prop

Type

Rückgabe

boolean: true während der Prime Time. Die Stunden sind die lokale Zeit des Servers; ein Fenster, dessen Start später als sein Ende liegt, läuft über Mitternacht, und gleicher Start und gleiches Ende bedeuten den ganzen Tag. Wenn das Panel ein Skript als Quelle wählt und dieses Skript gestoppt ist, zählt jede Stunde als Prime Time. Es funktioniert unabhängig davon, ob die Prime-Time-Kürzung des Gehalts aktiv ist.

Beispiel

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

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

/** Ein Ladenüberfall bringt außerhalb der Polizei-Prime-Time 50 % mehr. */
export function robberyReward(base: number): number {
  return core.IsPrimeTime("police") ? base : Math.round(base * 1.5);
}

GetJobDefinitions

Jede Job-Definition aus dem Panel, als eine Kopie. Nutze es für seltene Lesevorgänge, etwa um eine Liste einmal aufzubauen; für einen einzelnen Job nutze GetJobDefinition.

Seite: Server · Wartet: nein · Lib: keine

Signature
GetJobDefinitions(): Record<string, JobDefinition>
Lua
local jobs = exports['ai-core']:GetJobDefinitions() -- Tabelle mit Jobnamen als Schlüssel

Parameter

Keine.

Rückgabe

Record<string, JobDefinition>: jeder Job nach Namen. Jeder hat label, type, defaultDuty, listed (in Jobcentern angezeigt) und grades (jeder mit label, salary und boss). Siehe JobDefinition und GradeDefinition.

Beispiel

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

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

// Das Jobcenter listet jeden Job, der im Panel als „listed“ markiert ist.
onClientCallback("myscript:jobCenter", () => ({
  ok: true,
  jobs: Object.entries(core.GetJobDefinitions())
    .filter(([, def]) => def.listed)
    .map(([name, def]) => ({ name, label: def.label, salary: def.grades[0]?.salary ?? 0 })),
}));

In Lua ist def.grades[1] Rang 0: Lua-Listen beginnen bei 1, Ränge bei 0.

GetJobDefinition

Die Definition eines Jobs: Label, Typ, Standarddienst, ob Jobcenter ihn listen, und seine Ränge.

Seite: Server · Wartet: nein · Lib: definitions.job(name) (liest jeden Job einmal und vergisst ihn, wenn das Panel ihn ändert)

Signature
GetJobDefinition(job: string): JobDefinition | null
Lua
local def = exports['ai-core']:GetJobDefinition('police') -- Tabelle oder nil

Parameter

Prop

Type

Rückgabe

JobDefinition | null: der Job (JobDefinition). null für einen unbekannten Job oder einen Wert, der kein Text ist.

Beispiel

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

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

// Nur ein Chef-Rang darf das Chefmenü öffnen.
onClientCallback("myscript:bossMenu", (source) => {
  const job = online.dutyJob(source);
  const grade = job ? online.jobGrade(source, job) : null;
  if (!job || grade === null) return fail("NOT_ON_DUTY");
  if (!core.GetJobDefinition(job)?.grades[grade]?.boss) return fail("NOT_BOSS");
  return { ok: true };
});

GetGangs

Jede Gang-Mitgliedschaft des Charakters eines Spielers.

Seite: Server · Wartet: nein · Lib: online.gangs(source) liest dasselbe aus dem Spiegel der Lib

Signature
GetGangs(src: number): GangMembership[] | null
Lua
local gangs = exports['ai-core']:GetGangs(source) -- Liste von { gang, grade } oder nil

Parameter

Prop

Type

Rückgabe

GangMembership[] | null: ein { gang, grade } pro Gang (GangMembership). Eine leere Liste ohne Gangs. null, wenn der Spieler keinen geladenen Charakter hat.

Beispiel

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

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

/** Ob ein Spieler zu irgendeiner Gang gehört (aktiv oder nicht). */
export function inAnyGang(source: number): boolean {
  return (core.GetGangs(source)?.length ?? 0) > 0;
}

GetActiveGang

Die Gang, die der Spieler gerade aktiv hat. Gang-Gebiete, Gang-Lager und Gang-Chats sollten die aktive Gang nutzen.

Seite: Server · Wartet: nein · Lib: keine

Signature
GetActiveGang(src: number): string | null
Lua
local gang = exports['ai-core']:GetActiveGang(source) -- Gangname oder nil

Parameter

Prop

Type

Rückgabe

string | null: der Gangname. null, wenn keine Gang aktiv ist oder der Spieler keinen geladenen Charakter hat.

Beispiel

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

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

onClientCallback("myscript:gangStash", (source) => {
  const gang = core.GetActiveGang(source);
  if (!gang) return fail("NO_GANG");
  return inventory.openInventory(source, `gang_${gang}`) ? { ok: true } : fail("STASH_FAILED");
});

SetGang

Fügt einen Spieler einer Gang hinzu oder ändert seinen Rang in einer Gang, zu der er gehört. Ein Charakter ohne aktive Gang bekommt die neue Gang als aktive.

Seite: Server · Wartet: nein · Lib: keine

Signature
SetGang(src: number, gang: string, grade: number): boolean
Lua
local ok = exports['ai-core']:SetGang(source, 'ballas', 0)

Parameter

Prop

Type

Rückgabe

boolean: true, wenn der Charakter jetzt mit grade zu gang gehört. false, wenn die Gang oder der Rang nicht existiert, der Charakter bereits zu so vielen Gangs gehört, wie Most gangs per character erlaubt, oder der Spieler keinen geladenen Charakter hat. Wenn die Panel-Einstellung Several gangs per character (mehrere Gangs pro Charakter) aus ist, ersetzt die neue Gang die alte.

Beispiel

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

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

addCommand("setgang", {
  help: "Adds a player to a gang",
  params: [{ name: "id", type: "playerId" }, { name: "gang", type: "string" }, { name: "grade", type: "number" }],
  restricted: true,
}, (_source, args) => {
  console.log(core.SetGang(args.id, args.gang, args.grade) ? "done" : "refused");
});

RemoveGang

Entfernt einen Spieler aus einer Gang. War es die aktive Gang, wird die nächste verbleibende Gang aktiv (oder keine).

Seite: Server · Wartet: nein · Lib: keine

Signature
RemoveGang(src: number, gang: string): boolean
Lua
local ok = exports['ai-core']:RemoveGang(source, 'ballas')

Parameter

Prop

Type

Rückgabe

boolean: true, wenn die Mitgliedschaft entfernt wurde. false, wenn der Charakter nicht in dieser Gang ist oder der Spieler keinen geladenen Charakter hat.

Beispiel

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

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

onClientCallback("myscript:leaveGang", (source) => {
  const gang = core.GetActiveGang(source);
  return gang && core.RemoveGang(source, gang) ? { ok: true } : fail("NO_GANG");
});

SetActiveGang

Wählt, welche der Gangs des Spielers aktiv ist, oder keine.

Seite: Server · Wartet: nein · Lib: keine

Signature
SetActiveGang(src: number, gang: string | null): boolean
Lua
local ok = exports['ai-core']:SetActiveGang(source, 'vagos') -- nil = keine aktive Gang

Parameter

Prop

Type

Rückgabe

boolean: true, wenn gang jetzt aktiv ist (auch wenn sie es schon war). false, wenn der Charakter nicht in dieser Gang ist oder der Spieler keinen geladenen Charakter hat. Die aktive Gang wird gespeichert.

Beispiel

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

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

onClientCallback(
  "myscript:pickGang",
  { args: ([gang]) => { const name = readText(gang, 32); return name ? [name] : null; } },
  (source, gang) => (core.SetActiveGang(source, gang) ? { ok: true } : fail("NOT_MEMBER")),
);

GetGangDefinitions

Jede Gang-Definition aus dem Panel, als eine Kopie.

Seite: Server · Wartet: nein · Lib: keine

Signature
GetGangDefinitions(): Record<string, GangDefinition>
Lua
local gangs = exports['ai-core']:GetGangDefinitions() -- Tabelle mit Gangnamen als Schlüssel

Parameter

Keine.

Rückgabe

Record<string, GangDefinition>: jede Gang nach Namen, jede mit label und grades. Siehe GangDefinition.

Beispiel

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

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

onClientCallback("myscript:gangList", () => ({
  ok: true,
  gangs: Object.entries(core.GetGangDefinitions()).map(([name, def]) => ({ name, label: def.label })),
}));

GetGangDefinition

Die Definition einer Gang: ihr Label und ihre Ränge.

Seite: Server · Wartet: nein · Lib: definitions.gang(name)

Signature
GetGangDefinition(gang: string): GangDefinition | null
Lua
local def = exports['ai-core']:GetGangDefinition('ballas') -- Tabelle oder nil

Parameter

Prop

Type

Rückgabe

GangDefinition | null: die Gang (GangDefinition). null für eine unbekannte Gang oder einen Wert, der kein Text ist.

Beispiel

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

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

/** „Ballas“ für „ballas“, der Name selbst für eine unbekannte Gang. */
export function gangLabel(gang: string): string {
  return core.GetGangDefinition(gang)?.label ?? gang;
}

Auf dieser Seite