Skip to content

Electric vehicles

Needed only if you turn on Battery regeneration in /hud → Admin → Vehicles.

GTA V has no battery. Electric vehicles use the same fuel field as petrol cars, and the game does not even drain it by default — that is FiveM’s SetFuelConsumptionState, and it only ever drains. There is no regeneration anywhere in the game.

So the work is split:

Side Job
Aurora HUD Measures acceleration at 10 Hz and knows which models are electric
ox_fuel Owns the fuel value and writes it

Two resources writing the same value would fight — one overwrites, the other undoes it. The bridge is a read-and-clear export: the HUD accumulates at its own rate, ox_fuel drains at its own rate. The two do not have to line up, and a missed call never double-credits.

Two blocks in ox_fuel/client/init.lua.

1. Before local function startDrivingVehicle()

Section titled “1. Before local function startDrivingVehicle()”
local AURORA_HUD = 'hud' -- the Aurora HUD resource name
local function auroraRegen()
-- The HUD keeps this statebag LOCAL: it is only true in an ELECTRIC vehicle with
-- regeneration enabled. Reading it is cheap. Without it, this patch would pay the
-- cross-resource export boundary (~0.2ms) once a second in ANY car, petrol included,
-- only to be handed 0. It also saves a GetResourceState call: if the flag is true,
-- the HUD is running and set it.
if not LocalPlayer.state.aurora_ev_regen then return 0 end
local ok, gain = pcall(function() return exports[AURORA_HUD]:ConsumeElectricRegen() end)
return (ok and type(gain) == 'number' and gain > 0) and gain or 0
end

If you renamed the HUD resource, change AURORA_HUD to match. The dependency is optional: without the HUD the flag never exists, this is one nil read per second, and ox_fuel behaves exactly as before.

2. Inside the driving loop, right after the leaking-tank block

Section titled “2. Inside the driving loop, right after the leaking-tank block”
if fuelAmount > 0 then
if GetVehiclePetrolTankHealth(vehicle) < 700 then
newFuel -= math.random(10, 20) * 0.01
end
-- AURORA PATCH
local regen = auroraRegen()
if regen > 0 then newFuel = math.min(newFuel + regen, 100.0) end

A punctured tank still leaks. Regenerating does not plug a hole.

All of these live on the HUD side, so you do not configure them in ox_fuel:

Guard Why
Ceiling, default 85% Braking never takes you above it; the rest needs a charger. Stops a long descent from filling the car, and matches reality — a nearly full battery will not take charge.
8 m/s² limit Above that it is not braking, it is a crash. Without the cap, hitting a wall would hand you half a battery. It is capped rather than ignored so there is no step change.
Intensity, default 30% How much of the braking energy comes back. ~30% is the real-world order of magnitude.
Only while slowing, above 2 m/s Stationary, there is no kinetic energy to recover.
Credit cleared on vehicle change Leaving with undelivered charge must not hand it to the next car.

The test is whether the motor is braking, not whether the car is slowing down — those are not the same thing. The balance is of forces, per unit of mass, which cancels out:

motor = measured acceleration + gravity for/against + drag

Two calibrations do the rest:

  • Drag is per vehicle, via GetVehicleEstimatedMaxSpeed. At top speed on the flat a car is by definition giving everything it has, so drag at that point is full scale. A fixed curve assuming 200 km/h for every car underestimated it badly in a slow one.
  • No regeneration while on the throttle (GetVehicleThrottleOffset). In a real electric car it starts when you lift off or brake.

With that, every case falls out on its own:

Situation Readout
Coasting downhill, off the throttle 0% — gravity is doing the work, the battery gives nothing
Downhill braking on the motor −50% · charging
Downhill, throttle floored +100% · consuming
Flat, at top speed, floored +100% · consuming
Uphill at constant speed +58% · consuming — it is fighting gravity

At the default 30% intensity:

Situation Gain
Hard stop, 100 → 0 km/h 0.11% of battery
Gentle stop, 50 → 0 km/h 0.03%
Crashing at 100 km/h 0.11% — same as a hard stop, which is the cap working
60 accelerate-brake cycles 1.6%, having spent far more than that accelerating
Descending all of Mount Chiliad (700 m, braking) ~1.7%

Chiliad gives so little because the energy is limited by height, not by time: 700 m of descent is about 6.4% of a battery in raw energy, and only 30% of that comes back.

There is no perpetual motion here — to come down you had to go up, and going up costs far more than the descent returns.