Browse docs
External Death Screen
Overview
External mode disables only the bundled death-screen NUI and its focus handling. Sky Ambulancejob continues to own the death state, persistence, bleed-out timer, dispatch requests, AI Medic requests, respawn rules, reconnect handling, death causes, injuries, and revives.
An external death-screen resource is responsible for presentation and user input. It should read the published state and request supported actions instead of creating a second death system.
Job Configurator Setup
Use the following path:
/jobconfig → Ambulance Jobs → Settings → Death Screen →
General → Integration → Screen Mode → External → Save
Changes saved through the Job Configurator apply live. A resource restart is not required.
Static uses the configured death animation, while
Natural preserves ragdoll physics until the body settles. Changing Death Handling does not enable
an external death screen.Recommended Integration Flow
- Call
getDeathState()when the external resource starts. - Listen to
sky_ambulancejob:deathStateChangedfor complete state snapshots. - Replace the external UI state whenever a new snapshot arrives.
- Use
requestDeathAction()for dispatch, respawn, and AI Medic actions. - Hide the external UI when
state.deadbecomesfalse.
Do not maintain a second authoritative timer or death state. Use remainingSeconds for display and
the availability fields to enable or disable actions.
Client Death State
getDeathState()
Returns a complete snapshot for the local player. The export is registered in both internal and external screen modes.
local state = exports["sky_ambulancejob"]:getDeathState()
Example snapshot:
{
dead = true,
phase = "downed",
screenMode = "external",
handlingMode = "natural",
bodyStable = true,
deathTimestamp = 1786788000,
remainingSeconds = 420,
canRespawn = false,
respawnBlockedReason = "timer_active",
canRequestDispatch = true,
canRequestAiMedic = false,
aiMedicBlockedReason = "timer_active",
aiMedicState = "idle",
aiMedicReason = nil,
cause = {
category = "vehicle",
weaponHash = 0,
attackerServerId = nil
}
}
Death State Fields
| Field | Type | Description |
|---|---|---|
dead | boolean | Whether the player is currently considered dead by Sky Ambulancejob. |
phase | string | Current death lifecycle phase: alive, settling, downed, treatment, or respawning. |
screenMode | string | Configured screen mode: internal or external. |
handlingMode | string | Configured body handling mode: static or natural. |
bodyStable | boolean | Whether the body has reached a stable position. This is especially relevant in natural handling mode. |
deathTimestamp | number | nil | Unix timestamp in seconds at which the current death started. It is nil when no death timestamp is available. |
remainingSeconds | number | Remaining seconds on the authoritative bleed-out timer. Display this value instead of maintaining another timer. |
canRespawn | boolean | Whether the player may currently request an early respawn. |
respawnBlockedReason | string | nil | Machine-readable reason why respawning is unavailable. It is nil when no restriction applies. |
canRequestDispatch | boolean | Whether the player may currently send a dispatch request. |
canRequestAiMedic | boolean | Whether the player may currently request an AI Medic. |
aiMedicBlockedReason | string | nil | Machine-readable reason why the AI Medic cannot currently be requested. |
aiMedicState | string | Current AI Medic lifecycle state. |
aiMedicReason | string | nil | Additional reason associated with the current AI Medic state, such as a failure or cancellation reason. |
cause | table | nil | Detected death-cause information. It is nil when no cause information is available. |
Death Phases
| Phase | Description |
|---|---|
alive | No active death state exists. |
settling | The player died in natural handling mode and the body is still moving. |
downed | The death state is active and normal death-system interactions are available. |
treatment | A medic is currently treating the player. |
respawning | A respawn request was accepted and is currently being processed. |
Respawn Blocked Reasons
| Code | Description |
|---|---|
player_not_dead | The player is not currently dead. |
respawn_in_progress | A respawn is already being processed. |
knockout_active | Early respawn is unavailable during a knockout. |
early_respawn_disabled | Early respawn is disabled in the configuration. |
timer_active | The configured waiting period has not elapsed. |
medics_online | Respawn is blocked because medics are online. |
self_respawn_blocked | Self-respawn is blocked for the current death. |
AI Medic State
The standard AI Medic lifecycle uses these states:
| State | Description |
|---|---|
idle | No AI Medic request is active. |
requesting | A request is being validated. |
dispatched | An AI Medic was dispatched. |
driving | The AI Medic is travelling to the player. |
arrived | The AI Medic reached the player. |
reviving | The AI Medic is performing the revive. |
finished | The AI Medic mission completed. |
failed | The request or mission failed. Read aiMedicReason for additional context. |
cooldown | Another request is temporarily blocked by a cooldown. |
AI Medic Blocked Reasons
| Code | Description |
|---|---|
player_not_dead | The player is not currently dead. |
respawn_in_progress | A respawn is already being processed. |
knockout_active | AI Medic requests are unavailable during a knockout. |
ai_medic_disabled | The AI Medic feature is disabled. |
body_not_stable | The body is still moving in natural handling mode. |
revive_blocked | The current death state prevents an AI Medic revive. |
medics_online | The AI Medic is unavailable because human medics are online. |
already_active | An AI Medic request is already active. |
timer_active | The configured waiting period has not elapsed. |
Death Cause
When available, state.cause contains:
{
category = "vehicle",
weaponHash = 0,
attackerServerId = nil
}
| Field | Type | Description |
|---|---|---|
category | string | nil | Normalized detected death category. |
weaponHash | number | nil | FiveM weapon or damage-source hash associated with the death. |
attackerServerId | number | nil | Server ID of the detected attacker, or nil when no player attacker was identified. |
Pending AI Medic Offer
When a remote AI Medic offer is waiting for the player, the client snapshot additionally contains:
state.aiMedicOffer = {
pending = true,
dispatcherName = "Alex",
remainingSeconds = 25
}
The object is omitted when no offer is pending.
Death State Event
sky_ambulancejob:deathStateChanged
This local client event publishes the same complete snapshot as getDeathState(). Use it for UI
updates instead of polling every frame.
AddEventHandler("sky_ambulancejob:deathStateChanged", function(state)
if not state.dead then
-- Hide the external death screen.
return
end
-- Show or update the external death screen.
-- Display state.remainingSeconds.
-- Use the canRequest* fields to control action buttons.
end)
Call getDeathState() once during resource startup because an external resource can start after the
current death began and therefore may not have seen the first event.
Requesting Death Actions
requestDeathAction(action, payload?)
Requests an action for the local player. Sky Ambulancejob validates the current death state, timers, prices, medic availability, cooldowns, and all other restrictions.
local success, result = exports["sky_ambulancejob"]:requestDeathAction(action, payload)
Supported actions:
| Action | Purpose | Payload |
|---|---|---|
request_dispatch | Send the configured death dispatch. | None |
request_early_respawn | Request the configured early respawn. | Optional { hospitalId = "pillbox" } |
request_ai_medic | Request the configured AI Medic. | None |
respond_ai_medic_offer | Accept or reject a pending remote AI Medic offer. | Required { accepted = true } or { accepted = false } |
Request a Dispatch
local success, result = exports["sky_ambulancejob"]:requestDeathAction("request_dispatch")
Request an Early Respawn
local success, result = exports["sky_ambulancejob"]:requestDeathAction("request_early_respawn", {
hospitalId = "pillbox" -- Optional configured hospital ID
})
Request an AI Medic
local success, result = exports["sky_ambulancejob"]:requestDeathAction("request_ai_medic")
Respond to an AI Medic Offer
local success, result = exports["sky_ambulancejob"]:requestDeathAction("respond_ai_medic_offer", {
accepted = true
})
Set accepted to false to reject the offer.
Action Results
A successful request returns:
true, {
action = "request_dispatch"
}
A rejected request returns:
false, {
code = "timer_active",
message = "The configured waiting time has not elapsed."
}
The code is the machine-readable value intended for program logic. The English message is a
developer diagnostic. External UIs should map the code to their own localized user-facing message.
Possible action error codes include:
invalid_action
invalid_payload
player_not_dead
respawn_in_progress
knockout_active
dispatch_disabled
dispatch_already_sent
early_respawn_disabled
timer_active
medics_online
self_respawn_blocked
ai_medic_disabled
body_not_stable
revive_blocked
already_active
on_cooldown
cooldown_active
no_pending_offer
request_blocked_by_hook
request_failed
payment_failed
not_enough_money
disabled
not_dead
remote_wait
target_offline
Simple Client Death Check
Use isDead() when only a boolean is required:
local dead = exports["sky_ambulancejob"]:isDead()
For an external death screen, getDeathState() is normally preferable because it also provides the
timer, phase, action availability, and blocked reasons.
Server API
getDeathState(playerId)
Returns the server-authoritative death snapshot for a player. It returns nil for an invalid or
offline player.
local state = exports["sky_ambulancejob"]:getDeathState(playerId)
if not state then
-- Invalid player ID or the player is offline.
return
end
isDead(playerId)
Use this export when only a server-side boolean is required:
local dead = exports["sky_ambulancejob"]:isDead(playerId)
revive(playerId, reason?)
Revives a player through the normal server-authoritative cleanup and logging path:
local success = exports["sky_ambulancejob"]:revive(
playerId,
"external_deathscreen"
)
The reason may also be supplied as a table:
local success = exports["sky_ambulancejob"]:revive(playerId, {
reason = "external_deathscreen"
})
revive is intended only for trusted server resources. Never expose an unrestricted client event
that forwards a client-provided player ID to this export.Internal UI Exports
These client exports belong to the bundled internal death-screen UI:
exports["sky_ambulancejob"]:open()
exports["sky_ambulancejob"]:updateTime(seconds)
exports["sky_ambulancejob"]:addTime(seconds)
They must not be used by an external death-screen integration. In external mode they return:
false, {
code = "external_deathscreen_active",
message = "The bundled deathscreen UI is disabled because external mode is active."
}
Read the timer through getDeathState() and request gameplay actions through
requestDeathAction().
Authority and Security
The external death screen must not:
- set the player death state itself;
- maintain a separate authoritative bleed-out timer;
- revive the local player directly from client code;
- trigger undocumented internal server events;
- trust a client-provided player ID; or
- bypass
requestDeathAction()validation.
Sky Ambulancejob remains authoritative for death state, persistence, respawn, payments, dispatch, AI Medic availability, and revive handling.
Support
When opening an integration support request, include the Sky Ambulancejob version, whether the integration runs on the client or server, the requested action, and the returned error code.
Join Discord