Назад к блогу
Guide9 мин чтения

Система фермерства FiveM: урожай, животные и цепочки продаж

Создайте глубокую систему фермерства для FiveM. Урожай, скот, переработка, NPC-продавцы и лучшие скрипты фермерства для погружения в ролевую экономику.

Agency Scripts

Основатель и ведущий разработчик Agency Scripts

Философия дизайна системы фермерства

Система фермерства и сельского хозяйства привносит совершенно иной ритм в ролевые серверы FiveM, предлагая игрокам расслабляющую альтернативу высокоадреналиновым криминальным действиям и правоохранительным органам. Лучшие фермерские системы создают самоподдерживающийся экономический цикл, где игроки покупают семена, сажают культуры на выделенных полях, ухаживают за ними в течение реальных циклов роста, собирают урожай и продают его на рынке с прибылью. Задача дизайна , сделать систему достаточно увлекательной, чтобы игроки возвращались регулярно, но не настолько времязатратной, чтобы она казалась рутиной. Используйте реальные циклы роста, которые продолжаются даже когда игрок офлайн, чтобы фермеры при входе видели культуры на разных стадиях роста. Основная модель данных должна отслеживать каждый отдельный участок с его позицией, типом культуры, текущей стадией роста, временем посадки, уровнем воды и рейтингом качества. Храните всё это на сервере в базе данных, чтобы состояние фермы сохранялось между перезапусками сервера и было защищено от манипуляций на клиенте.

Посадка культур и схема базы данных

Система посадки начинается с выбора игроком семян из инвентаря и размещения их на допустимых сельскохозяйственных зонах. Определите сельхозугодья как настраиваемые полигоны на карте, где разрешена посадка, предотвращая выращивание на тротуарах или внутри зданий. Каждый участок имеет ограниченное количество слотов в зависимости от размера земли, а игроки могут арендовать или покупать землю через NPC или систему недвижимости. При посадке семени создаётся запись в базе данных, отслеживающая культуру на всех этапах роста. Вот практическая схема базы данных и серверный обработчик посадки:

CREATE TABLE IF NOT EXISTS farm_crops (
    id INT AUTO_INCREMENT PRIMARY KEY,
    owner VARCHAR(50) NOT NULL,
    farm_id VARCHAR(50) NOT NULL,
    crop_type VARCHAR(50) NOT NULL,
    position_x FLOAT NOT NULL,
    position_y FLOAT NOT NULL,
    position_z FLOAT NOT NULL,
    planted_at BIGINT NOT NULL,
    growth_stage INT DEFAULT 0,
    water_level FLOAT DEFAULT 100.0,
    quality FLOAT DEFAULT 1.0,
    is_harvestable TINYINT DEFAULT 0,
    is_dead TINYINT DEFAULT 0,
    last_watered BIGINT DEFAULT 0,
    INDEX idx_owner (owner),
    INDEX idx_farm (farm_id)
);

CREATE TABLE IF NOT EXISTS farm_plots (
    id INT AUTO_INCREMENT PRIMARY KEY,
    farm_id VARCHAR(50) NOT NULL UNIQUE,
    owner VARCHAR(50) DEFAULT NULL,
    max_slots INT DEFAULT 20,
    rent_price INT DEFAULT 500,
    coords_center_x FLOAT NOT NULL,
    coords_center_y FLOAT NOT NULL,
    coords_center_z FLOAT NOT NULL,
    radius FLOAT DEFAULT 30.0
);
RegisterNetEvent('farming:server:plantCrop', function(cropType, position)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local citizenid = Player.PlayerData.citizenid
    local seedItem = 'seed_' .. cropType

    if not Player.Functions.GetItemByName(seedItem) then
        return TriggerClientEvent('QBCore:Notify', src, 'You need seeds to plant', 'error')
    end

    local farmId = GetFarmAtPosition(position)
    if not farmId then
        return TriggerClientEvent('QBCore:Notify', src, 'You can only plant on farmland', 'error')
    end

    local currentCrops = MySQL.scalar.await(
        'SELECT COUNT(*) FROM farm_crops WHERE farm_id = ? AND is_dead = 0',
        {farmId}
    )
    local maxSlots = MySQL.scalar.await(
        'SELECT max_slots FROM farm_plots WHERE farm_id = ?', {farmId}
    )

    if currentCrops >= maxSlots then
        return TriggerClientEvent('QBCore:Notify', src, 'Farm is full', 'error')
    end

    Player.Functions.RemoveItem(seedItem, 1)

    MySQL.insert(
        'INSERT INTO farm_crops (owner, farm_id, crop_type, position_x, position_y, position_z, planted_at, last_watered) VALUES (?, ?, ?, ?, ?, ?, ?, ?)',
        {citizenid, farmId, cropType, position.x, position.y, position.z, os.time(), os.time()}
    )

    TriggerClientEvent('QBCore:Notify', src, 'Planted ' .. cropType, 'success')
    TriggerClientEvent('farming:client:spawnCropProp', -1, position, cropType, 0)
end)

Для каждого типа урожая должны быть определены разные параметры роста в конфигурационной таблице. Пшеница может расти 30 реальных минут в 4 этапа, тогда как каннабис или виноград могут требовать несколько часов с 6 этапами, вознаграждая терпеливых фермеров более ценной продукцией. Стадия роста определяет, какая модель объекта отображается в мире, переходя от маленького ростка к взрослому растению с течением времени.

Движок цикла роста и полива

Движок цикла роста , это серверный цикл, который периодически проверяет все посаженные культуры и продвигает их стадии роста в зависимости от прошедшего времени и условий, таких как уровень воды. Запускайте это как таймерный серверный поток, который выполняется каждые несколько минут, вычисляя, должна ли каждая культура перейти к следующей стадии на основе длительности роста для данного типа культуры и времени с момента посадки. Уровень воды , основной механизм, который удерживает игроков вовлеченными: культуры потребляют воду со временем, и если уровень воды падает до нуля, рост приостанавливается, а качество культуры ухудшается. Игроки должны возвращаться на свою ферму и использовать лейку или систему орошения для пополнения уровня воды. Вот серверный движок роста:

local CropConfig = {
    wheat = {
        stages = 4,
        growthTime = 1800,    -- 30 min total, ~7.5 min per stage
        waterConsumption = 5, -- per cycle
        baseYield = 5,
        sellPrice = 50
    },
    corn = {
        stages = 5,
        growthTime = 3600,
        waterConsumption = 7,
        baseYield = 4,
        sellPrice = 80
    },
    tomato = {
        stages = 4,
        growthTime = 2400,
        waterConsumption = 8,
        baseYield = 6,
        sellPrice = 65
    },
    grape = {
        stages = 6,
        growthTime = 7200,
        waterConsumption = 4,
        baseYield = 8,
        sellPrice = 120
    }
}

CreateThread(function()
    while true do
        Wait(60000 * 5) -- Run every 5 minutes

        local crops = MySQL.query.await(
            'SELECT * FROM farm_crops WHERE is_dead = 0 AND is_harvestable = 0'
        )

        for _, crop in ipairs(crops or {}) do
            local config = CropConfig[crop.crop_type]
            if not config then goto continue end

            local elapsed = os.time() - crop.planted_at
            local stageTime = config.growthTime / config.stages
            local expectedStage = math.min(math.floor(elapsed / stageTime), config.stages)

            -- Degrade water
            local newWater = math.max(0, crop.water_level - config.waterConsumption)
            local newQuality = crop.quality

            -- Quality degrades without water
            if newWater <= 0 then
                newQuality = math.max(0.3, crop.quality - 0.05)
                expectedStage = crop.growth_stage -- Pause growth
            end

            local isHarvestable = expectedStage >= config.stages and newWater > 0

            if expectedStage ~= crop.growth_stage or newWater ~= crop.water_level then
                MySQL.update(
                    'UPDATE farm_crops SET growth_stage = ?, water_level = ?, quality = ?, is_harvestable = ? WHERE id = ?',
                    {expectedStage, newWater, newQuality, isHarvestable and 1 or 0, crop.id}
                )

                if expectedStage ~= crop.growth_stage then
                    TriggerClientEvent('farming:client:updateCropStage', -1,
                        crop.id, expectedStage, crop.crop_type,
                        vector3(crop.position_x, crop.position_y, crop.position_z))
                end
            end

            :continue:
        end
    end
end)

Механика полива должна быть интерактивной, а не утомительной. Дайте игроку предмет лейки, который запускает анимацию при использовании рядом с растениями, и поливайте несколько близлежащих растений за одно действие, а не по одному. Для больших ферм введите улучшение системы орошения, которое автоматически поливает все растения на участке с регулярными интервалами, снижая ручной труд, но требуя первоначальных вложений в материалы. Отображайте уровень воды и прогресс роста каждого растения через небольшой индикатор над объектом, когда игрок смотрит на него, используя 3D-текст или наложение системы прицеливания.

Сбор урожая и качество продукции

Сбор урожая , это момент вознаграждения, делающий весь цикл фермерства удовлетворительным. Когда культура достигает финальной стадии роста и была достаточно полита, она становится готовой к сбору. Игрок взаимодействует с культурой, выполняет анимацию сбора и получает предметы урожая в инвентарь. Количество и качество продукции зависят от того, насколько хорошо игрок ухаживал за культурой в течение цикла роста: регулярный полив дает продукцию более высокого качества, которая продается дороже, а заброшенные культуры дают меньше предметов низкого качества. Реализуйте множитель качества, влияющий как на количество урожая, так и на цену продажи, создавая сильный стимул для внимательного фермерства. После сбора удаляйте культуру из базы данных и удаляйте объект из мира, освобождая слот для повторной посадки. Рассмотрите возможность добавления механики компостирования, где урожай низкого качества можно превращать в удобрение, повышающее качество будущих культур, создавая замкнутый цикл без отходов, поощряющий продолжение фермерской деятельности.

Система животноводства

Животные добавляют второе измерение в опыт фермерства и создают дополнительные источники дохода. Реализуйте покупаемых животных, таких как куры, коровы и овцы, которые размещаются в специально отведенных загонах на ферме. Каждый тип животного имеет свой производственный цикл: куры несут яйца каждые несколько часов, коровы дают молоко ежедневно, а овец можно стричь для получения шерсти периодически. Животные требуют кормления из инвентаря продукции игрока, связывая систему выращивания культур напрямую с системой животных и создавая замкнутый экономический цикл. Вот конфигурация и система кормления для фермерских животных:

Config.Animals = {
    chicken = {
        model = 'a_c_hen',
        purchasePrice = 500,
        feedItem = 'wheat',
        feedInterval = 3600,       -- needs feeding every hour
        productionItem = 'eggs',
        productionAmount = 3,
        productionInterval = 7200, -- produces every 2 hours
        maxPerFarm = 10
    },
    cow = {
        model = 'a_c_cow',
        purchasePrice = 3000,
        feedItem = 'corn',
        feedInterval = 5400,
        productionItem = 'milk',
        productionAmount = 2,
        productionInterval = 14400,
        maxPerFarm = 5
    },
    sheep = {
        model = 'a_c_sheep',
        purchasePrice = 1500,
        feedItem = 'wheat',
        feedInterval = 4800,
        productionItem = 'wool',
        productionAmount = 1,
        productionInterval = 21600,
        maxPerFarm = 8
    }
}

RegisterNetEvent('farming:server:feedAnimal', function(animalId)
    local src = source
    local Player = QBCore.Functions.GetPlayer(src)
    if not Player then return end

    local animal = MySQL.query.await(
        'SELECT * FROM farm_animals WHERE id = ? AND owner = ?',
        {animalId, Player.PlayerData.citizenid}
    )

    if not animal or not animal[1] then return end
    animal = animal[1]

    local config = Config.Animals[animal.animal_type]
    if not Player.Functions.GetItemByName(config.feedItem) then
        return TriggerClientEvent('QBCore:Notify', src, 'Need ' .. config.feedItem .. ' to feed', 'error')
    end

    Player.Functions.RemoveItem(config.feedItem, 1)

    MySQL.update(
        'UPDATE farm_animals SET last_fed = ?, hunger = 100 WHERE id = ?',
        {os.time(), animalId}
    )

    TriggerClientEvent('QBCore:Notify', src, 'Animal fed successfully', 'success')
end)

Животные, которых не кормят вовремя, становятся несчастными, что снижает их производительность. Если их слишком долго не кормить, они полностью прекращают производство. Отображайте статус животных через взаимодействие с целью, показывающее уровень голода, счастья и время до следующего производства. Это создает ежедневную рутину проверки для фермеров, которая поддерживает их вовлеченность в сервер между циклами роста культур.

Система рынка и продажа продукции

Система рынка связывает фермеров с широкой экономикой сервера. Создайте NPC-продавцов на фермерских рынках, в продуктовых магазинах и ресторанах по всей карте, где игроки могут продавать свою продукцию. Реализуйте динамическую систему ценообразования, где цены колеблются в зависимости от спроса и предложения: если много фермеров выращивают пшеницу, цена на пшеницу падает, стимулируя разнообразие культур. Отслеживайте общий объём продаж по типам культур за скользящие временные окна и корректируйте цены соответственно. Премиальная продукция из высококачественных культур продаётся с множителем выше базовой цены, вознаграждая тщательное земледелие. Рассмотрите возможность добавления опции торговли между игроками, где фермеры могут устанавливать рыночные палатки в назначенных местах и продавать напрямую другим игрокам по индивидуальным ценам. Это создаёт органичные ролевые взаимодействия между фермерами и покупателями и позволяет предприимчивым игрокам зарабатывать, покупая дешёвую оптовую продукцию и продавая её с розничной наценкой в местах с высоким трафиком.

Влияние погоды на фермерство

Интеграция погоды добавляет непредсказуемость и стратегию в фермерство. Подключитесь к системе погоды вашего сервера, чтобы применять модификаторы к росту урожая и потреблению воды. Дождь естественно поливает все открытые культуры, уменьшая необходимость ручного полива в сырые периоды. Экстремальная жара увеличивает потребление воды, заставляя фермеров чаще поливать в жаркую погоду. Штормы могут повредить урожай, снижая качество или даже уничтожая неубранные плоды, оставленные слишком долго. Морозы зимой могут полностью уничтожить определённые типы культур, требуя от фермеров выбирать морозоустойчивые сорта или инвестировать в теплицы, защищающие урожай от погодных условий. Реализуйте систему прогноза погоды, доступную через приложение телефона в игре или телевизионное вещание, чтобы фермеры могли планировать посадки с учётом предстоящих условий, добавляя стратегический уровень планирования, который поднимает опыт фермерства выше простых механик "нажми-и-жди".

Улучшения фермы и прогресс

Система прогрессии дает фермерам долгосрочные цели и вознаграждает регулярную игру. Игроки начинают с небольшого участка, где можно выращивать несколько культур, затем могут получить расширения через XP фермерства или прямую покупку. Каждый уровень улучшения открывает новые возможности: автоматические системы полива, большие загоны для животных, амбар для хранения излишков, перерабатывающие станции, превращающие сырье в товары с повышенной ценностью, например пшеницу в муку или виноград в вино, и трактор для ускорения посадки и сбора на больших участках. XP фермерства отслеживается отдельно от общей прогрессии сервера, создавая отдельный навык, который улучшает качество урожая и сокращает время роста на высоких уровнях. Система переработки особенно важна для экономики, так как добавляет этапы с добавленной стоимостью между сырьем и готовой продукцией, создавая возможности для ролевой игры в цепочке поставок, где фермеры продают сырье пекарням, винодельням или ресторанам, принадлежащим игрокам, которые превращают его в конечные продукты для потребителей.

Готовы начать?

Возьмите скрипты в нашем магазине или заходите в Discord за поддержкой, обновлениями и анонсами.