esx_death
esx_death handles death state, the death screen, respawn timers, penalties and revives in ESX Legacy. Config keys, exports, events and /revive explained.
esx_death is the global death system for ESX Legacy. It shows a branded death screen when a player dies, persists the dead state in the database, runs the early-respawn and bleedout timers, applies respawn penalties and exposes exports to revive players. esx_ambulancejob builds on it for EMS revives and distress calls.
esx_death has no page in the official ESX documentation. This reference is written from the resource source (version 1.0.0).
Overview
| Fact | Value |
|---|---|
| Resource | esx_death |
| Side | Client + server + NUI |
| Dependencies | es_extended, esx_lib, oxmysql, OneSync (/onesync) |
| Database | users.is_dead, users.death_time |
| Commands | /revive, /reviveall (group admin) |
| Required by | esx_ambulancejob |
How it works
- es_extended detects the death on the client and triggers
esx:onPlayerDeath(client and server) with killer data. - esx_death stores
is_dead = 1anddeath_time(unix seconds), sets theisDeadstate bag and opens the death screen. - After
Config.EarlyRespawnTimerthe player can hold E forConfig.HoldDurationms to respawn at the closestConfig.RespawnPointsentry. Respawning before the bleedout ends costsConfig.EarlyRespawnFineAmountfrom the bank whenConfig.EarlyRespawnFineis enabled. - When the bleedout timer (
EarlyRespawnTimer + BleedoutTimer) runs out, the client respawns automatically without a fine. - On respawn the configured penalties remove items, cash, black money and weapons. A revive (EMS, admin, txAdmin) keeps everything.
Death screen controls
| Key | Action |
|---|---|
| E (hold) | Respawn when allowed. |
| G | Send a distress signal (cooldown Config.DistressCooldown). |
| F2 | Toggle the mouse cursor to click the NUI buttons. |
Chat (T) and push-to-talk stay enabled. All other controls are disabled while dead.
Installation
Database
With Config.AutoMigrate = true (default) the server adds the two users columns on start. To migrate manually, run esx_death.sql, which adds them only if missing:
ALTER TABLE `users` ADD COLUMN `is_dead` TINYINT(1) NOT NULL DEFAULT 0;
ALTER TABLE `users` ADD COLUMN `death_time` BIGINT NULL DEFAULT NULL;The resource runs SELECT is_dead, death_time FROM users LIMIT 0 at start, so it fails loudly if the columns are missing.
server.cfg
OneSync must be enabled. Start esx_death before esx_ambulancejob:
set onesync on
ensure esx_lib
ensure es_extended
ensure esx_death
ensure esx_ambulancejobConfiguration
| Key | Default | Description |
|---|---|---|
Config.Debug | false | Print detailed client and server debug logs. |
Config.Locale | GetConvar('esx:locale', 'en') | Locale for the death screen and commands. |
Config.DeathAnim | { enabled = true, dict = 'misslamar1dead_body', name = 'dead_idle', fadeIn = 10.0, fadeOut = 10.0, flags = 1 | 2 | 8, playbackRate = 1.0 } | Looping animation while dead. |
Config.zoom | { min = 1, max = 6, step = 0.5 } | Zoom limits for the death camera. |
Config.MedalClip | true | Trigger a Medal.tv clip on death through xLib.medal.triggerClip(). |
Config.EarlyRespawnTimer | 60000 * 1 | Time in ms before respawn becomes available. |
Config.BleedoutTimer | 60000 * 10 | Additional time in ms until the player bleeds out and respawns automatically. |
Config.RemoveWeaponsAfterRPDeath | true | Remove all weapons on respawn (ESX inventory only). |
Config.RemoveCashAfterRPDeath | true | Remove all cash and black money on respawn. |
Config.RemoveItemsAfterRPDeath | true | Clear the inventory on respawn (ox_inventory:ClearInventory with ox_inventory). |
Config.EarlyRespawnFine | false | Charge a bank fine when respawning before the bleedout ends. |
Config.EarlyRespawnFineAmount | 5000 | Amount of that fine. Respawn is refused if the bank balance is too low. |
Config.OxInventory | ESX.GetConfig('CustomInventory') == 'ox' or GetResourceState('ox_inventory') == 'started' | Detected automatically. Switches item and weapon handling to ox_inventory. |
Config.RespawnPoints | 2 points | { coords = vector3, heading = number } list. The closest point is used. |
Config.HoldDuration | 1500 | Ms to hold E for respawn. |
Config.DistressCooldown | 60000 | Ms between distress signals. |
Config.ShowDeathReason | true | Show "killed by a player" under the buttons for player kills. |
Config.ShowKillerName | false | Show the killer's name instead (requires ShowDeathReason). |
Config.CameraEnabled | false | Use the orbit death camera instead of the normal camera. |
Config.AutoMigrate | true | Add missing users.is_dead / users.death_time columns on start. |
Default respawn points:
Config.RespawnPoints = {
{ coords = vector3(341.0, -1397.3, 32.5), heading = 48.5 }, -- Central Los Santos
{ coords = vector3(1836.03, 3670.99, 34.28), heading = 296.06 } -- Sandy Shores
}Server exports
IsDead
exports.esx_death:IsDead(playerId) --> booleanReturns true if the cached state of the player is dead. Returns false for players whose state is not loaded yet.
GetDeathState
exports.esx_death:GetDeathState(playerId) --> table | nilReturns a snapshot or nil when no state is cached:
| Field | Type | Description |
|---|---|---|
dead | boolean | Current state. |
elapsed | number | Seconds since death. |
earlyRemaining | number | Seconds until respawn is allowed. |
remaining | number | Seconds until bleedout. |
total | number | Total bleedout length in seconds. |
distressRemaining | number | Seconds until the next distress signal. |
distressSent | boolean | A distress signal was sent during this death. |
fine | number | Early respawn fine, 0 when disabled. |
killedByPlayer | boolean | Death was caused by another player. |
killerServerId | number? | Validated killer server id. |
deathCause | number|string? | Weapon hash or cause name. |
GetDeadPlayers
exports.esx_death:GetDeadPlayers() --> { [playerId] = 'dead' | 'distress' }GetDeadPlayerLocations
exports.esx_death:GetDeadPlayerLocations() --> { [playerId] = { x, y, z } }Revive
exports.esx_death:Revive(playerId, reason?) --> ok, wasDead| Name | Type | Description |
|---|---|---|
playerId | number | Server id of the player. |
reason | string? | Passed to esx_death:stateChanged. Defaults to 'revive'. |
Revives in place, keeps the inventory, sets hunger and thirst to 500000 through esx_status:set and clears the dead flag in the database. Returns false, false if the player was not dead.
local ok = exports.esx_death:Revive(targetId, 'mymedic')
if ok then
TriggerClientEvent('esx:showNotification', targetId, 'You have been revived.')
endSetDead
exports.esx_death:SetDead(playerId) --> booleanMarks a player as dead in the database and syncs the death screen to that client. This does not kill the ped; use it together with your own logic.
Client exports
exports.esx_death:IsDead() --> boolean
exports.esx_death:GetDeathState() --> { dead, earlyRemaining, remaining, distressRemaining }The server also sets the replicated state bag isDead, so LocalPlayer.state.isDead (client) and Player(src).state.isDead (server) work without exports.
Events
Server events (local)
| Event | Arguments | When |
|---|---|---|
esx_death:stateChanged | playerId, dead, reason | State flips. reason is 'death', 'respawn', 'revive', 'admin', 'txadmin', 'restore', 'logout' or a custom revive reason. |
esx_death:distress | playerId, coords | A dead player sent a distress signal. esx_ambulancejob uses it to alert medics. |
AddEventHandler('esx_death:stateChanged', function(playerId, dead, reason)
if dead then
print(('Player %s died'):format(playerId))
elseif reason == 'respawn' then
print(('Player %s respawned at a hospital'):format(playerId))
end
end)Client events (local)
| Event | Arguments | When |
|---|---|---|
esx_death:entered | none | The death screen opened. |
esx_death:recovered | 'respawn' or 'revive' | The player was respawned or revived. |
esx_death:requestDistress | none | Trigger it to send a distress signal (same as pressing G). |
On recovery esx_death also fires esx:onPlayerSpawn (client and server), playerSpawned and esx_basicneeds:resetStatus.
Net events and callbacks (security)
| Name | Type | Notes |
|---|---|---|
esx:onPlayerDeath | net event | Client-triggerable. A client can only mark itself dead. Rate limited (3 per 5 s), killer id and cause are sanitized, timestamps and penalties are always set by the server. |
esx_ambulancejob:onPlayerDistress | net event | Client-triggerable. Only works while the sender is dead and respects Config.DistressCooldown. |
esx_death:respawn | callback | Refused if not dead, too early or the fine cannot be paid. |
esx_death:distress, esx_death:getState | callbacks | Only affect the calling player. |
esx_death:sync, esx_death:recover, esx_ambulancejob:clsearch | client net events | The client ignores them unless they come from the server. |
Commands
| Command | Group | Arguments | Description |
|---|---|---|---|
/revive | admin | playerId | Revive one player. Also works from the server console. |
/reviveall | admin | none | Revive every online player. |
The txAdmin "Heal" action (txAdmin:events:healedPlayer) revives the player, or everyone when txAdmin heals all.
Integration tips
- Block actions while dead (shops, phones, inventories) with
LocalPlayer.state.isDeadon the client andexports.esx_death:IsDead(source)on the server. - Use
Reviveinstead of callingNetworkResurrectLocalPlayeryourself; otherwise the database still says dead and the player is restored as dead on the next login. - To change who gets alerted on distress, listen to
esx_death:distressin your own dispatch resource.
Common issues
- SQL error about
is_deadon start: theuserstable lacksis_dead/death_timeandConfig.AutoMigrateis off. Runesx_death.sql. - Two death screens or instant respawn: another death or revive script is still running. Only esx_death should handle death.
- Weapons not removed with ox_inventory: with ox_inventory, weapons are items. Use
Config.RemoveItemsAfterRPDeathinstead of the weapons option. - Player respawns dead after relog: expected when they logged out while dead. Revive them or let the timer run out.
Related
Frequently asked questions
Independent documentation
Last updated on
esx_datastore
esx_datastore stores JSON data per player or per society in ESX Legacy. Learn the tables, the get/set store API, server events and autosave behavior.
esx_dmvschool
esx_dmvschool adds a theory test and car, motorcycle and truck driving tests to ESX Legacy. Covers licenses, config keys, checkpoints, events and common issues.