Tutorial 2026-02-09

FiveM Fuel System & Gas Station Development

TDYSKY

TDYSKY

Founder & Lead Developer at Agency Scripts

Fuel Consumption Mechanics

A realistic fuel system adds an essential layer of immersion and creates a natural money sink that helps balance your server's economy. The core mechanic involves tracking each vehicle's fuel level as a floating-point value between 0 and 100, decreasing it based on engine activity and driving behavior. Store the fuel level using entity state bags with Entity(vehicle).state.fuel so the value persists across all clients and survives network ownership changes. Calculate consumption rate per tick based on the vehicle's current RPM obtained through GetVehicleCurrentRpm, the throttle position from GetControlNormal, and the vehicle's class-specific consumption multiplier. Sports and super cars should consume fuel significantly faster than economy vehicles, while trucks and SUVs fall somewhere in between. Apply additional consumption modifiers for aggressive driving behaviors like rapid acceleration, high sustained speeds, and engine braking. When fuel reaches zero, gradually reduce the vehicle's maximum speed using SetVehicleMaxSpeed to simulate sputtering rather than killing the engine instantly, giving the player a few critical seconds to pull over safely.

-- Client-side fuel consumption thread
local fuelConsumptionRate = 0.0

CreateThread(function()
    while true do
        local ped = PlayerPedId()
        local vehicle = GetVehiclePedIsIn(ped, false)

        if vehicle ~= 0 and GetPedInVehicleSeat(vehicle, -1) == ped then
            local engineOn = GetIsVehicleEngineRunning(vehicle)

            if engineOn then
                local rpm = GetVehicleCurrentRpm(vehicle)
                local speed = GetEntitySpeed(vehicle) * 3.6 -- km/h
                local classMultiplier = Config.ClassConsumption[GetVehicleClass(vehicle)] or 1.0

                -- Base consumption + RPM factor + speed factor
                fuelConsumptionRate = (Config.BaseConsumption
                    + (rpm * Config.RpmFactor)
                    + (speed * Config.SpeedFactor)
                ) * classMultiplier

                local currentFuel = Entity(vehicle).state.fuel or 100.0
                local newFuel = math.max(0.0, currentFuel - fuelConsumptionRate)

                Entity(vehicle).state:set('fuel', newFuel, true)

                -- Engine stall when empty
                if newFuel <= 0 then
                    SetVehicleUndriveable(vehicle, true)
                    SetVehicleEngineOn(vehicle, false, true, true)
                elseif newFuel <= 5.0 then
                    -- Sputtering effect
                    SetVehicleMaxSpeed(vehicle, 30.0 * (newFuel / 5.0))
                end
            end
        end

        Wait(1000) -- Update every second
    end
end)

Gas Station UI and Refueling

The gas station experience should feel polished and intuitive through a well-designed NUI interface. When a player parks near a fuel pump within a defined radius, display an interaction prompt. Upon interaction, open a refueling UI that shows the current fuel level as a gauge or progress bar, the vehicle's tank capacity, the price per liter based on the current fuel type, and options to fill up completely or pump a specific dollar amount. The refueling animation should play on both the player character, who stands next to the vehicle holding a fuel nozzle prop using TaskPlayAnim, and the fuel pump itself if you use a custom prop setup. Fuel should fill gradually in real-time rather than instantly jumping to full, creating a brief wait that adds realism and prevents players from speed-refueling during chases. Show the running cost total updating live as fuel pumps, and deduct payment only when the player stops pumping or the tank is full. Support multiple fuel types at premium stations: regular unleaded at standard price, premium fuel that provides a small performance boost and costs more, and diesel for trucks and industrial vehicles that uses separate pumps.

Jerry Can and Emergency Refueling

Running out of fuel on the highway is a realistic scenario that your system should handle gracefully without forcing the player to abandon their vehicle. Implement a jerry can item that can be purchased at gas stations or hardware stores and filled with fuel at any pump. The jerry can should function as a usable inventory item with metadata tracking its current fill level, typically holding 10-20 liters. When a player uses a jerry can near an empty vehicle, play a pouring animation and transfer fuel from the can to the vehicle's tank. The jerry can should have weight in the inventory system proportional to how much fuel it contains, making a full can heavier than an empty one. Add a mechanic where roadside assistance can be called through the in-game phone, dispatching an NPC or player-operated tow truck with a fuel delivery service for a fee. For immersion, players should be able to siphon fuel from other vehicles using a hose item, transferring fuel between vehicles at the cost of time and the risk of being caught in the act.

-- Jerry can usage handler
RegisterNetEvent('fuel:useJerryCan')
AddEventHandler('fuel:useJerryCan', function(slot)
    local src = source
    local ped = GetPlayerPed(src)
    local coords = GetEntityCoords(ped)

    -- Find nearest vehicle
    local nearbyVehicle = GetClosestVehicle(coords, 3.0)
    if not nearbyVehicle or nearbyVehicle == 0 then
        return notify(src, 'No vehicle nearby.', 'error')
    end

    -- Get jerry can metadata
    local canData = exports.ox_inventory:GetSlot(src, slot)
    if not canData or not canData.metadata or not canData.metadata.fuel then
        return notify(src, 'Jerry can is empty.', 'error')
    end

    local canFuel = canData.metadata.fuel
    local vehicleFuel = Entity(nearbyVehicle).state.fuel or 0.0
    local maxTransfer = math.min(canFuel, 100.0 - vehicleFuel)

    if maxTransfer <= 0 then
        return notify(src, 'Vehicle tank is already full.', 'error')
    end

    -- Transfer fuel
    Entity(nearbyVehicle).state:set('fuel', vehicleFuel + maxTransfer, true)

    -- Update jerry can metadata
    local remainingFuel = canFuel - maxTransfer
    if remainingFuel <= 0 then
        exports.ox_inventory:SetMetadata(src, slot, { fuel = 0, label = 'Empty Jerry Can' })
    else
        exports.ox_inventory:SetMetadata(src, slot, { fuel = remainingFuel })
    end

    notify(src, ('Transferred %.1f liters to the vehicle.'):format(maxTransfer), 'success')
end)

Electric Vehicle Support

Modern roleplay servers increasingly feature electric vehicles that need a parallel charging infrastructure. Electric vehicles should not consume gasoline and instead drain a battery charge level that functions identically to the fuel gauge but depletes at a different rate. EV consumption should be lower per kilometer than gasoline vehicles, reflecting their real-world efficiency advantage, but charging should take longer than pumping gas, creating a different gameplay rhythm. Place charging stations at select locations around the map, not necessarily at traditional gas stations, to create distinct travel patterns for EV owners. Implement a charging UI that shows the current charge percentage, estimated time to full charge, and the cost per kilowatt-hour. Add a fast-charging option at premium stations that fills the battery in half the time at double the cost per unit. For the vehicle configuration, classify EVs by their model hash and store the vehicle type in your config so the system automatically detects whether a vehicle needs gasoline or electricity. Support hybrid vehicles that can use both fuel types, switching between electric mode at low speeds and gasoline at highway speeds, consuming both resources at reduced individual rates.

Dynamic Fuel Pricing Economy

A dynamic pricing system makes the fuel economy feel alive and creates interesting economic decisions for players. Base fuel prices on a configurable rate that fluctuates based on supply and demand mechanics. Track the total fuel purchased across all stations over rolling time windows, and when consumption is high, prices rise gradually. When consumption drops, prices decrease to attract more customers. Implement station-specific pricing where remote stations in Blaine County charge more due to transportation costs while city stations compete with lower margins. Allow player-owned gas stations where the owner can set their own fuel prices within a minimum and maximum range defined by the server config, creating genuine price competition between station operators. The station owner purchases wholesale fuel from a supplier NPC at a bulk rate and marks it up to their retail price, with the profit margin being their income. Add seasonal or event-based price surges where fuel costs spike during server events involving high vehicle activity like races or heists, creating economic ripple effects that affect all players and encourage conservation or strategic fuel purchases before anticipated price increases.

Gas Station as a Business

Transforming gas stations into player-operated businesses adds a complete economic loop to the fuel system. The station owner manages inventory by ordering fuel deliveries from a wholesale supplier, maintains equipment by paying for pump repairs and upgrades, and handles staffing by hiring other players as pump attendants who earn hourly wages. Implement a station management panel accessible only to the owner that displays daily sales volume, revenue, profit margins, current fuel inventory in the underground tanks, and employee attendance records. The station should have a physical underground tank with a limited capacity that depletes as customers refuel, requiring the owner to schedule delivery truck visits that take time to arrive and cost money upfront. Add a store component inside the station where the owner can stock convenience items like snacks, drinks, and basic supplies that customers can purchase alongside their fuel, creating an additional revenue stream. Allow upgrades to the station itself such as adding additional pump bays to serve more customers simultaneously, installing car wash equipment for an extra service fee, or adding EV charging stations to capture the electric vehicle market. Track station reputation based on pricing fairness, availability uptime, and customer satisfaction so that stations with better reputations appear highlighted on the map and attract more traffic.

HUD Integration and Fuel Gauge

The fuel gauge is a persistent HUD element that players will see constantly, so it must be visually clean and non-intrusive while conveying essential information at a glance. Design a minimal fuel indicator that sits near the speedometer or in a corner of the screen, showing the current fuel level as a semicircular gauge, a vertical bar, or a simple percentage readout. Use color coding where green indicates a healthy fuel level above 50%, yellow signals moderate fuel between 20-50%, and red warns of critically low fuel below 20%. When fuel drops below 15%, trigger a periodic low-fuel warning sound and flash the gauge to ensure the player does not accidentally run empty. Display the estimated remaining distance based on the current consumption rate, calculated by dividing the remaining fuel by the average consumption per kilometer over the last few minutes of driving. Hide the fuel gauge entirely when the player is on foot to reduce HUD clutter, and fade it in smoothly when they enter a vehicle. For players who prefer a minimal HUD, offer a setting to hide the fuel gauge entirely and only show it as a temporary notification when fuel drops below a configurable threshold. Integrate the gauge with other vehicle HUD elements like speedometer and engine health to create a cohesive vehicle dashboard experience.

Performance and Synchronization

The fuel system runs continuously on every client that is driving a vehicle, so performance optimization is critical. Use a consumption update interval of 1000 milliseconds rather than running on every frame tick, as fuel changes are gradual enough that per-second updates are visually indistinguishable from per-frame updates while using roughly 60 times less processing power. Store fuel values in entity state bags rather than custom network events, since state bags are optimized for frequently changing values and only synchronize when the value actually changes. When saving fuel to the database for persistence across server restarts, batch all vehicle fuel updates into a single query executed every 60 seconds rather than writing individually each time a vehicle's fuel changes. Use the vehicle's network ID as the key for fuel tracking, and clean up stored fuel data for vehicles that no longer exist to prevent database bloat. Handle the edge case where a vehicle changes network ownership during refueling by checking ownership before applying fuel changes and using server-side validation for all payment transactions. For stations with many simultaneous customers, implement a queue system that prevents two players from using the same pump simultaneously while showing a visual indicator that the pump is in use.

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.