Bodybag Script
Do you want to bring more immersive roleplay to your server, even after the death of a player? This bodybag script might be the addition you are looking for.
Get it here: gamzkystore.com
Support: Discord
Detailed preview: Youtube
Features
- Will work on any framework and only requires a target system to interact with dead players.
- Optional job and/or item requirement before placing a bodybag.
- Uses statebags for seamless synchronization between clients, the script can even be restarted when in use without causing problems.
- Bodybags can be removed as well (this feature can also be disabled).
- Exports and events are available to add or remove bodybags via other scripts, enabling easy integration into your server.
- Highly configurable, bridge functions also enable you to edit the most important code.
Resmon: 0.00ms
The code snippets below are accessible in the encrypted version:
Config
Config = {}
-- The distance the player has to be to interact with the target
Config.InteractDistance = 2.0
-- A saveguard such that people cannot bodybag a target that is to far away due to desync
Config.MaximumBodybagDistance = 25.0
-- The prop used as a bodybag
Config.BodybagModel = 'xm_prop_body_bag'
-- If the bodybag should be frozen in place
Config.FreezeBodybag = true
-- If the players can also remove the bodybag
Config.CanRemoveBodybag = true
-- The job that is required to put the body in a bodybag, or set Enabled to false to not require a job
Config.RequiredJob = {
Enabled = true,
Name = 'police',
}
-- The item that is required to put the body in a bodybag, or set Enabled to false to not require an item
Config.RequiredItem = {
Enabled = true,
ItemName = 'bodybag',
ItemAmount = 1,
}
-- The animations to play when putting a player in a bodybag or removing a bodybag
Config.Animations = {
['put_in_bodybag'] = {
Dict = 'missexile3', -- Replace to '' to not play an animation
Name = 'ex03_dingy_search_case_base_michael',
Time = 2000,
Blend = 8.0,
Flag = 1,
},
['remove_bodybag'] = {
Dict = 'missexile3', -- Replace to '' to not play an animation
Name = 'ex03_dingy_search_case_base_michael',
Time = 2000,
Blend = 8.0,
Flag = 1,
},
}
-- Language configuration
Config.Locales = {
['put_in_bodybag'] = 'Put in bodybag',
['remove_bodybag'] = 'Remove bodybag',
['missing_required_job'] = 'You do not have the required job',
['missing_required_item'] = 'You do not have the required item',
}
-- Adds some prints for debugging
Config.Debug = false
Accessible Client Bridge Functions
Functions = {}
-- A function that checks if the player can interact with the target
Functions.CanInteract = function()
local ped = PlayerPedId()
local isPedInVehicle = IsPedInAnyVehicle(ped, false)
local isPedDead = IsPedDeadOrDying(ped, true)
if (isPedInVehicle or isPedDead) then
return false
end
return true
end
-- A function that checks if the target can be placed in a bodybag, by default returns only true if the target is dead
Functions.CanTargetBePlacedInBodybag = function(entity)
local isPedDead = IsPedDeadOrDying(entity, true)
return isPedDead
end
-- This function is triggered after the bodybag is created, you can execute any code you want here
Functions.OnBodybagCreated = function(bodybagEntity)
local ped = PlayerPedId()
SetEntityVisible(ped, false, 0)
SetEntityCollision(ped, false, true)
FreezeEntityPosition(ped, true)
end
-- This function is triggered after the bodybag is removed, you can execute any code you want here
Functions.OnBodybagRemoved = function()
local ped = PlayerPedId()
SetEntityCollision(ped, true, true)
SetEntityVisible(ped, true, 0)
FreezeEntityPosition(ped, false)
end
Functions.AddGlobalTargetOptions = function()
-- For the people ussing ox-target
if (GetResourceState('ox_target') == 'started') then
exports.ox_target:addGlobalPlayer({
{
icon = 'fas fa-briefcase',
label = Config.Locales['put_in_bodybag'],
distance = Config.InteractDistance,
groups = Config.RequiredJob.Enabled and Config.RequiredJob.Name or nil,
items = Config.RequiredItem.Enabled and Config.RequiredItem.ItemName or nil,
onSelect = function(data)
AttemptUseBodybag(data.entity)
end,
canInteract = function(entity)
return (Functions.CanInteract() and IsTargetValid(entity) and Functions.CanTargetBePlacedInBodybag(entity) and not IsTargetEntityInBodybag(entity))
end
},
})
return
end
-- For the people using qb-target
if (GetResourceState('qb-target') == 'started') then
exports['qb-target']:AddGlobalPlayer({
options = {
{
icon = 'fas fa-briefcase',
label = Config.Locales['put_in_bodybag'],
job = Config.RequiredJob.Enabled and Config.RequiredJob.Name or nil,
item = Config.RequiredItem.Enabled and Config.RequiredItem.ItemName or nil,
action = function(entity)
AttemptUseBodybag(entity)
end,
canInteract = function(entity)
return (Functions.CanInteract() and IsTargetValid(entity) and Functions.CanTargetBePlacedInBodybag(entity) and not IsTargetEntityInBodybag(entity))
end,
},
},
distance = Config.InteractDistance,
})
return
end
print('gs_bodybag: [ERROR] No target interaction defined')
end
Functions.AddRemoveBodybagOption = function(bodybagEntityNetIds)
-- For the people ussing ox-target
if (GetResourceState('ox_target') == 'started') then
exports.ox_target:addEntity(bodybagEntityNetIds, {
{
icon = 'fas fa-trash-can-arrow-up',
label = Config.Locales['remove_bodybag'],
distance = Config.InteractDistance,
groups = Config.RequiredJob.Enabled and Config.RequiredJob.Name or nil,
onSelect = function(data)
AttemptRemoveBodybag(data.entity)
end,
canInteract = function()
return (Config.CanRemoveBodybag and Functions.CanInteract())
end
},
})
return
end
-- For the people ussing qb-target
if (GetResourceState('qb-target') == 'started') then
exports['qb-target']:AddTargetEntity(bodybagEntityNetIds, {
options = {
{
icon = 'fas fa-trash-can-arrow-up',
label = Config.Locales['remove_bodybag'],
job = Config.RequiredJob.Enabled and Config.RequiredJob.Name or nil,
action = function(entity)
AttemptRemoveBodybag(entity)
end,
canInteract = function()
return (Config.CanRemoveBodybag and Functions.CanInteract())
end,
},
},
distance = Config.InteractDistance,
})
return
end
print('gs_bodybag: [ERROR] No target interaction defined')
end
Accessible Server Bridge Functions
local ESX = nil
local QBCore = nil
-- Select the correct framework
CreateThread(function()
if (GetResourceState('es_extended') == 'started') then
ESX = exports['es_extended']:getSharedObject()
elseif (GetResourceState('qb-core') == 'started') then
QBCore = exports['qb-core']:GetCoreObject()
end
end)
Functions = {}
Functions.CanSourcePlaceTargetInBodybag = function(source, target)
-- You can add any additional checks here, to prevent abuse if you wish
return true
end
-- Check if the player has the required job
Functions.DoesPlayerHaveRequiredJob = function(src)
if (not Config.RequiredJob.Enabled) then
return true
end
-- Case for ESX
if (ESX ~= nil) then
local xPlayer = ESX.GetPlayerFromId(src)
if xPlayer.job.name == Config.RequiredJob.Name then
return true
end
TriggerClientEvent('esx:showNotification', src, Config.Locales['missing_required_job'], 'error')
-- Case for QBCore
elseif (QBCore ~= nil) then
local Player = QBCore.Functions.GetPlayer(src)
if Player.PlayerData.job.name == Config.RequiredJob.Name then
return true
end
TriggerClientEvent('QBCore:Notify', src, Config.Locales['missing_required_job'], 'error')
end
return false
end
-- Check if the player has the required item and remove it
Functions.UseBodybagItem = function(src)
if (not Config.RequiredItem.Enabled) then
return true
end
-- Case for ESX
if (ESX ~= nil) then
local xPlayer = ESX.GetPlayerFromId(src)
if xPlayer.getInventoryItem(Config.RequiredItem.ItemName).count >= Config.RequiredItem.ItemAmount then
xPlayer.removeInventoryItem(Config.RequiredItem.ItemName, Config.RequiredItem.ItemAmount)
return true
end
TriggerClientEvent('esx:showNotification', src, Config.Locales['missing_required_item'], 'error')
-- Case for QBCore
elseif (QBCore ~= nil) then
local Player = QBCore.Functions.GetPlayer(src)
if Player.Functions.GetItemByName(Config.RequiredItem.ItemName).amount >= Config.RequiredItem.ItemAmount then
Player.Functions.RemoveItem(Config.RequiredItem.ItemName, Config.RequiredItem.ItemAmount)
return true
end
TriggerClientEvent('QBCore:Notify', src, Config.Locales['missing_required_item'], 'error')
end
return false
end
Functions.ReturnBodybagItem = function(src)
if (not Config.RequiredItem.Enabled) then
return
end
-- Case for ESX
if (ESX ~= nil) then
local xPlayer = ESX.GetPlayerFromId(src)
xPlayer.addInventoryItem(Config.RequiredItem.ItemName, Config.RequiredItem.ItemAmount)
-- Case for QBCore
elseif (QBCore ~= nil) then
local Player = QBCore.Functions.GetPlayer(src)
Player.Functions.AddItem(Config.RequiredItem.ItemName, Config.RequiredItem.ItemAmount)
end
end
-- The exports below can be triggered from the SERVER which will add or remove a bodybag to/from a specific player (this skips the check for the correct job and/or item)
exports('AddBodybag', AddBodybag) -- Call through exports.gs_bodybag:AddBodybag(playerServerId)
exports('RemoveBodybag', RemoveBodybag) -- Call through exports.gs_bodybag:RemoveBodybag(playerServerId)
-- The events below can be triggered from the CLIENT which will add or remove a bodybag to/from to the source of the event (this skips the check for the correct job and/or item)
RegisterNetEvent('gs_bodybag:AddBodybagForPlayer', function()
local src = source
AddBodybag(src)
end)
RegisterNetEvent('gs_bodybag:RemoveBodybagForPlayer', function()
local src = source
RemoveBodybag(src)
end)
Code is accessible | No, but there is an unencrypted version |
Subscription-based | No |
Lines (approximately) | ~600 |
Requirements | Only a target script (i.e. ox-target or qb-target) |
Support | Yes |