Skip to content

Commit

Permalink
feat: rewrite and improve deathcam + adding zoom feature.
Browse files Browse the repository at this point in the history
  • Loading branch information
Arctos2win authored Jul 27, 2024
1 parent 5065bae commit 9f1f1ae
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 127 deletions.
56 changes: 56 additions & 0 deletions client/deathcam.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
function GetShapeTestResultSync(shape)
local handle, hit, coords, normal, entity
repeat handle, hit, coords, normal, entity = GetShapeTestResult(shape)
until handle ~= 1 or Wait()
return hit, coords, normal, entity
end

local camera
local x = 0
local y = 0
local camera_radius = 5
local zoom = Config.zoom
local playerPed

function StartDeathCam()
camera = CreateCamWithParams('DEFAULT_SCRIPTED_CAMERA', 0, 0, 0, 0, 0, 0, GetGameplayCamFov(), 1)
RenderScriptCams(true, true, 1000, true, false)

playerPed = PlayerPedId()
end

function EndDeathCam()
RenderScriptCams(0)
camera = DestroyCam(camera)
end

function ProcessCamControls()
local playerCoords = GetEntityCoords(playerPed)
if camera_radius < zoom.max and IsDisabledControlPressed(0, 14) then
camera_radius += zoom.step
elseif camera_radius > zoom.min and IsDisabledControlPressed(0, 15) then
camera_radius -= zoom.step
end

local coords = ProcessNewPosition(playerCoords)
SetCamCoord(camera, coords)
PointCamAtCoord(camera, playerCoords.x, playerCoords.y, playerCoords.z)
end

function ProcessNewPosition(playerCoords)
x -= GetDisabledControlNormal(0, 1)
y -= GetDisabledControlNormal(0, 2)
if y < math.rad(15) then
y = math.rad(15)
elseif y > math.rad(90) then
y = math.rad(90)
end
local normal = vector3(
math.sin(y) * math.cos(x),
math.sin(y) * math.sin(x),
math.cos(y)
)
local pos = playerCoords + normal * camera_radius
local hit, coords = GetShapeTestResultSync(StartShapeTestLosProbe(playerCoords, pos, -1, playerPed))
return (hit == 1 and playerCoords + normal * (#(playerCoords - coords) - 1)) or pos
end
155 changes: 28 additions & 127 deletions client/main.lua
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
local firstSpawn = true

isDead, isSearched, medic = false, false, 0

RegisterNetEvent('esx:playerLoaded')
Expand Down Expand Up @@ -51,32 +50,6 @@ CreateThread(function()
AddTextComponentSubstringPlayerName(TranslateCap('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

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')
Expand All @@ -99,7 +72,6 @@ AddEventHandler('esx_ambulancejob:clsearch', function(medicId)
end)

function OnPlayerDeath()
isDead = true
ESX.CloseContext()
ClearTimecycleModifier()
SetTimecycleModifier("REDMIST_blend")
Expand All @@ -110,6 +82,8 @@ function OnPlayerDeath()
TriggerServerEvent('esx_ambulancejob:setDeathStatus', true)
StartDeathTimer()
StartDeathCam()
isDead = true
StartDeathLoop()
StartDistressSignal()
end

Expand Down Expand Up @@ -155,6 +129,29 @@ AddEventHandler('esx_ambulancejob:useItem', function(itemName)
end
end)

function StartDeathLoop()
CreateThread(function()
while isDead do
DisableAllControlActions(0)
EnableControlAction(0, 47, true) -- G
EnableControlAction(0, 245, true) -- T
EnableControlAction(0, 38, true) -- E

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
end)
end

function StartDistressSignal()
CreateThread(function()
local timer = Config.BleedoutTimer
Expand All @@ -169,7 +166,7 @@ function StartDistressSignal()
SetTextDropshadow(0.1, 3, 27, 27, 255)
BeginTextCommandDisplayText('STRING')
AddTextComponentSubstringPlayerName(TranslateCap('distress_send'))
EndTextCommandDisplayText(0.43, 0.77)
EndTextCommandDisplayText(0.446, 0.77)

if IsControlJustReleased(0, 47) then
SendDistressSignal()
Expand Down Expand Up @@ -375,107 +372,11 @@ AddEventHandler('esx_ambulancejob:revive', function()
ClearTimecycleModifier()
SetPedMotionBlur(playerPed, false)
ClearExtraTimecycleModifier()
EndDeathCam()
EndDeathCam()
DoScreenFadeIn(800)
end)

-- Load unloaded IPLs
if Config.LoadIpl then
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
end
6 changes: 6 additions & 0 deletions config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ Config.DistressBlip = {
Scale = 2.0
}

Config.zoom = {
min = 1,
max = 6,
step = 0.5
}

Config.EarlyRespawnTimer = 60000 * 1 -- time til respawn is available
Config.BleedoutTimer = 60000 * 10 -- time til the player bleeds out

Expand Down

0 comments on commit 9f1f1ae

Please sign in to comment.