AI Core
Справочник APIAI Core: серверные экспорты

Работы и банды

Читать и менять работы, банды, ранги и дежурство персонажа, считать игроков на дежурстве, прайм-тайм, читать определения работ и банд.

Персонаж может иметь несколько работ и несколько банд (до значений панели Most jobs per character и Most gangs per character). Одновременно на дежурстве может быть не более одной работы, и только она платит зарплату. Активной может быть не более одной банды. Работы и банды с их рангами задаются в админ-панели (разделы Jobs и Gangs).

Ранг - это позиция в списке рангов работы, считая от 0: ранг 0 - первая строка в панели, ранг 1 - вторая и так далее.

Каждое изменение вызывает серверное событие (ai-core:jobsChanged, ai-core:dutyChanged, ai-core:gangsChanged, ai-core:activeGangChanged) и доходит до игры самого игрока. Ресурсы, которым нужны работы многих игроков, следят за этими событиями через зеркало online из библиотеки, а не вызывают экспорты ниже для каждого игрока. См. События и состояние.

GetJobs

Все работы персонажа игрока.

Сторона: сервер · Ожидание: нет · Библиотека: online.jobs(source) читает то же из зеркала библиотеки

Сигнатура
GetJobs(src: number): JobMembership[] | null
Lua
local jobs = exports['ai-core']:GetJobs(source) -- список { job, grade } или nil

Параметры

Prop

Type

Возвращает

JobMembership[] | null: по { job, grade } на каждую работу (JobMembership). Пустой список, когда у персонажа нет работы (безработная работа из панели никогда не сохраняется). null, когда у игрока нет загруженного персонажа.

Пример

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

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

// Экран биржи труда показывает работы игрока с их названиями.
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

Та единственная работа, которую другие скрипты должны считать «той самой» работой игрока: работа на дежурстве, иначе последняя работа, где игрок был на дежурстве, иначе первая работа, иначе безработная работа из панели. Скрипты ESX и QB видят эту работу через мост.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetCurrentJob(src: number): JobMembership | null
Lua
local job = exports['ai-core']:GetCurrentJob(source) -- { job, grade } или nil

Параметры

Prop

Type

Возвращает

JobMembership | null: { job, grade }. Для персонажа без работы это безработная работа (настройка панели, по умолчанию unemployed) с рангом 0. null только тогда, когда у игрока нет загруженного персонажа.

Пример

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

Работа, на которой игрок сейчас на дежурстве. Используйте для каждой проверки вида «это может делать только полиция на дежурстве».

Сторона: сервер · Ожидание: нет · Библиотека: online.dutyJob(source) читает то же из зеркала библиотеки

Сигнатура
GetDutyJob(src: number): string | null
Lua
local job = exports['ai-core']:GetDutyJob(source) -- имя работы или nil

Параметры

Prop

Type

Возвращает

string | null: имя работы. null, когда игрок вне дежурства или у него нет загруженного персонажа.

Пример

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

Ставит игрока на дежурство по одной из его работ (и снимает с дежурства по любой другой) или снимает с дежурства.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
SetDuty(src: number, job: string | null): boolean
Lua
local ok = exports['ai-core']:SetDuty(source, 'police') -- nil = вне дежурства

Параметры

Prop

Type

Возвращает

boolean: true, когда игрок теперь на дежурстве по job (или вне дежурства для null), и тогда, когда ничего не нужно было менять. false, когда у игрока нет job или нет загруженного персонажа.

Пример

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

// Переключатель дежурства в раздевалке участка.
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");
});

Дежурство не сохраняется: зашедший игрок находится вне дежурства, если в панели не включена настройка Keep duty after rejoining.

SetJob

Выдаёт игроку работу или меняет ранг работы, которая у него уже есть.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
SetJob(src: number, job: string, grade: number): boolean
Lua
local ok = exports['ai-core']:SetJob(source, 'mechanic', 0)

Параметры

Prop

Type

Возвращает

boolean: true, когда у персонажа теперь есть job с рангом grade. false, когда работа не существует, ранг не существует (не целое число, ниже 0 или после последнего ранга), у персонажа уже столько работ, сколько разрешает Most jobs per character, или у игрока нет загруженного персонажа.

Когда в панели выключена настройка Several jobs per character, новая работа заменяет другую работу персонажа.

Пример

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

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

// Биржа труда: любой может взять работу из списка панели, с рангом 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

Забирает у игрока работу. Игрок на дежурстве по этой работе сначала снимается с дежурства.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
RemoveJob(src: number, job: string): boolean
Lua
local ok = exports['ai-core']:RemoveJob(source, 'mechanic')

Параметры

Prop

Type

Возвращает

boolean: true, когда работа забрана. false, когда у персонажа её нет или у игрока нет загруженного персонажа.

Пример

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

Сколько игроков сейчас на дежурстве по работе. Используйте для правил вида «нужно 2 полицейских в сети».

Сторона: сервер · Ожидание: нет · Библиотека: нет (online.countOnDuty(jobs) считает несколько работ по зеркалу библиотеки)

Сигнатура
GetOnDutyCount(job: string): number
Lua
local officers = exports['ai-core']:GetOnDutyCount('police')

Параметры

Prop

Type

Возвращает

number: игроки на дежурстве по job. 0, если никого или работа неизвестна. То же число лежит в GlobalState ai:duty:<job> для клиентских скриптов.

Пример

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");
  // ... начать ограбление
  return { ok: true };
});

IsPrimeTime

Прайм-тайм ли сейчас для работы. Часы прайм-тайма берутся из источника, выбранного в панели: скрипт со своими часами (tgiann-policealert), пока он работает, иначе собственные часы ai-core (собственное окно работы или окно по умолчанию). Используйте для правил, которые меняются в часы пик, например ограбление, которое платит больше.

Сторона: сервер · Ожидание: нет · Библиотека: isPrimeTime(job?)

Сигнатура
IsPrimeTime(job?: string): boolean
Lua
local prime = exports['ai-core']:IsPrimeTime('police')

Параметры

Prop

Type

Возвращает

boolean: true во время прайм-тайма. Часы - это местное время сервера; окно, у которого начало позже конца, переходит через полночь, а одинаковые начало и конец означают весь день. Когда панель выбирает источником скрипт, а этот скрипт остановлен, каждый час считается прайм-таймом. Работает независимо от того, включено ли урезание зарплаты в прайм-тайм.

Пример

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

Все определения работ из панели одной копией. Используйте для редкого чтения, например чтобы один раз построить список; для одной работы используйте GetJobDefinition.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetJobDefinitions(): Record<string, JobDefinition>
Lua
local jobs = exports['ai-core']:GetJobDefinitions() -- таблица с ключами по имени работы

Параметры

Нет.

Возвращает

Record<string, JobDefinition>: все работы с ключами по имени. У каждой есть label, type, defaultDuty, listed (показывается на биржах труда) и grades (у каждого label, salary и boss). См. JobDefinition и GradeDefinition.

Пример

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

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

// Биржа труда показывает каждую работу, отмеченную в панели как "listed".
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 })),
}));

В Lua def.grades[1] - это ранг 0: списки Lua начинаются с 1, а ранги с 0.

GetJobDefinition

Определение одной работы: название, тип, дежурство по умолчанию, показывают ли её биржи труда и её ранги.

Сторона: сервер · Ожидание: нет · Библиотека: definitions.job(name) (читает каждую работу один раз и забывает её, когда панель её меняет)

Сигнатура
GetJobDefinition(job: string): JobDefinition | null
Lua
local def = exports['ai-core']:GetJobDefinition('police') -- table или nil

Параметры

Prop

Type

Возвращает

JobDefinition | null: работа (JobDefinition). null для неизвестной работы или значения, которое не является текстом.

Пример

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

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

// Меню босса может открыть только ранг босса.
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

Все банды персонажа игрока.

Сторона: сервер · Ожидание: нет · Библиотека: online.gangs(source) читает то же из зеркала библиотеки

Сигнатура
GetGangs(src: number): GangMembership[] | null
Lua
local gangs = exports['ai-core']:GetGangs(source) -- список { gang, grade } или nil

Параметры

Prop

Type

Возвращает

GangMembership[] | null: по { gang, grade } на каждую банду (GangMembership). Пустой список без банд. null, когда у игрока нет загруженного персонажа.

Пример

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

Банда, которая сейчас активна у игрока. Территории банд, тайники банд и чаты банд должны использовать активную банду.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetActiveGang(src: number): string | null
Lua
local gang = exports['ai-core']:GetActiveGang(source) -- имя банды или nil

Параметры

Prop

Type

Возвращает

string | null: имя банды. null, когда активной банды нет или у игрока нет загруженного персонажа.

Пример

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

Добавляет игрока в банду или меняет его ранг в банде, где он состоит. Персонаж без активной банды получает новую банду как активную.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
SetGang(src: number, gang: string, grade: number): boolean
Lua
local ok = exports['ai-core']:SetGang(source, 'ballas', 0)

Параметры

Prop

Type

Возвращает

boolean: true, когда персонаж теперь состоит в gang с рангом grade. false, когда банда или ранг не существует, персонаж уже состоит в стольких бандах, сколько разрешает Most gangs per character, или у игрока нет загруженного персонажа. Когда в панели выключена настройка Several gangs per character, новая банда заменяет старую.

Пример

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

Исключает игрока из банды. Если это была активная банда, активной становится следующая оставшаяся (или никакая).

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
RemoveGang(src: number, gang: string): boolean
Lua
local ok = exports['ai-core']:RemoveGang(source, 'ballas')

Параметры

Prop

Type

Возвращает

boolean: true, когда членство удалено. false, когда персонаж не в этой банде или у игрока нет загруженного персонажа.

Пример

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

Выбирает, какая из банд игрока активна, или никакая.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
SetActiveGang(src: number, gang: string | null): boolean
Lua
local ok = exports['ai-core']:SetActiveGang(source, 'vagos') -- nil = нет активной банды

Параметры

Prop

Type

Возвращает

boolean: true, когда gang теперь активна (и тогда, когда уже была). false, когда персонаж не в этой банде или у игрока нет загруженного персонажа. Активная банда сохраняется.

Пример

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

Все определения банд из панели одной копией.

Сторона: сервер · Ожидание: нет · Библиотека: нет

Сигнатура
GetGangDefinitions(): Record<string, GangDefinition>
Lua
local gangs = exports['ai-core']:GetGangDefinitions() -- таблица с ключами по имени банды

Параметры

Нет.

Возвращает

Record<string, GangDefinition>: все банды с ключами по имени, у каждой label и grades. См. GangDefinition.

Пример

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

Определение одной банды: её название и ранги.

Сторона: сервер · Ожидание: нет · Библиотека: definitions.gang(name)

Сигнатура
GetGangDefinition(gang: string): GangDefinition | null
Lua
local def = exports['ai-core']:GetGangDefinition('ballas') -- table или nil

Параметры

Prop

Type

Возвращает

GangDefinition | null: банда (GangDefinition). null для неизвестной банды или значения, которое не является текстом.

Пример

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

На этой странице