MAATRIX GAMES / Блог / Система работ (jobs) на RP-сервере FiveM

Система работ (jobs) на RP-сервере FiveM

MAATRIX GAMES

Голый RP-сервер без работ — это просто карта, по которой бегают игроки без цели: без денег на бензин, без причины ехать в город, без экономики, которая держит комьюнити живым дольше недели. Система работ — это тот самый каркас, который превращает набор скриптов в живой ролевой сервер: игрок садится в такси, едет на вызов как EMS или чинит тачки в гараже — и за это получает деньги, которые тратит внутри той же экономики. Разберём, как устроены работы в ESX и QBCore, как настроить зарплату по грейдам и как добавить свою кастомную работу через target-зоны.

Как устроена система работ в ESX и QBCore

В обоих фреймворках работа — это запись в таблице/файле с уникальным именем (taxi, police, ambulance, mechanic), набором грейдов (должностей) внутри неё и зарплатой за каждый грейд. У игрока в базе данных хранится текущая работа и её грейд — это и определяет, какие меню, машины и права ему доступны в скриптах.

В ESX Legacy работы задаются в таблице jobs и job_grades в MySQL — либо напрямую через SQL, либо через админку вроде esx_menu_default и qtargetnet. Игрок привязан к работе полем job и job_grade в таблице users, а получить объект игрока с job внутри скрипта — xPlayer.job.name и xPlayer.job.grade.

В QBCore работы описаны прямо в Lua-файле qb-core/shared/jobs.lua — это удобнее для кастомизации, потому что не нужно лезть в базу, чтобы добавить новую должность или поменять зарплату: правишь файл, перезапускаешь ресурс qb-core. Доступ к текущей работе игрока — QBCore.Functions.GetPlayerData().job.

Если ты ещё не определился с фреймворком — сначала прочитай сравнение ESX и QBCore: структура работ в этой статье описана именно под оба варианта, но детали синтаксиса отличаются.

Стандартные работы: такси, полиция, EMS, механик

Большинство RP-серверов стартуют с одинакового базового набора — эти четыре работы покрывают львиную долю типового геймплея и почти всегда идут готовыми ресурсами вместе с ядром или как отдельные community-скрипты.

Такси — самая простая работа для входа новичка: берёшь машину со стоянки, возишь пассажиров (реальных игроков через NPC-заказы или скрипт вроде qb-taxi), получаешь зарплату по счётчику или фиксированную ставку за смену. Обычно не требует оружия и прав доступа — хорошая стартовая работа для игрока, который только зашёл на сервер.

Полиция (police в обоих фреймворках) — одна из ключевых фракций RP: доступ к оружию, спецмашинам, системе арестов и штрафов через скрипты вроде esx_policejob или qb-policejob. Требует ACE-разрешений и обычно отдельной whitelist-логики, потому что напрямую влияет на баланс сервера — слишком много или слишком мало активных полицейских ломает геймплей для криминальных фракций.

EMS/скорая (ambulance) — лечит игроков после урона, реанимирует, часто завязана на систему рёгдолла и «состояния смерти» (esx_ambulancejob, qb-ambulancejob). Без рабочей EMS-фракции смерть на сервере превращается либо в мгновенный респавн без последствий, либо в вечное ожидание — баланс тут напрямую зависит от количества активных игроков этой работы.

Механик — чинит и тюнингует машины через esx_mechanicjob или qb-mechanicjob, обычно с мини-игрой на ремонт и доступом к гаражу-мастерской. Хорошо сочетается с системой поломок машин, если она у тебя включена — иначе работа механика становится декоративной, потому что чинить особо нечего.

Пример базовой структуры работы в стиле QBCore (qb-core/shared/jobs.lua):

['police'] = {
    label = 'Полиция',
    type = 'leo',
    defaultDuty = true,
    offDutyPay = false,
    grades = {
        ['0'] = { name = 'Стажёр', payment = 60 },
        ['1'] = { name = 'Патрульный', payment = 75 },
        ['2'] = { name = 'Сержант', payment = 90 },
        ['3'] = { name = 'Лейтенант', payment = 110, isboss = true },
    },
},

Это учебный шаблон структуры — перед вставкой в свой jobs.lua сверяйся с актуальной версией qb-policejob или аналога, названия полей между версиями ресурсов иногда меняются.

Поднять сервер FiveM (GTA V) за пару минут

Готовый образ MAATRIX GAMES: NVMe, AMD EPYC, DDoS-защита, панель управления. Локации UK, US, RU. Оплата картой РФ, СБП или криптой.

Создать сервер

Привязка зарплаты к грейду

Зарплата в обоих фреймворках привязана не к работе целиком, а к конкретному грейду внутри неё — это позволяет платить стажёру меньше, чем боссу той же фракции, и мотивировать игроков расти внутри работы, а не просто занимать слот.

В ESX зарплата хранится в поле grade_salary таблицы job_grades и выплачивается автоматически по таймеру через серверный скрипт ядра (обычно раз в несколько минут игрового времени, интервал настраивается в конфиге es_extended/config.lua, параметр вроде Config.EnablePaycheck и Config.PaycheckInterval).

В QBCore зарплата — поле payment в грейде из примера выше, интервал выплаты настраивается в qb-core/config.lua параметром Config.PayCheckTimeOut (в миллисекундах). Отдельный нюанс — offDutyPay: если true, игрок получает зарплату даже не будучи на смене (duty = false), что имеет смысл для гражданских работ и обычно отключено для полиции и EMS, чтобы не платить за пассивность.

Частая ошибка новичков — выставить одинаковую зарплату всем грейдам «на будущее» и забыть вернуться к балансу. На практике разница между стажёром и боссом должна быть ощутимой (в 1.5-2 раза как ориентир, не как измеренная норма), иначе прогрессия внутри работы теряет смысл, а игроки не видят причины держаться за фракцию дольше пары дней.

Создание кастомной работы через target-зоны

Стандартных четырёх работ обычно мало для уникальности сервера — большинство RP-проектов добавляют свои: рыбак, лесоруб, шахтёр, курьер, наркодилер (легальная и нелегальная сторона баланса разберём отдельно). Разберём создание простой работы «Рыбак» с точкой сбора улова через qb-target (или ox_target, если ты уже перешёл на него — синтаксис отличается, но принцип идентичен).

Шаг 1 — добавляем работу в qb-core/shared/jobs.lua:

['fisher'] = {
    label = 'Рыбак',
    defaultDuty = true,
    grades = {
        ['0'] = { name = 'Новичок', payment = 40 },
        ['1'] = { name = 'Рыбак', payment = 55 },
    },
},

Шаг 2 — создаём отдельный ресурс (папку в resources/, например qb-fisherjob) с fxmanifest.lua:

fx_version 'cerulean'
game 'gta5'

shared_script '@qb-core/shared/locale.lua'
client_scripts { 'client.lua' }
dependencies { 'qb-target' }

Шаг 3 — вешаем target-зону на точку выдачи удочки в client.lua:

local FishSpot = vector3(-1580.0, 5220.0, 3.5)

exports['qb-target']:AddBoxZone('FishingSpot', FishSpot, 2.0, 2.0, {
    name = 'FishingSpot',
    heading = 0,
    debugPoly = false,
}, {
    options = {
        {
            icon = 'fas fa-fish',
            label = 'Взять удочку',
            action = function()
                TriggerServerEvent('qb-fisherjob:server:getRod')
            end,
        },
    },
    distance = 2.0,
})

Шаг 4 — серверная логика выдачи предмета и, при желании, простая мини-игра на поимку рыбы с шансом улова и его продажей через отдельную точку сдачи (аналогичная target-зона, но с TriggerServerEvent на добавление денег вместо предмета). Полную механику ловли (таймер заброса, шанс поклёвки, вариативность улова) уже пишешь сам под концепцию сервера — готового универсального стандарта под это нет, потому что разные проекты делают это принципиально по-разному.

Если тебе нужны собственные предметы под работу (удочка, рыба, наживка), не забудь добавить их в qb-core/shared/items.lua (или в конфиг ox_inventory, если используешь его) — без записи в таблице предметов инвентарь просто откажется давать игроку несуществующий item. Подробнее про установку кастомных скриптов и типовые грабли с зависимостями — в статье про установку кастомных скриптов на FiveM.

Легальные работы против криминальных активностей: баланс экономики

Ключевая ошибка новичков-владельцев RP-серверов — сделать легальные работы либо слишком прибыльными (тогда никто не идёт в криминал, и сервер превращается в симулятор такси), либо слишком скудными (тогда все поголовно грабят магазины, потому что легальный доход не окупает потраченное время).

Практический ориентир, а не измеренная норма: базовая легальная работа должна давать игроку возможность закрыть основные бытовые траты сервера (бензин, аптечки, аренда) за разумную игровую сессию, но не выводить его в серьёзный плюс без риска. Криминальные активности (ограбления, наркоторговля через esx_drugs/qb-drugs, угон машин на разбор) должны платить заметно больше легальной работы того же грейда — это компенсирует риск ареста, потери оружия и времени в тюрьме/на респавне.

Частая практика — вводить кулдауны и лимиты на криминальные активности (например, ограбление конкретного магазина доступно раз в N игровых минут через серверную переменную-таймер), чтобы одна прибыльная точка не убивала мотивацию держать легальную работу вообще. Также стоит следить, чтобы зарплата боссов легальных фракций (например, лейтенанта полиции) не проваливалась ниже среднего криминального дохода — иначе даже верхушка легальной иерархии начинает смотреть в сторону криминала не по ролевым причинам, а по чисто экономическим.

Отдельно держи в голове инфляцию: если на сервере одновременно растёт число активных игроков и легальные зарплаты не пересматриваются месяцами, а криминальные схемы приносят фиксированные (не индексируемые) суммы, баланс постепенно съезжает в одну сторону. Это не разовая настройка при запуске, а параметр, который стоит пересматривать по мере роста комьюнити.

Whitelist и доступ к работам

Фракции вроде полиции и EMS почти всегда требуют whitelist — иначе любой новый игрок может зайти в полицейский участок и взять оружие без модерации. В ESX и QBCore это чаще всего реализовано через ACE-разрешения (add_ace group.police command allow в server.cfg) в связке с админ-командой, которая назначает игроку работу и группу разрешений одновременно.

Пример команды выдачи работы в QBCore (серверная консоль или админ-меню):

/setjob [id] police 3

Где id — идентификатор игрока (обычно server ID), police — имя работы из jobs.lua, 3 — грейд. В ESX аналогичная механика чаще реализована через esx_adminmenu или прямую SQL-правку users.job/users.job_grade, если под рукой нет готовой команды.

Отдельно продумай процесс отбора в whitelist-фракции — часто это анкета в Discord плюс собеседование или испытательный срок с наставником из уже принятых. Чисто техническая выдача работы без отбора людей быстро приводит к тому, что в полиции оказываются игроки, которые используют доступ не по ролевому назначению, а ради оружия и машин.

Поднять сервер FiveM (GTA V) за пару минут

Готовый образ MAATRIX GAMES: NVMe, AMD EPYC, DDoS-защита, панель управления. Локации UK, US, RU. Оплата картой РФ, СБП или криптой.

Создать сервер

Частые вопросы

Можно ли одному игроку иметь две работы одновременно?

В базовой логике ESX и QBCore — нет, у игрока одна активная работа (job) плюс опционально отдельное поле gang для бандформирования, которое существует параллельно. Некоторые community-ресурсы добавляют «вторую работу» как отдельный слот, но это нестандартное расширение, а не часть ядра.

Как сделать работу временной или сезонной (например, праздничное событие)?

Технически это обычная работа в jobs.lua/таблице jobs, которую ты просто не выдаёшь игрокам после окончания события — либо снимаешь через /setjob обратно на unemployed, либо пишешь отдельный серверный скрипт-таймер, который делает это автоматически по дате.

Что делать, если после добавления новой работы в jobs.lua она не появляется у игроков?

Чаще всего забыли перезапустить ресурс qb-core (restart qb-core в консоли сервера) или не пересоздали игрока в базе — новая запись в shared-файле подхватывается сразу, а вот кэш уже залогиненных игроков иногда нужно обновить через реконнект.

Нужен ли обязательно qb-target/ox_target, чтобы сделать кастомную работу?

Нет, это удобный способ через взаимодействие с зоной, но работу можно завязать и на маркеры (DrawMarker + проверка дистанции в цикле), просто target-система сейчас стандарт де-факто как более отзывчивая для игрока и менее нагруженная на клиент, чем постоянный цикл маркеров.

Как ограничить количество слотов в whitelist-фракции (например, максимум 15 полицейских онлайн)?

Готового решения в ядре нет — обычно это отдельный серверный скрипт, который считает онлайн-игроков с job police при попытке захода на смену и блокирует превышение лимита через Config-параметр максимума.