Guide 2026-04-08

Creating a Farming & Agriculture System for FiveM

TDYSKY

TDYSKY

Founder & Lead Developer at Agency Scripts

Farming System Design Philosophy

A farming and agriculture system brings a completely different pace to FiveM roleplay servers, offering players a relaxing alternative to high-adrenaline criminal activities and law enforcement. The best farming systems create a self-sustaining economic loop where players purchase seeds, plant crops on designated farmland, tend to them over real-time growth cycles, harvest the produce, and sell it at market for profit. The design challenge lies in making the system engaging enough that players return regularly without making it so time-intensive that it feels like a chore. Use real-time growth cycles that continue even when the player is offline, so farmers log in to find their crops at different growth stages. The core data model needs to track each individual crop plot with its position, crop type, current growth stage, planted timestamp, water level, and quality rating. Store all of this server-side in a database so that farm state persists across server restarts and is protected from client-side manipulation.

Crop Planting and Database Schema

The planting system starts with a player selecting seeds from their inventory and placing them on valid farmland zones. Define farmland as configurable polygonal zones on the map where planting is permitted, preventing players from growing crops on sidewalks or inside buildings. Each farm plot should have a limited number of slots based on the land size, and players can rent or purchase farmland through an NPC or real estate system. When a player plants a seed, create a database record that tracks the crop through its entire lifecycle. Here is a practical database schema and the server-side planting handler:

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)

Each crop type should have different growth parameters defined in a configuration table. Wheat might grow in 30 real-world minutes across 4 stages, while cannabis or grapes could take several hours with 6 stages, rewarding patient farmers with higher-value produce. The growth stage determines which prop model is displayed in the world, transitioning from a small sprout to a full-grown plant as time progresses.

Growth Cycle Engine and Watering

The growth cycle engine is a server-side loop that periodically checks all planted crops and advances their growth stages based on elapsed time and conditions like water level. Run this as a timed server thread that executes every few minutes, calculating whether each crop should advance to the next stage based on its crop type's growth duration and the time since planting. Water level is the primary mechanic that keeps players engaged: crops consume water over time, and if the water level drops to zero, growth pauses and the crop's quality degrades. Players must return to their farm and use a watering can or irrigation system to replenish water levels. Here is the server-side growth engine:

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)

The watering mechanic should feel interactive rather than tedious. Give the player a watering can item that triggers an animation when used near crops, and water multiple nearby crops in a single action rather than requiring one-by-one watering. For larger farms, introduce an irrigation system upgrade that automatically waters all crops on the plot at regular intervals, reducing manual labor but requiring an upfront investment in materials. Display each crop's water level and growth progress through a small indicator above the prop when the player looks at it, using 3D text or a target system overlay.

Harvesting and Produce Quality

Harvesting is the payoff moment that makes the entire farming loop satisfying. When a crop reaches its final growth stage and has been watered adequately, it becomes harvestable. The player interacts with the crop, plays a harvesting animation, and receives produce items in their inventory. The quantity and quality of produce depend on how well the player maintained the crop during its growth cycle: consistent watering produces higher quality items that sell for more, while neglected crops yield fewer items of lower quality. Implement a quality multiplier that affects both the yield count and the sale price, creating a strong incentive for attentive farming. After harvesting, remove the crop from the database and delete the prop from the world, freeing the plot slot for replanting. Consider adding a composting mechanic where low-quality harvests can be converted into fertilizer that boosts the quality of future crops, creating a zero-waste loop that rewards continued farming activity.

Animal Husbandry System

Animals add a second dimension to the farming experience and create additional revenue streams. Implement purchasable animals like chickens, cows, and sheep that are placed in designated animal pens on the farmland. Each animal type has its own production cycle: chickens produce eggs every few hours, cows produce milk daily, and sheep can be sheared for wool periodically. Animals require feeding from the player's produce inventory, connecting the crop system directly to the animal system and creating a closed economic loop. Here is a configuration and feeding system for farm animals:

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)

Animals that are not fed on time become unhappy, reducing their production output. If left unfed for too long, they stop producing entirely. Display animal status through a target interaction that shows hunger level, happiness, and time until next production. This creates a daily check-in routine for farmers that keeps them engaged with the server between crop growth cycles.

Market System and Selling Produce

The market system connects farmers to the broader server economy. Create NPC vendor locations at farmers markets, grocery stores, and restaurants around the map where players can sell their produce. Implement a dynamic pricing system where prices fluctuate based on supply and demand: if many farmers are growing wheat, wheat prices drop, incentivizing crop diversity. Track total sales volume per crop type over rolling time windows and adjust prices accordingly. Premium produce from high-quality crops sells at a multiplier above the base price, rewarding careful farming. Consider adding a player-to-player trading option where farmers can set up market stalls at designated areas, selling directly to other players at custom prices. This creates organic roleplay interactions between farmers and buyers, and lets entrepreneurial players profit by buying cheap wholesale produce and selling at retail markup in high-traffic areas.

Weather Effects on Farming

Weather integration adds unpredictability and strategy to farming. Hook into your server's weather system to apply modifiers to crop growth and water consumption. Rain naturally waters all outdoor crops, reducing the need for manual watering during wet periods. Extreme heat increases water consumption, forcing farmers to water more frequently during hot weather. Storms can damage crops, reducing quality or even destroying unharvested produce that has been left too long. Frost events during winter seasons can kill certain crop types entirely, requiring farmers to choose cold-resistant varieties or invest in greenhouse structures that protect crops from weather effects. Implement a weather forecast system accessible through an in-game phone app or TV broadcast so farmers can plan their planting schedule around upcoming conditions, adding a strategic planning layer that elevates the farming experience beyond simple click-and-wait mechanics.

Farm Upgrades and Progression

A progression system gives farmers long-term goals and rewards consistent play. Start players with a small plot that can hold a handful of crops, then let them earn expansions through farming XP or direct purchase. Each upgrade level unlocks new capabilities: automated sprinkler systems that handle watering, larger animal pens for more livestock, a barn for storing surplus produce, processing stations that convert raw items into higher-value goods like wheat into flour or grapes into wine, and a tractor vehicle that speeds up planting and harvesting across large plots. Track farming XP separately from other server progression to create a dedicated farming skill that improves yield quality and reduces growth times at higher levels. The processing system is especially important for the economy because it adds value-added steps between raw produce and finished goods, creating opportunities for supply chain roleplay where farmers sell raw materials to player-owned bakeries, wineries, or restaurants that convert them into final products for consumers.

Share this article

Ready to upgrade your server?

Check out our premium FiveM scripts in the Agency Scripts store or join our Discord community for support and updates.