Citizen.CreateThread(function() if Config.Voice.System == 'saltychat' then local idCount = 0 local function getVoiceRangeIndex() local voiceRange = exports.saltychat:GetVoiceRange() for _, range in pairs(Config.Voice.Ranges) do if range == voiceRange then return _ - 1 end end end AddEventHandler('SaltyChat_VoiceRangeChanged', function(voiceRange, index, availableVoiceRanges) local voiceRangeIndex = getVoiceRangeIndex() if not voiceRangeIndex then voiceRangeIndex = index end SendNUIMessage({ action = 'voice', data = { type = 'range', range = voiceRangeIndex, availableVoiceRanges = availableVoiceRanges } }) local curId = idCount idCount = idCount + 1 change = curId SetTimeout(2500, function() if change == curId then change = nil end end) Citizen.CreateThread(function() local opacity = 175 while change == curId do Citizen.Wait(0) local ped = PlayerPedId() local coords = GetEntityCoords(ped) opacity = opacity - 1 DrawMarker(1, coords.x, coords.y, coords.z - 1.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, voiceRange * 2.0, voiceRange * 2.0, 1.0, Config.Voice.RangeColor.red, Config.Voice.RangeColor.green, Config.Voice.RangeColor.blue, opacity, false, false, true, 2, false, false, false) end end) end) AddEventHandler('SaltyChat_MicStateChanged', function(isMicrophoneEnabled) SendNUIMessage({ action = 'voice', data = { type = 'mic', state = isMicrophoneEnabled } }) end) AddEventHandler('SaltyChat_TalkStateChanged', function(isTalking) SendNUIMessage({ action = 'voice', data = { type = 'speak', state = isTalking } }) end) AddEventHandler('SaltyChat_RadioChannelChanged', function(radioChannel, isPrimaryChannel) if radioChannel and radioChannel ~= '0' then SendNUIMessage({ action = 'voice', data = { type = 'radio', state = true } }) else SendNUIMessage({ action = 'voice', data = { type = 'radio', state = false } }) end end) function GetCurrentVoiceRange() return getVoiceRangeIndex() end elseif Config.Voice.System == 'pma' then local function stringStarts(string, start) return string:sub(1, string.len(start)) == start end AddStateBagChangeHandler('radioChannel', 'player:' .. GetPlayerServerId(PlayerId()), function(bagName, key, value, reserved, replicated) if replicated or not stringStarts(bagName, "player:") then return end SendNUIMessage({ action = 'voice', data = { type = 'radio', state = value ~= 0 } }) end) Citizen.CreateThread(function() local isTalking = false while true do Citizen.Wait(33) local networkTalking = NetworkIsPlayerTalking(PlayerId()) if not isTalking and networkTalking then isTalking = true SendNUIMessage({ action = 'voice', data = { type = 'speak', state = true } }) elseif isTalking and not networkTalking then isTalking = false SendNUIMessage({ action = 'voice', data = { type = 'speak', state = false } }) end end end) local idCount = 0 AddEventHandler('pma-voice:setTalkingMode', function(voiceMode) local voice = Config.Voice.Ranges[voiceMode] SendNUIMessage({ action = 'voice', data = { type = 'range', range = voiceMode - 1, availableVoiceRanges = #Config.Voice.Ranges } }) local curId = idCount idCount = idCount + 1 change = curId voiceReachTimeout = SetTimeout(1500, function() if change == curId then change = nil end end) Citizen.CreateThread(function() local opacity = 175 while change == curId do Citizen.Wait(0) local ped = PlayerPedId() local coords = GetEntityCoords(ped) opacity = opacity - 1 DrawMarker(1, coords.x, coords.y, coords.z - 1.2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, voice * 2.0, voice * 2.0, 1.0, Config.Voice.RangeColor.red, Config.Voice.RangeColor.green, Config.Voice.RangeColor.blue, opacity, false, false, true, 2, false, false, false) end end) end) function GetCurrentVoiceRange() local proximity = Player(GetPlayerServerId(PlayerId())).state['proximity'] return (proximity.index or 2) - 1 end end end)