Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: start adding make shift radio channel name support #226

Merged
merged 16 commits into from
Jan 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2020 Dillon Skaggs
Copyright (c) 2021 Dillon Skaggs

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ You can access the state with `Player(source).state['state bag here']`
| [proximity](docs/state-getters/stateBagGetters.md) | Returns a table with the mode index, distance, and mode name | table |
| [radioChannel](docs/state-getters/stateBagGetters.md) | Returns the players current radio channel, or 0 for none | int |
| [callChannel](docs/state-getters/stateBagGetters.md) | Returns the players current call channel, or 0 for none | int |

| [voiceIntent](docs/state-getters/stateBagGetters.md) | Returns the players current voice intent, either 'speech' or 'music' | string |

###### Exports

Expand Down
4 changes: 2 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
## TODO
- [ ] Add the ability to override proximity with exports
- [ ] Rename everything that uses 'phone' to 'call' for consistency.
- [ ] Ability to display radio members on the client
- [ ] Use commands to define voiceModes in shared.lua and only leave debug logs in shared.lua
- [ ] Convert the UI to React.
- [ ] Multiple radio channels

## DONE
- [ x ] Implement a easy way to get the players current radio channel on the server
- [ x ] Implement a easy way to get the players current radio channel on the server
- [ x ] Add the ability to override proximity with exports
70 changes: 51 additions & 19 deletions client/commands.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
local wasProximityDisabledFromOverride = false
disableProximityCycle = false
RegisterCommand('setvoiceintent', function(source, args)
if GetConvarInt('voice_allowSetIntent', 1) == 1 then
local intent = args[1]
Expand All @@ -6,37 +8,67 @@ RegisterCommand('setvoiceintent', function(source, args)
elseif intent == 'music' then
MumbleSetAudioInputIntent(GetHashKey('music'))
end
LocalPlayer.state:set('voiceIntent', intent, true)
end
end)

-- TODO: Better implementation of this?
RegisterCommand('vol', function(_, args)
if not args[1] then return end
setVolume(args[1])
setVolume(tonumber(args[1]))
end)

RegisterCommand('cycleproximity', function()
if GetConvarInt('voice_enableProximity', 1) ~= 1 then return end
if playerMuted then return end

local voiceMode = mode
local newMode = voiceMode + 1
exports('setAllowProximityCycleState', function(state)
type_check({state, "boolean"})
disableProximityCycle = state
end)

voiceMode = (newMode <= #Cfg.voiceModes and newMode) or 1
local voiceModeData = Cfg.voiceModes[voiceMode]
MumbleSetTalkerProximity(voiceModeData[1] + 0.0)
mode = voiceMode
function setProximityState(proximityRange, isCustom)
local voiceModeData = Cfg.voiceModes[mode]
MumbleSetTalkerProximity(proximityRange + 0.0)
LocalPlayer.state:set('proximity', {
index = voiceMode,
distance = voiceModeData[1],
mode = voiceModeData[2],
index = mode,
distance = proximityRange,
mode = isCustom and "Custom" or voiceModeData[2],
}, true)
-- make sure we update the UI to the latest voice mode
SendNUIMessage({
voiceMode = voiceMode - 1
sendUIMessage({
-- JS expects this value to be - 1, "custom" voice is on the last index
voiceMode = isCustom and #Cfg.voiceModes or mode - 1
})
TriggerEvent('pma-voice:setTalkingMode', voiceMode)
end

exports("overrideProximityRange", function(range, disableCycle)
type_check({range, "number"})
setProximityState(range, true)
if disableCycle then
disableProximityCycle = true
wasProximityDisabledFromOverride = true
end
end)

exports("clearProximityOverride", function()
local voiceModeData = Cfg.voiceModes[mode]
setProximityState(voiceModeData[1], false)
if wasProximityDisabledFromOverride then
disableProximityCycle = false
end
end)

RegisterCommand('cycleproximity', function()
-- Proximity is either disabled, or manually overwritten.
if GetConvarInt('voice_enableProximityCycle', 1) ~= 1 or disableProximityCycle then return end
local newMode = mode + 1

-- If we're within the range of our voice modes, allow the increase, otherwise reset to the first state
if newMode <= #Cfg.voiceModes then
mode = newMode
else
mode = 1
end

setProximityState(Cfg.voiceModes[mode][1], false)
TriggerEvent('pma-voice:setTalkingMode', mode)
end, false)
if gameVersion == 'fivem' then
RegisterKeyMapping('cycleproximity', 'Cycle Proximity', 'keyboard', GetConvar('voice_defaultCycle', 'F11'))
end
end
29 changes: 16 additions & 13 deletions client/events.lua
Original file line number Diff line number Diff line change
@@ -1,17 +1,5 @@
AddEventHandler('mumbleConnected', function(address, isReconnecting)
logger.info('Connected to mumble server with address of %s, is this a reconnect %s', GetConvarInt('voice_hideEndpoints', 1) == 1 and 'HIDDEN' or address, isReconnecting)

logger.log('Connecting to mumble, setting targets.')
-- don't try to set channel instantly, we're still getting data.
function handleInitialState()
local voiceModeData = Cfg.voiceModes[mode]
-- sets how far the player can talk
MumbleSetAudioInputDistance(voiceModeData[1] + 0.0)
LocalPlayer.state:set('proximity', {
index = mode,
distance = voiceModeData[1],
mode = voiceModeData[2],
}, true)

MumbleSetTalkerProximity(voiceModeData[1] + 0.0)
MumbleClearVoiceTarget(voiceTarget)
MumbleSetVoiceTarget(voiceTarget)
Expand All @@ -24,6 +12,21 @@ AddEventHandler('mumbleConnected', function(address, isReconnecting)
MumbleAddVoiceTargetChannel(voiceTarget, playerServerId)

addNearbyPlayers()
end

AddEventHandler('mumbleConnected', function(address, isReconnecting)
logger.info('Connected to mumble server with address of %s, is this a reconnect %s', GetConvarInt('voice_hideEndpoints', 1) == 1 and 'HIDDEN' or address, isReconnecting)

logger.log('Connecting to mumble, setting targets.')
-- don't try to set channel instantly, we're still getting data.
local voiceModeData = Cfg.voiceModes[mode]
LocalPlayer.state:set('proximity', {
index = mode,
distance = voiceModeData[1],
mode = voiceModeData[2],
}, true)

handleInitialState()

logger.log('Finished connection logic')
end)
Expand Down
11 changes: 4 additions & 7 deletions client/init/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -24,12 +24,9 @@ AddEventHandler('onClientResourceStart', function(resource)
SetResourceKvp('pma-voice_enableMicClicks', tostring(true))
micClicks = 'true'
end
Wait(1000)
if GetConvarInt('voice_enableUi', 1) == 1 then
SendNUIMessage({
voiceModes = json.encode(Cfg.voiceModes),
voiceMode = mode - 1
})
end
sendUIMessage({
voiceModes = json.encode(Cfg.voiceModes),
voiceMode = mode - 1
}, true)
print('Script initialization finished.')
end)
8 changes: 3 additions & 5 deletions client/init/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ local volumes = {
['phone'] = tonumber(GetConvar('voice_defaultPhoneVolume', '0.6')) + 0.0,
}

radioEnabled, radioPressed, mode = false, false, Cfg.defaultProximityMode
radioEnabled, radioPressed, mode = true, false, GetConvarInt('voice_defaultVoiceMode', 2)
radioData = {}
callData = {}

Expand Down Expand Up @@ -59,9 +59,7 @@ end)
-- o_freq_lo = 348.0
-- 0_freq_hi = 4900.0


if gameVersion == 'fivem' then
-- radio submix
radioEffectId = CreateAudioSubmix('Radio')
SetAudioSubmixEffectRadioFx(radioEffectId, 0)
SetAudioSubmixEffectParamInt(radioEffectId, 0, GetHashKey('default'), 1)
Expand Down Expand Up @@ -150,7 +148,7 @@ end
---@param clickType boolean whether to play the 'on' or 'off' click.
function playMicClicks(clickType)
if micClicks ~= 'true' then return end
SendNUIMessage({
sendUIMessage({
sound = (clickType and "audio_on" or "audio_off"),
volume = (clickType and (volumes["radio"]) or 0.05)
})
Expand All @@ -176,7 +174,7 @@ exports('toggleMutePlayer', toggleMutePlayer)
function setVoiceProperty(type, value)
if type == "radioEnabled" then
radioEnabled = value
SendNUIMessage({
sendUIMessage({
radioEnabled = value
})
elseif type == "micClicks" then
Expand Down
83 changes: 69 additions & 14 deletions client/init/proximity.lua
Original file line number Diff line number Diff line change
@@ -1,13 +1,30 @@
-- used when muted
local disableUpdates = false
local isListenerEnabled = false
local plyCoords = GetEntityCoords(PlayerPedId())

function addNearbyPlayers()
if disableUpdates then return end
local coords = 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
Expand All @@ -16,8 +33,7 @@ function addNearbyPlayers()

if serverId == playerServerId then goto skip_loop end

local ped = GetPlayerPed(ply)
if #(coords - GetEntityCoords(ped)) < distance then
if addProximityCheck(ply) then
if isTarget then goto skip_loop end

logger.verbose('Added %s as a voice target', serverId)
Expand Down Expand Up @@ -70,6 +86,7 @@ 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" },
Expand All @@ -80,24 +97,62 @@ Citizen.CreateThread(function()
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
if lastRadioStatus ~= radioPressed or lastTalkingStatus ~= (MumbleIsPlayerTalking(PlayerId()) == 1) then
local curTalkingStatus = MumbleIsPlayerTalking(PlayerId()) == 1
if lastRadioStatus ~= radioPressed or lastTalkingStatus ~= curTalkingStatus then
lastRadioStatus = radioPressed
lastTalkingStatus = MumbleIsPlayerTalking(PlayerId()) == 1
SendNUIMessage({
lastTalkingStatus = curTalkingStatus
sendUIMessage({
usingRadio = lastRadioStatus,
talking = lastTalkingStatus
})
end
end
addNearbyPlayers()
local isSpectating = NetworkIsInSpectatorMode()
if isSpectating and not isListenerEnabled then
setSpectatorMode(true)
elseif not isSpectating and isListenerEnabled then
setSpectatorMode(false)

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)
8 changes: 3 additions & 5 deletions client/module/phone.lua
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,9 @@ function setCallChannel(channel)
if GetConvarInt('voice_enablePhones', 1) ~= 1 then return end
TriggerServerEvent('pma-voice:setPlayerCall', channel)
callChannel = channel
if GetConvarInt('voice_enableUi', 1) == 1 then
SendNUIMessage({
callInfo = channel
})
end
sendUIMessage({
callInfo = channel
}, true)
createPhoneThread()
end

Expand Down
Loading