Saltychat Remove and PMA install
This commit is contained in:
parent
0bff8ae174
commit
2fd3c1fe70
94 changed files with 8799 additions and 5199 deletions
42
resources/[voice]/pma-voice/client/init/init.lua
Normal file
42
resources/[voice]/pma-voice/client/init/init.lua
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
|
||||
AddEventHandler('onClientResourceStart', function(resource)
|
||||
if resource ~= GetCurrentResourceName() then
|
||||
return
|
||||
end
|
||||
print('Starting script initialization')
|
||||
|
||||
-- Some people modify pma-voice and mess up the resource Kvp, which means that if someone
|
||||
-- joins another server that has pma-voice, it will error out, this will catch and fix the kvp.
|
||||
local success = pcall(function()
|
||||
local micClicksKvp = GetResourceKvpString('pma-voice_enableMicClicks')
|
||||
if not micClicksKvp then
|
||||
SetResourceKvp('pma-voice_enableMicClicks', tostring(true))
|
||||
else
|
||||
if micClicksKvp ~= 'true' and micClicksKvp ~= 'false' then
|
||||
error('Invalid Kvp, throwing error for automatic cleaning')
|
||||
end
|
||||
micClicks = micClicksKvp
|
||||
end
|
||||
end)
|
||||
|
||||
if not success then
|
||||
logger.warn('Failed to load resource Kvp, likely was inappropriately modified by another server, resetting the Kvp.')
|
||||
SetResourceKvp('pma-voice_enableMicClicks', tostring(true))
|
||||
micClicks = 'true'
|
||||
end
|
||||
sendUIMessage({
|
||||
uiEnabled = GetConvarInt("voice_enableUi", 1) == 1,
|
||||
voiceModes = json.encode(Cfg.voiceModes),
|
||||
voiceMode = mode - 1
|
||||
})
|
||||
|
||||
-- Reinitialize channels if they're set.
|
||||
if LocalPlayer.state.radioChannel ~= 0 then
|
||||
setRadioChannel(LocalPlayer.state.radioChannel)
|
||||
end
|
||||
|
||||
if LocalPlayer.state.callChannel ~= 0 then
|
||||
setCallChannel(LocalPlayer.state.callChannel)
|
||||
end
|
||||
print('Script initialization finished.')
|
||||
end)
|
||||
224
resources/[voice]/pma-voice/client/init/main.lua
Normal file
224
resources/[voice]/pma-voice/client/init/main.lua
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
local mutedPlayers = {}
|
||||
|
||||
-- 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 = {
|
||||
-- people are setting this to 1 instead of 1.0 and expecting it to work.
|
||||
['radio'] = GetConvarInt('voice_defaultRadioVolume', 30) / 100,
|
||||
['phone'] = GetConvarInt('voice_defaultPhoneVolume', 60) / 100,
|
||||
}
|
||||
|
||||
radioEnabled, radioPressed, mode = true, false, GetConvarInt('voice_defaultVoiceMode', 2)
|
||||
radioData = {}
|
||||
callData = {}
|
||||
|
||||
--- 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)
|
||||
type_check({volume, "number"})
|
||||
local volume = volume / 100
|
||||
|
||||
if volumeType then
|
||||
local volumeTbl = volumes[volumeType]
|
||||
if volumeTbl then
|
||||
LocalPlayer.state:set(volumeType, volume, true)
|
||||
volumes[volumeType] = volume
|
||||
else
|
||||
error(('setVolume got a invalid volume type %s'):format(volumeType))
|
||||
end
|
||||
else
|
||||
-- _ is here to not mess with global 'type' function
|
||||
for _type, vol in pairs(volumes) do
|
||||
volumes[_type] = volume
|
||||
LocalPlayer.state:set(_type, volume, true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
if gameVersion == 'fivem' then
|
||||
radioEffectId = CreateAudioSubmix('Radio')
|
||||
SetAudioSubmixEffectRadioFx(radioEffectId, 0)
|
||||
SetAudioSubmixEffectParamInt(radioEffectId, 0, `default`, 1)
|
||||
AddAudioSubmixOutput(radioEffectId, 0)
|
||||
|
||||
phoneEffectId = CreateAudioSubmix('Phone')
|
||||
SetAudioSubmixEffectRadioFx(phoneEffectId, 1)
|
||||
SetAudioSubmixEffectParamInt(phoneEffectId, 1, `default`, 1)
|
||||
SetAudioSubmixEffectParamFloat(phoneEffectId, 1, `freq_low`, 300.0)
|
||||
SetAudioSubmixEffectParamFloat(phoneEffectId, 1, `freq_hi`, 6000.0)
|
||||
AddAudioSubmixOutput(phoneEffectId, 1)
|
||||
end
|
||||
|
||||
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)
|
||||
if mutedPlayers[plySource] then return end
|
||||
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', 1) == 1 and gameVersion == 'fivem' then
|
||||
if moduleType then
|
||||
disableSubmixReset[plySource] = true
|
||||
submixFunctions[moduleType](plySource)
|
||||
else
|
||||
MumbleSetSubmixForServerId(plySource, -1)
|
||||
end
|
||||
end
|
||||
else
|
||||
if GetConvarInt('voice_enableSubmix', 1) == 1 and gameVersion == 'fivem' 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.
|
||||
---@diagnostic disable-next-line: undefined-doc-param
|
||||
---@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(voiceTarget, 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 logger.verbose("Not playing mic clicks because client has them disabled") end
|
||||
sendUIMessage({
|
||||
sound = (clickType and "audio_on" or "audio_off"),
|
||||
volume = (clickType and volumes["radio"] or 0.05)
|
||||
})
|
||||
end
|
||||
|
||||
--- toggles the targeted player muted
|
||||
---@param source number the player to mute
|
||||
function toggleMutePlayer(source)
|
||||
if mutedPlayers[source] then
|
||||
mutedPlayers[source] = nil
|
||||
MumbleSetVolumeOverrideByServerId(source, -1.0)
|
||||
else
|
||||
mutedPlayers[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
|
||||
sendUIMessage({
|
||||
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)
|
||||
|
||||
|
||||
-- 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)
|
||||
|
||||
|
||||
if gameVersion == 'redm' then
|
||||
CreateThread(function()
|
||||
while true do
|
||||
if IsControlJustPressed(0, 0xA5BDCD3C --[[ Right Bracket ]]) then
|
||||
ExecuteCommand('cycleproximity')
|
||||
end
|
||||
if IsControlJustPressed(0, 0x430593AA --[[ Left Bracket ]]) then
|
||||
ExecuteCommand('+radiotalk')
|
||||
elseif IsControlJustReleased(0, 0x430593AA --[[ Left Bracket ]]) then
|
||||
ExecuteCommand('-radiotalk')
|
||||
end
|
||||
|
||||
Wait(0)
|
||||
end
|
||||
end)
|
||||
end
|
||||
156
resources/[voice]/pma-voice/client/init/proximity.lua
Normal file
156
resources/[voice]/pma-voice/client/init/proximity.lua
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
-- used when muted
|
||||
local disableUpdates = false
|
||||
local isListenerEnabled = false
|
||||
local plyCoords = GetEntityCoords(PlayerPedId())
|
||||
|
||||
function orig_addProximityCheck(ply)
|
||||
local tgtPed = GetPlayerPed(ply)
|
||||
local voiceModeData = Cfg.voiceModes[mode]
|
||||
local distance = GetConvar('voice_useNativeAudio', 'false') == 'true' and voiceModeData[1] * 3 or voiceModeData[1]
|
||||
|
||||
return #(plyCoords - GetEntityCoords(tgtPed)) < distance
|
||||
end
|
||||
local addProximityCheck = orig_addProximityCheck
|
||||
|
||||
exports("overrideProximityCheck", function(fn)
|
||||
addProximityCheck = fn
|
||||
end)
|
||||
|
||||
exports("resetProximityCheck", function()
|
||||
addProximityCheck = orig_addProximityCheck
|
||||
end)
|
||||
|
||||
function addNearbyPlayers()
|
||||
if disableUpdates then return end
|
||||
-- update here so we don't have to update every call of addProximityCheck
|
||||
plyCoords = GetEntityCoords(PlayerPedId())
|
||||
|
||||
MumbleClearVoiceTargetChannels(voiceTarget)
|
||||
local players = GetActivePlayers()
|
||||
for i = 1, #players do
|
||||
local ply = players[i]
|
||||
local serverId = GetPlayerServerId(ply)
|
||||
|
||||
if addProximityCheck(ply) then
|
||||
if isTarget then goto skip_loop end
|
||||
|
||||
logger.verbose('Added %s as a voice target', serverId)
|
||||
MumbleAddVoiceTargetChannel(voiceTarget, serverId)
|
||||
end
|
||||
|
||||
::skip_loop::
|
||||
end
|
||||
end
|
||||
|
||||
function setSpectatorMode(enabled)
|
||||
logger.info('Setting spectate mode to %s', enabled)
|
||||
isListenerEnabled = enabled
|
||||
local players = GetActivePlayers()
|
||||
if isListenerEnabled then
|
||||
for i = 1, #players do
|
||||
local ply = players[i]
|
||||
local serverId = GetPlayerServerId(ply)
|
||||
if serverId == playerServerId then goto skip_loop end
|
||||
logger.verbose("Adding %s to listen table", serverId)
|
||||
MumbleAddVoiceChannelListen(serverId)
|
||||
::skip_loop::
|
||||
end
|
||||
else
|
||||
for i = 1, #players do
|
||||
local ply = players[i]
|
||||
local serverId = GetPlayerServerId(ply)
|
||||
if serverId == playerServerId then goto skip_loop end
|
||||
logger.verbose("Removing %s from listen table", serverId)
|
||||
MumbleRemoveVoiceChannelListen(serverId)
|
||||
::skip_loop::
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent('onPlayerJoining', function(serverId)
|
||||
if isListenerEnabled then
|
||||
MumbleAddVoiceChannelListen(serverId)
|
||||
logger.verbose("Adding %s to listen table", serverId)
|
||||
end
|
||||
end)
|
||||
|
||||
RegisterNetEvent('onPlayerDropped', function(serverId)
|
||||
if isListenerEnabled then
|
||||
MumbleRemoveVoiceChannelListen(serverId)
|
||||
logger.verbose("Removing %s from listen table", serverId)
|
||||
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
|
||||
local voiceState = "proximity"
|
||||
Citizen.CreateThread(function()
|
||||
TriggerEvent('chat:addSuggestion', '/muteply', 'Mutes the player with the specified id', {
|
||||
{ name = "player id", help = "the player to toggle mute" },
|
||||
{ name = "duration", help = "(opt) the duration the mute in seconds (default: 900)" }
|
||||
})
|
||||
while true do
|
||||
-- wait for mumble to reconnect
|
||||
while not MumbleIsConnected() do
|
||||
Wait(100)
|
||||
end
|
||||
-- Leave the check here as we don't want to do any of this logic
|
||||
if GetConvarInt('voice_enableUi', 1) == 1 then
|
||||
local curTalkingStatus = MumbleIsPlayerTalking(PlayerId()) == 1
|
||||
if lastRadioStatus ~= radioPressed or lastTalkingStatus ~= curTalkingStatus then
|
||||
lastRadioStatus = radioPressed
|
||||
lastTalkingStatus = curTalkingStatus
|
||||
sendUIMessage({
|
||||
usingRadio = lastRadioStatus,
|
||||
talking = lastTalkingStatus
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
if voiceState == "proximity" then
|
||||
addNearbyPlayers()
|
||||
local isSpectating = NetworkIsInSpectatorMode()
|
||||
if isSpectating and not isListenerEnabled then
|
||||
setSpectatorMode(true)
|
||||
elseif not isSpectating and isListenerEnabled then
|
||||
setSpectatorMode(false)
|
||||
end
|
||||
end
|
||||
|
||||
Wait(GetConvarInt('voice_refreshRate', 200))
|
||||
end
|
||||
end)
|
||||
|
||||
exports("setVoiceState", function(_voiceState, channel)
|
||||
if _voiceState ~= "proximity" and _voiceState ~= "channel" then
|
||||
logger.error("Didn't get a proper voice state, expected proximity or channel, got %s", _voiceState)
|
||||
end
|
||||
voiceState = _voiceState
|
||||
if voiceState == "channel" then
|
||||
type_check({channel, "number"})
|
||||
-- 65535 is the highest a client id can go, so we add that to the base channel so we don't manage to get onto a players channel
|
||||
channel = channel + 65535
|
||||
MumbleSetVoiceChannel(channel)
|
||||
while MumbleGetVoiceChannelFromServerId(playerServerId) ~= channel do
|
||||
Wait(250)
|
||||
end
|
||||
MumbleAddVoiceTargetChannel(voiceTarget, channel)
|
||||
elseif voiceState == "proximity" then
|
||||
handleInitialState()
|
||||
end
|
||||
end)
|
||||
|
||||
|
||||
AddEventHandler("onClientResourceStop", function(resource)
|
||||
if type(addProximityCheck) == "table" then
|
||||
local proximityCheckRef = addProximityCheck.__cfx_functionReference
|
||||
if proximityCheckRef then
|
||||
local isResource = string.match(proximityCheckRef, resource)
|
||||
if isResource then
|
||||
addProximityCheck = orig_addProximityCheck
|
||||
logger.warn('Reset proximity check to default, the original resource [%s] which provided the function restarted', resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
Loading…
Add table
Add a link
Reference in a new issue