forked from Simnation/Main
224 lines
No EOL
7 KiB
Lua
224 lines
No EOL
7 KiB
Lua
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 |