Trabajos y bandas
Lee y cambia los trabajos, bandas, rangos y el servicio de un personaje, cuenta los jugadores de servicio, prime time, lee las definiciones de trabajos y bandas.
Un personaje puede tener varios trabajos y varias bandas (hasta lo que marquen Most jobs per character (máximo de trabajos por personaje) y Most gangs per character (máximo de bandas por personaje) en el panel). Como mucho un trabajo está de servicio a la vez, y solo ese trabajo paga sueldo. Como mucho una banda está activa. Los trabajos y las bandas, con sus rangos, se definen en el panel de administración (secciones Jobs y Gangs).
Un rango es una posición en la lista de rangos del trabajo, contada desde 0: el rango 0 es la primera fila del panel, el rango 1 la segunda, y así sucesivamente.
Cada cambio dispara un evento de servidor (ai-core:jobsChanged, ai-core:dutyChanged, ai-core:gangsChanged, ai-core:activeGangChanged) y llega al propio juego del jugador. Los recursos que necesitan los trabajos de muchos jugadores siguen estos eventos mediante el espejo online de la lib en lugar de llamar a los exports de abajo para cada jugador. Consulta Eventos y estado.
GetJobs
Cada pertenencia a un trabajo del personaje de un jugador.
Lado: Servidor · Espera: no · Lib: online.jobs(source) lee lo mismo del espejo de la lib
GetJobs(src: number): JobMembership[] | nulllocal jobs = exports['ai-core']:GetJobs(source) -- lista de { job, grade } o nilParámetros
Prop
Type
Devuelve
JobMembership[] | null: un { job, grade } por trabajo (JobMembership). Una lista vacía cuando el personaje no tiene trabajo (el trabajo de desempleado del panel nunca se guarda). null cuando el jugador no tiene un personaje cargado.
Ejemplo
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
// La pantalla de una oficina de empleo lista los trabajos del jugador con sus etiquetas.
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
El único trabajo que los demás scripts deberían tratar como "el" trabajo del jugador: el de servicio; si no, el último trabajo en el que estuvo de servicio; si no, el primer trabajo; si no, el trabajo de desempleado del panel. Los scripts de ESX y QB ven este trabajo a través del puente.
Lado: Servidor · Espera: no · Lib: ninguna
GetCurrentJob(src: number): JobMembership | nulllocal job = exports['ai-core']:GetCurrentJob(source) -- { job, grade } o nilParámetros
Prop
Type
Devuelve
JobMembership | null: { job, grade }. Para un personaje sin ningún trabajo es el trabajo de desempleado (ajuste del panel, unemployed por defecto) con el rango 0. null solo cuando el jugador no tiene un personaje cargado.
Ejemplo
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
El trabajo para el que el jugador está de servicio ahora mismo. Úsalo para cada comprobación del tipo "solo la policía de servicio puede hacer esto".
Lado: Servidor · Espera: no · Lib: online.dutyJob(source) lee lo mismo del espejo de la lib
GetDutyJob(src: number): string | nulllocal job = exports['ai-core']:GetDutyJob(source) -- nombre del trabajo o nilParámetros
Prop
Type
Devuelve
string | null: el nombre del trabajo. null cuando el jugador está fuera de servicio o no tiene un personaje cargado.
Ejemplo
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
Pone a un jugador de servicio en uno de sus trabajos (y fuera de servicio en cualquier otro), o fuera de servicio.
Lado: Servidor · Espera: no · Lib: ninguna
SetDuty(src: number, job: string | null): booleanlocal ok = exports['ai-core']:SetDuty(source, 'police') -- nil = fuera de servicioParámetros
Prop
Type
Devuelve
boolean: true cuando el jugador está ahora de servicio en job (o fuera de servicio con null), también cuando no hubo que cambiar nada. false cuando el jugador no tiene job o no tiene un personaje cargado.
Ejemplo
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 };
// Un interruptor de servicio en el vestuario de la comisaría.
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");
});El servicio no se guarda: un jugador que entra está fuera de servicio, salvo que esté activado el ajuste Keep duty after rejoining (mantener el servicio al volver a entrar) del panel.
SetJob
Da un trabajo a un jugador, o cambia el rango de un trabajo que ya tiene.
Lado: Servidor · Espera: no · Lib: ninguna
SetJob(src: number, job: string, grade: number): booleanlocal ok = exports['ai-core']:SetJob(source, 'mechanic', 0)Parámetros
Prop
Type
Devuelve
boolean: true cuando el personaje tiene ahora job con el rango grade. false cuando el trabajo no existe, el rango no existe (no es un número entero, es menor que 0 o pasa del último rango), el personaje ya tiene tantos trabajos como permite Most jobs per character o el jugador no tiene un personaje cargado.
Cuando el ajuste Several jobs per character (varios trabajos por personaje) del panel está desactivado, un trabajo nuevo reemplaza el otro trabajo del personaje.
Ejemplo
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
import { fail, readText } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
// Una oficina de empleo: cualquiera puede tomar un trabajo que liste el panel, con el rango 0.
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
Quita un trabajo a un jugador. Un jugador de servicio en ese trabajo sale primero de servicio.
Lado: Servidor · Espera: no · Lib: ninguna
RemoveJob(src: number, job: string): booleanlocal ok = exports['ai-core']:RemoveJob(source, 'mechanic')Parámetros
Prop
Type
Devuelve
boolean: true cuando se quitó el trabajo. false cuando el personaje no lo tiene o el jugador no tiene un personaje cargado.
Ejemplo
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
Cuántos jugadores están de servicio en un trabajo ahora mismo. Úsalo para reglas del tipo "hacen falta 2 policías conectados".
Lado: Servidor · Espera: no · Lib: ninguna (online.countOnDuty(jobs) cuenta varios trabajos desde el espejo de la lib)
GetOnDutyCount(job: string): numberlocal officers = exports['ai-core']:GetOnDutyCount('police')Parámetros
Prop
Type
Devuelve
number: jugadores de servicio en job. 0 si no hay nadie o el trabajo es desconocido. El mismo número está en el GlobalState ai:duty:<job> para los scripts de cliente.
Ejemplo
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");
// ... empieza el robo
return { ok: true };
});IsPrimeTime
Si ahora es prime time para un trabajo. Las horas de prime time vienen de la fuente que elige el panel: un script que lleva sus propias horas (tgiann-policealert) mientras está en marcha; si no, las horas propias de ai-core (la franja propia del trabajo o la de por defecto). Úsalo para reglas que cambian con las horas de más actividad, como un robo que paga más.
Lado: Servidor · Espera: no · Lib: isPrimeTime(job?)
IsPrimeTime(job?: string): booleanlocal prime = exports['ai-core']:IsPrimeTime('police')Parámetros
Prop
Type
Devuelve
boolean: true durante el prime time. Las horas son la hora local del servidor; una franja cuyo inicio es posterior a su fin pasa de la medianoche, y el mismo inicio y fin significa el día entero. Cuando el panel elige un script como fuente y ese script está detenido, todas las horas cuentan como prime time. Funciona tanto si el recorte de prime time de la nómina está activado como si no.
Ejemplo
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
/** A store robbery pays 50% more outside police prime time. */
export function robberyReward(base: number): number {
return core.IsPrimeTime("police") ? base : Math.round(base * 1.5);
}GetJobDefinitions
Cada definición de trabajo del panel, en una sola copia. Úsalo para lecturas raras como construir una lista una vez; para un solo trabajo usa GetJobDefinition.
Lado: Servidor · Espera: no · Lib: ninguna
GetJobDefinitions(): Record<string, JobDefinition>local jobs = exports['ai-core']:GetJobDefinitions() -- tabla con el nombre del trabajo como claveParámetros
Ninguno.
Devuelve
Record<string, JobDefinition>: cada trabajo con su nombre como clave. Cada uno tiene label, type, defaultDuty, listed (se muestra en las oficinas de empleo) y grades (cada uno con label, salary y boss). Consulta JobDefinition y GradeDefinition.
Ejemplo
import { onClientCallback, resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
// La oficina de empleo lista cada trabajo marcado como "listed" en el panel.
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 })),
}));En Lua, def.grades[1] es el rango 0: las listas de Lua empiezan en 1, los rangos empiezan en 0.
GetJobDefinition
La definición de un trabajo: etiqueta, tipo, servicio por defecto, si las oficinas de empleo lo listan y sus rangos.
Lado: Servidor · Espera: no · Lib: definitions.job(name) (lee cada trabajo una vez y lo olvida cuando el panel lo cambia)
GetJobDefinition(job: string): JobDefinition | nulllocal def = exports['ai-core']:GetJobDefinition('police') -- table o nilParámetros
Prop
Type
Devuelve
JobDefinition | null: el trabajo (JobDefinition). null para un trabajo desconocido o un valor que no es un texto.
Ejemplo
import { onClientCallback, online, resourceExport } from "@aicore-fivem/lib/server";
import { fail } from "@aicore-fivem/lib/shared";
const core = resourceExport("ai-core");
// Solo un rango de jefe puede abrir el menú de jefe.
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
Cada pertenencia a una banda del personaje de un jugador.
Lado: Servidor · Espera: no · Lib: online.gangs(source) lee lo mismo del espejo de la lib
GetGangs(src: number): GangMembership[] | nulllocal gangs = exports['ai-core']:GetGangs(source) -- lista de { gang, grade } o nilParámetros
Prop
Type
Devuelve
GangMembership[] | null: un { gang, grade } por banda (GangMembership). Una lista vacía si no tiene bandas. null cuando el jugador no tiene un personaje cargado.
Ejemplo
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
/** Whether a player belongs to any gang (active or not). */
export function inAnyGang(source: number): boolean {
return (core.GetGangs(source)?.length ?? 0) > 0;
}GetActiveGang
La banda que el jugador tiene activa ahora mismo. El territorio de banda, los alijos de banda y los chats de banda deberían usar la banda activa.
Lado: Servidor · Espera: no · Lib: ninguna
GetActiveGang(src: number): string | nulllocal gang = exports['ai-core']:GetActiveGang(source) -- nombre de la banda o nilParámetros
Prop
Type
Devuelve
string | null: el nombre de la banda. null cuando no hay ninguna banda activa o el jugador no tiene un personaje cargado.
Ejemplo
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
Añade a un jugador a una banda, o cambia su rango en una banda a la que pertenece. Un personaje sin banda activa recibe la nueva banda como activa.
Lado: Servidor · Espera: no · Lib: ninguna
SetGang(src: number, gang: string, grade: number): booleanlocal ok = exports['ai-core']:SetGang(source, 'ballas', 0)Parámetros
Prop
Type
Devuelve
boolean: true cuando el personaje pertenece ahora a gang con el rango grade. false cuando la banda o el rango no existen, el personaje ya pertenece a tantas bandas como permite Most gangs per character o el jugador no tiene un personaje cargado. Cuando el ajuste Several gangs per character (varias bandas por personaje) del panel está desactivado, la banda nueva reemplaza a la anterior.
Ejemplo
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
Saca a un jugador de una banda. Cuando era la banda activa, la siguiente banda que le quede pasa a ser la activa (o ninguna).
Lado: Servidor · Espera: no · Lib: ninguna
RemoveGang(src: number, gang: string): booleanlocal ok = exports['ai-core']:RemoveGang(source, 'ballas')Parámetros
Prop
Type
Devuelve
boolean: true cuando se quitó la pertenencia. false cuando el personaje no está en esa banda o el jugador no tiene un personaje cargado.
Ejemplo
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
Elige cuál de las bandas del jugador está activa, o ninguna.
Lado: Servidor · Espera: no · Lib: ninguna
SetActiveGang(src: number, gang: string | null): booleanlocal ok = exports['ai-core']:SetActiveGang(source, 'vagos') -- nil = sin banda activaParámetros
Prop
Type
Devuelve
boolean: true cuando gang está ahora activa (también cuando ya lo estaba). false cuando el personaje no está en esa banda o el jugador no tiene un personaje cargado. La banda activa se guarda.
Ejemplo
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
Cada definición de banda del panel, en una sola copia.
Lado: Servidor · Espera: no · Lib: ninguna
GetGangDefinitions(): Record<string, GangDefinition>local gangs = exports['ai-core']:GetGangDefinitions() -- tabla con el nombre de la banda como claveParámetros
Ninguno.
Devuelve
Record<string, GangDefinition>: cada banda con su nombre como clave, cada una con label y grades. Consulta GangDefinition.
Ejemplo
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
La definición de una banda: su etiqueta y sus rangos.
Lado: Servidor · Espera: no · Lib: definitions.gang(name)
GetGangDefinition(gang: string): GangDefinition | nulllocal def = exports['ai-core']:GetGangDefinition('ballas') -- table o nilParámetros
Prop
Type
Devuelve
GangDefinition | null: la banda (GangDefinition). null para una banda desconocida o un valor que no es un texto.
Ejemplo
import { resourceExport } from "@aicore-fivem/lib/server";
const core = resourceExport("ai-core");
/** "Ballas" for "ballas", the name itself for an unknown gang. */
export function gangLabel(gang: string): string {
return core.GetGangDefinition(gang)?.label ?? gang;
}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.
Metadatos y ajustes
Lee y escribe la bolsa de metadatos de un personaje, lee la marca del servidor y la lista de scripts desactualizados.