FiveM Docs
Addons

esx_status

esx_status stores and syncs player needs like hunger, thirst and drunk in ESX Legacy. Covers the server-authoritative model, config, events and examples.

esx_status is the engine behind player needs in ESX Legacy. It keeps a list of named values per player (for example hunger, thirst, drunk), saves them in users.status, decays them over time and broadcasts them to the client every tick. esx_basicneeds and esx_optionalneeds build on it, and HUDs such as esx_hud read from it.

Overview

FactValue
Resourceesx_status
SideServer (authoritative values, saving) and client (status objects, ticks, optional bars)
Dependenciesesx_lib, es_extended (oxmysql is loaded by the manifest)
SQLesx_status.sql adds users.status
UIOptional NUI bars (html/ui.html), off by default

Two kinds of statuses

KindExamplesWho owns the value
AuthoritativeStatuses listed in Config.AuthoritativeStatuses (default hunger, thirst)The server. It decays them and pushes the result to the client with esx_status:sync.
CustomEverything else, for example drunkThe client. It ticks them and sends them to the server every Config.UpdateInterval.

Since version 1.1 hunger and thirst are decided on the server. Change them with the server events. Client-side changes only last until the next sync.

Installation

Import the SQL

esx_status.sql
ALTER TABLE `users` ADD COLUMN `status` LONGTEXT NULL;

Start it before resources that register statuses

server.cfg
ensure esx_status
ensure esx_basicneeds
ensure esx_optionalneeds

Configuration

KeyDefaultDescription
Config.StatusMax1000000Value that equals 100 percent. Values are clamped between 0 and this number on the server.
Config.TickTime1000Client tick length in ms. Also the time unit for decay in AuthoritativeStatuses.
Config.UpdateInterval30000How often (ms) the server syncs authoritative statuses and the client sends custom statuses.
Config.SyncSlices30The server spreads one sync round over this many batches to avoid spikes.
Config.MinUpdateInterval10000Minimum time (ms) between two accepted esx_status:update messages from one client.
Config.LoadRetryInitial5000First retry delay (ms) when loading statuses fails. Doubles on each failure.
Config.LoadRetryMax60000Upper limit for the retry delay.
Config.DisplayfalseShow the built-in esx_status bars. Keep false when you use another HUD.
Config.AuthoritativeStatuseshunger = { default = 1000000, decay = 100 }, thirst = { default = 1000000, decay = 75 }Statuses the server owns. default is the start value for new players, decay the amount removed per Config.TickTime.

With the defaults, hunger drops from full to zero in about 2 hours 47 minutes (1,000,000 / 100 seconds) and thirst in about 3 hours 42 minutes.

config.lua
Config.AuthoritativeStatuses = {
    hunger = { default = 1000000, decay = 100 },
    thirst = { default = 1000000, decay = 75 },
    stress = { default = 0, decay = 0 }, -- server-owned, changed only by your scripts
}

Status data shape

Every status entry sent between server and client looks like this:

FieldTypeDescription
namestringUnique name, 1 to 64 characters.
valnumberCurrent value, 0 to Config.StatusMax.
percentnumberval / Config.StatusMax * 100.

A player can hold at most 64 statuses. The loaded list is also mirrored to ESX.PlayerData.variables.status on the client.

Server API

All server events below are local (AddEventHandler). Only other server scripts can trigger them.

esx_status:set

Sets a status to an exact value.

TriggerEvent('esx_status:set', playerId, name, value)
NameTypeDescription
playerIdnumberServer ID of the player.
namestringStatus name.
valuenumberNew value. Clamped to 0 … Config.StatusMax.
server/main.lua
-- fill hunger and thirst after a revive
TriggerEvent('esx_status:set', source, 'hunger', 1000000)
TriggerEvent('esx_status:set', source, 'thirst', 1000000)

esx_status:add

Adds to a status. Use a negative value to remove.

TriggerEvent('esx_status:add', playerId, name, value)
NameTypeDescription
playerIdnumberServer ID of the player.
namestringStatus name.
valuenumberAmount to add (negative to subtract). The result is clamped.
server/main.lua
ESX.RegisterUsableItem('sandwich', function(source)
    local xPlayer = ESX.Player(source)
    xPlayer.removeInventoryItem('sandwich', 1)
    TriggerEvent('esx_status:add', source, 'hunger', 250000)
end)

set and add only change a status the player already has. After the change the server sends esx_status:sync to the client right away.

esx_status:getStatus

Reads one status of a player.

TriggerEvent('esx_status:getStatus', playerId, name, cb)
NameTypeDescription
playerIdnumberServer ID.
namestringStatus name.
cbfunctionReceives { name, val, percent }.
server/main.lua
TriggerEvent('esx_status:getStatus', source, 'thirst', function(status)
    if status.percent < 10 then
        TriggerClientEvent('esx:showNotification', source, 'You are very thirsty')
    end
end)

The callback is not called when the player is not loaded or does not have that status. Do not wait on it forever.

Client API

esx_status:registerStatus

Creates a status object on the client. Register custom statuses in a handler for esx_status:loaded so the saved value is applied.

TriggerEvent('esx_status:registerStatus', name, default, color, visible, tickCallback)
NameTypeDescription
namestringStatus name.
defaultnumberStart value when nothing is saved.
colorstringCSS color for the built-in bar, for example '#CFAD0F'.
visiblefunctionfunction(status) return boolean end. Decides if the bar is shown. Called when Config.Display is on, so always pass a function.
tickCallbackfunctionfunction(status) end, called every Config.TickTime. Usually status.remove(x).
client/main.lua
AddEventHandler('esx_status:loaded', function()
    TriggerEvent('esx_status:registerStatus', 'stress', 0, '#E74C3C',
        function(status) return status.val > 0 end,
        function(status) status.remove(500) end
    )
end)

If a status with the same name exists, the new object replaces it and keeps the current value.

Status object

esx_status:getStatus and esx_status:getAllStatus return status objects with these members:

MemberDescription
name, val, default, colorFields.
set(val)Set the value (no clamping).
add(val)Add, capped at Config.StatusMax.
remove(val)Subtract, floored at 0.
getPercent()Value as percent.
onTick()Runs the tick callback.
_set(key, value), _get(key)Raw field access.

esx_status:unregisterStatus

TriggerEvent('esx_status:unregisterStatus', name)

Removes the status from the client list. It stops ticking and is no longer sent to the server.

esx_status:getStatus (client)

TriggerEvent('esx_status:getStatus', name, cb)
client/main.lua
TriggerEvent('esx_status:getStatus', 'hunger', function(status)
    print(('Hunger: %.1f%%'):format(status.getPercent()))
end)

esx_status:getAllStatus

TriggerEvent('esx_status:getAllStatus', function(statuses)
    for i = 1, #statuses do
        print(statuses[i].name, statuses[i].val)
    end
end)

esx_status:set / add / remove (client)

TriggerEvent('esx_status:set', name, val)
TriggerEvent('esx_status:add', name, val)
TriggerEvent('esx_status:remove', name, val)

These change the local status object. They are also net events, so the server can send them with TriggerClientEvent('esx_status:add', playerId, 'drunk', 250000). For custom statuses the new value reaches the server with the next update. For authoritative statuses (hunger, thirst) the change is overwritten by the next server sync, so use the server events instead.

esx_status:setDisplay

TriggerEvent('esx_status:setDisplay', 0.5)

Sets the opacity of the built-in bars (0.0 hides them). Only useful with Config.Display = true.

Events you can listen to

EventSidePayloadWhen
esx_status:loadedclientnoneSaved statuses arrived from the server. Register custom statuses here.
esx_status:onTickclientarray of { name, val, percent }Every Config.TickTime after loading. Ideal for HUDs and effects.
esx_status:loadclient (from server)full status listSent by the server after esx:playerLoaded or on request. Internal.
esx_status:syncclient (from server)changed entriesServer pushes authoritative values. Internal.
client/hud.lua
AddEventHandler('esx_status:onTick', function(statuses)
    for _, status in ipairs(statuses) do
        if status.name == 'thirst' then
            SendNUIMessage({ action = 'thirst', value = status.percent })
        end
    end
end)

Network events (client to server)

EventPayloadProtection
esx_status:requestLoadnoneIgnored while loading; rate limited with the load retry delay.
esx_status:updatearray of { name, val }Accepted at most every Config.MinUpdateInterval. Entries are validated (max 64, names 1-64 chars, finite numbers, clamped). Authoritative statuses in the payload are ignored.

Custom statuses are client-controlled

A modified client can send any value for custom statuses. Do not base money, items or permissions on them. If a status matters, add it to Config.AuthoritativeStatuses and change it only through the server events.

Saving

The server loads users.status on esx:playerLoaded and writes it back on esx:playerDropped. During the session values live in the xPlayer variable status. Authoritative values are advanced from elapsed time whenever they are read, synced or saved.

Common issues

  • Hunger or thirst jumps back after eating: your item script changes them on the client. Use TriggerEvent('esx_status:add', source, 'hunger', amount) on the server.
  • Status bars do not show: Config.Display is false by default. Enable it or use a HUD.
  • Custom status always starts at the default: it was registered before esx_status:loaded fired and then never received the saved value, or the player never stayed long enough for an update. Register inside esx_status:loaded.
  • users.status column missing: import esx_status.sql. Loading fails and is retried with backoff.
  • Changing an unknown status on the server does nothing: set and add only touch statuses that already exist for the player.

Frequently asked questions

Independent documentation

esx-fivem.com is a community project and is not affiliated with the ESX Framework team. Facts on this page were checked against the upstream source. Official resources: docs.esx-framework.org and github.com/esx-framework.
Edit on GitHub

Last updated on

On this page