mirror of
https://github.com/esx-framework/esx_core.git
synced 2026-08-29 09:18:53 +00:00
Feat: ESX_Ambulancejob: Allow Camera movement while dead
This commit is contained in:
@@ -4,375 +4,478 @@ isDead, isSearched, medic = false, false, 0
|
||||
|
||||
RegisterNetEvent('esx:playerLoaded')
|
||||
AddEventHandler('esx:playerLoaded', function(xPlayer)
|
||||
ESX.PlayerLoaded = true
|
||||
ESX.PlayerLoaded = true
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx:onPlayerLogout')
|
||||
AddEventHandler('esx:onPlayerLogout', function()
|
||||
ESX.PlayerLoaded = false
|
||||
firstSpawn = true
|
||||
ESX.PlayerLoaded = false
|
||||
firstSpawn = true
|
||||
end)
|
||||
|
||||
AddEventHandler('esx:onPlayerSpawn', function()
|
||||
isDead = false
|
||||
isDead = false
|
||||
ClearTimecycleModifier()
|
||||
SetPedMotionBlur(PlayerPedId(), false)
|
||||
ClearExtraTimecycleModifier()
|
||||
EndDeathCam()
|
||||
if firstSpawn then
|
||||
firstSpawn = false
|
||||
|
||||
if firstSpawn then
|
||||
firstSpawn = false
|
||||
if Config.SaveDeathStatus then
|
||||
while not ESX.PlayerLoaded do
|
||||
Wait(1000)
|
||||
end
|
||||
|
||||
if Config.SaveDeathStatus then
|
||||
while not ESX.PlayerLoaded do
|
||||
Wait(1000)
|
||||
end
|
||||
|
||||
ESX.TriggerServerCallback('esx_ambulancejob:getDeathStatus', function(shouldDie)
|
||||
if shouldDie then
|
||||
Wait(1000)
|
||||
SetEntityHealth(PlayerPedId(), 0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
ESX.TriggerServerCallback('esx_ambulancejob:getDeathStatus', function(shouldDie)
|
||||
if shouldDie then
|
||||
Wait(1000)
|
||||
SetEntityHealth(PlayerPedId(), 0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
-- Create blips
|
||||
CreateThread(function()
|
||||
for k,v in pairs(Config.Hospitals) do
|
||||
local blip = AddBlipForCoord(v.Blip.coords)
|
||||
for k, v in pairs(Config.Hospitals) do
|
||||
local blip = AddBlipForCoord(v.Blip.coords)
|
||||
|
||||
SetBlipSprite(blip, v.Blip.sprite)
|
||||
SetBlipScale(blip, v.Blip.scale)
|
||||
SetBlipColour(blip, v.Blip.color)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
SetBlipSprite(blip, v.Blip.sprite)
|
||||
SetBlipScale(blip, v.Blip.scale)
|
||||
SetBlipColour(blip, v.Blip.color)
|
||||
SetBlipAsShortRange(blip, true)
|
||||
|
||||
BeginTextCommandSetBlipName('STRING')
|
||||
AddTextComponentSubstringPlayerName(_U('blip_hospital'))
|
||||
EndTextCommandSetBlipName(blip)
|
||||
end
|
||||
BeginTextCommandSetBlipName('STRING')
|
||||
AddTextComponentSubstringPlayerName(_U('blip_hospital'))
|
||||
EndTextCommandSetBlipName(blip)
|
||||
end
|
||||
|
||||
while true do
|
||||
local Sleep = 1500
|
||||
|
||||
if isDead then
|
||||
Sleep = 0
|
||||
DisableAllControlActions(0)
|
||||
EnableControlAction(0, 47, true) -- G
|
||||
EnableControlAction(0, 245, true) -- T
|
||||
EnableControlAction(0, 38, true) -- E
|
||||
while true do
|
||||
local Sleep = 1500
|
||||
|
||||
if isSearched then
|
||||
local playerPed = PlayerPedId()
|
||||
local ped = GetPlayerPed(GetPlayerFromServerId(medic))
|
||||
isSearched = false
|
||||
|
||||
AttachEntityToEntity(playerPed, ped, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true)
|
||||
Wait(1000)
|
||||
DetachEntity(playerPed, true, false)
|
||||
ClearPedTasksImmediately(playerPed)
|
||||
end
|
||||
end
|
||||
if isDead then
|
||||
Sleep = 0
|
||||
DisableAllControlActions(0)
|
||||
EnableControlAction(0, 47, true) -- G
|
||||
EnableControlAction(0, 245, true) -- T
|
||||
EnableControlAction(0, 38, true) -- E
|
||||
|
||||
Wait(Sleep)
|
||||
end
|
||||
ProcessCamControls()
|
||||
if isSearched then
|
||||
local playerPed = PlayerPedId()
|
||||
local ped = GetPlayerPed(GetPlayerFromServerId(medic))
|
||||
isSearched = false
|
||||
|
||||
AttachEntityToEntity(playerPed, ped, 11816, 0.54, 0.54, 0.0, 0.0, 0.0, 0.0, false, false, false, false, 2, true)
|
||||
Wait(1000)
|
||||
DetachEntity(playerPed, true, false)
|
||||
ClearPedTasksImmediately(playerPed)
|
||||
end
|
||||
end
|
||||
|
||||
Wait(Sleep)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx_ambulancejob:clsearch')
|
||||
AddEventHandler('esx_ambulancejob:clsearch', function(medicId)
|
||||
local playerPed = PlayerPedId()
|
||||
local playerPed = PlayerPedId()
|
||||
|
||||
if isDead then
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
local playersInArea = ESX.Game.GetPlayersInArea(coords, 50.0)
|
||||
if isDead then
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
local playersInArea = ESX.Game.GetPlayersInArea(coords, 50.0)
|
||||
|
||||
for i=1, #playersInArea, 1 do
|
||||
local player = playersInArea[i]
|
||||
if player == GetPlayerFromServerId(medicId) then
|
||||
medic = tonumber(medicId)
|
||||
isSearched = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
for i = 1, #playersInArea, 1 do
|
||||
local player = playersInArea[i]
|
||||
if player == GetPlayerFromServerId(medicId) then
|
||||
medic = tonumber(medicId)
|
||||
isSearched = true
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
function OnPlayerDeath()
|
||||
isDead = true
|
||||
ESX.UI.Menu.CloseAll()
|
||||
ESX.HideUI()
|
||||
TriggerServerEvent('esx_ambulancejob:setDeathStatus', true)
|
||||
StartDeathTimer()
|
||||
StartDistressSignal()
|
||||
isDead = true
|
||||
ESX.UI.Menu.CloseAll()
|
||||
ClearTimecycleModifier()
|
||||
SetTimecycleModifier("REDMIST_blend")
|
||||
SetTimecycleModifierStrength(0.7)
|
||||
SetExtraTimecycleModifier("fp_vig_red")
|
||||
SetExtraTimecycleModifierStrength(1.0)
|
||||
SetPedMotionBlur(PlayerPedId(), true)
|
||||
TriggerServerEvent('esx_ambulancejob:setDeathStatus', true)
|
||||
StartDeathTimer()
|
||||
StartDeathCam()
|
||||
StartDistressSignal()
|
||||
end
|
||||
|
||||
RegisterNetEvent('esx_ambulancejob:useItem')
|
||||
AddEventHandler('esx_ambulancejob:useItem', function(itemName)
|
||||
ESX.UI.Menu.CloseAll()
|
||||
ESX.UI.Menu.CloseAll()
|
||||
|
||||
if itemName == 'medikit' then
|
||||
local lib, anim = 'anim@heists@narcotics@funding@gang_idle', 'gang_chatting_idle01' -- TODO better animations
|
||||
local playerPed = PlayerPedId()
|
||||
if itemName == 'medikit' then
|
||||
local lib, anim = 'anim@heists@narcotics@funding@gang_idle', 'gang_chatting_idle01' -- TODO better animations
|
||||
local playerPed = PlayerPedId()
|
||||
|
||||
ESX.Streaming.RequestAnimDict(lib, function()
|
||||
TaskPlayAnim(playerPed, lib, anim, 8.0, -8.0, -1, 0, 0, false, false, false)
|
||||
RemoveAnimDict(lib)
|
||||
ESX.Streaming.RequestAnimDict(lib, function()
|
||||
TaskPlayAnim(playerPed, lib, anim, 8.0, -8.0, -1, 0, 0, false, false, false)
|
||||
RemoveAnimDict(lib)
|
||||
|
||||
Wait(500)
|
||||
while IsEntityPlayingAnim(playerPed, lib, anim, 3) do
|
||||
Wait(0)
|
||||
DisableAllControlActions(0)
|
||||
end
|
||||
Wait(500)
|
||||
while IsEntityPlayingAnim(playerPed, lib, anim, 3) do
|
||||
Wait(0)
|
||||
DisableAllControlActions(0)
|
||||
end
|
||||
|
||||
TriggerEvent('esx_ambulancejob:heal', 'big', true)
|
||||
ESX.ShowNotification(_U('used_medikit'))
|
||||
end)
|
||||
TriggerEvent('esx_ambulancejob:heal', 'big', true)
|
||||
ESX.ShowNotification(_U('used_medikit'))
|
||||
end)
|
||||
|
||||
elseif itemName == 'bandage' then
|
||||
local lib, anim = 'anim@heists@narcotics@funding@gang_idle', 'gang_chatting_idle01' -- TODO better animations
|
||||
local playerPed = PlayerPedId()
|
||||
elseif itemName == 'bandage' then
|
||||
local lib, anim = 'anim@heists@narcotics@funding@gang_idle', 'gang_chatting_idle01' -- TODO better animations
|
||||
local playerPed = PlayerPedId()
|
||||
|
||||
ESX.Streaming.RequestAnimDict(lib, function()
|
||||
TaskPlayAnim(playerPed, lib, anim, 8.0, -8.0, -1, 0, 0, false, false, false)
|
||||
RemoveAnimDict(lib)
|
||||
ESX.Streaming.RequestAnimDict(lib, function()
|
||||
TaskPlayAnim(playerPed, lib, anim, 8.0, -8.0, -1, 0, 0, false, false, false)
|
||||
RemoveAnimDict(lib)
|
||||
|
||||
Wait(500)
|
||||
while IsEntityPlayingAnim(playerPed, lib, anim, 3) do
|
||||
Wait(0)
|
||||
DisableAllControlActions(0)
|
||||
end
|
||||
Wait(500)
|
||||
while IsEntityPlayingAnim(playerPed, lib, anim, 3) do
|
||||
Wait(0)
|
||||
DisableAllControlActions(0)
|
||||
end
|
||||
|
||||
TriggerEvent('esx_ambulancejob:heal', 'small', true)
|
||||
ESX.ShowNotification(_U('used_bandage'))
|
||||
end)
|
||||
end
|
||||
TriggerEvent('esx_ambulancejob:heal', 'small', true)
|
||||
ESX.ShowNotification(_U('used_bandage'))
|
||||
end)
|
||||
end
|
||||
end)
|
||||
|
||||
function StartDistressSignal()
|
||||
CreateThread(function()
|
||||
local timer = Config.BleedoutTimer
|
||||
CreateThread(function()
|
||||
local timer = Config.BleedoutTimer
|
||||
|
||||
while timer > 0 and isDead do
|
||||
Wait(0)
|
||||
timer = timer - 30
|
||||
while timer > 0 and isDead do
|
||||
Wait(0)
|
||||
timer = timer - 30
|
||||
|
||||
SetTextFont(4)
|
||||
SetTextScale(0.5, 0.5)
|
||||
SetTextColour(200, 50, 50, 255)
|
||||
SetTextDropshadow(0.1, 3, 27, 27 , 255)
|
||||
BeginTextCommandDisplayText('STRING')
|
||||
AddTextComponentSubstringPlayerName(_U('distress_send'))
|
||||
EndTextCommandDisplayText(0.43, 0.77)
|
||||
SetTextFont(4)
|
||||
SetTextScale(0.5, 0.5)
|
||||
SetTextColour(200, 50, 50, 255)
|
||||
SetTextDropshadow(0.1, 3, 27, 27, 255)
|
||||
BeginTextCommandDisplayText('STRING')
|
||||
AddTextComponentSubstringPlayerName(_U('distress_send'))
|
||||
EndTextCommandDisplayText(0.43, 0.77)
|
||||
|
||||
if IsControlJustReleased(0, 47) then
|
||||
SendDistressSignal()
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
if IsControlJustReleased(0, 47) then
|
||||
SendDistressSignal()
|
||||
break
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function SendDistressSignal()
|
||||
local playerPed = PlayerPedId()
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
local playerPed = PlayerPedId()
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
|
||||
ESX.ShowNotification(_U('distress_sent'))
|
||||
TriggerServerEvent('esx_ambulancejob:onPlayerDistress')
|
||||
ESX.ShowNotification(_U('distress_sent'))
|
||||
TriggerServerEvent('esx_ambulancejob:onPlayerDistress')
|
||||
end
|
||||
|
||||
function DrawGenericTextThisFrame()
|
||||
SetTextFont(4)
|
||||
SetTextScale(0.0, 0.5)
|
||||
SetTextColour(255, 255, 255, 255)
|
||||
SetTextDropshadow(0, 0, 0, 0, 255)
|
||||
SetTextDropShadow()
|
||||
SetTextOutline()
|
||||
SetTextCentre(true)
|
||||
SetTextFont(4)
|
||||
SetTextScale(0.0, 0.5)
|
||||
SetTextColour(255, 255, 255, 255)
|
||||
SetTextDropshadow(0, 0, 0, 0, 255)
|
||||
SetTextDropShadow()
|
||||
SetTextOutline()
|
||||
SetTextCentre(true)
|
||||
end
|
||||
|
||||
function secondsToClock(seconds)
|
||||
local seconds, hours, mins, secs = tonumber(seconds), 0, 0, 0
|
||||
local seconds, hours, mins, secs = tonumber(seconds), 0, 0, 0
|
||||
|
||||
if seconds <= 0 then
|
||||
return 0, 0
|
||||
else
|
||||
local hours = string.format('%02.f', math.floor(seconds / 3600))
|
||||
local mins = string.format('%02.f', math.floor(seconds / 60 - (hours * 60)))
|
||||
local secs = string.format('%02.f', math.floor(seconds - hours * 3600 - mins * 60))
|
||||
if seconds <= 0 then
|
||||
return 0, 0
|
||||
else
|
||||
local hours = string.format('%02.f', math.floor(seconds / 3600))
|
||||
local mins = string.format('%02.f', math.floor(seconds / 60 - (hours * 60)))
|
||||
local secs = string.format('%02.f', math.floor(seconds - hours * 3600 - mins * 60))
|
||||
|
||||
return mins, secs
|
||||
end
|
||||
return mins, secs
|
||||
end
|
||||
end
|
||||
|
||||
function StartDeathTimer()
|
||||
local canPayFine = false
|
||||
local canPayFine = false
|
||||
|
||||
if Config.EarlyRespawnFine then
|
||||
ESX.TriggerServerCallback('esx_ambulancejob:checkBalance', function(canPay)
|
||||
canPayFine = canPay
|
||||
end)
|
||||
end
|
||||
if Config.EarlyRespawnFine then
|
||||
ESX.TriggerServerCallback('esx_ambulancejob:checkBalance', function(canPay)
|
||||
canPayFine = canPay
|
||||
end)
|
||||
end
|
||||
|
||||
local earlySpawnTimer = ESX.Math.Round(Config.EarlyRespawnTimer / 1000)
|
||||
local bleedoutTimer = ESX.Math.Round(Config.BleedoutTimer / 1000)
|
||||
local earlySpawnTimer = ESX.Math.Round(Config.EarlyRespawnTimer / 1000)
|
||||
local bleedoutTimer = ESX.Math.Round(Config.BleedoutTimer / 1000)
|
||||
|
||||
CreateThread(function()
|
||||
-- early respawn timer
|
||||
while earlySpawnTimer > 0 and isDead do
|
||||
Wait(1000)
|
||||
CreateThread(function()
|
||||
-- early respawn timer
|
||||
while earlySpawnTimer > 0 and isDead do
|
||||
Wait(1000)
|
||||
|
||||
if earlySpawnTimer > 0 then
|
||||
earlySpawnTimer = earlySpawnTimer - 1
|
||||
end
|
||||
end
|
||||
if earlySpawnTimer > 0 then
|
||||
earlySpawnTimer = earlySpawnTimer - 1
|
||||
end
|
||||
end
|
||||
|
||||
-- bleedout timer
|
||||
while bleedoutTimer > 0 and isDead do
|
||||
Wait(1000)
|
||||
-- bleedout timer
|
||||
while bleedoutTimer > 0 and isDead do
|
||||
Wait(1000)
|
||||
|
||||
if bleedoutTimer > 0 then
|
||||
bleedoutTimer = bleedoutTimer - 1
|
||||
end
|
||||
end
|
||||
end)
|
||||
if bleedoutTimer > 0 then
|
||||
bleedoutTimer = bleedoutTimer - 1
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
CreateThread(function()
|
||||
local text, timeHeld
|
||||
CreateThread(function()
|
||||
local text, timeHeld
|
||||
|
||||
-- early respawn timer
|
||||
while earlySpawnTimer > 0 and isDead do
|
||||
Wait(0)
|
||||
text = _U('respawn_available_in', secondsToClock(earlySpawnTimer))
|
||||
-- early respawn timer
|
||||
while earlySpawnTimer > 0 and isDead do
|
||||
Wait(0)
|
||||
text = _U('respawn_available_in', secondsToClock(earlySpawnTimer))
|
||||
|
||||
DrawGenericTextThisFrame()
|
||||
BeginTextCommandDisplayText('STRING')
|
||||
AddTextComponentSubstringPlayerName(text)
|
||||
EndTextCommandDisplayText(0.5, 0.8)
|
||||
end
|
||||
DrawGenericTextThisFrame()
|
||||
BeginTextCommandDisplayText('STRING')
|
||||
AddTextComponentSubstringPlayerName(text)
|
||||
EndTextCommandDisplayText(0.5, 0.8)
|
||||
end
|
||||
|
||||
-- bleedout timer
|
||||
while bleedoutTimer > 0 and isDead do
|
||||
Wait(0)
|
||||
text = _U('respawn_bleedout_in', secondsToClock(bleedoutTimer))
|
||||
-- bleedout timer
|
||||
while bleedoutTimer > 0 and isDead do
|
||||
Wait(0)
|
||||
text = _U('respawn_bleedout_in', secondsToClock(bleedoutTimer))
|
||||
|
||||
if not Config.EarlyRespawnFine then
|
||||
text = text .. _U('respawn_bleedout_prompt')
|
||||
if not Config.EarlyRespawnFine then
|
||||
text = text .. _U('respawn_bleedout_prompt')
|
||||
|
||||
if IsControlPressed(0, 38) and timeHeld > 120 then
|
||||
RemoveItemsAfterRPDeath()
|
||||
break
|
||||
end
|
||||
elseif Config.EarlyRespawnFine and canPayFine then
|
||||
text = text .. _U('respawn_bleedout_fine', ESX.Math.GroupDigits(Config.EarlyRespawnFineAmount))
|
||||
if IsControlPressed(0, 38) and timeHeld > 120 then
|
||||
RemoveItemsAfterRPDeath()
|
||||
break
|
||||
end
|
||||
elseif Config.EarlyRespawnFine and canPayFine then
|
||||
text = text .. _U('respawn_bleedout_fine', ESX.Math.GroupDigits(Config.EarlyRespawnFineAmount))
|
||||
|
||||
if IsControlPressed(0, 38) and timeHeld > 120 then
|
||||
TriggerServerEvent('esx_ambulancejob:payFine')
|
||||
RemoveItemsAfterRPDeath()
|
||||
break
|
||||
end
|
||||
end
|
||||
if IsControlPressed(0, 38) and timeHeld > 120 then
|
||||
TriggerServerEvent('esx_ambulancejob:payFine')
|
||||
RemoveItemsAfterRPDeath()
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if IsControlPressed(0, 38) then
|
||||
timeHeld += 1
|
||||
else
|
||||
timeHeld = 0
|
||||
end
|
||||
if IsControlPressed(0, 38) then
|
||||
timeHeld += 1
|
||||
else
|
||||
timeHeld = 0
|
||||
end
|
||||
|
||||
DrawGenericTextThisFrame()
|
||||
DrawGenericTextThisFrame()
|
||||
|
||||
BeginTextCommandDisplayText('STRING')
|
||||
AddTextComponentSubstringPlayerName(text)
|
||||
EndTextCommandDisplayText(0.5, 0.8)
|
||||
end
|
||||
BeginTextCommandDisplayText('STRING')
|
||||
AddTextComponentSubstringPlayerName(text)
|
||||
EndTextCommandDisplayText(0.5, 0.8)
|
||||
end
|
||||
|
||||
if bleedoutTimer < 1 and isDead then
|
||||
RemoveItemsAfterRPDeath()
|
||||
end
|
||||
end)
|
||||
if bleedoutTimer < 1 and isDead then
|
||||
RemoveItemsAfterRPDeath()
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function GetClosestRespawnPoint()
|
||||
local PlyCoords = GetEntityCoords(PlayerPedId())
|
||||
local ClosestDist, ClosestHospital, ClosestCoord = 10000, {}, nil
|
||||
local PlyCoords = GetEntityCoords(PlayerPedId())
|
||||
local ClosestDist, ClosestHospital, ClosestCoord = 10000, {}, nil
|
||||
|
||||
for k,v in pairs(Config.RespawnPoints) do
|
||||
local Distance = #(PlyCoords - vector3(v.coords.x, v.coords.y, v.coords.z))
|
||||
if Distance <= ClosestDist then
|
||||
ClosestDist = Distance
|
||||
ClosestHospital = v
|
||||
ClosestCoord = vector3(v.coords.x, v.coords.y, v.coords.z)
|
||||
end
|
||||
end
|
||||
for k, v in pairs(Config.RespawnPoints) do
|
||||
local Distance = #(PlyCoords - vector3(v.coords.x, v.coords.y, v.coords.z))
|
||||
if Distance <= ClosestDist then
|
||||
ClosestDist = Distance
|
||||
ClosestHospital = v
|
||||
ClosestCoord = vector3(v.coords.x, v.coords.y, v.coords.z)
|
||||
end
|
||||
end
|
||||
|
||||
return ClosestCoord, ClosestHospital
|
||||
return ClosestCoord, ClosestHospital
|
||||
end
|
||||
|
||||
function RemoveItemsAfterRPDeath()
|
||||
TriggerServerEvent('esx_ambulancejob:setDeathStatus', false)
|
||||
TriggerServerEvent('esx_ambulancejob:setDeathStatus', false)
|
||||
|
||||
CreateThread(function()
|
||||
ESX.TriggerServerCallback('esx_ambulancejob:removeItemsAfterRPDeath', function()
|
||||
local RespawnCoords, ClosestHospital = GetClosestRespawnPoint()
|
||||
|
||||
ESX.SetPlayerData('loadout', {})
|
||||
CreateThread(function()
|
||||
ESX.TriggerServerCallback('esx_ambulancejob:removeItemsAfterRPDeath', function()
|
||||
local RespawnCoords, ClosestHospital = GetClosestRespawnPoint()
|
||||
|
||||
DoScreenFadeOut(800)
|
||||
RespawnPed(PlayerPedId(), RespawnCoords, ClosestHospital.heading)
|
||||
while not IsScreenFadedOut() do
|
||||
Wait(0)
|
||||
end
|
||||
DoScreenFadeIn(800)
|
||||
end)
|
||||
end)
|
||||
ESX.SetPlayerData('loadout', {})
|
||||
|
||||
DoScreenFadeOut(800)
|
||||
RespawnPed(PlayerPedId(), RespawnCoords, ClosestHospital.heading)
|
||||
while not IsScreenFadedOut() do
|
||||
Wait(0)
|
||||
end
|
||||
DoScreenFadeIn(800)
|
||||
end)
|
||||
end)
|
||||
end
|
||||
|
||||
function RespawnPed(ped, coords, heading)
|
||||
SetEntityCoordsNoOffset(ped, coords.x, coords.y, coords.z, false, false, false)
|
||||
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, heading, true, false)
|
||||
SetPlayerInvincible(ped, false)
|
||||
ClearPedBloodDamage(ped)
|
||||
SetEntityCoordsNoOffset(ped, coords.x, coords.y, coords.z, false, false, false)
|
||||
NetworkResurrectLocalPlayer(coords.x, coords.y, coords.z, heading, true, false)
|
||||
SetPlayerInvincible(ped, false)
|
||||
ClearPedBloodDamage(ped)
|
||||
|
||||
TriggerServerEvent('esx:onPlayerSpawn')
|
||||
TriggerEvent('esx:onPlayerSpawn')
|
||||
TriggerEvent('playerSpawned') -- compatibility with old scripts, will be removed soon
|
||||
TriggerServerEvent('esx:onPlayerSpawn')
|
||||
TriggerEvent('esx:onPlayerSpawn')
|
||||
TriggerEvent('playerSpawned') -- compatibility with old scripts, will be removed soon
|
||||
end
|
||||
|
||||
RegisterNetEvent('esx_phone:loaded')
|
||||
AddEventHandler('esx_phone:loaded', function(phoneNumber, contacts)
|
||||
local specialContact = {
|
||||
name = 'Ambulance',
|
||||
number = 'ambulance',
|
||||
base64Icon = 'data:image/png;base64,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'
|
||||
}
|
||||
local specialContact = {name = 'Ambulance', number = 'ambulance',
|
||||
base64Icon = 'data:image/png;base64,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'}
|
||||
|
||||
TriggerEvent('esx_phone:addSpecialContact', specialContact.name, specialContact.number, specialContact.base64Icon)
|
||||
TriggerEvent('esx_phone:addSpecialContact', specialContact.name, specialContact.number, specialContact.base64Icon)
|
||||
end)
|
||||
|
||||
AddEventHandler('esx:onPlayerDeath', function(data)
|
||||
OnPlayerDeath()
|
||||
OnPlayerDeath()
|
||||
end)
|
||||
|
||||
RegisterNetEvent('esx_ambulancejob:revive')
|
||||
AddEventHandler('esx_ambulancejob:revive', function()
|
||||
local playerPed = PlayerPedId()
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
TriggerServerEvent('esx_ambulancejob:setDeathStatus', false)
|
||||
|
||||
DoScreenFadeOut(800)
|
||||
local playerPed = PlayerPedId()
|
||||
local coords = GetEntityCoords(playerPed)
|
||||
TriggerServerEvent('esx_ambulancejob:setDeathStatus', false)
|
||||
|
||||
while not IsScreenFadedOut() do
|
||||
Wait(50)
|
||||
end
|
||||
DoScreenFadeOut(800)
|
||||
|
||||
local formattedCoords = {
|
||||
x = ESX.Math.Round(coords.x, 1),
|
||||
y = ESX.Math.Round(coords.y, 1),
|
||||
z = ESX.Math.Round(coords.z, 1)
|
||||
}
|
||||
while not IsScreenFadedOut() do
|
||||
Wait(50)
|
||||
end
|
||||
|
||||
RespawnPed(playerPed, formattedCoords, 0.0)
|
||||
isDead = false
|
||||
DoScreenFadeIn(800)
|
||||
local formattedCoords = {x = ESX.Math.Round(coords.x, 1), y = ESX.Math.Round(coords.y, 1), z = ESX.Math.Round(coords.z, 1)}
|
||||
|
||||
RespawnPed(playerPed, formattedCoords, 0.0)
|
||||
isDead = false
|
||||
ClearTimecycleModifier()
|
||||
SetPedMotionBlur(playerPed, false)
|
||||
ClearExtraTimecycleModifier()
|
||||
EndDeathCam()
|
||||
DoScreenFadeIn(800)
|
||||
end)
|
||||
|
||||
-- Load unloaded IPLs
|
||||
if Config.LoadIpl then
|
||||
RequestIpl('Coroner_Int_on') -- Morgue
|
||||
RequestIpl('Coroner_Int_on') -- Morgue
|
||||
end
|
||||
|
||||
local cam = nil
|
||||
|
||||
local isDead = false
|
||||
|
||||
local angleY = 0.0
|
||||
|
||||
local angleZ = 0.0
|
||||
|
||||
-------------------------------------------------------
|
||||
|
||||
-----------------DEATH CAMERA FUNCTIONS ---------------
|
||||
|
||||
--------------------------------------------------------
|
||||
|
||||
-- initialize camera
|
||||
|
||||
function StartDeathCam()
|
||||
ClearFocus()
|
||||
local playerPed = PlayerPedId()
|
||||
cam = CreateCamWithParams("DEFAULT_SCRIPTED_CAMERA", GetEntityCoords(playerPed), 0, 0, 0, GetGameplayCamFov())
|
||||
SetCamActive(cam, true)
|
||||
RenderScriptCams(true, true, 1000, true, false)
|
||||
end
|
||||
|
||||
-- destroy camera
|
||||
|
||||
function EndDeathCam()
|
||||
ClearFocus()
|
||||
RenderScriptCams(false, false, 0, true, false)
|
||||
DestroyCam(cam, false)
|
||||
cam = nil
|
||||
end
|
||||
-- process camera controls
|
||||
function ProcessCamControls()
|
||||
local playerPed = PlayerPedId()
|
||||
local playerCoords = GetEntityCoords(playerPed)
|
||||
-- disable 1st person as the 1st person camera can cause some glitches
|
||||
DisableFirstPersonCamThisFrame()
|
||||
-- calculate new position
|
||||
local newPos = ProcessNewPosition()
|
||||
SetFocusArea(newPos.x, newPos.y, newPos.z, 0.0, 0.0, 0.0)
|
||||
-- set coords of cam
|
||||
SetCamCoord(cam, newPos.x, newPos.y, newPos.z)
|
||||
-- set rotation
|
||||
PointCamAtCoord(cam, playerCoords.x, playerCoords.y, playerCoords.z + 0.5)
|
||||
end
|
||||
|
||||
function ProcessNewPosition()
|
||||
local mouseX = 0.0
|
||||
local mouseY = 0.0
|
||||
-- keyboard
|
||||
if (IsInputDisabled(0)) then
|
||||
-- rotation
|
||||
mouseX = GetDisabledControlNormal(1, 1) * 8.0
|
||||
|
||||
mouseY = GetDisabledControlNormal(1, 2) * 8.0
|
||||
-- controller
|
||||
else
|
||||
mouseX = GetDisabledControlNormal(1, 1) * 1.5
|
||||
|
||||
mouseY = GetDisabledControlNormal(1, 2) * 1.5
|
||||
end
|
||||
|
||||
angleZ = angleZ - mouseX -- around Z axis (left / right)
|
||||
|
||||
angleY = angleY + mouseY -- up / down
|
||||
-- limit up / down angle to 90°
|
||||
|
||||
if (angleY > 89.0) then
|
||||
angleY = 89.0
|
||||
elseif (angleY < -89.0) then
|
||||
angleY = -89.0
|
||||
end
|
||||
local pCoords = GetEntityCoords(PlayerPedId())
|
||||
local behindCam = {x = pCoords.x + ((Cos(angleZ) * Cos(angleY)) + (Cos(angleY) * Cos(angleZ))) / 2 * (5.5 + 0.5),
|
||||
|
||||
y = pCoords.y + ((Sin(angleZ) * Cos(angleY)) + (Cos(angleY) * Sin(angleZ))) / 2 * (5.5 + 0.5),
|
||||
|
||||
z = pCoords.z + ((Sin(angleY))) * (5.5 + 0.5)}
|
||||
local rayHandle = StartShapeTestRay(pCoords.x, pCoords.y, pCoords.z + 0.5, behindCam.x, behindCam.y, behindCam.z, -1, PlayerPedId(), 0)
|
||||
|
||||
local a, hitBool, hitCoords, surfaceNormal, entityHit = GetShapeTestResult(rayHandle)
|
||||
|
||||
local maxRadius = 1.9
|
||||
if (hitBool and Vdist(pCoords.x, pCoords.y, pCoords.z + 0.5, hitCoords) < 5.5 + 0.5) then
|
||||
maxRadius = Vdist(pCoords.x, pCoords.y, pCoords.z + 0.5, hitCoords)
|
||||
end
|
||||
|
||||
local offset = {x = ((Cos(angleZ) * Cos(angleY)) + (Cos(angleY) * Cos(angleZ))) / 2 * maxRadius,
|
||||
y = ((Sin(angleZ) * Cos(angleY)) + (Cos(angleY) * Sin(angleZ))) / 2 * maxRadius, z = ((Sin(angleY))) * maxRadius}
|
||||
|
||||
local pos = {x = pCoords.x + offset.x, y = pCoords.y + offset.y, z = pCoords.z + offset.z}
|
||||
|
||||
return pos
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user