I was having a conversation with SaMatra today about how useful it would be to have a scripting command + Event Handler for VoN (Voice over Network), so that when someone speaks it is possible to detect who speaks, when and on what channel and when they stop. SaMatra also made a feature request, please upvote. So I got curious if it was possible to make some kind of scripting solution in the meantime.

Rather than to rely on key detection + key assignment routine (which is very limiting) I decided to detect a GUI icon instead. When you talk in Multiplayer you get 2 GUI elements to show, one is microphone icon and another one is text box with the channel name.


The thing is while the icon is universal, the channel name is not, it will be displayed in different languages for users from different countries. The channel name needs to be converted to universal channel code, like 0 for global chat, 1 for side chat, etc., and this is what VoN_ChannelId_fnc function does. The channel Id is an array, where 1st element is stringtable variable, in case you will want to display channel name in local language, and second element is a number corresponding to generic description.ext value for channels.

Since there is no event handler for display to show, I used button, mouse and joystick press events to run the detection rather than loop checks on each frame or else. Why mouse and joystick? This is for when you get an odd person who like to bind game functionality to his foot. It is a little frustrating because BIS give you ability to freely bind actions to anything you can press, but do not give you ways of detecting when functionality is bound to mouse of joystick. I’m talking about DIK code in actionKeys routine.

Anyway, we are detecting GUI on/off. Icon display is 55 and channel display is 63 with control 101 containing the channel name. There is this special case when you can leave voice on and then just change channel, this will also get detected. You can put this code in init.sqf. The receiving end functionality is just an example, which will log in server .rpt who speaks on what channel and when they stop, something like this:

“KK speaks on channel 5 (Direct communication)”
“KK stopped speaking”
“KK speaks on channel 5 (Direct communication)”
“KK speaks on channel 0 (Global channel)”
“KK speaks on channel 1 (Side channel)”
“KK speaks on channel 2 (Command channel)”
“KK speaks on channel 3 (Group channel)”
“KK stopped speaking”

The code:

//transmitting end if (!isDedicated) then { VoN_ChannelId_fnc = { switch _this do { case localize "str_channel_global" : {["str_channel_global",0]}; case localize "str_channel_side" : {["str_channel_side",1]}; case localize "str_channel_command" : {["str_channel_command",2]}; case localize "str_channel_group" : {["str_channel_group",3]}; case localize "str_channel_vehicle" : {["str_channel_vehicle",4]}; case localize "str_channel_direct" : {["str_channel_direct",5]}; default {["",-1]}; } }; VoN_Event_fnc = { VoN_currentTxt = _this; VoN_channelId = VoN_currentTxt call VoN_ChannelId_fnc; PLAYER_SPEAKS_PV = [netId player] + VoN_channelId; publicVariable "PLAYER_SPEAKS_PV"; }; 0 = [] spawn { VoN_isOn = false; VoN_currentTxt = ""; VoN_channelId = -1; _fncDown = { if (!VoN_isOn) then { if (!isNull findDisplay 55 && !isNull findDisplay 63) then { VoN_isOn = true; ctrlText (findDisplay 63 displayCtrl 101) call VoN_Event_fnc; findDisplay 55 displayAddEventHandler ["Unload", { VoN_isOn = false; "" call VoN_Event_fnc; }]; }; }; false }; _fncUp = { if (VoN_isOn) then { _ctrlText = ctrlText (findDisplay 63 displayCtrl 101); if (VoN_currentTxt != _ctrlText) then { _ctrlText call VoN_Event_fnc; }; }; false }; waitUntil {!isNull findDisplay 46}; findDisplay 46 displayAddEventHandler ["KeyDown", _fncDown]; findDisplay 46 displayAddEventHandler ["KeyUp", _fncUp]; findDisplay 46 displayAddEventHandler ["MouseButtonDown", _fncDown]; findDisplay 46 displayAddEventHandler ["MouseButtonUp", _fncUp]; findDisplay 46 displayAddEventHandler ["JoystickButton", _fncDown]; }; }; //recieving end "PLAYER_SPEAKS_PV" addPublicVariableEventHandler { _spkr = objectFromNetId (_this select 1 select 0); _chTxt = localize (_this select 1 select 1); _chID = _this select 1 select 2; if (isServer) then { //log VoN event to .rpt on the server if (_chID < 0) then { diag_log format [ "%1 stopped speaking", name _spkr ]; } else { diag_log format [ "%1 speaks on channel %2 (%3)", name _spkr, _chID, _chTxt ]; }; }; };

What are the applications for this functionality? SaMatra wanted to show who’s talking with an icon above player’s head in 3D world. I think this is great idea. In Arma your character would move lips when you talk and others can see this. Cool? Yes. Practical? Not as much. But since there is already some kind of mechanism in place, maybe it would be easier for BIS to add requested features? Who knows.