MAATRIX GAMES / Блог / FiveM: система крафта и производства

FiveM: система крафта и производства

MAATRIX GAMES

Крафт на RP-сервере — это не просто "смешать три предмета и получить четвёртый". Как только у вас появляется рабочая экономика, крафт превращается в главный рычаг баланса: через него игроки либо зарабатывают адекватные деньги за реальное время, либо за пять минут штампуют партию оружия, которая обесценивает весь чёрный рынок. Разберём, как собрать рецепты через ox_inventory, не спалить прогрузку сервера бесконечными таймерами и привязать производственные цепочки к работам так, чтобы легальный и нелегальный крафт не конкурировали друг с другом за одни и те же ресурсы.

Почему ox_inventory, а не самописный крафт

У ox_inventory (форк на замену qb-inventory, совместим и с ESX, и с QBCore через ox_core/мостовые скрипты) крафт встроен из коробки — не нужно городить отдельный ресурс с нуля. Рецепты описываются прямо в data/items.lua или в отдельном конфиге, и система сама проверяет наличие ингредиентов, снимает их со стека и выдаёт результат с учётом веса инвентаря. Это критично: самописные крафты часто забывают про вес и позволяют держать в кармане производство на сто единиц сырья, что ломает баланс с первого дня.

Вторая причина — производительность. ox_inventory держит инвентарь на сервере как единый Lua-стейт с кэшем, а не дёргает MySQL на каждое открытие крафт-меню, как некоторые старые самописные системы. На сервере с онлайном под сотню игроков это ощутимая разница в нагрузке на базу, особенно если крафт открывают массово — например, всей фракцией сразу после рейда на завод.

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

Структура рецепта в ox_inventory

Базовый рецепт задаётся в объекте crafting внутри конфига предметов или в отдельном файле рецептов (в зависимости от версии ресурса — сверьтесь с актуальной документацией на GitHub автора, синтаксис между релизами иногда меняется). Общий вид:

Crafting = {
    ['weapon_repair_kit'] = {
        ingredients = {
            ['scrap_metal'] = 5,
            ['duct_tape'] = 2,
            ['gunpowder'] = 1,
        },
        result = { name = 'weapon_repair_kit', count = 1 },
        time = 8000,           -- мс на крафт одной единицы
        requiredItem = 'workbench_gunsmith', -- нужен верстак/инструмент рядом
        job = 'mechanic',      -- опционально: доступно только этой работе
        jobGrade = 2,          -- опционально: с какого грейда
    },
}

Ключевое поле — time. Именно оно определяет, окупается ли крафт по времени игрока. Если рецепт даёт предмет стоимостью 500 виртуальных денег, а крафтится за 2 секунды, игроки быстро посчитают часовую "зарплату" от крафта и либо забросят легальные работы ради него, либо, если крафт нелегальный, обвалят цену на чёрном рынке за один вечер.

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

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

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

Точки крафта и привязка к верстакам

Открывать крафт-меню через команду в любой точке карты — плохая идея, даже если это удобно на старте разработки. Правильный паттерн — зона с ox_target (или qb-target), которая триггерит открытие меню только рядом с конкретным объектом (верстак, наковальня, химическая лаборатория):

exports.ox_target:addBoxZone({
    coords = vec3(1090.5, -3196.2, -39.0),
    size = vec3(1.5, 1.5, 2.0),
    rotation = 0,
    debug = false,
    options = {
        {
            name = 'open_gunsmith_bench',
            icon = 'fas fa-hammer',
            label = 'Верстак оружейника',
            distance = 2.0,
            onSelect = function()
                exports.ox_inventory:openInventory('crafting', { id = 'gunsmith_bench' })
            end,
        },
    },
})

Параметр id в openInventory — это ссылка на группу рецептов, доступных именно на этом верстаке (задаётся в конфиге как crafting.gunsmith_bench = { ... }). Так вы разводите крафты по локациям: оружейные рецепты — только в мастерской у гаражного бокса, наркотики — только в подпольной лаборатории, еда — на кухне ресторана. Это не только логично по RP, но и снимает нагрузку — не нужно грузить весь список рецептов игроку в любой точке карты.

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

Баланс времени крафта и выхода ресурсов

Главная ошибка новых RP-серверов — считать баланс "на глаз". Рабочий подход — привязать время и выход крафта к почасовой ставке легальной работы на вашем сервере, и держать это в одной таблице для сверки:

Тип производстваПример рецептаВремя на 1 ед.Ориентировочный доход/час*
Легальное, простоеРемкомплект (механик)5-10 сексравнимо с базовой ставкой механика
Легальное, сложноеДеталь под тюнинг30-60 секвыше базовой ставки, требует апгрейда верстака
Нелегальное, низкий тирПростое зелье/настойка15-30 секзаметно выше легальных, но с риском рейда
Нелегальное, высокий тирОружие, крупная партия наркотиков60-180 сек + кулдаунмаксимальный доход, максимальный риск (полиция, PvP)

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

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

Экономику RP-сервера в целом — курс валюты, зарплаты, налоги — мы разбирали отдельно в статье про базовую настройку экономики RP-сервера: цифры крафта стоит сверять именно с этой шкалой, а не выдумывать отдельно.

Производственные цепочки: от сырья до готового товара

Одноступенчатый крафт (сырьё → готовый предмет) быстро надоедает и легко скриптуется ботами/макросами. Цепочка в несколько этапов держит игроков вовлечёнными дольше и даёт больше точек для RP-взаимодействия (продажа полуфабрикатов между игроками, разделение труда во фракции). Пример трёхступенчатой цепочки для нелегального производства:

Сырьё (добывается на точке, например "coca_leaf")
   → Полуфабрикат ("coca_paste", крафтится в лаборатории, требует химика)
      → Готовый товар ("cocaine_brick", крафтится в другой точке, требует пресс)

Каждый этап стоит привязывать к отдельному верстаку/точке — так у цепочки появляется логистика: кто-то собирает сырьё, кто-то везёт его в лабораторию (риск перехвата по дороге), кто-то финализирует продукт. Технически это просто три записи в Crafting с разными requiredItem и координатами зон, но именно разделение на локации создаёт геймплей, а не просто циферки.

Crafting = {
    ['coca_paste'] = {
        ingredients = { ['coca_leaf'] = 10, ['chemical_reagent'] = 2 },
        result = { name = 'coca_paste', count = 3 },
        time = 20000,
        requiredItem = 'lab_equipment',
    },
    ['cocaine_brick'] = {
        ingredients = { ['coca_paste'] = 5, ['baking_soda'] = 1 },
        result = { name = 'cocaine_brick', count = 1 },
        time = 45000,
        requiredItem = 'press_machine',
    },
}

Для легальных цепочек логика та же: например, металлолом → слиток → деталь для тюнинга, с разными верстаками в мастерской. Если на сервере есть фракции (банды, картели, легальные корпорации) — привязка этапов цепочки к разным территориям делает контроль над цепочкой предметом борьбы, что для RP-сервера часто интереснее, чем сам факт производства. Про территориальную борьбу и структуру группировок — в статье про систему фракций и банд на RP-сервере.

Ограничение и защита от эксплойтов

Крафт — одна из самых частых целей читеров и дюп-эксплойтов, потому что через него легко умножить ресурсы, если проверки только на клиенте. Базовые правила, которые нужно соблюдать без исключений:

  • Все проверки (наличие ингредиентов, вес, доступность верстака, требование работы/грейда) — только на сервере. ox_inventory уже делает это по умолчанию, но если дописываете кастомную логику через exports.ox_inventory:CraftItem или свои ивенты — не полагайтесь на клиентские данные.
  • Ограничивайте количество крафта за раз (maxCraftAmount в конфиге), иначе игрок поставит крафт на 999 единиц в очередь и уйдёт спать, вернувшись к готовому складу.
  • Кулдаун между крафтами полезен для дорогих предметов (оружие высокого тира — не чаще раза в 10-15 минут на игрока), чтобы не превращать лабораторию в конвейер для одного человека.
  • Логируйте крафт через Discord-вебхук (кто, что, сколько, где) — это антифрод и заодно материал для модерации споров между игроками.
  • Проверяйте, что предмет-инструмент из requiredItem не расходуется случайно вместе с ингредиентами — частая ошибка конфига, когда верстак по ошибке попадает в список ingredients.

Отдельно продумайте вес готовых партий: если крафт даёт 20 единиц оружия по 2 кг каждая, а лимит инвентаря — 30 кг, вынести партию без транспорта физически невозможно — это уже элемент баланса, и отдельно "нерфить" выход не требуется.

Интеграция крафта с работами

Крафт редко существует сам по себе — он почти всегда прикручен к конкретной работе (job) через систему грейдов. В ox_inventory это делается полем job и jobGrade прямо в рецепте, но логичнее держать проверку доступа централизованно, если у вас много рецептов на одну работу:

-- серверная проверка перед открытием меню крафта (пример на QBCore)
RegisterNetEvent('crafting:server:requestOpen', function(benchId)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    local job = Player.PlayerData.job

    if job.name ~= 'mechanic' or job.grade.level < 2 then
        TriggerClientEvent('QBCore:Notify', src, 'Недостаточно квалификации', 'error')
        return
    end

    TriggerClientEvent('crafting:client:openBench', src, benchId)
end)

Для нелегальных производств проверка идёт не по легальной работе, а по членству во фракции/банде (обычно отдельная таблица в базе, не пересекающаяся с job в ESX/QBCore) — так игрок вне группировки не пройдёт проверку доступа, даже зная координаты лаборатории. Держите эти две системы раздельно в базе — смешивание часто приводит к багам, когда увольнение с легальной работы случайно снимает доступ к нелегальной точке.

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

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

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

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

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

Да, у ESX есть свои крафт-решения (например через esx_crafting или самописные скрипты на базе ox_lib для интерфейса), но встроенная система ox_inventory проще в поддержке и лучше документирована на момент написания — если сервер уже мигрировал на ox_inventory поверх ESX или QBCore, логичнее использовать её.

Нужно ли отдельно рестартить ресурс крафта после правки рецептов?

Да, изменения в data/items.lua или конфиге рецептов требуют restart ox_inventory (или ресурса с рецептами, если вынесены отдельно) — горячая перезагрузка конфигов "на лету" не гарантирована, проверяйте по актуальной документации вашей версии.

Как не дать игрокам обойти требование к работе через сторонний скрипт крафта?

Единственная надёжная защита — серверная проверка job/фракции при каждом вызове крафт-функции, а не только при открытии меню. Если проверка есть только на открытии, игрок может держать меню открытым, сменить работу и всё равно скрафтить — проверяйте доступ прямо в обработчике самого крафта.

Стоит ли делать крафт мгновенным (без времени ожидания) для QoL?

Не для всех рецептов — мгновенный крафт расходников (бинты, вода) улучшает опыт без вреда балансу, а мгновенный крафт ценных предметов (оружие, наркотики) почти всегда обваливает экономику за первую неделю. Разделяйте рецепты по важности осознанно, а не давайте всем одно и то же значение time.

Как связать крафт с системой голода/жажды, если она есть на сервере?

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