Problème avec mon chat vocal "pma-voice"

Bonjour, bonsoir

● Machine locale, VPS ● Framework utilisé (ES/ESX/…) ● Nom de la ressource pma-voice

● Quand est-ce que l’erreur apparaît ? aucune erreur apparaît dans les consoles

● Screen du bug image image_2022-01-29_155755

●Voilà j’ai un problème avec mon vocale quand je parle en radio et quand on se téléphone ça fonctionne quand on veut parler in game à distance nous on se voit parler mais on entend pas les autres il y aurait quelqu’un qui a une idée du pourquoi merci d’avance

●client `local Cfg = Cfg local currentGrid = 0 – we can’t use GetConvarInt because its not a integer, and theres no way to get a float… so use a hacky way it is! local volumes = { [‹ radio ›] = tonumber(GetConvar(‹ voice_defaultVolume ›, ‹ 0.3 ›)), [‹ phone ›] = tonumber(GetConvar(‹ voice_defaultVolume ›, ‹ 0.3 ›)), } plyState = LocalPlayer.state local micClicks = true playerServerId = GetPlayerServerId(PlayerId()) radioEnabled, radioPressed, mode, radioChannel, callChannel = false, false, 2, 0, 0

radioData = {} callData = {}

– TODO: Convert the last Cfg to a Convar, while still keeping it simple. AddEventHandler(‹ pma-voice:settingsCallback ›, function(cb) cb(Cfg) end)

AddEventHandler(‹ fl_voice:changeRadioVolume ›, function(newVolume) volume = newVolume if volume > 1.0 then volume = 1.0 end setVolume(volume, ‹ radio ›) end)

– TODO: Better implementation of this? RegisterCommand(‹ vol ›, function(source, args) local vol = tonumber(args[1]) if vol and vol > 1.0 then volume = setVolume(vol / 100) else volume = setVolume(vol) end end)

–[[RegisterCommand(‹ vol ›, function(_, args) print(args[1]) if args[1] then setVolume(args[1]) end end)]]

— function setVolume — Toggles the players volume —@param volume number between 0 and 100 —@param volumeType string the volume type (currently radio & call) to set the volume of (opt) function setVolume(volume, volumeType) local volume = tonumber(volume) local checkType = type(volume) if checkType ~= ‹ number › then return error((‹ setVolume expected type number, got %s ›):format(checkType)) end if volumeType then local volumeTbl = volumes[volumeType] if volumeTbl then plyState:set(volumeType, volume, GetConvarInt(‹ voice_syncData ›, 0) == 1) volumes[volumeType] = volume else error((‹ setVolume got a invalid volume type %s ›):format(volumeType)) end else for types, vol in pairs(volumes) do vol = volume plyState:set(types, volume, GetConvarInt(‹ voice_syncData ›, 0) == 1) end end end exports(‹ setVolume ›, setVolume)

exports(‹ setRadioVolume ›, function(vol) setVolume(vol, ‹ radio ›) end) exports(‹ getRadioVolume ›, function() return volumes[‹ radio ›] end) exports(« setCallVolume », function(vol) setVolume(vol, ‹ phone ›) end) exports(‹ getCallVolume ›, function() return volumes[‹ phone ›] end)

– default submix incase people want to fiddle with it. – freq_low = 389.0 – freq_hi = 3248.0 – fudge = 0.0 – rm_mod_freq = 0.0 – rm_mix = 0.16 – o_freq_lo = 348.0 – 0_freq_hi = 4900.0

– radio submix radioEffectId = CreateAudioSubmix(« Radio ») SetAudioSubmixEffectRadioFx(radioEffectId, 0) SetAudioSubmixEffectParamInt(radioEffectId, 0, GetHashKey(« default »), 1) SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« freq_low »), 389.0) SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« freq_hi »), 3248.0) –SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« fudge »), 0.0) –SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« rm_mod_freq »), 0.0) SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« rm_mix »), 0.16) –SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« o_freq_lo »), 348.0) –SetAudioSubmixEffectParamFloat(radioEffectId, 0, GetHashKey(« o_freq_hi »), 4900.0) AddAudioSubmixOutput(radioEffectId, 0)

local phoneEffectId = CreateAudioSubmix(‹ Phone ›) SetAudioSubmixEffectRadioFx(phoneEffectId, 1) SetAudioSubmixEffectParamInt(phoneEffectId, 1, GetHashKey(‹ default ›), 1) SetAudioSubmixEffectParamFloat(phoneEffectId, 1, GetHashKey(‹ freq_low ›), 300.0) SetAudioSubmixEffectParamFloat(phoneEffectId, 1, GetHashKey(‹ freq_hi ›), 6000.0) AddAudioSubmixOutput(phoneEffectId, 1)

local submixFunctions = { [‹ radio ›] = function(plySource) MumbleSetSubmixForServerId(plySource, radioEffectId) end, [‹ phone ›] = function(plySource) MumbleSetSubmixForServerId(plySource, phoneEffectId) end }

– used to prevent a race condition if they talk again afterwards, which would lead to their voice going to default. local disableSubmixReset = {} — function toggleVoice — Toggles the players voice —@param plySource number the players server id to override the volume for —@param enabled boolean if the players voice is getting activated or deactivated —@param moduleType string the volume & submix to use for the voice. function toggleVoice(plySource, enabled, moduleType) logger.verbose(’[main] Updating %s to talking: %s with submix %s’, plySource, enabled, moduleType) if enabled then MumbleSetVolumeOverrideByServerId(plySource, enabled and volumes[moduleType]) if GetConvarInt(‹ voice_enableSubmix ›, 0) == 1 or GetConvarInt(‹ voice_enableRadioSubmix ›, 0) == 1 then if moduleType then disableSubmixReset[plySource] = true submixFunctionsmoduleType else MumbleSetSubmixForServerId(plySource, -1) end end else if GetConvarInt(‹ voice_enableSubmix ›, 0) == 1 or GetConvarInt(‹ voice_enableRadioSubmix ›, 0) == 1 then – garbage collect it disableSubmixReset[plySource] = nil SetTimeout(250, function() if not disableSubmixReset[plySource] then MumbleSetSubmixForServerId(plySource, -1) end end) end MumbleSetVolumeOverrideByServerId(plySource, -1.0) end end

— function playerTargets —Adds players voices to the local players listen channels allowing —Them to communicate at long range, ignoring proximity range. —@param targets table expects multiple tables to be sent over function playerTargets(…) local targets = {…} local addedPlayers = { [playerServerId] = true }

for i = 1, #targets do
	for id, _ in pairs(targets[i]) do
		-- we don't want to log ourself, or listen to ourself
		if addedPlayers[id] and id ~= playerServerId then
			logger.verbose('[main] %s is already target don\'t re-add', id)
			goto skip_loop
		end
		if not addedPlayers[id] then
			logger.verbose('[main] Adding %s as a voice target', id)
			addedPlayers[id] = true
			MumbleAddVoiceTargetPlayerByServerId(1, id)
		end
		::skip_loop::
	end
end

end

— function playMicClicks —plays the mic click if the player has them enabled. —@param clickType boolean whether to play the ‹ on › or ‹ off › click. function playMicClicks(clickType) if micClicks ~= ‹ true › then return end SendNUIMessage({ sound = (clickType and « audio_on » or « audio_off »), volume = (clickType and (volume) or 0.05) }) end

local playerMuted = false RegisterCommand(’+cycleproximity’, function() if GetConvarInt(‹ voice_enableProximity ›, 1) ~= 1 then return end if playerMuted then return end

local voiceMode = mode
local newMode = voiceMode + 1

voiceMode = (newMode <= #Cfg.voiceModes and newMode) or 1
local voiceModeData = Cfg.voiceModes[voiceMode]
MumbleSetAudioInputDistance(voiceModeData[1] + 0.0)
mode = voiceMode
plyState:set('proximity', {
	index = voiceMode,
	distance =  voiceModeData[1],
	mode = voiceModeData[2],
}, GetConvarInt('voice_syncData', 0) == 1)
-- make sure we update the UI to the latest voice mode
SendNUIMessage({
	voiceMode = voiceMode - 1
})
TriggerEvent('pma-voice:setTalkingMode', voiceMode)
Citizen.CreateThread(function()
	local i = 0
	while i < 15 do
		Citizen.Wait(0)
		i = i + 1
		DrawMarker(1, GetEntityCoords(PlayerPedId()) - vector3(0, 0, 0.9), 0, 0, 0, 0, 0, 0, Cfg.voiceModes[voiceMode][1] * 2.0, Cfg.voiceModes[voiceMode][1] * 2.0, 0.8001, 0, 75, 255, 165, 0,0, 0,0)
	end
end)

end, false) RegisterCommand(’-cycleproximity’, function() end) RegisterKeyMapping(’+cycleproximity’, ‹ Porximité voix ›, ‹ keyboard ›, GetConvar(‹ voice_defaultCycle ›, ‹ W ›))

— Toggles the current player muted function toggleMute() playerMuted = not playerMuted

if playerMuted then
	plyState:set('proximity', {
		index = 0,
		distance = 0.1,
		mode = 'Muted',
	}, GetConvarInt('voice_syncData', 0) == 1)
	MumbleSetAudioInputDistance(0.1)
else
	local voiceModeData = Cfg.voiceModes[mode]
	plyState:set('proximity', {
		index = mode,
		distance =  voiceModeData[1],
		mode = voiceModeData[2],
	}, GetConvarInt('voice_syncData', 0) == 1)
	MumbleSetAudioInputDistance(Cfg.voiceModes[mode][1])
end

end exports(‹ toggleMute ›, toggleMute) RegisterNetEvent(‹ pma-voice:toggleMute ›, toggleMute)

local mutedTbl = {} — toggles the targeted player muted —@param source number the player to mute function toggleMutePlayer(source) if mutedTbl[source] then mutedTbl[source] = nil MumbleSetVolumeOverrideByServerId(source, -1.0) else mutedTbl[source] = true MumbleSetVolumeOverrideByServerId(source, 0.0) end end exports(‹ toggleMutePlayer ›, toggleMutePlayer)

— function setVoiceProperty — sets the specified voice property —@param type string what voice property you want to change (only takes ‹ radioEnabled › and ‹ micClicks ›) —@param value any the value to set the type to. function setVoiceProperty(type, value) if type == « radioEnabled » then radioEnabled = value SendNUIMessage({ radioEnabled = value }) elseif type == « micClicks » then local val = tostring(value) micClicks = val SetResourceKvp(‹ pma-voice_enableMicClicks ›, val) end end exports(‹ setVoiceProperty ›, setVoiceProperty) – compatibility exports(‹ SetMumbleProperty ›, setVoiceProperty) exports(‹ SetTokoProperty ›, setVoiceProperty)

local currentRouting = 0 local nextRoutingRefresh = GetGameTimer() local overrideCoords = false

— function setOverrideCoords — will have to be updated every so often if used for spectate. —@param coords vector3|boolean the coords to set override for, or false to reset function setOverrideCoords(coords) local coordType = type(coords) if coordType ~= ‹ vector3 › and coordType ~= ‹ boolean › then return logger.error(’« setOverrideCoords » expects a vector3 or boolean, got %s’, coordType) end overrideCoords = coords end exports(‹ setOverrideCoords ›, setOverrideCoords)

— function getGridZone — calculate the players grid —@return number returns the players current grid. local function getGridZone() local plyPos = overrideCoords or GetEntityCoords(PlayerPedId(), false) local zoneRadius = GetConvarInt(‹ voice_zoneRadius ›, 16) * 2 local zoneOffset = (256 / zoneRadius) if nextRoutingRefresh < GetGameTimer() then – Constant deserialization (every frame) is a bad idea, only update it every so often. nextRoutingRefresh = GetGameTimer() + 500 currentRouting = LocalPlayer.state.routingBucket or 0 end – this code might be hard to follow return ( –[[ 31 is the initial offses]] math.floor( 31 * ( --[[ offset from the original zone should return a multiple]] zoneOffset) + –[[ returns -6 * zoneOffset so we want to offset it ]] (zoneOffset * 6) - 6 )) + (–[[ Offset routing bucket by 5 (we listen to closest 5 channels) + 5 (routing starts at 0)]]((currentRouting) * 5) + 5) + math.ceil((plyPos.x + plyPos.y) / (zoneRadius)) end

— function updateZone — updates the players current grid, if they’re in a different grid. —@param forced boolean whether or not to force a grid refresh. default: false local function updateZone(forced) local newGrid = getGridZone() if newGrid ~= currentGrid or forced then logger.info(‹ Updating zone from %s to %s and adding nearby grids, was forced: %s. ›, currentGrid, newGrid, forced) currentGrid = newGrid MumbleClearVoiceTargetChannels(1) NetworkSetVoiceChannel(currentGrid) LocalPlayer.state:set(‹ grid ›, currentGrid, true) – add nearby grids to voice targets for nearbyGrids = currentGrid - 3, currentGrid + 3 do MumbleAddVoiceTargetChannel(1, nearbyGrids) end end end

– cache talking status so we only send a nui message when its not the same as what it was before local lastTalkingStatus = false local lastRadioStatus = false Citizen.CreateThread(function() TriggerEvent(‹ chat:addSuggestion ›, ‹ /mute ›, ‹ Mutes the player with the specified id ›, { { name = « player id », help = « the player to toggle mute » } }) while true do – wait for reconnection, trying to set your voice channel when theres nothing to set it to is useless. while not MumbleIsConnected() do currentGrid = -1 – reset the grid to something out of bounds so it will resync their zone on disconnect. Wait(100) end updateZone() if GetConvarInt(‹ voice_enableUi ›, 1) == 1 then if lastRadioStatus ~= radioPressed or lastTalkingStatus ~= (NetworkIsPlayerTalking(PlayerId()) == 1) then lastRadioStatus = radioPressed lastTalkingStatus = NetworkIsPlayerTalking(PlayerId()) == 1 SendNUIMessage({ usingRadio = lastRadioStatus, talking = lastTalkingStatus }) end end Wait(GetConvarInt(‹ voice_zoneRefreshRate ›, 50)) end end)

– cache their external servers so if it changes in runtime we can reconnect the client. local externalAddress = ‹  › local externalPort = 0 CreateThread(function() while true do Wait(500) – only change if what we have doesn’t match the cache if GetConvar(‹ voice_externalAddress ›, ‹  ›) ~= externalAddress or GetConvarInt(‹ voice_externalPort ›, 0) ~= externalPort then externalAddress = GetConvar(‹ voice_externalAddress ›, ‹  ›) externalPort = GetConvarInt(‹ voice_externalPort ›, 0) MumbleSetServerAddress(GetConvar(‹ voice_externalAddress ›, ‹  ›), GetConvarInt(‹ voice_externalPort ›, 0)) end end end)

— forces the player to resync with the mumble server — sets their server address (if there is one) and forces their grid to update RegisterCommand(‹ vsync ›, function() local newGrid = getGridZone() print((’[vsync] Forcing zone from %s to %s and resetting voice targets.’):format(currentGrid, newGrid)) if GetConvar(‹ voice_externalAddress ›, ‹  ›) ~= ‹  › and GetConvarInt(‹ voice_externalPort ›, 0) ~= 0 then MumbleSetServerAddress(GetConvar(‹ voice_externalAddress ›, ‹  ›), GetConvarInt(‹ voice_externalPort ›, 0)) while not MumbleIsConnected() do Wait(250) end end NetworkSetVoiceChannel(newGrid + 100) – reset the players voice targets MumbleSetVoiceTarget(0) MumbleClearVoiceTarget(1) MumbleSetVoiceTarget(1) MumbleClearVoiceTargetPlayers(1) – force a zone update. updateZone(true) end)

AddEventHandler(‹ onClientResourceStart ›, function(resource) if resource ~= GetCurrentResourceName() then return end print(‹ Starting script initialization ›)

local micClicksKvp = GetResourceKvpString('pma-voice_enableMicClicks')
if not micClicksKvp then
	SetResourceKvp('pma-voice_enableMicClicks', tostring(true))
else
	micClicks = micClicksKvp
end

local voiceModeData = Cfg.voiceModes[mode]
-- sets how far the player can talk
MumbleSetAudioInputDistance(voiceModeData[1] + 0.0)
plyState:set('proximity', {
	index = mode,
	distance =  voiceModeData[1],
	mode = voiceModeData[2],
}, GetConvarInt('voice_syncData', 0) == 1)

-- this sets how far the player can hear.
MumbleSetAudioOutputDistance(Cfg.voiceModes[#Cfg.voiceModes][1] + 0.0)

while not MumbleIsConnected() do
	Wait(250)
end


MumbleSetVoiceTarget(0)
MumbleClearVoiceTarget(1)
MumbleSetVoiceTarget(1)

updateZone()

print('Script initialization finished.')

-- not waiting right here (in testing) let to some cases of the UI 
-- just not working at all.
Wait(1000)
if GetConvarInt('voice_enableUi', 1) == 1 then
	SendNUIMessage({
		voiceModes = json.encode(Cfg.voiceModes),
		voiceMode = mode - 1
	})
end

end)

RegisterCommand(« grid », function() print((‹ Players current grid is %s ›):format(currentGrid)) end)

AddEventHandler(‹ mumbleConnected ›, function(address, shouldReconnect) logger.log(‹ Connected to mumble server with address of %s, should reconnect on disconnect is set to %s ›, GetConvarInt(‹ voice_hideEndpoints ›, 1) == 1 and ‹ HIDDEN › or address, shouldReconnect) – don’t try to set channel instantly, we’re still getting data. Wait(1000) updateZone(true) end)

AddEventHandler(‹ mumbleDisconnected ›, function(address) logger.log(‹ Disconnected from mumble server with address of %s ›, GetConvarInt(‹ voice_hideEndpoints ›, 1) == 1 and ‹ HIDDEN › or address) currentGrid = -1 end)`

Bonjour, tu as bien désactivé vMenus voice chat ?

Bonjour, oui je vais bien et toi cv ?? si je désactiver le vocal du vMenu je ne pouvais plus parler ni au téléphone ni à la radio maime en suprimant le vMenu

Rebonjour. En fait il faut que tu désactives le vocal du Vmenu pour avoir le son IG. Ensuite pour utiliser radio et téléphone tu dois orienter le port de la voix sur le protocole PMA, çà doit être dans le client du gcphone. Tu changes l’exports de l’acceptcall et du reject call par ceci : exports[‹ pma-voice ›]:setCallChannel(1)

Bon game

Ca fonctionne merci à toi et excuse-moi du retard j’ai eu d’autres problèmes merci

Pas de soucis, bon jeu à toi.