RX Scripts Logo
Death System

Configurables

All config & open sourced files included within this script.

Config Files

--[[
BY RX Scripts © rxscripts.xyz
--]]

Config = {}
Config.Locale = 'en'

Config.DownedPlayers = true -- Enable or disable getting downed
Config.RevivingDowned = true -- Enable or disable reviving downed players
Config.ClearInventoryOnDeath = true -- Enable or disable clearing inventory on death
Config.LootDownedInventory = true -- Enable or disable looting downed players
Config.SuicideCommand = "suicide" -- Command for suicide, set to false to disable

Config.DownTime = 20 -- Seconds you are downed

Config.DeathWait = 0 -- Seconds before executing onDeath code (in case u want to do something first after dying)

Config.SurvivingChance = 10 -- 0% - 100% chance to survive a down
Config.HealthAfterRevival = 50 -- 1% - 100% of max health after revival
Config.HealthOnDown = 5 -- 1% - 100% of max health after downed
Config.HealthOnSpawn = 100 -- 1% - 100% of max health after respawning

Config.BedsLimit = 3 -- Limit of beds
Config.BedCooldown = 300 -- Seconds
Config.BedObject = "imp_prop_impexp_campbed_01" -- Object spawning for bed, 'false' to disable
Config.BedSpawnZOffset = 1.0 -- Z offset for bed spawning

Config.PlaceBedBy = {
    command = "placebed", -- '"commandName"' to enable, 'false' to disable
    usableItem = "bed", -- Usable item to place bed (only possible with ESX & QBCore), 'false' to disable
    objectOnGroundProperly = true -- Place bed on ground properly by default, put to false if model bugs (modify coords in server/opensource.lua)
}

Config.RemoveBedBy = {
    command = "pickupbed", -- Command to remove bed when close to a bed, 'false' to disable
}

Config.Revive = {
    requiredItem = {
        enabled = true,
        item = "medikit", -- Item required to revive player
        removeOnUse = true, -- Remove item on use
    },
    command = {
        enabled = true,
        cmd = "revive", -- Command to revive player, 'false' to disable
        adminOnly = true, -- Only admins can revive
    }
    -- command = "revive",
    -- adminOnly = true,
}

Config.DownAnim = {
    dict = "missheist_agency3aig_19",
    anim = "ground_call_help",
}

Config.NpcKillerName = "Zombie"

Config.DefaultSpawns = {
    { label = "Hunting Zone", coords = vector4(-929.0053, 4829.2729, 312.1747, 317.3232) },
    { label = "Safezone B", coords = vector4(628.9008, 630.9257, 128.9125, 111.8532) },
    { label = "Safezone C", coords = vector4(627.4444, 634.0447, 128.9209, 24.2166) },
    { label = "Hospital A", coords = vector4(625.3577, 631.8191, 128.9563, 140.5466) },
    { label = "Hospital B", coords = vector4(628.8401, 627.0576, 128.9131, 222.7354) },
    { label = "Hospital C", coords = vector4(629.9598, 619.1959, 128.9137, 167.13540) },
}

Config.RandomRareSpawns = {
    chance = 10, -- 0% - 100% chance to spawn at a rare location
    locations = {
        vector4(628.6385, 646.9886, 129.1072, 307.6381),
        vector4(624.0039, 637.3432, 128.9113, 170.6805),
    },
}

Config.RandomCommonSpawns = {
    chance = 90, -- 0% - 100% chance to spawn at a common location
    locations = {
        vector4(624.0039, 637.3432, 128.9113, 170.6805),
        vector4(628.6385, 646.9886, 129.1072, 307.6381),
    },
}

Opensource Files

All script-related open source code is contained within these files. Third-party components, including frameworks, inventory systems, and other external code, are separately maintained & open sourced in our fmLib repository.
--[[
BY RX Scripts © rxscripts.xyz
--]]

local exampleCustomBedTable = {
    {
        bedKey = 'bed_1_unique',
        coords = vector3(0.0, 0.0, 0.0),
        heading = 0.0,
    },
    {
        bedKey = 'bed_2_unique',
        coords = vector3(0.0, 0.0, 0.0),
        heading = 0.0,
    },
    {
        bedKey = 'bed_3_unique',
        coords = vector3(0.0, 0.0, 0.0),
        heading = 0.0,
    },
}

function OpenDeathScreen()
    local playerBeds = lib.callback.await('ds:fetchBeds', false, false) -- exampleCustomBedTable

    playerBeds = lib.callback.await('ds:addCooldowns', false, playerBeds)

    local data = {
        beds = playerBeds,
        lastDeathData = LastDeathData,
        spawns = {
            default = Config.DefaultSpawns,
            rare = Config.RandomRareSpawns,
            common = Config.RandomCommonSpawns,
        }
    }

    SendReactMessage('openDeathScreen', json.encode(data))
    SetNuiFocus(true, true)
    DeathScreenOpen = true
end
exports('OpenDeathScreen', OpenDeathScreen)

function InitiateReviveProgressBar()
    return lib.progressBar({
        duration = 3000,
        label = 'Reviving',
        useWhileDead = false,
        canCancel = true,
        disable = {
            move = true,
            car = true,
            combat = true,
        },
        anim = {
            scenario = 'CODE_HUMAN_MEDIC_TEND_TO_DEAD',
        },
        prop = {
            model = 'prop_ld_health_pack',
            bone = 28422,
            pos = vector3(0.0, 0.0, 0.0),
            rot = vector3(0.0, 0.0, 0.0),
        },
    })
end

local function closeInventoryOnNotDowned()
    if Inventory == 'OX' then
        CreateThread(function()
            while OpenedInventory ~= nil do
                if not GetPlayerDowned(OpenedInventory) then
                    exports.ox_inventory:closeInventory()
                    OpenedInventory = nil
                end

                Wait(500)
            end
        end)
    end
end

function OpenInventory(targetNetId)
    OpenedInventory = targetNetId

    if Inventory == 'OX' then
        exports.ox_inventory:openInventory('player', targetNetId)
    end

    closeInventoryOnNotDowned()
end

function Notify(msg, type)
    if Core == 'ESX' then
        CoreObj.ShowNotification(msg, type)
    elseif Core == 'QBCore' then
        CoreObj.Functions.Notify(msg, type)
    end
end

function AddDownedTargets()
    if Target == 'OX' then
        exports.ox_target:addGlobalPlayer({
            {
                label = "Revive",
                name = "revive",
                icon = "fas fa-heartbeat",
                iconColor = "red",
                canInteract = function(entity, distance, coords, name, bone)
                    if not Config.RevivingDowned then return false end
                    if not IsEntityAPed(entity) then return false end
                    if distance > 2.0 then return false end

                    local targetId = NetworkGetPlayerIndexFromPed(entity)
                    local targetNetId = GetPlayerServerId(targetId)

                    return GetPlayerDowned(targetNetId)
                end,
                onSelect = function(data)
                    if not IsEntityAPed(data.entity) then return false end
                    local targetId = NetworkGetPlayerIndexFromPed(data.entity)
                    local targetNetId = GetPlayerServerId(targetId)

                    lib.callback('ds:canRevive', false, function(allowed)
                        if not allowed then return end

                        if InitiateReviveProgressBar() then
                            ClearPedTasksImmediately(PlayerPedId())
                            TriggerServerEvent('ds:revive', targetNetId)
                        end

                    end, targetNetId)
                end,
            },
            {
                label = "Loot Inventory",
                name = "openinv",
                icon = "fas fa-box-open",
                iconColor = "red",
                canInteract = function(entity, distance, coords, name, bone)
                    if not Config.LootDownedInventory then return false end
                    if not IsEntityAPed(entity) then return false end
                    if distance > 2.0 then return false end

                    local targetId = NetworkGetPlayerIndexFromPed(entity)
                    local targetNetId = GetPlayerServerId(targetId)

                    return GetPlayerDowned(targetNetId)
                end,
                onSelect = function(data)
                    if not IsEntityAPed(data.entity) then return false end
                    local targetId = NetworkGetPlayerIndexFromPed(data.entity)
                    local targetNetId = GetPlayerServerId(targetId)

                    OpenInventory(targetNetId)
                end,
            },
        })
    elseif Target == 'QB' then
        exports['qb-target']:AddGlobalPlayer({
            options = {
                {
                    num = 1,
                    icon = "fas fa-heartbeat",
                    label = "Revive",
                    canInteract = function(entity, distance, data)
                        if not Config.RevivingDowned then return false end
                        if not IsEntityAPed(entity) then return false end

                        local targetId = NetworkGetPlayerIndexFromPed(entity)
                        local targetNetId = GetPlayerServerId(targetId)

                        return GetPlayerDowned(targetNetId)
                    end,
                    action = function(entity)
                        if not IsEntityAPed(entity) then return false end
                        local targetId = NetworkGetPlayerIndexFromPed(entity)
                        local targetNetId = GetPlayerServerId(targetId)

                        lib.callback('ds:canRevive', false, function(allowed)
                            if not allowed then return end

                            if InitiateReviveProgressBar() then
                                ClearPedTasksImmediately(PlayerPedId())
                                TriggerServerEvent('ds:revive', targetNetId)
                            end
                        end, targetNetId)
                    end,
                },
                {
                    num = 2,
                    icon = "fas fa-box-open",
                    label = "Loot Inventory",
                    canInteract = function(entity, distance, data)
                        if not Config.LootDownedInventory then return false end
                        if not IsEntityAPed(entity) then return false end

                        local targetId = NetworkGetPlayerIndexFromPed(entity)
                        local targetNetId = GetPlayerServerId(targetId)

                        return GetPlayerDowned(targetNetId)
                    end,
                    action = function(entity)
                        if not IsEntityAPed(entity) then return false end
                        local targetId = NetworkGetPlayerIndexFromPed(entity)
                        local targetNetId = GetPlayerServerId(targetId)

                        OpenInventory(targetNetId)
                    end,
                }
            },
            distance = 2.0,
        })
    end
end

function InitDisableDownedActions(playerNetId)
    CreateThread(function()
        while GetPlayerDowned(playerNetId) do
            DisableAllControlActions(0)
            EnableControlAction(0, 1, true)
            EnableControlAction(0, 2, true)
            EnableControlAction(0, 245, true)
            EnableControlAction(0, 322, true)
            EnableControlAction(0, 249, true)
            EnableControlAction(0, 150, true)
            EnableControlAction(0, 147, true)
            EnableControlAction(0, 149, true)
            EnableControlAction(0, 148, true)
            EnableControlAction(0, 31, true)
            EnableControlAction(0, 30, true)
            EnableControlAction(0, 32, true)
            EnableControlAction(0, 33, true)
            EnableControlAction(0, 34, true)
            EnableControlAction(0, 35, true)
            Wait(0)
        end
    end)
end

function IgnoreDownSystem()
    return false
end

function IgnoreDeathSystem()
    return false
end

function IsPlayerLoggedIn()
    if Core == 'ESX' then
        return CoreObj.GetPlayerData().job ~= nil
    end
end

RegisterNetEvent('QBCore:Client:OnPlayerLoaded', function()
    CheckDeathStatus()
end)