Map Gestures - Rewrite and Add Zeus, and Spectator support (#7653)

* Initial Rewrite

* improve getProximityPlayers

* add Zeus Implementation

* fix missing simicolon

* add Spectator Support

* improve local responsiveness

* add Vanilla Spectator Support

* Fix Both Spectators are now working correctly

* exit mouse moving event early when disabled

* Move Diary Event registration to XEH DisplayLoaded

Port Settings to SQF
Add Setting for only showing Friendly Units pointing

* Fix Merge Issue in Stringtable

Redo Settings

* fix a copy past script error

* Update addons/map_gestures/functions/fnc_getProximityPlayers.sqf

Co-authored-by: PabstMirror <pabstmirror@gmail.com>

* Lazy evals and defines

* Small changes

* Simplify initDisplayDiary and fix loading saves

* Cache getProximityPlayers

Improve Vanilla Spectator Support and how Followed unit Nearby data

* Minor header update

Co-authored-by: PabstMirror <pabstmirror@gmail.com>
This commit is contained in:
Joko 2020-06-19 17:35:57 +02:00 committed by GitHub
parent 7d4a2b07bb
commit 00fa94e636
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 257 additions and 273 deletions

View File

@ -1,49 +1,20 @@
class ACE_Settings {
class GVAR(enabled) {
displayName = CSTRING(enabled_displayName);
description = CSTRING(enabled_description);
category = CSTRING(mapGestures_category);
typeName = "BOOL";
value = 1;
movedToSQF = 1;
};
class GVAR(maxRange) {
displayName = CSTRING(maxRange_displayName);
description = CSTRING(maxRange_description);
category = CSTRING(mapGestures_category);
typeName = "SCALAR";
value = 7;
sliderSettings[] = {0, 50, 7, 1};
movedToSQF = 1;
};
class GVAR(interval) {
displayName = CSTRING(interval_displayName);
description = CSTRING(interval_description);
category = CSTRING(mapGestures_category);
typeName = "SCALAR";
value = 0.03;
sliderSettings[] = {0, 1, 0.03, 2};
movedToSQF = 1;
};
class GVAR(nameTextColor) {
displayName = CSTRING(nameTextColor_displayName);
description = CSTRING(nameTextColor_description);
category = CSTRING(mapGestures_category);
isClientSettable = 1;
typeName = "COLOR";
value[] = {0.2, 0.2, 0.2, 0.3};
movedToSQF = 1;
};
class GVAR(defaultLeadColor) {
displayName = CSTRING(defaultLeadColor_displayName);
description = CSTRING(defaultLeadColor_description);
category = CSTRING(mapGestures_category);
isClientSettable = 1;
typeName = "COLOR";
value[] = {1, 0.88, 0, 0.95};
movedToSQF = 1;
};
class GVAR(defaultColor) {
displayName = CSTRING(defaultColor_displayName);
description = CSTRING(defaultColor_description);
category = CSTRING(mapGestures_category);
isClientSettable = 1;
typeName = "COLOR";
value[] = {1, 0.88, 0, 0.7};
movedToSQF = 1;
};
};

View File

@ -1,4 +1,3 @@
class Extended_PreStart_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_FILE(XEH_preStart));
@ -16,3 +15,15 @@ class Extended_PostInit_EventHandlers {
init = QUOTE(call COMPILE_FILE(XEH_postInit));
};
};
class Extended_DisplayLoad_EventHandlers {
class RscDisplayCurator {
ADDON = QUOTE(((_this select 0) displayCtrl ID_CURATOR_MAP) call FUNC(initDisplayCurator));
};
class RscDisplayEGSpectator {
ADDON = QUOTE((((_this select 0) displayCtrl ID_EG_MAP_CONTROL) controlsGroupCtrl ID_EG_MAP_CONTROLGROUP) call FUNC(initDisplaySpectator));
};
class RscDiary { // for loading saves use uiNamespace because missionNamespace is not restored before map is loaded
ADDON = QUOTE(((_this select 0) displayCtrl ID_DIARY_MAP) call (uiNamespace getVariable 'DFUNC(initDisplayDiary)'));
};
};

View File

@ -1,12 +1,9 @@
PREP(addGroupColorMapping);
PREP(drawMapGestures);
PREP(endTransmit);
PREP(getProximityPlayers);
PREP(initTransmit);
PREP(initDisplayCurator);
PREP(initDisplayDiary);
PREP(initDisplaySpectator);
PREP(isValidColorArray);
PREP(moduleGroupSettings);
PREP(moduleSettings);
PREP(receiverInit);
PREP(transmit);
PREP(transmitterInit);

View File

@ -4,21 +4,7 @@ if (["STMapGestures"] call EFUNC(common,isModLoaded)) exitWith {
WARNING("st_map_gestures is installed - exiting [remove st_map_gestures.pbo to allow ace version]");
};
if (!hasInterface) exitWith {};
["ace_settingsInitialized", {
if (!GVAR(enabled)) exitWith {};
GVAR(pointPosition) = [0,0,0];
[{
if (isNull (findDisplay 12)) exitWith {};
params ["", "_pfhId"];
call FUNC(receiverInit);
call FUNC(transmitterInit);
[_pfhId] call CBA_fnc_removePerFrameHandler;
}, 1, []] call CBA_fnc_addPerFrameHandler;
}] call CBA_fnc_addEventHandler;
["visibleMap", {
GVAR(EnableTransmit) = false;
ACE_player setVariable [QGVAR(pointPosition), nil, true]; // Instantly transmit nil to stop drawing icon
}, true] call CBA_fnc_addPlayerEventHandler;

View File

@ -6,6 +6,8 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp"
PREP_RECOMPILE_END;
#include "initSettings.sqf"
GVAR(GroupColorCfgMappingNew) = call CBA_fnc_createNamespace;
ADDON = true;

View File

@ -5,16 +5,18 @@
*
* Arguments:
* 0: Map Handle <CONTROL>
* 1: Positions (objects or posAGLs) <ARRAY>
*
* Return Value:
* None
*
* Example:
* [findDisplay 12 displayCtrl 51] call ace_map_gestures_fnc_drawMapGestures
* [findDisplay 12 displayCtrl 51, [player]] call ace_map_gestures_fnc_drawMapGestures
*
* Public: No
*/
BEGIN_COUNTER(draw);
#define ICON_RENDER_SIZE 55
@ -26,36 +28,30 @@ BEGIN_COUNTER(draw);
#define TEXT_SIZE 0.030
#define TEXT_SHADOW 0
if (!GVAR(enabled) || !visibleMap) exitWith {};
if (!GVAR(enabled)) exitWith {};
params ["_mapHandle"];
params ["_mapHandle", "_positions"];
private _players = [[_positions, GVAR(maxRange)], FUNC(getProximityPlayers), missionNamespace, QGVAR(proximityPlayersCache), 1] call EFUNC(common,cachedCall);
// Iterate over all nearby players and render their pointer if player is transmitting.
{
private _pos = _x getVariable QGVAR(pointPosition);
// Only render if the unit is alive and transmitting
if (alive _x && {_x getVariable [QGVAR(Transmit), false]}) then {
private _pos = _x getVariable [QGVAR(pointPosition), [0,0,0]];
private _group = group _x;
private _grpName = groupID _group;
// If color settings for the group exist, then use those, otherwise fall back to the default colors
private _colorMap = GVAR(GroupColorCfgMappingNew) getVariable _grpName;
private _color = if (isNil "_colorMap") then {
[GVAR(defaultLeadColor), GVAR(defaultColor)] select (_x != leader _group);
} else {
_colorMap select (_x != leader _group);
if (alive _x && { !isNil "_pos" }) then {
if (_x == ACE_player && { !isNil QGVAR(cursorPosition) }) then {
_pos = GVAR(cursorPosition);
};
// If color settings for the group exist, then use those, otherwise fall back to the default colors
private _colorMap = GVAR(GroupColorCfgMappingNew) getVariable [(groupID (group _x)), [GVAR(defaultLeadColor), GVAR(defaultColor)]];
private _color = _colorMap select (_x != leader _x);
TRACE_2("",_colorMap,_color);
// Render icon and player name
_mapHandle drawIcon ["\a3\ui_f\data\gui\cfg\Hints\icon_text\group_1_ca.paa", _color, _pos, ICON_RENDER_SIZE, ICON_RENDER_SIZE, ICON_ANGLE, "", ICON_SHADOW, TEXT_SIZE, TEXT_FONT, ICON_TEXT_ALIGN];
_mapHandle drawIcon ["#(argb,8,8,3)color(0,0,0,0)", GVAR(nameTextColor), _pos, TEXT_ICON_RENDER_SIZE, TEXT_ICON_RENDER_SIZE, ICON_ANGLE, name _x, TEXT_SHADOW, TEXT_SIZE, TEXT_FONT, ICON_TEXT_ALIGN];
};
nil
} count ([ACE_player, GVAR(maxRange)] call FUNC(getProximityPlayers));
} forEach _players;
END_COUNTER(draw);

View File

@ -1,21 +0,0 @@
#include "script_component.hpp"
/*
* Author: Dslyecxi, MikeMatrix
* Ensure that all variables used to indicate transmission are disabled.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_map_gestures_fnc_endTransmit
*
* Public: No
*/
if (!GVAR(enabled)) exitWith {};
ACE_player setVariable [QGVAR(Transmit), false, true];
GVAR(EnableTransmit) = false;

View File

@ -4,22 +4,35 @@
* Returns all players in a given range and in the units vehicle.
*
* Arguments:
* 0: Unit <OBJECT>
* 0: Positions (objects or posAGLs) <ARRAY>
* 1: Range <NUMBER>
*
* Return Value:
* All units in proximity <ARRAY>
* All units in proximity <ARRAY<OBJECT>>
*
* Example:
* [player, 7] call ace_map_gestures_fnc_getProximityPlayers
* [[player], 7] call ace_map_gestures_fnc_getProximityPlayers
*
* Public: No
*/
params ["_unit", "_range"];
params ["_positions", "_range"];
private _proximityPlayers = _unit nearEntities [["CAMAnBase"], _range];
_proximityPlayers deleteAt (_proximityPlayers find _unit);
_proximityPlayers append (crew vehicle _unit);
private _proximityPlayers = [];
_proximityPlayers select {[_x, false] call EFUNC(common,isPlayer);}
{
_proximityPlayers append (_x nearEntities [["CAMAnBase"], _range]);
if (_x isEqualType objNull) then {
_proximityPlayers append (crew vehicle _x);
};
} forEach _positions;
_proximityPlayers = _proximityPlayers arrayIntersect _proximityPlayers;
_proximityPlayers = _proximityPlayers select { [_x, false] call EFUNC(common,isPlayer); };
if (GVAR(onlyShowFriendlys)) then {
_proximityPlayers = _proximityPlayers select { [side group ace_player, side _x] call BIS_fnc_areFriendly; };
};
_proximityPlayers

View File

@ -0,0 +1,20 @@
#include "script_component.hpp"
/*
* Author: joko // Jonas
* Binds Draw EventHandlers to Zeus map.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* _mapCtrl call ace_map_gestures_fnc_initDisplayCurator
*
* Public: No
*/
params ["_mapCtrl"];
TRACE_1("initDisplayCurator",_mapCtrl);
_mapCtrl ctrlAddEventHandler ["Draw", { [_this select 0, [ACE_player, positionCameraToWorld [0, 0, 0]]] call FUNC(drawMapGestures);}];

View File

@ -0,0 +1,55 @@
#include "script_component.hpp"
/*
* Author: Dslyecxi, MikeMatrix, joko // Jonas
* Bind all required EventHandlers to Player map.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* _mapCtrl call ace_map_gestures_fnc_initDisplayDiary
*
* Public: No
*/
params ["_mapCtrl"];
TRACE_1("initDisplayDiary",_mapCtrl);
_mapCtrl ctrlAddEventHandler ["Draw", { [_this select 0, [ACE_player]] call FUNC(drawMapGestures); }];
// MouseMoving EH.
_mapCtrl ctrlAddEventHandler ["MouseMoving", {
if (!GVAR(enabled)) exitWith {};
params ["_control", "_posX", "_posY"];
private _position = _control ctrlMapScreenToWorld [_posX, _posY];
GVAR(cursorPosition) = _position;
// Don't transmit any data if we're using the map tools
if (!GVAR(EnableTransmit) || {(["ace_maptools"] call EFUNC(common,isModLoaded)) && {EGVAR(maptools,mapTool_isDragging) || EGVAR(maptools,mapTool_isRotating)}}) exitWith {};
if (_position distance2D (ACE_player getVariable [QGVAR(pointPosition), [0, 0, 0]]) >= 1) then {
[ACE_player, QGVAR(pointPosition), _position, GVAR(interval)] call EFUNC(common,setVariablePublic);
};
}];
// MouseDown EH
_mapCtrl ctrlAddEventHandler ["MouseButtonDown", {
if (getClientStateNumber < 10) exitWith {};
if (!GVAR(enabled)) exitWith {};
params ["", "_button", "_x", "_y", "_shift", "_ctrl", "_alt"];
if (_button == 0 && {[_shift, _ctrl, _alt] isEqualTo [false, false, false]}) then {
GVAR(EnableTransmit) = true;
};
}];
// MouseUp EH
_mapCtrl ctrlAddEventHandler ["MouseButtonUp", {
if (getClientStateNumber < 10) exitWith {};
if (!GVAR(enabled)) exitWith {};
params ["", "_button"];
if (_button == 0) then {
GVAR(EnableTransmit) = false;
ACE_player setVariable [QGVAR(pointPosition), nil, true]; // Instantly transmit nil to stop drawing icon
GVAR(cursorPosition) = nil;
};
}];

View File

@ -0,0 +1,32 @@
#include "script_component.hpp"
/*
* Author: joko // Jonas
* Binds Draw EventHandlers to Spectator map.
*
* Arguments:
* 0: Map Handle from a spectator gui <CONTROL>
*
* Return Value:
* None
*
* Example:
* _mapCtrl call ace_map_gestures_fnc_initDisplaySpectator
*
* Public: No
*/
params ["_mapCtrl"];
TRACE_1("initDisplaySpectator",_mapCtrl);
_mapCtrl ctrlAddEventHandler ["Draw", {
private _targets = [positionCameraToWorld [0, 0, 0]];
private _aceSpectatorFocus = missionNamespace getVariable [QEGVAR(spectator,camFocus), objNull];
if (!isNull _aceSpectatorFocus) then {
_targets pushback _aceSpectatorFocus;
};
private _vanillaSpectatorFocus = uiNamespace getVariable ["RscEGSpectator_focus", objNull];
if (!isNull _vanillaSpectatorFocus) then {
_targets pushback _vanillaSpectatorFocus;
};
[_this select 0, _targets] call FUNC(drawMapGestures);
}];

View File

@ -1,21 +0,0 @@
#include "script_component.hpp"
/*
* Author: Dslyecxi, MikeMatrix
* Initializes transmitting map gestures.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_map_gestures_fnc_initTransmit
*
* Public: No
*/
if (!GVAR(enabled)) exitWith {};
GVAR(EnableTransmit) = true;
[FUNC(transmit), GVAR(interval), []] call CBA_fnc_addPerFrameHandler;

View File

@ -1,25 +0,0 @@
#include "script_component.hpp"
/*
* Author: Dslyecxi, MikeMatrix
* Initializes the receiver and hooks it to the Draw event of the map.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_map_gestures_fnc_receiverInit
*
* Public: No
*/
ACE_player setVariable [QGVAR(Transmit), false, true];
GVAR(EnableTransmit) = false;
if (!isNil QGVAR(DrawMapHandlerID)) then {
(findDisplay 12 displayCtrl 51) ctrlRemoveEventHandler ["Draw", GVAR(DrawMapHandlerID)];
GVAR(DrawMapHandlerID) = nil;
};
GVAR(DrawMapHandlerID) = findDisplay 12 displayCtrl 51 ctrlAddEventHandler ["Draw", {call FUNC(drawMapGestures)}];

View File

@ -1,36 +0,0 @@
#include "script_component.hpp"
/*
* Author: Dslyecxi, MikeMatrix
* Transmit PFH
*
* Arguments:
* 0: Arguments <ARRAY>
* 1: PFH ID <NUMBER>
*
* Return Value:
* Return description <TYPE>
*
* Example:
* [[], 2] call ace_map_gestures_fnc_transmit
*
* Public: No
*/
BEGIN_COUNTER(transmit);
params ["", "_pfhId"];
if (!visibleMap) then {
call FUNC(endTransmit);
};
if (!GVAR(EnableTransmit) || !visibleMap) exitWith {
[_pfhId] call CBA_fnc_removePerFrameHandler;
};
private _remotePos = ACE_player getVariable [QGVAR(pointPosition), [0, 0, 0]];
if (_remotePos distance2D GVAR(pointPosition) > 1) then { // Only transmit when actually moving
ACE_player setVariable [QGVAR(pointPosition), GVAR(pointPosition), true];
};
END_COUNTER(transmit);

View File

@ -1,68 +0,0 @@
#include "script_component.hpp"
/*
* Author: Dslyecxi, MikeMatrix
* Initializes the transmitting event handlers.
*
* Arguments:
* None
*
* Return Value:
* None
*
* Example:
* [] call ace_map_gestures_fnc_transmitterInit
*
* Public: No
*/
disableSerialization;
private _mapCtrl = findDisplay 12 displayCtrl 51;
// MouseMoving EH.
if (!isNil QGVAR(MouseMoveHandlerID)) then {
_mapCtrl ctrlRemoveEventHandler ["MouseMoving", GVAR(MouseMoveHandlerID)];
GVAR(MouseMoveHandlerID) = nil;
};
GVAR(MouseMoveHandlerID) = _mapCtrl ctrlAddEventHandler ["MouseMoving", {
// Don't transmit any data if we're using the map tools
if (!GVAR(EnableTransmit) || {(["ace_maptools"] call EFUNC(common,isModLoaded)) && {EGVAR(maptools,mapTool_isDragging) || EGVAR(maptools,mapTool_isRotating)}}) exitWith {};
params ["_control", "_posX", "_posY"];
if (!(ACE_player getVariable QGVAR(Transmit))) then {
ACE_player setVariable [QGVAR(Transmit), true, true];
};
GVAR(pointPosition) = _control ctrlMapScreenToWorld [_posX, _posY];
}];
// MouseDown EH
if (!isNil QGVAR(MouseDownHandlerID)) then {
_mapCtrl ctrlRemoveEventHandler ["MouseButtonDown",GVAR(MouseDownHandlerID)];
GVAR(MouseDownHandlerID) = nil;
};
GVAR(MouseDownHandlerID) = _mapCtrl ctrlAddEventHandler ["MouseButtonDown", {
if (!GVAR(enabled)) exitWith {};
params ["", "_button", "_x", "_y", "_shift", "_ctrl", "_alt"];
if (_button == 0 && {[_shift, _ctrl, _alt] isEqualTo [false, false, false]}) then {
call FUNC(initTransmit);
};
}];
// MouseUp EH
if (!isNil QGVAR(MouseUpHandlerID)) then {
_mapCtrl ctrlRemoveEventHandler ["MouseButtonUp", GVAR(MouseUpHandlerID)];
GVAR(MouseUpHandlerID) = nil;
};
GVAR(MouseUpHandlerID) = _mapCtrl ctrlAddEventHandler ["MouseButtonUp", {
if (!GVAR(enabled)) exitWith {};
params ["", "_button"];
if (_button == 0) then {
call FUNC(endTransmit);
};
}];

View File

@ -0,0 +1,56 @@
[
QGVAR(enabled), "CHECKBOX",
[LSTRING(enabled_displayName), LSTRING(enabled_description)],
LSTRING(mapGestures_category),
true,
true
] call CBA_fnc_addSetting;
[
QGVAR(maxRange), "SLIDER",
[LSTRING(maxRange_displayName), LSTRING(maxRange_description)],
LSTRING(mapGestures_category),
[0,50,7,1],
true
] call CBA_fnc_addSetting;
[
QGVAR(onlyShowFriendlys),
"CHECKBOX",
[LSTRING(onlyShowFriendlys_displayName), LSTRING(onlyShowFriendlys_description)],
LSTRING(mapGestures_category),
false,
1
] call CBA_fnc_addSetting;
[
QGVAR(interval), "SLIDER",
[LSTRING(interval_displayName), LSTRING(interval_description)],
LSTRING(mapGestures_category),
[0,1,0.03,2],
true
] call CBA_fnc_addSetting;
[
QGVAR(nameTextColor), "COLOR",
[LSTRING(nameTextColor_displayName), LSTRING(nameTextColor_description)],
LSTRING(mapGestures_category),
[0.2,0.2,0.2,0.3],
false
] call CBA_fnc_addSetting;
[
QGVAR(defaultLeadColor), "COLOR",
[LSTRING(defaultLeadColor_displayName), LSTRING(defaultLeadColor_description)],
LSTRING(mapGestures_category),
[1,0.88,0,0.95],
false
] call CBA_fnc_addSetting;
[
QGVAR(defaultColor), "COLOR",
[LSTRING(defaultColor_displayName), LSTRING(defaultColor_description)],
LSTRING(mapGestures_category),
[1,0.88,0,0.7],
false
] call CBA_fnc_addSetting;

View File

@ -15,3 +15,8 @@
#endif
#include "\z\ace\addons\main\script_macros.hpp"
#define ID_CURATOR_MAP 50
#define ID_EG_MAP_CONTROL 63909
#define ID_EG_MAP_CONTROLGROUP 62609
#define ID_DIARY_MAP 51

View File

@ -265,6 +265,12 @@
<Chinese>改變與此同步小隊隊員的指示器顏色</Chinese>
<Czech>Barva pro členy skupin které jsou synchronizované s tímto modulem.</Czech>
</Key>
<Key ID="STR_ACE_Map_Gestures_onlyShowFriendlys_displayName">
<English>Only Show Friendly Gestures</English>
</Key>
<Key ID="STR_ACE_Map_Gestures_onlyShowFriendlys_description">
<English>Shows only Gestures from Units that are from the same side or a Friendly side.</English>
</Key>
<Key ID="STR_ACE_Map_Gestures_moduleGroupSettings_displayName">
<English>Map Gestures - Group Settings</English>
<Portuguese>Gestos no mapa - Definições de Grupo</Portuguese>
@ -281,20 +287,20 @@
<Chinese>地圖指示器 - 隊伍設定</Chinese>
</Key>
<Key ID="STR_ACE_Map_Gestures_mapGestures_category">
<English>Map Gestures</English>
<Portuguese>Gestos no mapa</Portuguese>
<Polish>Gesty na mapie</Polish>
<Russian>Жесты на карте</Russian>
<Czech>Ukazování v mapě</Czech>
<Italian>Gesti Mappa</Italian>
<German>Kartenzeichen</German>
<Spanish>Gestos en mapa</Spanish>
<French>Pointage sur carte</French>
<Japanese>マップ ジェスチャー</Japanese>
<Korean>지도 신호</Korean>
<Chinesesimp>地图标识器</Chinesesimp>
<Chinese>地圖指示器</Chinese>
<Turkish>Harita Hareketleri</Turkish>
<English>ACE Map Gestures</English>
<Portuguese>ACE Gestos no mapa</Portuguese>
<Polish>ACE Gesty na mapie</Polish>
<Russian>ACE Жесты на карте</Russian>
<Czech>ACE Ukazování v mapě</Czech>
<Italian>ACE Gesti Mappa</Italian>
<German>ACE Kartenzeichen</German>
<Spanish>ACE Gestos en mapa</Spanish>
<French>ACE Pointage sur carte</French>
<Japanese>ACE マップ ジェスチャー</Japanese>
<Korean>ACE 지도 신호</Korean>
<Chinesesimp>ACE 地图标识器</Chinesesimp>
<Chinese>ACE 地圖指示器</Chinese>
<Turkish>ACE Harita Hareketleri</Turkish>
</Key>
</Package>
</Project>

View File

@ -19,8 +19,13 @@ params ["_display"];
uiNamespace setVariable [QGVAR(display), _display];
if (["ace_map_gestures"] call EFUNC(common,isModLoaded)) then {
[_display displayCtrl IDC_MAP] call EFUNC(map_gestures,initDisplaySpectator);
};
[QGVAR(displayLoaded), _display] call CBA_fnc_localEvent;
// Handle ACRE2 Toggle Spectator (if present)
if (!isNil "acre_api_fnc_addDisplayPassthroughKeys") then {
[_display] call acre_api_fnc_addDisplayPassthroughKeys;