[HELP] Making spot lights

I have been working my but off to get DrawSpotLight or DrawSpotLightWithShadow to work, but I just have not been able to accomplish it this is the code i have been using so far:

					DrawSpotLightWithShadow(GetEntityCoords(heli).x, GetEntityCoords(heli).y, GetEntityCoords(heli).z, GetCamRot(cam, 2).x, GetCamRot(cam, 2).y, GetCamRot(cam, 2).z, 240, 240, 240, 200.0, 35.0, 2.0, 15.0, 50.0, 0.0)

I have been using the helicam script to try and get this to work, but so far no luck.

1 Like

There should be some commented code in the helicam script that should point you on your way.
2 things:

  1. You obviously need to run it in a loop
  2. It seems like you use the rotation values (GetCamRot) where you should actually put the direction where to shine the spotlight. So you need to make a forward pointing vector from those rotation values.

first it is in a loop, and second the native says that it needs dir.x y and z which the cam rotation should give, but regardless I have tried even with set values in it and no luck.

No, GetCamRot gives the rotation angle around the X, Y, and Z axis respectively, not the forwardVector.

Here is how I have done it in ELS-FiveM

2 Likes

I looked at your code, and I know it works in c# i have done it in that to make sure i was doing it right, but it doesnt work in lua and I want the script to be full lua.

1 Like

I got it working, thank you guys for all your help!

1 Like

you should share it :wink:

1 Like

oh yea, sorry just forgot.

Well if you want to take angles and get a forward vector like they said above you have to do a little tinkering with the values.

This was not made by me, and i cannot stress that enough, however here it is anyway

function RotAnglesToVec(rot) -- input vector3
	local z = math.rad(rot.z)
	local x = math.rad(rot.x)
	local num = math.abs(math.cos(x))
	return vector3(-math.sin(z)*num, math.cos(z)*num, math.sin(x))
end

you call that function with the angles as rot and bobs your uncle it spits out what you need for

local rotation = GetCamRot(cam, 2)
local forward_vector = RotAnglesToVec(rotation)
local camcoords = GetCamCoord(cam)
DrawSpotLightWithShadow(camcoords, forward_vector, 255, 255, 255, 600.0, 10.0, brightness, 10.0, 200.0, 20.0)

I just never noticed this inside of helicam before mraes told me about it!

2 Likes

In the “heli” script, Where could i add this? :slight_smile:

1 Like

Do i just put this up at the top? :slight_smile:


local rotation = GetCamRot(cam, 2)
local forward_vector = RotAnglesToVec(rotation)
local camcoords = GetCamCoord(cam)
DrawSpotLightWithShadow(camcoords, forward_vector, 255, 255, 255, 600.0, 10.0, brightness, 10.0, 200.0, 20.0)



1 Like

This is already feature of the heli script, I think he made a spotlight for normal vehicles

1 Like

Hmm, Im wanting the light to follow the camera or vehicle lock, At the moment it just beam’s forward? Or do i need to update for this feature to work

1 Like

you need to use the code i put in the thread for the light to follow it.

Can you show an example? Sorry i tried this but i broke the heli script doing so

make sure that you dont have 2 RotAnglesToVec functions

There is already one in the file i just dont know if it is commented out or not.

1 Like
-- FiveM Heli Cam by mraes
-- Version 1.3 2017-06-12
-- Modified version incorporating spotlight and other tweaks by Loque and by rjross2013. Credits for tips gleaned from these mods: Guadmaz's Simple Police Searchlight, devilkkw's Speed Camera and nynjardin's Simple Outlaw Alert.

-- config
local brightness = 1.0
local fov_max = 80.0
local fov_min = 10.0 -- max zoom level (smaller fov is more zoom)
local zoomspeed = 3.0 -- camera zoom speed
local speed_lr = 4.0 -- speed by which the camera pans left-right 
local speed_ud = 4.0 -- speed by which the camera pans up-down
local toggle_helicam = 51 -- control id of the button by which to toggle the helicam mode. Default: INPUT_CONTEXT (E)
local toggle_vision = 25 -- control id to toggle vision mode. Default: INPUT_AIM (Right mouse btn)
local toggle_rappel = 154 -- control id to rappel out of the heli. Default: INPUT_DUCK (X)
local toggle_spotlight = 183 -- control id to toggle the various spotlight states Default: INPUT_PhoneCameraGrid (G)
local toggle_lock_on = 22 -- control id to lock onto a vehicle with the camera or unlock from vehicle (with or without camera). Default is INPUT_SPRINT (spacebar)
local toggle_display = 44 -- control id to toggle vehicle info display. Default: INPUT_COVER (Q)
local maxtargetdistance = 700 -- max distance at which target lock is maintained

-- Script starts here
local target_vehicle = nil
local new_target = nil
local manual_spotlight = false
local vehicle_display = 0 -- 0 is default full vehicle info display with speed/model/plate, 1 is model/plate, 2 turns off display
local helicam = false
local polmav_hash = GetHashKey("polmav")
local fov = (fov_max+fov_min)*0.5
local vision_state = 0 -- 0 is normal, 1 is nightmode, 2 is thermal vision

Citizen.CreateThread(function() -- Register ped decorators used to pass some variables from heli pilot to other players (variable settings: 1=false, 2=true)
	while true do
	Citizen.Wait(0)
		if NetworkIsSessionStarted() then
			DecorRegister("EnableTrackingSpotlight", 3)
			DecorRegister("EnableManualSpotlight", 3)
			DecorRegister("DeleteTarget", 3)
			DecorRegister("PauseTrackingSpotlight", 3)
			DecorRegister("xSpotvector", 3)
			DecorRegister("ySpotvector", 3)
			DecorRegister("zSpotvector", 3)
			return
		end
	end
end)

Citizen.CreateThread(function()
	while true do
        Citizen.Wait(0)
		if IsPlayerInPolmav() then
			local lPed = GetPlayerPed(-1)
			local heli = GetVehiclePedIsIn(lPed)
			
			if IsHeliHighEnough(heli) then
				if IsControlJustPressed(0, toggle_helicam) then -- Toggle Helicam
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					helicam = true
				end
				
				if IsControlJustPressed(0, toggle_rappel) then -- Initiate rappel
					Citizen.Trace("try to rappel")
					if GetPedInVehicleSeat(heli, 1) == lPed or GetPedInVehicleSeat(heli, 2) == lPed then
						PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
						TaskRappelFromHeli(GetPlayerPed(-1), 1)
					else
						SetNotificationTextEntry( "STRING" )
						AddTextComponentString("~r~Can't rappel from this seat")
						DrawNotification(false, false )
						PlaySoundFrontend(-1, "5_Second_Timer", "DLC_HEISTS_GENERAL_FRONTEND_SOUNDS", false) 
					end
				end
			end
			
			if IsControlJustPressed(0, toggle_spotlight) and GetPedInVehicleSeat(heli, -1) == lPed and not helicam then -- Toggle forward and tracking spotlight states
				if target_vehicle then
					if DecorGetInt(lPed, "EnableTrackingSpotlight") == 2 then
						if DecorGetInt(lPed, "PauseTrackingSpotlight") == 1 then
							DecorSetInt(lPed, "PauseTrackingSpotlight", 2) 
						else
							DecorSetInt(lPed, "PauseTrackingSpotlight", 1)
						end
						PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					else
						spotlight_state = false	
						TriggerServerEvent("heli:forward.spotlight", spotlight_state)
						DecorSetInt(lPed, "EnableTrackingSpotlight", 2)
						DecorSetInt(lPed, "PauseTrackingSpotlight", 1)
						TriggerServerEvent("heli:tracking.spotlight", target_vehicle)
						PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					end				
				else
					DecorSetInt(lPed, "EnableTrackingSpotlight", 1)
					DecorSetInt(lPed, "PauseTrackingSpotlight", 1)
					spotlight_state = not spotlight_state
					TriggerServerEvent("heli:forward.spotlight", spotlight_state)
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
				end
			end

			if IsControlJustPressed(0, toggle_lock_on) and GetPedInVehicleSeat(heli, -1) == lPed then -- Delete target
				DecorSetInt(lPed, "DeleteTarget", 2)
				DecorSetInt(lPed, "EnableTrackingSpotlight", 1)
				DecorSetInt(lPed, "PauseTrackingSpotlight", 1) 
				target_vehicle = nil
				new_target = nil
				PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
			end

			if DecorGetInt(lPed, "DeleteTarget") == 2 then
				target_vehicle = nil
				new_target = nil
				Citizen.Wait(5)
				DecorSetInt(lPed, "DeleteTarget", 1)
			end

			if IsControlJustPressed(0, toggle_display) and GetPedInVehicleSeat(heli, -1) == lPed then 
				ChangeDisplay()
			end
		end
		
		if helicam then
			SetTimecycleModifier("heliGunCam")
			SetTimecycleModifierStrength(0.3)
			local scaleform = RequestScaleformMovie("HELI_CAM")
			while not HasScaleformMovieLoaded(scaleform) do
				Citizen.Wait(0)
			end
			local lPed = GetPlayerPed(-1)
			local heli = GetVehiclePedIsIn(lPed)
			local cam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true)
			AttachCamToEntity(cam, heli, 0.0,0.0,-1.5, true)
			SetCamRot(cam, 0.0,0.0,GetEntityHeading(heli))
			SetCamFov(cam, fov)
			RenderScriptCams(true, false, 0, 1, 0)
			PushScaleformMovieFunction(scaleform, "SET_CAM_LOGO")
			PushScaleformMovieFunctionParameterInt(1) -- 0 for nothing, 1 for LSPD logo
			PopScaleformMovieFunctionVoid()
			local locked_on_vehicle = nil
			while helicam and not IsEntityDead(lPed) and (GetVehiclePedIsIn(lPed) == heli) and IsHeliHighEnough(heli) do
				if IsControlJustPressed(0, toggle_helicam) then -- Toggle Helicam
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					if manual_spotlight and target_vehicle then
						DecorSetInt(lPed, "EnableTrackingSpotlight", 2)
						DecorSetInt(lPed, "PauseTrackingSpotlight", 1)
						TriggerServerEvent("heli:tracking.spotlight", target_vehicle)
					end
					manual_spotlight = false
					DecorSetInt(lPed, "EnableManualSpotlight", 1)
					helicam = false
					--brightness = 2
				end

				if IsControlJustPressed(0, toggle_vision) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					ChangeVision()
				end

				if IsControlJustPressed(0, toggle_spotlight) then
					if DecorGetInt(lPed, "EnableTrackingSpotlight") == 2 then -- Pause tracking spotlight 
						DecorSetInt(lPed, "PauseTrackingSpotlight", 2)
						manual_spotlight = not manual_spotlight
						if manual_spotlight then
							DecorSetInt(lPed, "EnableManualSpotlight", 2)
							DecorSetInt(lPed, "xSpotvector", xSpotvector)
							DecorSetInt(lPed, "ySpotvector", ySpotvector)
							DecorSetInt(lPed, "zSpotvector", zSpotvector)
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							TriggerServerEvent("heli:manual.spotlight")
						else
							DecorSetInt(lPed, "EnableManualSpotlight", 1)
						end
					elseif spotlight_state then -- Turn off forward spotlight
						spotlight_state = false
						TriggerServerEvent("heli:forward.spotlight", spotlight_state)
						manual_spotlight = not manual_spotlight
						if manual_spotlight then
							DecorSetInt(lPed, "EnableManualSpotlight", 2)
							DecorSetInt(lPed, "xSpotvector", xSpotvector)
							DecorSetInt(lPed, "ySpotvector", ySpotvector)
							DecorSetInt(lPed, "zSpotvector", zSpotvector)
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							TriggerServerEvent("heli:manual.spotlight")
						else
							DecorSetInt(lPed, "EnableManualSpotlight", 1)
						end
					else
						manual_spotlight = not manual_spotlight
						if manual_spotlight then
							DecorSetInt(lPed, "EnableManualSpotlight", 2)
							DecorSetInt(lPed, "xSpotvector", xSpotvector)
							DecorSetInt(lPed, "ySpotvector", ySpotvector)
							DecorSetInt(lPed, "zSpotvector", zSpotvector)
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							TriggerServerEvent("heli:manual.spotlight")
						else
							DecorSetInt(lPed, "EnableManualSpotlight", 1)
						end
					end
				end

				if IsControlJustPressed(0, 246) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					if manual_spotlight then
						lightUp()
					end
				end

				if IsControlJustPressed(0, 173) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					if manual_spotlight then
						lightDown()
					end
				end

				if IsControlJustPressed(0, toggle_display) then 
					ChangeDisplay()
				end

				if locked_on_vehicle then
					if DoesEntityExist(locked_on_vehicle) then
						PointCamAtEntity(cam, locked_on_vehicle, 0.0, 0.0, 0.0, true)
						RenderVehicleInfo(locked_on_vehicle)
						local coords1 = GetEntityCoords(heli)
						local coords2 = GetEntityCoords(locked_on_vehicle)
						local target_distance = GetDistanceBetweenCoords(coords1.x, coords1.y, coords1.z, coords2.x, coords2.y, coords2.z, false)
						if IsControlJustPressed(0, toggle_lock_on) or target_distance > maxtargetdistance then
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							locked_on_vehicle = nil
							target_vehicle = nil
							local rot = GetCamRot(cam, 2) -- All this because I can't seem to get the camera unlocked from the entity
							local fov = GetCamFov(cam)
							local old cam = cam
							DestroyCam(old_cam, false)
							cam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true)
							AttachCamToEntity(cam, heli, 0.0,0.0,-1.5, true)
							SetCamRot(cam, rot, 2)
							SetCamFov(cam, fov)
							RenderScriptCams(true, false, 0, 1, 0)
						end
					else
						locked_on_vehicle = nil -- Cam will auto unlock when entity doesn't exist anyway
						target_vehicle = nil
					end
				else
					local zoomvalue = (1.0/(fov_max-fov_min))*(fov-fov_min)
					CheckInputRotation(cam, zoomvalue)
					local vehicle_detected = GetVehicleInView(cam)
					if DoesEntityExist(vehicle_detected) then
						RenderVehicleInfo(vehicle_detected)
						if IsControlJustPressed(0, toggle_lock_on) then
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							DecorSetInt(lPed, "DeleteTarget", 1)
							locked_on_vehicle = vehicle_detected
							if target_vehicle then
								new_target = vehicle_detected
								target_vehicle = nil
								toggle = false
								TriggerServerEvent("heli:target.change", new_target) 
							else
								target_vehicle = vehicle_detected
							end
						end
					end
				end

				HandleZoom(cam)
				HideHUDThisFrame()
				PushScaleformMovieFunction(scaleform, "SET_ALT_FOV_HEADING")
				PushScaleformMovieFunctionParameterFloat(GetEntityCoords(heli).z)
				PushScaleformMovieFunctionParameterFloat(zoomvalue)
				PushScaleformMovieFunctionParameterFloat(GetCamRot(cam, 2).z)
				PopScaleformMovieFunctionVoid()
				DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255)
				Citizen.Wait(0)

				if manual_spotlight then
					local helicoords = GetEntityCoords(heli)
					local rotation = GetCamRot(cam, 2)
					local forward_vector = RotAnglesToVec(rotation)
					local xSpotvector, ySpotvector, zSpotvector = table.unpack(forward_vector)
					local camcoords = GetCamCoord(cam)
					DecorSetInt(lPed, "EnableManualSpotlight", 2)
					DecorSetInt(lPed, "xSpotvector", xSpotvector)
					DecorSetInt(lPed, "ySpotvector", ySpotvector)
					DecorSetInt(lPed, "zSpotvector", zSpotvector)
				else
					DecorSetInt(lPed, "EnableManualSpotlight", 1)
				end

			end
			DecorSetInt(lPed, "EnableManualSpotlight", 1)
			helicam = false
			ClearTimecycleModifier()
			fov = (fov_max+fov_min)*0.5 -- reset to starting zoom level
			RenderScriptCams(false, false, 0, 1, 0) -- Return to gameplay camera
			SetScaleformMovieAsNoLongerNeeded(scaleform) -- Cleanly release the scaleform
			DestroyCam(cam, false)
			SetNightvision(false)
			SetSeethrough(false)
		end

		if target_vehicle and not helicam and vehicle_display ~=2 then
			RenderVehicleInfo(target_vehicle)
		end
	end
end)

RegisterNetEvent('heli:forward.spotlight')
AddEventHandler('heli:forward.spotlight', function(serverID, state)
	local heli = GetVehiclePedIsIn(GetPlayerPed(GetPlayerFromServerId(serverID)), false)
	SetVehicleSearchlight(heli, state, false)
end)

RegisterNetEvent('heli:tracking.spotlight')
AddEventHandler('heli:tracking.spotlight', function(serverID, target_vehicle)
	local heli = GetVehiclePedIsIn(GetPlayerPed(GetPlayerFromServerId(serverID)), false)
	heliPed = GetPlayerPed(GetPlayerFromServerId(serverID))
	while not IsEntityDead(heliPed) and (GetVehiclePedIsIn(heliPed) == heli) and target_vehicle and (DecorGetInt(heliPed, "EnableTrackingSpotlight") == 2) do
		Citizen.Wait(1)
		if new_target then -- Target change
			target_vehicle = new_target
			new_target = nil
		end
		local helicoords = GetEntityCoords(heli)
		local targetcoords = GetEntityCoords(target_vehicle)
		local spotVector = targetcoords - helicoords
		local target_distance = (Vdist(targetcoords, helicoords) + 20)
		if DecorGetInt(heliPed, "DeleteTarget") == 2 or target_distance > maxtargetdistance then -- Target loss or deletion
			DecorSetInt(heliPed, "DeleteTarget", 2)
			new_target = nil
			target_vehicle = nil
			Citizen.Wait(10)
			DecorSetInt(heliPed, "DeleteTarget", 1)
			DecorSetInt(heliPed, "PauseTrackingSpotlight", 1)
			DecorSetInt(heliPed, "EnableTrackingSpotlight", 1)
			break
		end
		if DecorGetInt(heliPed, "PauseTrackingSpotlight") ~= 2 then
			DrawSpotLight(helicoords['x'], helicoords['y'], helicoords['z'], spotVector['x'], spotVector['y'], spotVector['z'], 255, 255, 255, target_distance, 10.0, brightness, 4.0, 1.0, 0.0)
		end
	end
	Citizen.Wait(5)
	new_target = nil
	target_vehicle = nil 
	DecorSetInt(heliPed, "EnableTrackingSpotlight", 1)
	DecorSetInt(heliPed, "DeleteTarget", 1)
	DecorSetInt(heliPed, "PauseTrackingSpotlight", 1)
end)

RegisterNetEvent('heli:manual.spotlight')
AddEventHandler('heli:manual.spotlight', function(serverID)
    --if GetPlayerServerId(PlayerId()) ~= serverID then -- If working, this could skip event for the source, allowing an improved client-side spotlight for heli pilot

	local heli = GetVehiclePedIsIn(GetPlayerPed(GetPlayerFromServerId(serverID)), false)
	heliPed = GetPlayerPed(GetPlayerFromServerId(serverID))
	while not IsEntityDead(heliPed) and (GetVehiclePedIsIn(heliPed) == heli) and (DecorGetInt(heliPed, "EnableManualSpotlight") == 2) do
		Citizen.Wait(0)
		local helicoords = GetEntityCoords(heli)
		spotoffset = helicoords + vector3(0.0, 0.0, -1.5)
		xSpotvector = DecorGetInt(heliPed, "xSpotvector")
		ySpotvector = DecorGetInt(heliPed, "ySpotvector")
		zSpotvector = DecorGetInt(heliPed, "zSpotvector")
		DrawSpotLight(spotoffset['x'], spotoffset['y'], spotoffset['z'], xSpotvector, ySpotvector, zSpotvector, 255, 255, 255, 800.0, 4.0, brightness, 6.0, 1.0, 1.0)
	end
	DecorSetInt(heliPed, "EnableManualSpotlight", 1)
    --end
end)

RegisterNetEvent('heli:target.change')
AddEventHandler('heli:target.change', function(serverID, new_target)
	if new_target then
		target_vehicle = new_target
		new_target = nil
	end
end)

function lightUp()
	brightness = brightness + 1.0
end

function lightDown()
	brightness = brightness - 1.0
end

function IsPlayerInPolmav()
	local lPed = GetPlayerPed(-1)
	local vehicle = GetVehiclePedIsIn(lPed)
	return IsVehicleModel(vehicle, polmav_hash)
end

function IsHeliHighEnough(heli)
	return GetEntityHeightAboveGround(heli) > 1.5
end

function ChangeVision()
	if vision_state == 0 then
		SetNightvision(true)
		vision_state = 1
	elseif vision_state == 1 then
		SetNightvision(false)
		SetSeethrough(true)
		vision_state = 2
	else
		SetSeethrough(false)
		vision_state = 0
	end
end

function ChangeDisplay()
	if vehicle_display == 0 then
		vehicle_display = 1
	elseif vehicle_display == 1 then
		vehicle_display = 2
	else
		vehicle_display = 0
	end
end

function HideHUDThisFrame()
	HideHelpTextThisFrame()
	HideHudAndRadarThisFrame()
	HideHudComponentThisFrame(19) -- weapon wheel
	HideHudComponentThisFrame(1) -- Wanted Stars
	HideHudComponentThisFrame(2) -- Weapon icon
	HideHudComponentThisFrame(3) -- Cash
	HideHudComponentThisFrame(4) -- MP CASH
	HideHudComponentThisFrame(13) -- Cash Change
	HideHudComponentThisFrame(11) -- Floating Help Text
	HideHudComponentThisFrame(12) -- more floating help text
	HideHudComponentThisFrame(15) -- Subtitle Text
	HideHudComponentThisFrame(18) -- Game Stream
end

function CheckInputRotation(cam, zoomvalue)
	local rightAxisX = GetDisabledControlNormal(0, 220)
	local rightAxisY = GetDisabledControlNormal(0, 221)
	local rotation = GetCamRot(cam, 2)
	if rightAxisX ~= 0.0 or rightAxisY ~= 0.0 then
		new_z = rotation.z + rightAxisX*-1.0*(speed_ud)*(zoomvalue+0.1)
		new_x = math.max(math.min(20.0, rotation.x + rightAxisY*-1.0*(speed_lr)*(zoomvalue+0.1)), -89.5) -- Clamping at top (cant see top of heli) and at bottom (doesn't glitch out in -90deg)
		SetCamRot(cam, new_x, 0.0, new_z, 2)
	end
end

function HandleZoom(cam)
	if IsControlJustPressed(0,241) then -- Scrollup
		fov = math.max(fov - zoomspeed, fov_min)
	end
	if IsControlJustPressed(0,242) then
		fov = math.min(fov + zoomspeed, fov_max) -- ScrollDown		
	end
	local current_fov = GetCamFov(cam)
	if math.abs(fov-current_fov) < 0.1 then -- the difference is too small, just set the value directly to avoid unneeded updates to FOV of order 10^-5
		fov = current_fov
	end
	SetCamFov(cam, current_fov + (fov - current_fov)*0.05) -- Smoothing of camera zoom
end

function GetVehicleInView(cam)
	local coords = GetCamCoord(cam)
	local forward_vector = RotAnglesToVec(GetCamRot(cam, 2))
	--DrawLine(coords, coords+(forward_vector*100.0), 255,0,0,255) -- debug line to show LOS of cam
	local rayhandle = CastRayPointToPoint(coords, coords+(forward_vector*200.0), 10, GetVehiclePedIsIn(GetPlayerPed(-1)), 0)
	local _, _, _, _, entityHit = GetRaycastResult(rayhandle)
	if entityHit>0 and IsEntityAVehicle(entityHit) then
		return entityHit
	else
		return nil
	end
end

function RenderVehicleInfo(vehicle)
	if DoesEntityExist(vehicle) then
		local model = GetEntityModel(vehicle)
		local vehname = GetLabelText(GetDisplayNameFromVehicleModel(model))
		local licenseplate = GetVehicleNumberPlateText(vehicle)
		local vehspeed = GetEntitySpeed(vehicle)*3.6
		--local vehspeed = GetEntitySpeed(vehicle)*2.236936 -- to change to Mph, use this line instead of previous, and update relevant text in AddTextComponentString line below
		SetTextFont(0)
		SetTextProportional(1)
		if vehicle_display == 0 then
			SetTextScale(0.0, 0.49)
		elseif vehicle_display == 1 then
			SetTextScale(0.0, 0.55)
		end
		SetTextColour(255, 255, 255, 255)
		SetTextDropshadow(0, 0, 0, 0, 255)
		SetTextEdge(1, 0, 0, 0, 255)
		SetTextDropShadow()
		SetTextOutline()
		SetTextEntry("STRING")
		if vehicle_display == 0 then
			AddTextComponentString("Speed: "..math.ceil(vehspeed).." Km/h\nModel: "..vehname.."\nPlate: "..licenseplate)
		elseif vehicle_display == 1 then
			AddTextComponentString("Model: "..vehname.."\nPlate: "..licenseplate)
		end
		DrawText(0.45, 0.9)
	end
end

function RotAnglesToVec(rot) -- input vector3
	local z = math.rad(rot.z)
	local x = math.rad(rot.x)
	local num = math.abs(math.cos(x))
	return vector3(-math.sin(z)*num, math.cos(z)*num, math.sin(x))
end

this is an example of how it works this is the full heli_client.lua file that is confirmed working, q starts light y and n increases and decreases brightness.

-- FiveM Heli Cam by mraes
-- Version 1.3 2017-06-12

-- config
local clientside_light = false
local fov_max = 80.0
local fov_min = 10.0 -- max zoom level (smaller fov is more zoom)
local zoomspeed = 2.0 -- camera zoom speed
local speed_lr = 3.0 -- speed by which the camera pans left-right 
local speed_ud = 3.0 -- speed by which the camera pans up-down
local toggle_helicam = 51 -- control id of the button by which to toggle the helicam mode. Default: INPUT_CONTEXT (E)
local toggle_vision = 25 -- control id to toggle vision mode. Default: INPUT_AIM (Right mouse btn)
local toggle_rappel = 154 -- control id to rappel out of the heli. Default: INPUT_DUCK (X)
local toggle_spotlight = 183 -- control id to toggle the front spotlight Default: INPUT_PhoneCameraGrid (G)
local toggle_lock_on = 22 -- control id to lock onto a vehicle with the camera. Default is INPUT_SPRINT (spacebar)
local brightness = 2
-- Script starts here
local helicam = false
local polmav_hash = GetHashKey("polmav")
local fov = (fov_max+fov_min)*0.5
local vision_state = 0 -- 0 is normal, 1 is nightmode, 2 is thermal vision
Citizen.CreateThread(function()
	while true do
        Citizen.Wait(0)
		if IsPlayerInPolmav() then
			local lPed = GetPlayerPed(-1)
			local heli = GetVehiclePedIsIn(lPed)
			
			if IsHeliHighEnough(heli) then
				if IsControlJustPressed(0, toggle_helicam) then -- Toggle Helicam
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					helicam = true
				end
				
				if IsControlJustPressed(0, toggle_rappel) then -- Initiate rappel
					Citizen.Trace("try to rappel")
					if GetPedInVehicleSeat(heli, 1) == lPed or GetPedInVehicleSeat(heli, 2) == lPed then
						PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
						TaskRappelFromHeli(GetPlayerPed(-1), 1)
					else
						SetNotificationTextEntry( "STRING" )
						AddTextComponentString("~r~Can't rappel from this seat")
						DrawNotification(false, false )
						PlaySoundFrontend(-1, "5_Second_Timer", "DLC_HEISTS_GENERAL_FRONTEND_SOUNDS", false) 
					end
				end
			end
			
			if IsControlJustPressed(0, toggle_spotlight)  and GetPedInVehicleSeat(heli, -1) == lPed then
				spotlight_state = not spotlight_state
				TriggerServerEvent("heli:spotlight", spotlight_state)
				PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
			end
			
		end
		
		if helicam then
			SetTimecycleModifier("heliGunCam")
			SetTimecycleModifierStrength(0.3)
			local scaleform = RequestScaleformMovie("HELI_CAM")
			while not HasScaleformMovieLoaded(scaleform) do
				Citizen.Wait(0)
			end
			local lPed = GetPlayerPed(-1)
			local heli = GetVehiclePedIsIn(lPed)
			local cam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true)
			AttachCamToEntity(cam, heli, 0.0,0.0,-1.5, true)
			SetCamRot(cam, 0.0,0.0,GetEntityHeading(heli))
			SetCamFov(cam, fov)
			RenderScriptCams(true, false, 0, 1, 0)
			PushScaleformMovieFunction(scaleform, "SET_CAM_LOGO")
			PushScaleformMovieFunctionParameterInt(1) -- 0 for nothing, 1 for LSPD logo
			PopScaleformMovieFunctionVoid()
			local locked_on_vehicle = nil
			while helicam and not IsEntityDead(lPed) and (GetVehiclePedIsIn(lPed) == heli) and IsHeliHighEnough(heli) do
				if IsControlJustPressed(0, toggle_helicam) then -- Toggle Helicam
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					helicam = false
					brightness = 2
				end
				if IsControlJustPressed(0, toggle_vision) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					ChangeVision()
				end
				if IsControlJustPressed(0, 44) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					if clientside_light then
						clientside_light = false
					else
						clientside_light = true
					end
				end
				if IsControlJustPressed(0, 246) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					if clientside_light then
						lightUp()
					end
				end
				if IsControlJustPressed(0, 173) then
					PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
					if clientside_light then
						lightDown()
					end
				end
				if locked_on_vehicle then
					if DoesEntityExist(locked_on_vehicle) then
						PointCamAtEntity(cam, locked_on_vehicle, 0.0, 0.0, 0.0, true)
						RenderVehicleInfo(locked_on_vehicle)
						local coords1 = GetEntityCoords(heli)
						local coords2 = GetEntityCoords(locked_on_vehicle)
						local dists = GetDistanceBetweenCoords(coords1.x, coords1.y, coords1.z, coords2.x, coords2.y, coords2.z, false)
						if dists > 2000 then
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							locked_on_vehicle = nil
							local rot = GetCamRot(cam, 2) -- All this because I can't seem to get the camera unlocked from the entity
							local fov = GetCamFov(cam)
							local old cam = cam
							DestroyCam(old_cam, false)
							cam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true)
							AttachCamToEntity(cam, heli, 0.0,0.0,-1.5, true)
							SetCamRot(cam, rot, 2)
							SetCamFov(cam, fov)
							RenderScriptCams(true, false, 0, 1, 0)
						end
						if IsControlJustPressed(0, toggle_lock_on) then
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							locked_on_vehicle = nil
							local rot = GetCamRot(cam, 2) -- All this because I can't seem to get the camera unlocked from the entity
							local fov = GetCamFov(cam)
							local old cam = cam
							DestroyCam(old_cam, false)
							cam = CreateCam("DEFAULT_SCRIPTED_FLY_CAMERA", true)
							AttachCamToEntity(cam, heli, 0.0,0.0,-1.5, true)
							SetCamRot(cam, rot, 2)
							SetCamFov(cam, fov)
							RenderScriptCams(true, false, 0, 1, 0)
						end
					else
						locked_on_vehicle = nil -- Cam will auto unlock when entity doesn't exist anyway
					end
				else
					local zoomvalue = (1.0/(fov_max-fov_min))*(fov-fov_min)
					CheckInputRotation(cam, zoomvalue)
					local vehicle_detected = GetVehicleInView(cam)
					if DoesEntityExist(vehicle_detected) then
						RenderVehicleInfo(vehicle_detected)
						if IsControlJustPressed(0, toggle_lock_on) then
							PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
							locked_on_vehicle = vehicle_detected
						end
					end
				end
				HandleZoom(cam)
				HideHUDThisFrame()
				PushScaleformMovieFunction(scaleform, "SET_ALT_FOV_HEADING")
				PushScaleformMovieFunctionParameterFloat(GetEntityCoords(heli).z)
				PushScaleformMovieFunctionParameterFloat(zoomvalue)
				PushScaleformMovieFunctionParameterFloat(GetCamRot(cam, 2).z)
				PopScaleformMovieFunctionVoid()
				DrawScaleformMovieFullscreen(scaleform, 255, 255, 255, 255)
				Citizen.Wait(0)
				if clientside_light then
					local spotoffset = GetEntityCoords(heli)
					
					local rotation = GetCamRot(cam, 2)
					local forward_vector = RotAnglesToVec(rotation)
					local camcoords = GetCamCoord(cam)
					DrawSpotLightWithShadow(camcoords, forward_vector, 255, 255, 255, 600.0, 10.0, brightness, 10.0, 200.0, 20.0)
				end
			end
			helicam = false
			ClearTimecycleModifier()
			fov = (fov_max+fov_min)*0.5 -- reset to starting zoom level
			RenderScriptCams(false, false, 0, 1, 0) -- Return to gameplay camera
			SetScaleformMovieAsNoLongerNeeded(scaleform) -- Cleanly release the scaleform
			DestroyCam(cam, false)
			SetNightvision(false)
			SetSeethrough(false)
		end
	end
end)

RegisterNetEvent('heli:spotlight')
AddEventHandler('heli:spotlight', function(serverID, state)
	local heli = GetVehiclePedIsIn(GetPlayerPed(GetPlayerFromServerId(serverID)), false)
	SetVehicleSearchlight(heli, state, false)
	Citizen.Trace("Set heli light state to "..tostring(state).." for serverID: "..serverID)
end)
function lightUp()
	brightness = brightness + 1.0
end
function lightDown()
	brightness = brightness - 1.0
end
function IsPlayerInPolmav()
	local lPed = GetPlayerPed(-1)
	local vehicle = GetVehiclePedIsIn(lPed)
	return IsVehicleModel(vehicle, polmav_hash)
end

function IsHeliHighEnough(heli)
	return GetEntityHeightAboveGround(heli) > 1.5
end

function ChangeVision()
	if vision_state == 0 then
		SetNightvision(true)
		vision_state = 1
	elseif vision_state == 1 then
		SetNightvision(false)
		SetSeethrough(true)
		vision_state = 2
	else
		SetSeethrough(false)
		vision_state = 0
	end
end

function HideHUDThisFrame()
	HideHelpTextThisFrame()
	HideHudAndRadarThisFrame()
	HideHudComponentThisFrame(19) -- weapon wheel
	HideHudComponentThisFrame(1) -- Wanted Stars
	HideHudComponentThisFrame(2) -- Weapon icon
	HideHudComponentThisFrame(3) -- Cash
	HideHudComponentThisFrame(4) -- MP CASH
	HideHudComponentThisFrame(13) -- Cash Change
	HideHudComponentThisFrame(11) -- Floating Help Text
	HideHudComponentThisFrame(12) -- more floating help text
	HideHudComponentThisFrame(15) -- Subtitle Text
	HideHudComponentThisFrame(18) -- Game Stream
end

function CheckInputRotation(cam, zoomvalue)
	local rightAxisX = GetDisabledControlNormal(0, 220)
	local rightAxisY = GetDisabledControlNormal(0, 221)
	local rotation = GetCamRot(cam, 2)
	if rightAxisX ~= 0.0 or rightAxisY ~= 0.0 then
		new_z = rotation.z + rightAxisX*-1.0*(speed_ud)*(zoomvalue+0.1)
		new_x = math.max(math.min(20.0, rotation.x + rightAxisY*-1.0*(speed_lr)*(zoomvalue+0.1)), -89.5) -- Clamping at top (cant see top of heli) and at bottom (doesn't glitch out in -90deg)
		SetCamRot(cam, new_x, 0.0, new_z, 2)
	end
end

function HandleZoom(cam)
	if IsControlJustPressed(0,241) then -- Scrollup
		fov = math.max(fov - zoomspeed, fov_min)
	end
	if IsControlJustPressed(0,242) then
		fov = math.min(fov + zoomspeed, fov_max) -- ScrollDown		
	end
	local current_fov = GetCamFov(cam)
	if math.abs(fov-current_fov) < 0.1 then -- the difference is too small, just set the value directly to avoid unneeded updates to FOV of order 10^-5
		fov = current_fov
	end
	SetCamFov(cam, current_fov + (fov - current_fov)*0.05) -- Smoothing of camera zoom
end

function GetVehicleInView(cam)
	local coords = GetCamCoord(cam)
	local forward_vector = RotAnglesToVec(GetCamRot(cam, 2))
	--DrawLine(coords, coords+(forward_vector*100.0), 255,0,0,255) -- debug line to show LOS of cam
	local rayhandle = CastRayPointToPoint(coords, coords+(forward_vector*200.0), 10, GetVehiclePedIsIn(GetPlayerPed(-1)), 0)
	local _, _, _, _, entityHit = GetRaycastResult(rayhandle)
	if entityHit>0 and IsEntityAVehicle(entityHit) then
		return entityHit
	else
		return nil
	end
end

function RenderVehicleInfo(vehicle)
	local model = GetEntityModel(vehicle)
	local vehname = GetLabelText(GetDisplayNameFromVehicleModel(model))
	local licenseplate = GetVehicleNumberPlateText(vehicle)
	SetTextFont(0)
	SetTextProportional(1)
	SetTextScale(0.0, 0.55)
	SetTextColour(255, 255, 255, 255)
	SetTextDropshadow(0, 0, 0, 0, 255)
	SetTextEdge(1, 0, 0, 0, 255)
	SetTextDropShadow()
	SetTextOutline()
	SetTextEntry("STRING")
	AddTextComponentString("Model: "..vehname.."\nPlate: "..licenseplate)
	DrawText(0.45, 0.9)
end

-- function HandleSpotlight(cam)
-- if IsControlJustPressed(0, toggle_spotlight) then
	-- PlaySoundFrontend(-1, "SELECT", "HUD_FRONTEND_DEFAULT_SOUNDSET", false)
	-- spotlight_state = not spotlight_state
-- end
-- if spotlight_state then
	-- local rotation = GetCamRot(cam, 2)
	-- local forward_vector = RotAnglesToVec(rotation)
	-- local camcoords = GetCamCoord(cam)
	-- DrawSpotLight(camcoords, forward_vector, 255, 255, 255, 300.0, 10.0, 0.0, 2.0, 1.0)
-- end
-- end

function RotAnglesToVec(rot) -- input vector3
	local z = math.rad(rot.z)
	local x = math.rad(rot.x)
	local num = math.abs(math.cos(x))
	return vector3(-math.sin(z)*num, math.cos(z)*num, math.sin(x))
end
1 Like

Wait, So this is for the Spotlight to follow the camera right? If so It’s not working for me.