Работы и банды
Читать и менять работы, банды, ранги и дежурство персонажа, считать игроков на дежурстве, прайм-тайм, читать определения работ и банд.
Персонаж может иметь несколько работ и несколько банд (до значений панели 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[] | nulllocal 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 | nulllocal 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 | nulllocal 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): booleanlocal 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): booleanlocal 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): booleanlocal 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): numberlocal 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): booleanlocal 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>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 | nulllocal 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[] | nulllocal 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 | nulllocal 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): booleanlocal 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): booleanlocal 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): booleanlocal 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>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 | nulllocal 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;
}