861 lines
		
	
	
		
			No EOL
		
	
	
		
			28 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
			
		
		
	
	
			861 lines
		
	
	
		
			No EOL
		
	
	
		
			28 KiB
		
	
	
	
		
			Lua
		
	
	
	
	
	
--[[
 | 
						|
---------------------------------------------------
 | 
						|
LUXART VEHICLE CONTROL V3 (FOR FIVEM)
 | 
						|
---------------------------------------------------
 | 
						|
Coded by Lt.Caine
 | 
						|
ELS Clicks by Faction
 | 
						|
Additional Modification by TrevorBarns
 | 
						|
---------------------------------------------------
 | 
						|
FILE: cl_lvc.lua
 | 
						|
PURPOSE: Core Functionality and User Input
 | 
						|
---------------------------------------------------
 | 
						|
This program is free software: you can redistribute it and/or modify
 | 
						|
it under the terms of the GNU General Public License as published by
 | 
						|
the Free Software Foundation, either version 3 of the License, or
 | 
						|
(at your option) any later version.
 | 
						|
 | 
						|
This program is distributed in the hope that it will be useful,
 | 
						|
but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
GNU General Public License for more details.
 | 
						|
 | 
						|
You should have received a copy of the GNU General Public License
 | 
						|
along with this program.  If not, see <https://www.gnu.org/licenses/>.
 | 
						|
---------------------------------------------------
 | 
						|
]]
 | 
						|
 | 
						|
--GLOBAL VARIABLES used in cl_ragemenu, UTILs, and plug-ins.
 | 
						|
--	GENERAL VARIABLES
 | 
						|
key_lock = false
 | 
						|
playerped = nil
 | 
						|
last_veh = nil
 | 
						|
veh = nil
 | 
						|
trailer = nil
 | 
						|
player_is_emerg_driver = false
 | 
						|
debug_mode = false
 | 
						|
 | 
						|
--	MAIN SIREN SETTINGS
 | 
						|
tone_main_reset_standby 	= reset_to_standby_default
 | 
						|
tone_airhorn_intrp 			= airhorn_interrupt_default
 | 
						|
park_kill 					= park_kill_default
 | 
						|
 | 
						|
--LOCAL VARIABLES
 | 
						|
local radio_wheel_active = false
 | 
						|
 | 
						|
local count_bcast_timer = 0
 | 
						|
local delay_bcast_timer = 300
 | 
						|
 | 
						|
local count_sndclean_timer = 0
 | 
						|
local delay_sndclean_timer = 400
 | 
						|
 | 
						|
local actv_ind_timer = false
 | 
						|
local count_ind_timer = 0
 | 
						|
local delay_ind_timer = 180
 | 
						|
 | 
						|
actv_lxsrnmute_temp = false
 | 
						|
local srntone_temp = 0
 | 
						|
local dsrn_mute = true
 | 
						|
local lights_on = false
 | 
						|
local new_tone = nil
 | 
						|
local tone_mem_id = nil
 | 
						|
local tone_mem_option = nil
 | 
						|
local default_tone = nil
 | 
						|
local default_tone_option = nil
 | 
						|
 | 
						|
state_indic = {}
 | 
						|
state_lxsiren = {}
 | 
						|
state_pwrcall = {}
 | 
						|
state_airmanu = {}
 | 
						|
 | 
						|
actv_manu = nil
 | 
						|
actv_horn = nil
 | 
						|
 | 
						|
local ind_state_o = 0
 | 
						|
local ind_state_l = 1
 | 
						|
local ind_state_r = 2
 | 
						|
local ind_state_h = 3
 | 
						|
 | 
						|
local snd_lxsiren = {}
 | 
						|
local snd_pwrcall = {}
 | 
						|
local snd_airmanu = {}
 | 
						|
 | 
						|
--	Local fn forward declaration
 | 
						|
local RegisterKeyMaps, MakeOrdinal
 | 
						|
 | 
						|
----------------THREADED FUNCTIONS----------------
 | 
						|
-- Set check variable `player_is_emerg_driver` if player is driver of emergency vehicle.
 | 
						|
-- Disables controls faster than previous thread.
 | 
						|
CreateThread(function()
 | 
						|
	if GetResourceState('lux_vehcontrol') ~= 'started' and GetResourceState('lux_vehcontrol') ~= 'starting' then
 | 
						|
		if GetCurrentResourceName() == 'lvc' then
 | 
						|
			if community_id ~= nil and community_id ~= '' then
 | 
						|
				while true do
 | 
						|
					playerped = GetPlayerPed(-1)
 | 
						|
					--IS IN VEHICLE
 | 
						|
					player_is_emerg_driver = false
 | 
						|
					if IsPedInAnyVehicle(playerped, false) then
 | 
						|
						veh = GetVehiclePedIsUsing(playerped)
 | 
						|
						_, trailer = GetVehicleTrailerVehicle(veh)
 | 
						|
						--IS DRIVER
 | 
						|
						if GetPedInVehicleSeat(veh, -1) == playerped then
 | 
						|
							--IS EMERGENCY VEHICLE
 | 
						|
							if GetVehicleClass(veh) == 18 then
 | 
						|
								player_is_emerg_driver = true
 | 
						|
								DisableControlAction(0, 80, true) -- INPUT_VEH_CIN_CAM
 | 
						|
								DisableControlAction(0, 86, true) -- INPUT_VEH_HORN
 | 
						|
								DisableControlAction(0, 172, true) -- INPUT_CELLPHONE_UP
 | 
						|
							end
 | 
						|
						end
 | 
						|
					end
 | 
						|
					Wait(1)
 | 
						|
				end
 | 
						|
			else
 | 
						|
				Wait(1000)
 | 
						|
				HUD:ShowNotification(Lang:t('error.missing_community_id_frontend'), true)
 | 
						|
				UTIL:Print(Lang:t('error.missing_community_id_console'), true)
 | 
						|
			end
 | 
						|
		else
 | 
						|
			Wait(1000)
 | 
						|
			HUD:ShowNotification(Lang:t('error.invalid_resource_name_frontend'), true)
 | 
						|
			UTIL:Print(Lang:t('error.invalid_resource_name_console'), true)
 | 
						|
		end
 | 
						|
	else
 | 
						|
		Wait(1000)
 | 
						|
		HUD:ShowNotification(Lang:t('error.resource_conflict_frontend'), true)
 | 
						|
		UTIL:Print(Lang:t('error.resource_conflict_console'), true)
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
--On resource start/restart
 | 
						|
CreateThread(function()
 | 
						|
	debug_mode = GetResourceMetadata(GetCurrentResourceName(), 'debug_mode', 0) == 'true'
 | 
						|
	TriggerEvent('chat:addSuggestion', Lang:t('command.lock_command'), Lang:t('command.lock_desc'))
 | 
						|
	SetNuiFocus( false )
 | 
						|
	
 | 
						|
	UTIL:FixOversizeKeys(SIREN_ASSIGNMENTS)
 | 
						|
	RegisterKeyMaps()
 | 
						|
	STORAGE:SetBackupTable()
 | 
						|
end)
 | 
						|
 | 
						|
-- Auxiliary Control Handling
 | 
						|
--	Handles radio wheel controls and default horn on siren change playback. 
 | 
						|
CreateThread(function()
 | 
						|
	while true do
 | 
						|
		if player_is_emerg_driver then
 | 
						|
			-- RADIO WHEEL
 | 
						|
			if IsControlPressed(0, 243) and AUDIO.radio_masterswitch then
 | 
						|
				while IsControlPressed(0, 243) do
 | 
						|
					radio_wheel_active = true
 | 
						|
					SetControlNormal(0, 85, 1.0)
 | 
						|
					Wait(0)
 | 
						|
				end
 | 
						|
				Wait(100)
 | 
						|
				radio_wheel_active = false
 | 
						|
			else
 | 
						|
				DisableControlAction(0, 85, true) -- INPUT_VEH_RADIO_WHEEL
 | 
						|
				SetVehicleRadioEnabled(veh, false)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		Wait(0)
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
------ON VEHICLE EXIT EVENT TRIGGER------
 | 
						|
CreateThread(function()
 | 
						|
	while true do
 | 
						|
		if player_is_emerg_driver then
 | 
						|
			while playerped ~= nil and veh ~= nil do
 | 
						|
				if GetIsTaskActive(playerped, 2) and GetVehiclePedIsIn(ped, true) then
 | 
						|
					TriggerEvent('lvc:onVehicleExit')
 | 
						|
					Wait(1000)
 | 
						|
				end
 | 
						|
				Wait(0)
 | 
						|
			end
 | 
						|
		end
 | 
						|
		Wait(1000)
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
------VEHICLE CHANGE DETECTION AND TRIGGER------
 | 
						|
CreateThread(function()
 | 
						|
	while true do
 | 
						|
		if player_is_emerg_driver and veh ~= nil then
 | 
						|
			if last_veh == nil then
 | 
						|
				TriggerEvent('lvc:onVehicleChange')
 | 
						|
			else
 | 
						|
				if last_veh ~= veh then
 | 
						|
					TriggerEvent('lvc:onVehicleChange')
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
		Wait(1000)
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
------------REGISTERED VEHICLE EVENTS------------
 | 
						|
--Kill siren on Exit
 | 
						|
RegisterNetEvent('lvc:onVehicleExit')
 | 
						|
AddEventHandler('lvc:onVehicleExit', function()
 | 
						|
	if park_kill_masterswitch and park_kill then
 | 
						|
		if not tone_main_reset_standby and state_lxsiren[veh] ~= 0 then
 | 
						|
			UTIL:SetToneByID('MAIN_MEM', state_lxsiren[veh])
 | 
						|
		end
 | 
						|
		SetLxSirenStateForVeh(veh, 0)
 | 
						|
		SetPowercallStateForVeh(veh, 0)
 | 
						|
		SetAirManuStateForVeh(veh, 0)
 | 
						|
		HUD:SetItemState('siren', false)
 | 
						|
		HUD:SetItemState('horn', false)
 | 
						|
		count_bcast_timer = delay_bcast_timer
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterNetEvent('lvc:onVehicleChange')
 | 
						|
AddEventHandler('lvc:onVehicleChange', function()
 | 
						|
	last_veh = veh
 | 
						|
	UTIL:UpdateApprovedTones(veh)
 | 
						|
	Wait(100)	--waiting for JS event handler
 | 
						|
	STORAGE:ResetSettings()
 | 
						|
	UTIL:BuildToneOptions()
 | 
						|
	STORAGE:LoadSettings()
 | 
						|
	HUD:RefreshHudItemStates()
 | 
						|
	SetVehRadioStation(veh, 'OFF')
 | 
						|
	Wait(500)
 | 
						|
	SetVehRadioStation(veh, 'OFF')
 | 
						|
end)
 | 
						|
 | 
						|
--------------REGISTERED COMMANDS---------------
 | 
						|
--Toggle Debug Mode
 | 
						|
RegisterCommand(Lang:t('command.debug_command'), function(source, args)
 | 
						|
	debug_mode = not debug_mode
 | 
						|
	HUD:ShowNotification(Lang:t('info.debug_mode_frontend', {state = debug_mode}), true)
 | 
						|
	UTIL:Print(Lang:t('info.debug_mode_console', {state = debug_mode}), true)
 | 
						|
	if debug_mode then
 | 
						|
		TriggerEvent('lvc:onVehicleChange')
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
--Toggle LUX lock command
 | 
						|
RegisterCommand(Lang:t('command.lock_command'), function(source, args)
 | 
						|
	if player_is_emerg_driver then
 | 
						|
		key_lock = not key_lock
 | 
						|
		AUDIO:Play('Key_Lock', AUDIO.lock_volume, true)
 | 
						|
		HUD:SetItemState('lock', key_lock)
 | 
						|
		--if HUD is visible do not show notification
 | 
						|
		if not HUD:GetHudState() then
 | 
						|
			if key_lock then
 | 
						|
				HUD:ShowNotification(Lang:t('info.locked'), true)
 | 
						|
			else
 | 
						|
				HUD:ShowNotification(Lang:t('info.unlocked'), true)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
RegisterKeyMapping(Lang:t('command.lock_command'), Lang:t('control.lock_desc'), 'keyboard', lockout_default_hotkey)
 | 
						|
 | 
						|
------------------------------------------------
 | 
						|
-------------------FUNCTIONS--------------------
 | 
						|
------------------------------------------------
 | 
						|
------------------------------------------------
 | 
						|
--Dynamically Run RegisterCommand and KeyMapping functions for all 14 possible sirens
 | 
						|
--Then at runtime 'slide' all sirens down removing any restricted sirens.
 | 
						|
RegisterKeyMaps = function()
 | 
						|
	for i, _ in ipairs(SIRENS) do
 | 
						|
		if i ~= 1 then
 | 
						|
			local command = '_lvc_siren_' .. i-1
 | 
						|
			local description = Lang:t('control.siren_control_desc', {ord_num = MakeOrdinal(i-1)})
 | 
						|
 | 
						|
			RegisterCommand(command, function(source, args)
 | 
						|
				if veh ~= nil and player_is_emerg_driver ~= nil then
 | 
						|
					if IsVehicleSirenOn(veh) and player_is_emerg_driver and not key_lock then
 | 
						|
						local proposed_tone = UTIL:GetToneAtPos(i)
 | 
						|
						local tone_option = UTIL:GetToneOption(proposed_tone)
 | 
						|
						if i-1 < #UTIL:GetApprovedTonesTable() then
 | 
						|
							if tone_option ~= nil then
 | 
						|
								if tone_option == 1 or tone_option == 3 then
 | 
						|
									if ( state_lxsiren[veh] ~= proposed_tone or state_lxsiren[veh] == 0 ) then
 | 
						|
										HUD:SetItemState('siren', true)
 | 
						|
										AUDIO:Play('Upgrade', AUDIO.upgrade_volume)
 | 
						|
										SetLxSirenStateForVeh(veh, proposed_tone)
 | 
						|
										count_bcast_timer = delay_bcast_timer
 | 
						|
									else
 | 
						|
										if state_pwrcall[veh] == 0 then
 | 
						|
											HUD:SetItemState('siren', false)
 | 
						|
										end
 | 
						|
										AUDIO:Play('Downgrade', AUDIO.downgrade_volume)
 | 
						|
										SetLxSirenStateForVeh(veh, 0)
 | 
						|
										count_bcast_timer = delay_bcast_timer
 | 
						|
									end
 | 
						|
								end
 | 
						|
							else
 | 
						|
								HUD:ShowNotification(Lang:t('error.reg_keymap_nil_1', {i = i, proposed_tone = proposed_tone, profile_name = UTIL:GetVehicleProfileName()}), true)
 | 
						|
								HUD:ShowNotification(Lang:t('error.reg_keymap_nil_2'), true)
 | 
						|
							end
 | 
						|
						end
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end)
 | 
						|
 | 
						|
			--CHANGE BELOW if you'd like to change which keys are used for example NUMROW1 through 0
 | 
						|
			if i > 0 and i < 11 and main_siren_set_register_keys_set_defaults then
 | 
						|
				RegisterKeyMapping(command, description, 'keyboard', i-1)
 | 
						|
			elseif i == 11 and main_siren_set_register_keys_set_defaults then
 | 
						|
				RegisterKeyMapping(command, description, 'keyboard', '0')
 | 
						|
			else
 | 
						|
				RegisterKeyMapping(command, description, 'keyboard', '')
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
--Make number into ordinal number, used for FiveM RegisterKeys
 | 
						|
MakeOrdinal = function(number)
 | 
						|
	local sufixes = { 'th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th' }
 | 
						|
	local mod = (number % 100)
 | 
						|
	if mod == 11 or mod == 12 or mod == 13 then
 | 
						|
		return number .. 'th'
 | 
						|
	else
 | 
						|
		return number..sufixes[(number % 10) + 1]
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
local function CleanupSounds()
 | 
						|
	if count_sndclean_timer > delay_sndclean_timer then
 | 
						|
		count_sndclean_timer = 0
 | 
						|
		for k, v in pairs(state_lxsiren) do
 | 
						|
			if v > 0 then
 | 
						|
				if not DoesEntityExist(k) or IsEntityDead(k) then
 | 
						|
					if snd_lxsiren[k] ~= nil then
 | 
						|
						StopSound(snd_lxsiren[k])
 | 
						|
						ReleaseSoundId(snd_lxsiren[k])
 | 
						|
						snd_lxsiren[k] = nil
 | 
						|
						state_lxsiren[k] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
		for k, v in pairs(state_pwrcall) do
 | 
						|
			if v > 0 then
 | 
						|
				if not DoesEntityExist(k) or IsEntityDead(k) then
 | 
						|
					if snd_pwrcall[k] ~= nil then
 | 
						|
						StopSound(snd_pwrcall[k])
 | 
						|
						ReleaseSoundId(snd_pwrcall[k])
 | 
						|
						snd_pwrcall[k] = nil
 | 
						|
						state_pwrcall[k] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
		for k, v in pairs(state_airmanu) do
 | 
						|
			if v == true then
 | 
						|
				if not DoesEntityExist(k) or IsEntityDead(k) or IsVehicleSeatFree(k, -1) then
 | 
						|
					if snd_airmanu[k] ~= nil then
 | 
						|
						StopSound(snd_airmanu[k])
 | 
						|
						ReleaseSoundId(snd_airmanu[k])
 | 
						|
						snd_airmanu[k] = nil
 | 
						|
						state_airmanu[k] = nil
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
	else
 | 
						|
		count_sndclean_timer = count_sndclean_timer + 1
 | 
						|
	end
 | 
						|
end
 | 
						|
---------------------------------------------------------------------
 | 
						|
function TogIndicStateForVeh(veh, newstate)
 | 
						|
	if DoesEntityExist(veh) and not IsEntityDead(veh) then
 | 
						|
		if newstate == ind_state_o then
 | 
						|
			SetVehicleIndicatorLights(veh, 0, false) -- R
 | 
						|
			SetVehicleIndicatorLights(veh, 1, false) -- L
 | 
						|
		elseif newstate == ind_state_l then
 | 
						|
			SetVehicleIndicatorLights(veh, 0, false) -- R
 | 
						|
			SetVehicleIndicatorLights(veh, 1, true) -- L
 | 
						|
		elseif newstate == ind_state_r then
 | 
						|
			SetVehicleIndicatorLights(veh, 0, true) -- R
 | 
						|
			SetVehicleIndicatorLights(veh, 1, false) -- L
 | 
						|
		elseif newstate == ind_state_h then
 | 
						|
			SetVehicleIndicatorLights(veh, 0, true) -- R
 | 
						|
			SetVehicleIndicatorLights(veh, 1, true) -- L
 | 
						|
		end
 | 
						|
		state_indic[veh] = newstate
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
function TogMuteDfltSrnForVeh(veh, toggle)
 | 
						|
	if DoesEntityExist(veh) and not IsEntityDead(veh) then
 | 
						|
		DisableVehicleImpactExplosionActivation(veh, toggle)
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
function SetLxSirenStateForVeh(veh, newstate)
 | 
						|
	if DoesEntityExist(veh) and not IsEntityDead(veh) then
 | 
						|
		if newstate ~= state_lxsiren[veh] and newstate ~= nil then
 | 
						|
			if snd_lxsiren[veh] ~= nil then
 | 
						|
				StopSound(snd_lxsiren[veh])
 | 
						|
				ReleaseSoundId(snd_lxsiren[veh])
 | 
						|
				snd_lxsiren[veh] = nil
 | 
						|
			end
 | 
						|
			if newstate ~= 0 then
 | 
						|
				snd_lxsiren[veh] = GetSoundId()
 | 
						|
				PlaySoundFromEntity(snd_lxsiren[veh], SIRENS[newstate].String, veh, SIRENS[newstate].Ref, 0, 0)
 | 
						|
				TogMuteDfltSrnForVeh(veh, true)
 | 
						|
			end
 | 
						|
			state_lxsiren[veh] = newstate
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
function SetPowercallStateForVeh(veh, newstate)
 | 
						|
	if DoesEntityExist(veh) and not IsEntityDead(veh) then
 | 
						|
		if newstate ~= state_pwrcall[veh] and newstate ~= nil then
 | 
						|
			if snd_pwrcall[veh] ~= nil then
 | 
						|
				StopSound(snd_pwrcall[veh])
 | 
						|
				ReleaseSoundId(snd_pwrcall[veh])
 | 
						|
				snd_pwrcall[veh] = nil
 | 
						|
			end
 | 
						|
			if newstate ~= 0 then
 | 
						|
				snd_pwrcall[veh] = GetSoundId()
 | 
						|
				PlaySoundFromEntity(snd_pwrcall[veh], SIRENS[newstate].String, veh, SIRENS[newstate].Ref, 0, 0)
 | 
						|
			end
 | 
						|
			state_pwrcall[veh] = newstate
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
function SetAirManuStateForVeh(veh, newstate)
 | 
						|
	if DoesEntityExist(veh) and not IsEntityDead(veh) then
 | 
						|
		if newstate ~= state_airmanu[veh] and newstate ~= nil then
 | 
						|
			if snd_airmanu[veh] ~= nil then
 | 
						|
				StopSound(snd_airmanu[veh])
 | 
						|
				ReleaseSoundId(snd_airmanu[veh])
 | 
						|
				snd_airmanu[veh] = nil
 | 
						|
			end
 | 
						|
			if newstate ~= 0 then
 | 
						|
				snd_airmanu[veh] = GetSoundId()
 | 
						|
				PlaySoundFromEntity(snd_airmanu[veh], SIRENS[newstate].String, veh, SIRENS[newstate].Ref, 0, 0)
 | 
						|
			end
 | 
						|
			state_airmanu[veh] = newstate
 | 
						|
		end
 | 
						|
	end
 | 
						|
end
 | 
						|
 | 
						|
------------------------------------------------
 | 
						|
----------------EVENT HANDLERS------------------
 | 
						|
------------------------------------------------
 | 
						|
RegisterNetEvent('lvc:TogIndicState_c')
 | 
						|
AddEventHandler('lvc:TogIndicState_c', function(sender, newstate)
 | 
						|
	local player_s = GetPlayerFromServerId(sender)
 | 
						|
	local ped_s = GetPlayerPed(player_s)
 | 
						|
	if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then
 | 
						|
		if ped_s ~= GetPlayerPed(-1) then
 | 
						|
			if IsPedInAnyVehicle(ped_s, false) then
 | 
						|
				local veh = GetVehiclePedIsUsing(ped_s)
 | 
						|
				TogIndicStateForVeh(veh, newstate)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
RegisterNetEvent('lvc:TogDfltSrnMuted_c')
 | 
						|
AddEventHandler('lvc:TogDfltSrnMuted_c', function(sender)
 | 
						|
	local player_s = GetPlayerFromServerId(sender)
 | 
						|
	local ped_s = GetPlayerPed(player_s)
 | 
						|
	if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then
 | 
						|
		if ped_s ~= GetPlayerPed(-1) then
 | 
						|
			if IsPedInAnyVehicle(ped_s, false) then
 | 
						|
				local veh = GetVehiclePedIsUsing(ped_s)
 | 
						|
				TogMuteDfltSrnForVeh(veh, true)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
RegisterNetEvent('lvc:SetLxSirenState_c')
 | 
						|
AddEventHandler('lvc:SetLxSirenState_c', function(sender, newstate)
 | 
						|
	local player_s = GetPlayerFromServerId(sender)
 | 
						|
	local ped_s = GetPlayerPed(player_s)
 | 
						|
	if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then
 | 
						|
		if ped_s ~= GetPlayerPed(-1) then
 | 
						|
			if IsPedInAnyVehicle(ped_s, false) then
 | 
						|
				local veh = GetVehiclePedIsUsing(ped_s)
 | 
						|
				SetLxSirenStateForVeh(veh, newstate)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
RegisterNetEvent('lvc:SetPwrcallState_c')
 | 
						|
AddEventHandler('lvc:SetPwrcallState_c', function(sender, newstate)
 | 
						|
	local player_s = GetPlayerFromServerId(sender)
 | 
						|
	local ped_s = GetPlayerPed(player_s)
 | 
						|
	if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then
 | 
						|
		if ped_s ~= GetPlayerPed(-1) then
 | 
						|
			if IsPedInAnyVehicle(ped_s, false) then
 | 
						|
				local veh = GetVehiclePedIsUsing(ped_s)
 | 
						|
				SetPowercallStateForVeh(veh, newstate)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
RegisterNetEvent('lvc:SetAirManuState_c')
 | 
						|
AddEventHandler('lvc:SetAirManuState_c', function(sender, newstate)
 | 
						|
	local player_s = GetPlayerFromServerId(sender)
 | 
						|
	local ped_s = GetPlayerPed(player_s)
 | 
						|
	if DoesEntityExist(ped_s) and not IsEntityDead(ped_s) then
 | 
						|
		if ped_s ~= GetPlayerPed(-1) then
 | 
						|
			if IsPedInAnyVehicle(ped_s, false) then
 | 
						|
				local veh = GetVehiclePedIsUsing(ped_s)
 | 
						|
				SetAirManuStateForVeh(veh, newstate)
 | 
						|
			end
 | 
						|
		end
 | 
						|
	end
 | 
						|
end)
 | 
						|
 | 
						|
 | 
						|
---------------------------------------------------------------------
 | 
						|
CreateThread(function()
 | 
						|
	while true do
 | 
						|
		CleanupSounds()
 | 
						|
		DistantCopCarSirens(false)
 | 
						|
		----- IS IN VEHICLE -----
 | 
						|
		if GetPedInVehicleSeat(veh, -1) == playerped then
 | 
						|
			if state_indic[veh] == nil then
 | 
						|
				state_indic[veh] = ind_state_o
 | 
						|
			end
 | 
						|
 | 
						|
			-- INDIC AUTO CONTROL
 | 
						|
			if actv_ind_timer == true then
 | 
						|
				if state_indic[veh] == ind_state_l or state_indic[veh] == ind_state_r then
 | 
						|
					if GetEntitySpeed(veh) < 6 then
 | 
						|
						count_ind_timer = 0
 | 
						|
					else
 | 
						|
						if count_ind_timer > delay_ind_timer then
 | 
						|
							count_ind_timer = 0
 | 
						|
							actv_ind_timer = false
 | 
						|
							state_indic[veh] = ind_state_o
 | 
						|
							TogIndicStateForVeh(veh, state_indic[veh])
 | 
						|
							count_bcast_timer = delay_bcast_timer
 | 
						|
						else
 | 
						|
							count_ind_timer = count_ind_timer + 1
 | 
						|
						end
 | 
						|
					end
 | 
						|
				end
 | 
						|
			end
 | 
						|
 | 
						|
			--- IS EMERG VEHICLE ---
 | 
						|
			if GetVehicleClass(veh) == 18 then
 | 
						|
				lights_on = IsVehicleSirenOn(veh)
 | 
						|
				--  FORCE RADIO ENABLED PER FRAME
 | 
						|
				if radio_masterswitch then
 | 
						|
					SetVehicleRadioEnabled(veh, true)
 | 
						|
				end
 | 
						|
 | 
						|
				if not IsEntityDead(veh) then
 | 
						|
					TogMuteDfltSrnForVeh(veh, true)
 | 
						|
					--- SET INIT TABLE VALUES ---
 | 
						|
					if state_lxsiren[veh] == nil then
 | 
						|
						state_lxsiren[veh] = 0
 | 
						|
					end
 | 
						|
					if state_pwrcall[veh] == nil then
 | 
						|
						state_pwrcall[veh] = 0
 | 
						|
					end
 | 
						|
					if state_airmanu[veh] == nil then
 | 
						|
							state_airmanu[veh] = 0
 | 
						|
					end
 | 
						|
 | 
						|
					--- IF LIGHTS ARE OFF TURN OFF SIREN ---
 | 
						|
					if not lights_on and state_lxsiren[veh] > 0 then
 | 
						|
						--	SAVE TONE BEFORE TURNING OFF
 | 
						|
						if not tone_main_reset_standby then
 | 
						|
							UTIL:SetToneByID('MAIN_MEM', state_lxsiren[veh])
 | 
						|
						end
 | 
						|
						SetLxSirenStateForVeh(veh, 0)
 | 
						|
						count_bcast_timer = delay_bcast_timer
 | 
						|
					end
 | 
						|
					if not lights_on and state_pwrcall[veh] > 0 then
 | 
						|
						SetPowercallStateForVeh(veh, 0)
 | 
						|
						count_bcast_timer = delay_bcast_timer
 | 
						|
					end
 | 
						|
 | 
						|
					----- CONTROLS -----
 | 
						|
					if not IsPauseMenuActive() and UpdateOnscreenKeyboard() ~= 0 and not radio_wheel_active then
 | 
						|
						if not key_lock then
 | 
						|
							------ TOG DFLT SRN LIGHTS ------
 | 
						|
							if IsDisabledControlJustReleased(0, 85) then
 | 
						|
								if lights_on then
 | 
						|
									AUDIO:Play('Off', AUDIO.off_volume)
 | 
						|
									--	SET NUI IMAGES
 | 
						|
									HUD:SetItemState('switch', false)
 | 
						|
									HUD:SetItemState('siren', false)
 | 
						|
									--	TURN OFF SIRENS (R* LIGHTS)
 | 
						|
									SetVehicleSiren(veh, false)
 | 
						|
									if trailer ~= nil and trailer ~= 0 then
 | 
						|
										SetVehicleSiren(trailer, false)
 | 
						|
									end
 | 
						|
 | 
						|
								else
 | 
						|
									AUDIO:Play('On', AUDIO.on_volume) -- On
 | 
						|
									--	SET NUI IMAGES
 | 
						|
									HUD:SetItemState('switch', true)
 | 
						|
									--	TURN OFF SIRENS (R* LIGHTS)
 | 
						|
									SetVehicleSiren(veh, true)
 | 
						|
									if trailer ~= nil and trailer ~= 0 then
 | 
						|
										SetVehicleSiren(trailer, true)
 | 
						|
									end
 | 
						|
								end
 | 
						|
								AUDIO:ResetActivityTimer()
 | 
						|
								count_bcast_timer = delay_bcast_timer
 | 
						|
							------ TOG LX SIREN ------
 | 
						|
							elseif IsDisabledControlJustReleased(0, 19) then
 | 
						|
								if state_lxsiren[veh] == 0 then
 | 
						|
									if lights_on then
 | 
						|
										AUDIO:Play('Upgrade', AUDIO.upgrade_volume)
 | 
						|
										HUD:SetItemState('siren', true)
 | 
						|
										if not tone_main_reset_standby then
 | 
						|
											--	GET THE SAVED TONE VERIFY IT IS APPROVED, AND NOT DISABLED / BUTTON ONLY
 | 
						|
											tone_mem_id = UTIL:GetToneID('MAIN_MEM')
 | 
						|
											tone_mem_option = UTIL:GetToneOption(tone_mem_id)
 | 
						|
											if UTIL:IsApprovedTone(tone_mem_id) and tone_mem_option ~= 3 and tone_mem_option ~= 4 then
 | 
						|
												SetLxSirenStateForVeh(veh, tone_mem_id)
 | 
						|
											else
 | 
						|
												new_tone = UTIL:GetNextSirenTone(tone_mem_id, veh, true)
 | 
						|
												UTIL:SetToneByID('MAIN_MEM', new_tone)
 | 
						|
												SetLxSirenStateForVeh(veh, new_tone)
 | 
						|
											end
 | 
						|
 | 
						|
										else
 | 
						|
											default_tone = UTIL:GetToneAtPos(2)
 | 
						|
											default_tone_option = UTIL:GetToneOption(default_tone)
 | 
						|
											if default_tone_option == 3 or default_tone_option == 4 then
 | 
						|
												new_tone = UTIL:GetNextSirenTone(default_tone, veh, true)
 | 
						|
											else
 | 
						|
												new_tone = UTIL:GetToneAtPos(2)
 | 
						|
											end
 | 
						|
											SetLxSirenStateForVeh(veh, new_tone)
 | 
						|
										end
 | 
						|
									end
 | 
						|
								else
 | 
						|
									AUDIO:Play('Downgrade', AUDIO.downgrade_volume)
 | 
						|
									-- ONLY CHANGE NUI STATE IF PWRCALL IS OFF AS WELL
 | 
						|
									if state_pwrcall[veh] == 0 then
 | 
						|
										HUD:SetItemState('siren', false)
 | 
						|
									end
 | 
						|
									if not tone_main_reset_standby then
 | 
						|
										UTIL:SetToneByID('MAIN_MEM', state_lxsiren[veh])
 | 
						|
									end
 | 
						|
									SetLxSirenStateForVeh(veh, 0)
 | 
						|
								end
 | 
						|
								AUDIO:ResetActivityTimer()
 | 
						|
								count_bcast_timer = delay_bcast_timer
 | 
						|
							-- POWERCALL
 | 
						|
							elseif IsDisabledControlJustReleased(0, 172) and not IsMenuOpen() then
 | 
						|
								if state_pwrcall[veh] == 0 then
 | 
						|
									if lights_on then
 | 
						|
										AUDIO:Play('Upgrade', AUDIO.upgrade_volume)
 | 
						|
										HUD:SetItemState('siren', true)
 | 
						|
										SetPowercallStateForVeh(veh, UTIL:GetToneID('AUX'))
 | 
						|
										count_bcast_timer = delay_bcast_timer
 | 
						|
									end
 | 
						|
								else
 | 
						|
									AUDIO:Play('Downgrade', AUDIO.downgrade_volume)
 | 
						|
									if state_lxsiren[veh] == 0 then
 | 
						|
										HUD:SetItemState('siren', false)
 | 
						|
									end
 | 
						|
									SetPowercallStateForVeh(veh, 0)
 | 
						|
								end
 | 
						|
								AUDIO:ResetActivityTimer()
 | 
						|
								count_bcast_timer = delay_bcast_timer
 | 
						|
							end
 | 
						|
							-- CYCLE LX SRN TONES
 | 
						|
							if state_lxsiren[veh] > 0 then
 | 
						|
								if IsDisabledControlJustReleased(0, 80) then
 | 
						|
									AUDIO:Play('Upgrade', AUDIO.upgrade_volume)
 | 
						|
									HUD:SetItemState('horn', false)
 | 
						|
									SetLxSirenStateForVeh(veh, UTIL:GetNextSirenTone(state_lxsiren[veh], veh, true))
 | 
						|
									count_bcast_timer = delay_bcast_timer
 | 
						|
								elseif IsDisabledControlPressed(0, 80) then
 | 
						|
									HUD:SetItemState('horn', true)
 | 
						|
								end
 | 
						|
							end
 | 
						|
 | 
						|
							-- MANU
 | 
						|
							if state_lxsiren[veh] < 1 then
 | 
						|
								if IsDisabledControlPressed(0, 80) then
 | 
						|
									AUDIO:ResetActivityTimer()
 | 
						|
									actv_manu = true
 | 
						|
									HUD:SetItemState('siren', true)
 | 
						|
								else
 | 
						|
									if actv_manu then
 | 
						|
										HUD:SetItemState('siren', false)
 | 
						|
									end
 | 
						|
									actv_manu = false
 | 
						|
								end
 | 
						|
							else
 | 
						|
								if actv_manu then
 | 
						|
									HUD:SetItemState('siren', false)
 | 
						|
								end
 | 
						|
								actv_manu = false
 | 
						|
							end
 | 
						|
 | 
						|
							-- HORN
 | 
						|
							if IsDisabledControlPressed(0, 86) then
 | 
						|
								actv_horn = true
 | 
						|
								AUDIO:ResetActivityTimer()
 | 
						|
								HUD:SetItemState('horn', true)
 | 
						|
							else
 | 
						|
								if actv_horn or actv_manu then
 | 
						|
									HUD:SetItemState('horn', false)
 | 
						|
								end
 | 
						|
								actv_horn = false
 | 
						|
							end
 | 
						|
 | 
						|
 | 
						|
							--AIRHORN AND MANU BUTTON SFX
 | 
						|
							if AUDIO.airhorn_button_SFX then
 | 
						|
								if IsDisabledControlJustPressed(0, 86) then
 | 
						|
									AUDIO:Play('Press', AUDIO.upgrade_volume)
 | 
						|
								end
 | 
						|
								if IsDisabledControlJustReleased(0, 86) then
 | 
						|
									AUDIO:Play('Release', AUDIO.upgrade_volume)
 | 
						|
								end
 | 
						|
							end
 | 
						|
							if AUDIO.manu_button_SFX and state_lxsiren[veh] == 0 then
 | 
						|
								if IsDisabledControlJustPressed(0, 80) then
 | 
						|
									AUDIO:Play('Press', AUDIO.upgrade_volume)
 | 
						|
								end
 | 
						|
								if IsDisabledControlJustReleased(0, 80) then
 | 
						|
									AUDIO:Play('Release', AUDIO.upgrade_volume)
 | 
						|
								end
 | 
						|
							end
 | 
						|
						else
 | 
						|
							if (IsDisabledControlJustReleased(0, 86) or
 | 
						|
								IsDisabledControlJustReleased(0, 172) or
 | 
						|
								IsDisabledControlJustReleased(0, 19) or
 | 
						|
								IsDisabledControlJustReleased(0, 85)) then
 | 
						|
									if locked_press_count % reminder_rate == 0 then
 | 
						|
										AUDIO:Play('Locked_Press', AUDIO.lock_reminder_volume, true) -- lock reminder
 | 
						|
										HUD:ShowNotification('~y~~h~Reminder:~h~ ~s~Your siren control box is ~r~locked~s~.', true)
 | 
						|
									end
 | 
						|
									locked_press_count = locked_press_count + 1
 | 
						|
							end
 | 
						|
						end
 | 
						|
					end
 | 
						|
 | 
						|
					---- ADJUST HORN / MANU STATE ----
 | 
						|
					local hmanu_state_new = 0
 | 
						|
					if actv_horn == true and actv_manu == false then
 | 
						|
						hmanu_state_new = UTIL:GetToneID('ARHRN')
 | 
						|
					elseif actv_horn == false and actv_manu == true then
 | 
						|
						hmanu_state_new = UTIL:GetToneID('PMANU')
 | 
						|
					elseif actv_horn == true and actv_manu == true then
 | 
						|
						hmanu_state_new = UTIL:GetToneID('SMANU')
 | 
						|
					end
 | 
						|
					if tone_airhorn_intrp then
 | 
						|
						if hmanu_state_new == UTIL:GetToneID('ARHRN') then
 | 
						|
							if state_lxsiren[veh] > 0 and actv_lxsrnmute_temp == false then
 | 
						|
								srntone_temp = state_lxsiren[veh]
 | 
						|
								SetLxSirenStateForVeh(veh, 0)
 | 
						|
								actv_lxsrnmute_temp = true
 | 
						|
							end
 | 
						|
						else
 | 
						|
							if actv_lxsrnmute_temp == true then
 | 
						|
								SetLxSirenStateForVeh(veh, srntone_temp)
 | 
						|
								actv_lxsrnmute_temp = false
 | 
						|
							end
 | 
						|
						end
 | 
						|
					end
 | 
						|
 | 
						|
					if state_airmanu[veh] ~= hmanu_state_new then
 | 
						|
						SetAirManuStateForVeh(veh, hmanu_state_new)
 | 
						|
						count_bcast_timer = delay_bcast_timer
 | 
						|
					end
 | 
						|
				end
 | 
						|
			else
 | 
						|
				-- DISABLE SIREN AUDIO FOR ALL VEHICLES NOT VC_EMERGENCY (VEHICLES.META)
 | 
						|
				TogMuteDfltSrnForVeh(veh, true)
 | 
						|
			end
 | 
						|
 | 
						|
			--- IS ANY LAND VEHICLE ---
 | 
						|
			if GetVehicleClass(veh) ~= 14 and GetVehicleClass(veh) ~= 15 and GetVehicleClass(veh) ~= 16 and GetVehicleClass(veh) ~= 21 then
 | 
						|
				----- CONTROLS -----
 | 
						|
				if not IsPauseMenuActive() then
 | 
						|
					-- IND L
 | 
						|
					if IsDisabledControlJustReleased(0, left_signal_key) then -- INPUT_VEH_PREV_RADIO_TRACK
 | 
						|
						local cstate = state_indic[veh]
 | 
						|
						if cstate == ind_state_l then
 | 
						|
							state_indic[veh] = ind_state_o
 | 
						|
							actv_ind_timer = false
 | 
						|
						else
 | 
						|
							state_indic[veh] = ind_state_l
 | 
						|
							actv_ind_timer = true
 | 
						|
						end
 | 
						|
						TogIndicStateForVeh(veh, state_indic[veh])
 | 
						|
						count_ind_timer = 0
 | 
						|
						count_bcast_timer = delay_bcast_timer
 | 
						|
					-- IND R
 | 
						|
					elseif IsDisabledControlJustReleased(0, right_signal_key) then -- INPUT_VEH_NEXT_RADIO_TRACK
 | 
						|
						local cstate = state_indic[veh]
 | 
						|
						if cstate == ind_state_r then
 | 
						|
							state_indic[veh] = ind_state_o
 | 
						|
							actv_ind_timer = false
 | 
						|
						else
 | 
						|
							state_indic[veh] = ind_state_r
 | 
						|
							actv_ind_timer = true
 | 
						|
						end
 | 
						|
						TogIndicStateForVeh(veh, state_indic[veh])
 | 
						|
						count_ind_timer = 0
 | 
						|
						count_bcast_timer = delay_bcast_timer
 | 
						|
					-- IND H
 | 
						|
					elseif IsControlPressed(0, hazard_key) then -- INPUT_FRONTEND_CANCEL / Backspace
 | 
						|
						if GetLastInputMethod(0) then -- last input was with kb
 | 
						|
							Wait(hazard_hold_duration)
 | 
						|
							if IsControlPressed(0, hazard_key) then -- INPUT_FRONTEND_CANCEL / Backspace
 | 
						|
								local cstate = state_indic[veh]
 | 
						|
								if cstate == ind_state_h then
 | 
						|
									state_indic[veh] = ind_state_o
 | 
						|
									AUDIO:Play('Hazards_Off', AUDIO.hazards_volume, true) -- Hazards Off
 | 
						|
								else
 | 
						|
									state_indic[veh] = ind_state_h
 | 
						|
									AUDIO:Play('Hazards_On', AUDIO.hazards_volume, true) -- Hazards On
 | 
						|
								end
 | 
						|
								TogIndicStateForVeh(veh, state_indic[veh])
 | 
						|
								actv_ind_timer = false
 | 
						|
								count_ind_timer = 0
 | 
						|
								count_bcast_timer = delay_bcast_timer
 | 
						|
								Wait(300)
 | 
						|
							end
 | 
						|
						end
 | 
						|
					end
 | 
						|
				end
 | 
						|
 | 
						|
				----- AUTO BROADCAST VEH STATES -----
 | 
						|
				if count_bcast_timer > delay_bcast_timer then
 | 
						|
					count_bcast_timer = 0
 | 
						|
					--- IS EMERG VEHICLE ---
 | 
						|
					if GetVehicleClass(veh) == 18 then
 | 
						|
						TriggerServerEvent('lvc:TogDfltSrnMuted_s')
 | 
						|
						TriggerServerEvent('lvc:SetLxSirenState_s', state_lxsiren[veh])
 | 
						|
						TriggerServerEvent('lvc:SetPwrcallState_s', state_pwrcall[veh])
 | 
						|
						TriggerServerEvent('lvc:SetAirManuState_s', state_airmanu[veh])
 | 
						|
					end
 | 
						|
					--- IS ANY OTHER VEHICLE ---
 | 
						|
					TriggerServerEvent('lvc:TogIndicState_s', state_indic[veh])
 | 
						|
				else
 | 
						|
					count_bcast_timer = count_bcast_timer + 1
 | 
						|
				end
 | 
						|
			end
 | 
						|
		end
 | 
						|
		Wait(0)
 | 
						|
	end
 | 
						|
end) |