Skip to content

Commit

Permalink
refactor: update pma-voice to support the latest fivem changes
Browse files Browse the repository at this point in the history
  • Loading branch information
bitpredator committed Oct 12, 2023
1 parent 4e31f0b commit 6d01636
Show file tree
Hide file tree
Showing 20 changed files with 710 additions and 382 deletions.
2 changes: 2 additions & 0 deletions server-data/resources/[phone]/pma-voice/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.idea
.vscode
41 changes: 31 additions & 10 deletions server-data/resources/[phone]/pma-voice/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## PLEASE NOTE: Currently master branch has some breaking changes

If you previously used `voice_defaultPhoneVolume` you will instead need to use `voice_defaultCallVolume`
If you previously used `voice_enablePhones` you will instead need to use `voice_enableCalls`

If you were previously using the state bag getter `Player(source).state.phone` you will instead need to use `Player(source).state.call`

# pma-voice
A voice system designed around the use of FiveM/RedM internal mumble server.

Expand All @@ -11,7 +18,7 @@ Please report any issues you have in the GitHub [Issues](https://github.com/Avar

This script is not compatible with other voice systems (duh), that means if you have vMenus voice chat you will **have** to [disable](https://docs.vespura.com/vmenu/faq/#q-how-do-i-disable-voice-chat) it.

Please do not override `NetworkSetTalkerProximity`, `MumbleSetAudioInputDistance`, `MumbleSetAudioOutputDistance` or `NetworkSetVoiceActive` in any of your other scripts as there have been cases where it breaks pma-voice.
Please do not override `NetworkSetTalkerProximity`, `MumbleSetTalkerProximity`, `MumbleSetAudioInputDistance`, `MumbleSetAudioOutputDistance` or `NetworkSetVoiceActive` in any of your other scripts as there have been cases where it breaks pma-voice.

# Credits

Expand All @@ -30,8 +37,8 @@ Native audio will not work on RedM, you will have to use 3d audio.

| ConVar | Default | Description | Parameter(s) |
|----------------------------|---------|---------------------------------------------------------------|--------------|
| voice_useNativeAudio | false | **This will not work for RedM** Uses the games native audio, will add 3d sound, echo, reverb, and more. **Required for submixs** | boolean |
| voice_use2dAudio | false | Uses 2d audio, will result in same volume sound no matter where they're at until they leave proximity. | boolean
| voice_useNativeAudio | false | Uses the games native audio, will add 3d sound, echo, reverb, and more. **Required for submixs** | boolean |
| voice_use2dAudio | false | Uses 2d audio, will result in same volume sound no matter where they're at until they leave proximity. | boolean
| voice_use3dAudio | false | Uses 3d audio | boolean |
| voice_useSendingRangeOnly | false | Only allows you to hear people within your hear/send range, prevents people from connecting to your mumble server and trolling. | boolean |

Expand All @@ -55,17 +62,17 @@ All of the configs here are set using `setr [voice_configOption] [int]` OR `setr
| voice_enableProximityCycle | 1 | Enables the usage of the F11 proximity key, if disabled players are stuck on the first proximity | int |
| voice_defaultCycle | F11 | The default key to cycle the players proximity. You can find a list of valid keys [in the Cfx docs](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | string |
| voice_defaultRadioVolume | 30 | The default volume to set the radio to (has to be between 1 and 100) *NOTE: Only new joins will have the new value, players that already joined will not.* | float |
| voice_defaultPhoneVolume | 60 | The default volume to set the phone to (has to be between 1 and 100) *NOTE: Only new joins will have the new value, players that already joined will not.* | float |
| voice_defaultCallVolume | 60 | The default volume to set the call to (has to be between 1 and 100) *NOTE: Only new joins will have the new value, players that already joined will not.* | float |
| voice_defaultVoiceMode | 2 | Default proximity voice value when player joins server. (Voice Modes; 1:Whisper, 2:Normal, 3:Shouting) | int |

### Phone & Radio
### Call & Radio

| ConVar | Default | Description | Parameter(s) |
|-------------------------|---------|--------------------------------------------------------------------|--------------|
| voice_enableRadios | 1 | Enables the radio sub-modules | int |
| voice_enablePhones | 1 | Enables the phone sub-modules | int |
| voice_enableSubmix | 1 | Enables the submix which adds a radio/phone style submix to their voice **NOTE: Submixs require native audio** | int |
| voice_enableRadioAnim | 0 | Enables (grab shoulder mic) animation while talking on the radio. | int |
| voice_enableCalls | 1 | Enables the call sub-modules | int |
| voice_enableSubmix | 1 | Enables the submix which adds a radio/call style submix to their voice **NOTE: Submixs require native audio** | int |
| voice_enableRadioAnim | 1 | Enables (grab shoulder mic) animation while talking on the radio. | int |
| voice_defaultRadio | LMENU | The default key to use the radio. You can find a list of valid keys [in the FiveM docs](https://docs.fivem.net/docs/game-references/input-mapper-parameter-ids/keyboard/) | string |

### Sync
Expand Down Expand Up @@ -100,7 +107,7 @@ This would only allow the superadmin group to mute players.
#### Client

##### Setters

| Export | Description | Parameter(s) |
|---------------------|-----------------------------|--------------|
| [setVoiceProperty](docs/client-setters/setVoiceProperty.md) | Set config options | string, any |
Expand Down Expand Up @@ -130,14 +137,15 @@ Supported from mumble-voip / toko-voip

#### Getters

The majority of setters are done through player states, while a small
The majority of setters are done through player states.


| State Bag | Description | Return Type |
|---------------|--------------------------------------------------------------|--------------|
| [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 |
| [disableRadio](docs/state-getters/stateBagGetters.md) | Returns if the players radio is currently disabled, or 0 if its not. This is expected to be use as a bitwise, do *not* use a bool | int |

#### Events

Expand Down Expand Up @@ -172,6 +180,19 @@ You can access the state with `Player(source).state['state bag here']`
| [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 |
| [disableRadio](docs/state-getters/stateBagGetters.md) | Returns if the players radio is currently disabled, or 0 if its not. This is expected to be use as a bitwise, do *not* use a bool | int |

```ts
enum DisabledRadioStates {
Enabled = 0,
IsDead = 1,
IsCuffed = 2,
IsPdCuffed = 4,
IsUnderWater = 8,
DoesntHaveItem = 16,
PlayerDisabledRadio = 32,
}
```

###### Exports

Expand Down
12 changes: 6 additions & 6 deletions server-data/resources/[phone]/pma-voice/TODO.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
## TODO
- [ ] 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
- [ ] 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
- [ ] Multiple radio channels.

## DONE
- [ x ] Implement a easy way to get the players current radio channel on the server
- [ x ] Add the ability to override proximity with exports
- [ x ] Implement a easy way to get the players current radio channel on the server.
- [ x ] Add the ability to override proximity with exports.
- [ x ] Rename everything that uses 'phone' to 'call' for consistency.
15 changes: 12 additions & 3 deletions server-data/resources/[phone]/pma-voice/client/commands.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
local wasProximityDisabledFromOverride = false
disableProximityCycle = false
RegisterCommand('setvoiceintent', function(_, args)
RegisterCommand('setvoiceintent', function(source, args)
if GetConvarInt('voice_allowSetIntent', 1) == 1 then
local intent = args[1]
if intent == 'speech' then
Expand All @@ -11,15 +11,24 @@ RegisterCommand('setvoiceintent', function(_, args)
LocalPlayer.state:set('voiceIntent', intent, true)
end
end)
TriggerEvent('chat:addSuggestion', '/setvoiceintent', 'Sets the players voice intent', {
{
name = "intent",
help = "speech is default and enables noise suppression & high pass filter, music disables both of these."
},
})

-- TODO: Better implementation of this?
RegisterCommand('vol', function(_, args)
if not args[1] then return end
setVolume(tonumber(args[1]))
end)
TriggerEvent('chat:addSuggestion', '/vol', 'Sets the radio/phone volume', {
{ name = "volume", help = "A range between 1-100 on how loud you want them to be" },
})

exports('setAllowProximityCycleState', function(state)
type_check({state, "boolean"})
type_check({ state, "boolean" })
disableProximityCycle = state
end)

Expand All @@ -38,7 +47,7 @@ function setProximityState(proximityRange, isCustom)
end

exports("overrideProximityRange", function(range, disableCycle)
type_check({range, "number"})
type_check({ range, "number" })
setProximityState(range, true)
if disableCycle then
disableProximityCycle = true
Expand Down
17 changes: 10 additions & 7 deletions server-data/resources/[phone]/pma-voice/client/events.lua
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ function handleInitialState()
MumbleSetTalkerProximity(voiceModeData[1] + 0.0)
MumbleClearVoiceTarget(voiceTarget)
MumbleSetVoiceTarget(voiceTarget)
MumbleSetVoiceChannel(playerServerId)
MumbleSetVoiceChannel(LocalPlayer.state.assignedChannel)

while MumbleGetVoiceChannelFromServerId(playerServerId) ~= playerServerId do
while MumbleGetVoiceChannelFromServerId(playerServerId) ~= LocalPlayer.state.assignedChannel do
Wait(250)
MumbleSetVoiceChannel(LocalPlayer.state.assignedChannel)
end

MumbleAddVoiceTargetChannel(voiceTarget, playerServerId)
MumbleAddVoiceTargetChannel(voiceTarget, LocalPlayer.state.assignedChannel)

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.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],
distance = voiceModeData[1],
mode = voiceModeData[2],
}, true)

Expand All @@ -32,10 +34,11 @@ AddEventHandler('mumbleConnected', function(address, isReconnecting)
end)

AddEventHandler('mumbleDisconnected', function(address)
logger.info('Disconnected from mumble server with address of %s', GetConvarInt('voice_hideEndpoints', 1) == 1 and 'HIDDEN' or address)
logger.info('Disconnected from mumble server with address of %s',
GetConvarInt('voice_hideEndpoints', 1) == 1 and 'HIDDEN' or address)
end)

-- TODO: Convert the last Cfg to a Convar, while still keeping it simple.
AddEventHandler('pma-voice:settingsCallback', function(cb)
cb(Cfg)
end)
end)
25 changes: 16 additions & 9 deletions server-data/resources/[phone]/pma-voice/client/init/init.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@

AddEventHandler('onClientResourceStart', function(resource)
if resource ~= GetCurrentResourceName() then
return
Expand All @@ -10,18 +9,19 @@ AddEventHandler('onClientResourceStart', function(resource)
local success = pcall(function()
local micClicksKvp = GetResourceKvpString('pma-voice_enableMicClicks')
if not micClicksKvp then
SetResourceKvp('pma-voice_enableMicClicks', tostring(true))
SetResourceKvp('pma-voice_enableMicClicks', "true")
else
if micClicksKvp ~= 'true' and micClicksKvp ~= 'false' then
error('Invalid Kvp, throwing error for automatic cleaning')
error('Invalid Kvp, throwing error for automatic fix')
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))
logger.warn(
'Failed to load resource Kvp, likely was inappropriately modified by another server, resetting the Kvp.')
SetResourceKvp('pma-voice_enableMicClicks', "true")
micClicks = 'true'
end
sendUIMessage({
Expand All @@ -30,13 +30,20 @@ AddEventHandler('onClientResourceStart', function(resource)
voiceMode = mode - 1
})

local radioChannel = LocalPlayer.state.radioChannel or 0
local callChannel = LocalPlayer.state.callChannel or 0

-- Reinitialize channels if they're set.
if LocalPlayer.state.radioChannel ~= 0 then
setRadioChannel(LocalPlayer.state.radioChannel)
if radioChannel ~= 0 then
setRadioChannel(radioChannel)
end

if LocalPlayer.state.callChannel ~= 0 then
setCallChannel(LocalPlayer.state.callChannel)
if callChannel ~= 0 then
setCallChannel(callChannel)
end
if not LocalPlayer.state.disableRadio then
LocalPlayer.state:set("disableRadio", 0, true)
end

print('Script initialization finished.')
end)
Loading

0 comments on commit 6d01636

Please sign in to comment.