mirror of
https://github.com/acemod/ACE3.git
synced 2024-08-30 18:23:18 +00:00
dfca4fdcf8
* Pass functions by "reference" to bis event handlers * Add Doc * Fix
495 lines
18 KiB
Plaintext
495 lines
18 KiB
Plaintext
/*
|
|
* Author: SilentSpike
|
|
* Handles spectator interface events
|
|
*
|
|
* Arguments:
|
|
* 0: Event name <STRING>
|
|
* 1: Event arguments <ANY>
|
|
*
|
|
* Return Value:
|
|
* None <NIL>
|
|
*
|
|
* Example:
|
|
* ["onLoad",_this] call ace_spectator_fnc_handleInterface
|
|
*
|
|
* Public: No
|
|
*/
|
|
|
|
#include "script_component.hpp"
|
|
|
|
params ["_mode",["_args",[]]];
|
|
|
|
switch (toLower _mode) do {
|
|
case "onload": {
|
|
_args params ["_display"];
|
|
SETUVAR(GVAR(interface),_display);
|
|
|
|
// Always show interface and hide map upon opening
|
|
[_display,nil,nil,!GVAR(showInterface),GVAR(showMap)] call FUNC(toggleInterface);
|
|
|
|
// Initalize the unit tree
|
|
["onUnitsUpdate",[(_display displayCtrl IDC_UNIT) controlsGroupCtrl IDC_UNIT_TREE]] call FUNC(handleInterface);
|
|
|
|
// Keep unit list and tree up to date
|
|
[FUNC(handleUnits), 9, _display] call CBA_fnc_addPerFrameHandler;
|
|
|
|
// Handle 3D unit icons
|
|
GVAR(iconHandler) = addMissionEventHandler ["Draw3D", {call FUNC(handleIcons)}];
|
|
|
|
// Populate the help window
|
|
private _help = (_display displayCtrl IDC_HELP) controlsGroupCtrl IDC_HELP_LIST;
|
|
{
|
|
_i = _help lbAdd (_x select 0);
|
|
if ((_x select 1) == "") then {
|
|
_help lbSetPicture [_i,"\A3\ui_f\data\map\markers\military\dot_CA.paa"];
|
|
_help lbSetPictureColor [_i,[COL_FORE]];
|
|
} else {
|
|
_help lbSetTooltip [_i,_x select 1];
|
|
};
|
|
} forEach [
|
|
[localize LSTRING(uiControls),""],
|
|
[localize LSTRING(uiToggleUnits),keyName 2],
|
|
[localize LSTRING(uiToggleHelp),keyName 3],
|
|
[localize LSTRING(uiToggleTools),keyName 4],
|
|
[localize LSTRING(uiToggleCompass),keyName 5],
|
|
[localize LSTRING(uiToggleIcons),keyName 6],
|
|
[localize LSTRING(uiToggleMap),keyName 50],
|
|
[localize LSTRING(uiToggleInterface),keyName 14],
|
|
[localize LSTRING(freeCamControls),""],
|
|
[localize LSTRING(freeCamForward),keyName 17],
|
|
[localize LSTRING(freeCamBackward),keyName 31],
|
|
[localize LSTRING(freeCamLeft),keyName 30],
|
|
[localize LSTRING(freeCamRight),keyName 32],
|
|
[localize LSTRING(freeCamUp),keyName 16],
|
|
[localize LSTRING(freeCamDown),keyName 44],
|
|
[localize LSTRING(freeCamPan),"RMB (Hold)"],
|
|
[localize LSTRING(freeCamDolly),"LMB (Hold)"],
|
|
[localize LSTRING(freeCamBoost),"Shift (Hold)"],
|
|
[localize LSTRING(attributeControls),""],
|
|
[localize LSTRING(nextCam),keyName 200],
|
|
[localize LSTRING(prevCam),keyName 208],
|
|
[localize LSTRING(nextUnit),keyName 205],
|
|
[localize LSTRING(prevUnit),keyName 203],
|
|
[localize LSTRING(nextVis),keyName 49],
|
|
[localize LSTRING(prevVis),format["%1 + %2",keyName 29,keyname 49]],
|
|
[localize LSTRING(adjZoom),"Scrollwheel"],
|
|
[localize LSTRING(adjSpeed),format["%1 + Scrollwheel",keyName 29]],
|
|
[localize LSTRING(incZoom),format["%1/%2",keyName 74,keyName 78]],
|
|
[localize LSTRING(incSpeed),format["%1 + %2/%3",keyName 29,keyName 74,keyName 78]],
|
|
[localize LSTRING(reZoom),format["%1 + %2",keyName 56,keyName 74]],
|
|
[localize LSTRING(reSpeed),format["%1 + %2",keyName 56,keyName 78]]
|
|
];
|
|
|
|
// Handle support for BI's respawn counter
|
|
[{
|
|
if !(isNull (GETUVAR(RscRespawnCounter,displayNull))) then {
|
|
disableSerialization;
|
|
private ["_counter","_title","_back","_timer","_frame","_x","_y"];
|
|
_counter = GETUVAR(RscRespawnCounter,displayNull);
|
|
_title = _counter displayCtrl 1001;
|
|
_back = _counter displayCtrl 1002;
|
|
_timer = _counter displayCtrl 1003;
|
|
_frame = _counter ctrlCreate ["RscFrame",1008];
|
|
|
|
_x = safeZoneX + safeZoneW - TOOL_W * 4 - MARGIN * 3;
|
|
_y = safeZoneY + safeZoneH - TOOL_H;
|
|
|
|
// Timer
|
|
_title ctrlSetPosition [_x,_y,TOOL_W,TOOL_H];
|
|
_back ctrlSetPosition [_x,_y,TOOL_W,TOOL_H];
|
|
_timer ctrlSetPosition [_x,_y,TOOL_W,TOOL_H];
|
|
_frame ctrlSetPosition [_x,_y,TOOL_W,TOOL_H];
|
|
|
|
_title ctrlSetBackgroundColor [0,0,0,0];
|
|
_back ctrlSetBackgroundColor [COL_BACK];
|
|
_timer ctrlSetFontHeight TOOL_H;
|
|
_frame ctrlSetTextColor [COL_FORE];
|
|
|
|
_title ctrlCommit 0;
|
|
_back ctrlCommit 0;
|
|
_timer ctrlCommit 0;
|
|
_frame ctrlCommit 0;
|
|
};
|
|
},[],0.5] call CBA_fnc_waitAndExecute;
|
|
};
|
|
case "onunload": {
|
|
// Kill GUI PFHs
|
|
removeMissionEventHandler ["Draw3D",GVAR(iconHandler)];
|
|
GVAR(camHandler) = nil;
|
|
GVAR(compHandler) = nil;
|
|
GVAR(iconHandler) = nil;
|
|
GVAR(toolHandler) = nil;
|
|
|
|
// Reset variables
|
|
GVAR(camBoom) = 0;
|
|
GVAR(camDolly) = [0,0];
|
|
GVAR(ctrlKey) = false;
|
|
GVAR(heldKeys) = [];
|
|
GVAR(heldKeys) resize 255;
|
|
GVAR(mouse) = [false,false];
|
|
GVAR(mousePos) = [0.5,0.5];
|
|
};
|
|
// Mouse events
|
|
case "onmousebuttondown": {
|
|
_args params ["_ctrl","_button"];
|
|
GVAR(mouse) set [_button,true];
|
|
|
|
// Detect right click
|
|
if ((_button == 1) && (GVAR(camMode) == 1)) then {
|
|
// In first person toggle sights mode
|
|
GVAR(camGun) = !GVAR(camGun);
|
|
[] call FUNC(transitionCamera);
|
|
};
|
|
};
|
|
case "onmousebuttonup": {
|
|
_args params ["_ctrl","_button"];
|
|
|
|
GVAR(mouse) set [_button,false];
|
|
if (_button == 0) then { GVAR(camDolly) = [0,0]; };
|
|
};
|
|
case "onmousezchanged": {
|
|
_args params ["_ctrl","_zChange"];
|
|
|
|
// Scroll to modify distance value in third person
|
|
if (GVAR(camMode) == 0) then {
|
|
// Scroll to change speed, modifier for zoom
|
|
if (GVAR(ctrlKey)) then {
|
|
[nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + _zChange * 0.2] call FUNC(setCameraAttributes);
|
|
} else {
|
|
[nil,nil,nil,nil,nil,nil, GVAR(camZoom) + _zChange * 0.1] call FUNC(setCameraAttributes);
|
|
};
|
|
} else {
|
|
GVAR(camDistance) = ((GVAR(camDistance) - _zChange * 2) max 5) min 50;
|
|
};
|
|
};
|
|
case "onmousemoving": {
|
|
_args params ["_ctrl","_x","_y"];
|
|
|
|
[_x,_y] call FUNC(handleMouse);
|
|
};
|
|
// Keyboard events
|
|
case "onkeydown": {
|
|
_args params ["_display","_dik","_shift","_ctrl","_alt"];
|
|
|
|
if ((alive player) && {_dik in (actionKeys "curatorInterface")} && {!isNull (getAssignedCuratorLogic player)}) exitWith {
|
|
[QGVAR(zeus)] call FUNC(interrupt);
|
|
["zeus"] call FUNC(handleInterface);
|
|
};
|
|
if (_dik in (actionKeys "Chat")) exitWith {
|
|
false
|
|
};
|
|
if (_dik in (actionKeys "PrevChannel" + actionKeys "NextChannel")) exitWith {
|
|
!(isServer || serverCommandAvailable "#kick")
|
|
};
|
|
|
|
// Handle held keys (prevent repeat calling)
|
|
if (GVAR(heldKeys) param [_dik,false]) exitWith {};
|
|
// Exclude movement/adjustment keys so that speed can be adjusted on fly
|
|
if !(_dik in [16,17,30,31,32,44,74,78]) then {
|
|
GVAR(heldKeys) set [_dik,true];
|
|
};
|
|
|
|
switch (_dik) do {
|
|
case 1: { // Esc
|
|
[QGVAR(escape)] call FUNC(interrupt);
|
|
["escape"] call FUNC(handleInterface);
|
|
};
|
|
case 2: { // 1
|
|
[_display,nil,nil,nil,nil,nil,true] call FUNC(toggleInterface);
|
|
};
|
|
case 3: { // 2
|
|
[_display,nil,true] call FUNC(toggleInterface);
|
|
};
|
|
case 4: { // 3
|
|
[_display,nil,nil,nil,nil,true] call FUNC(toggleInterface);
|
|
};
|
|
case 5: { // 4
|
|
[_display,true] call FUNC(toggleInterface);
|
|
};
|
|
case 6: { // 5
|
|
GVAR(showIcons) = !GVAR(showIcons);
|
|
};
|
|
case 14: { // Backspace
|
|
[_display,nil,nil,true] call FUNC(toggleInterface);
|
|
};
|
|
case 16: { // Q
|
|
GVAR(camBoom) = 0.5 * GVAR(camSpeed) * ([1, 2] select _shift);
|
|
};
|
|
case 17: { // W
|
|
GVAR(camDolly) set [1, GVAR(camSpeed) * ([1, 2] select _shift)];
|
|
};
|
|
case 29: { // Ctrl
|
|
GVAR(ctrlKey) = true;
|
|
};
|
|
case 30: { // A
|
|
GVAR(camDolly) set [0, -GVAR(camSpeed) * ([1, 2] select _shift)];
|
|
};
|
|
case 31: { // S
|
|
GVAR(camDolly) set [1, -GVAR(camSpeed) * ([1, 2] select _shift)];
|
|
};
|
|
case 32: { // D
|
|
GVAR(camDolly) set [0, GVAR(camSpeed) * ([1, 2] select _shift)];
|
|
};
|
|
case 44: { // Z
|
|
GVAR(camBoom) = -0.5 * GVAR(camSpeed) * ([1, 2] select _shift);
|
|
};
|
|
case 49: { // N
|
|
if (GVAR(camMode) != 1) then {
|
|
if (_ctrl) then {
|
|
[nil,nil,-1] call FUNC(cycleCamera);
|
|
} else {
|
|
[nil,nil,1] call FUNC(cycleCamera);
|
|
};
|
|
};
|
|
};
|
|
case 50: { // M
|
|
[_display,nil,nil,nil,true] call FUNC(toggleInterface);
|
|
};
|
|
case 57: { // Spacebar
|
|
// Switch between unit and freecam here
|
|
};
|
|
case 74: { // Num -
|
|
if (_alt) exitWith { [nil,nil,nil,nil,nil,nil, 1.25] call FUNC(setCameraAttributes); };
|
|
if (_ctrl) then {
|
|
[nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) - 0.05] call FUNC(setCameraAttributes);
|
|
} else {
|
|
[nil,nil,nil,nil,nil,nil, GVAR(camZoom) - 0.01] call FUNC(setCameraAttributes);
|
|
};
|
|
};
|
|
case 78: { // Num +
|
|
if (_alt) exitWith { [nil,nil,nil,nil,nil,nil,nil, 1.5] call FUNC(setCameraAttributes); };
|
|
if (_ctrl) then {
|
|
[nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + 0.05] call FUNC(setCameraAttributes);
|
|
} else {
|
|
[nil,nil,nil,nil,nil,nil, GVAR(camZoom) + 0.01] call FUNC(setCameraAttributes);
|
|
};
|
|
};
|
|
case 200: { // Up arrow
|
|
[-1] call FUNC(cycleCamera);
|
|
};
|
|
case 203: { // Left arrow
|
|
[nil,1] call FUNC(cycleCamera);
|
|
};
|
|
case 205: { // Right arrow
|
|
[nil,-1] call FUNC(cycleCamera);
|
|
};
|
|
case 208: { // Down arrow
|
|
[1] call FUNC(cycleCamera);
|
|
};
|
|
};
|
|
|
|
true
|
|
};
|
|
case "onkeyup": {
|
|
_args params ["_display","_dik","_shift","_ctrl","_alt"];
|
|
|
|
// No longer being held
|
|
GVAR(heldKeys) set [_dik,nil];
|
|
|
|
switch (_dik) do {
|
|
case 16: { // Q
|
|
GVAR(camBoom) = 0;
|
|
};
|
|
case 17: { // W
|
|
GVAR(camDolly) set [1, 0];
|
|
};
|
|
case 29: { // Ctrl
|
|
GVAR(ctrlKey) = false;
|
|
};
|
|
case 30: { // A
|
|
GVAR(camDolly) set [0, 0];
|
|
};
|
|
case 31: { // S
|
|
GVAR(camDolly) set [1, 0];
|
|
};
|
|
case 32: { // D
|
|
GVAR(camDolly) set [0, 0];
|
|
};
|
|
case 44: { // Z
|
|
GVAR(camBoom) = 0;
|
|
};
|
|
};
|
|
|
|
true
|
|
};
|
|
// Tree events
|
|
case "ontreedblclick": {
|
|
// Update camera view when listbox unit is double clicked on
|
|
_args params ["_tree","_sel"];
|
|
|
|
// Ensure a unit was selected
|
|
if (count _sel == 3) then {
|
|
private ["_netID","_newUnit","_newMode"];
|
|
_netID = (_args select 0) tvData _sel;
|
|
_newUnit = objectFromNetId _netID;
|
|
|
|
// When unit is reselected, toggle camera mode
|
|
if (_newUnit == GVAR(camUnit) || GVAR(camMode) == 0) then {
|
|
_newMode = [2,2,1] select GVAR(camMode);
|
|
};
|
|
|
|
[_newMode,_newUnit] call FUNC(transitionCamera);
|
|
};
|
|
};
|
|
case "onunitsupdate": {
|
|
_args params ["_tree"];
|
|
private ["_cachedUnits","_cachedGrps","_cachedSides","_sT","_gT","_uT","_s","_g","_u","_grp","_unit","_side"];
|
|
|
|
// Cache existing group and side nodes and cull removed data
|
|
_cachedUnits = [];
|
|
_cachedGrps = [];
|
|
_cachedSides = [];
|
|
// Track deleted nodes to account for decrease in index
|
|
_sT = _tree tvCount [];
|
|
for [{_s = 0;}, {_s < _sT}, {_s = _s + 1}] do {
|
|
_gT = _tree tvCount [_s];
|
|
|
|
for [{_g = 0;}, {_g < _gT}, {_g = _g + 1}] do {
|
|
_grp = groupFromNetID (_tree tvData [_s,_g]);
|
|
|
|
if (_grp in GVAR(groupList)) then {
|
|
_cachedGrps pushBack _grp;
|
|
_cachedGrps pushBack _g;
|
|
|
|
_uT = _tree tvCount [_s,_g];
|
|
for [{_u = 0;}, {_u < _uT}, {_u = _u + 1}] do {
|
|
_unit = objectFromNetId (_tree tvData [_s,_g,_u]);
|
|
|
|
if (_unit in GVAR(unitList)) then {
|
|
_cachedUnits pushBack _unit;
|
|
} else {
|
|
_tree tvDelete [_s,_g,_u];
|
|
_u = _u - 1;
|
|
_uT = _uT - 1;
|
|
};
|
|
};
|
|
} else {
|
|
_tree tvDelete [_s,_g];
|
|
_g = _g - 1;
|
|
_gT = _gT - 1;
|
|
};
|
|
};
|
|
|
|
if ((_tree tvCount [_s]) > 0) then {
|
|
_cachedSides pushBack (_tree tvText [_s]);
|
|
_cachedSides pushBack _s;
|
|
} else {
|
|
_tree tvDelete [_s];
|
|
_s = _s - 1;
|
|
_sT = _sT - 1;
|
|
};
|
|
};
|
|
|
|
// Update the tree from the unit list
|
|
{
|
|
_grp = group _x;
|
|
_side = [side _grp] call BIS_fnc_sideName;
|
|
|
|
// Use correct side node
|
|
if !(_side in _cachedSides) then {
|
|
// Add side node
|
|
_s = _tree tvAdd [[], _side];
|
|
_tree tvExpand [_s];
|
|
|
|
_cachedSides pushBack _side;
|
|
_cachedSides pushBack _s;
|
|
} else {
|
|
// If side already processed, use existing node
|
|
_s = _cachedSides select ((_cachedSides find _side) + 1);
|
|
};
|
|
|
|
// Use correct group node
|
|
if !(_grp in _cachedGrps) then {
|
|
// Add group node
|
|
_g = _tree tvAdd [[_s], groupID _grp];
|
|
_tree tvSetData [[_s,_g], netID _grp];
|
|
|
|
_cachedGrps pushBack _grp;
|
|
_cachedGrps pushBack _g;
|
|
} else {
|
|
// If group already processed, use existing node
|
|
_g = _cachedGrps select ((_cachedGrps find _grp) + 1);
|
|
};
|
|
|
|
_u = _tree tvAdd [[_s,_g], GETVAR(_x,GVAR(uName),"")];
|
|
_tree tvSetData [[_s,_g,_u], netID _x];
|
|
_tree tvSetPicture [[_s,_g,_u], GETVAR(_x,GVAR(uIcon),"")];
|
|
_tree tvSetPictureColor [[_s,_g,_u], GETVAR(_grp,GVAR(gColor),[ARR_4(1,1,1,1)])];
|
|
|
|
_tree tvSort [[_s,_g],false];
|
|
} forEach (GVAR(unitList) - _cachedUnits);
|
|
|
|
_tree tvSort [[],false];
|
|
|
|
if ((_tree tvCount []) <= 0) then {
|
|
_tree tvAdd [[], localize LSTRING(units_none)];
|
|
};
|
|
};
|
|
// Map events
|
|
case "onmapclick": {
|
|
_args params ["_map","_button","_x","_y","_shift","_ctrl","_alt"];
|
|
private ["_newPos","_oldZ"];
|
|
|
|
if ((GVAR(camMode) == 0) && (_button == 0)) then {
|
|
_newPos = _map ctrlMapScreenToWorld [_x,_y];
|
|
_oldZ = (ASLtoATL GVAR(camPos)) select 2;
|
|
_newPos set [2, _oldZ];
|
|
[nil,nil,nil, _newPos] call FUNC(setCameraAttributes);
|
|
};
|
|
};
|
|
// Interrupt events
|
|
case "escape": {
|
|
createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select isMultiplayer);
|
|
|
|
disableSerialization;
|
|
private _dlg = finddisplay 49;
|
|
_dlg displayAddEventHandler ["KeyDown", {
|
|
_key = _this select 1;
|
|
!(_key == 1)
|
|
}];
|
|
|
|
// Disable save, respawn, options & manual buttons
|
|
(_dlg displayCtrl 103) ctrlEnable false;
|
|
if !(alive player) then {
|
|
(_dlg displayCtrl 1010) ctrlEnable false;
|
|
};
|
|
(_dlg displayCtrl 101) ctrlEnable false;
|
|
(_dlg displayCtrl 122) ctrlEnable false;
|
|
|
|
// Initalize abort button (the "spawn" is a necessary evil)
|
|
(_dlg displayCtrl 104) ctrlAddEventHandler ["ButtonClick",{_this spawn {
|
|
disableSerialization;
|
|
_display = ctrlparent (_this select 0);
|
|
_abort = [localize "str_msg_confirm_return_lobby",nil,localize "str_disp_xbox_hint_yes",localize "str_disp_xbox_hint_no",_display,nil,true] call BIS_fnc_guiMessage;
|
|
if (_abort) then {_display closeDisplay 2; failMission "loser"};
|
|
}}];
|
|
|
|
// PFH to re-open display when menu closes
|
|
[{
|
|
if !(isNull (_this select 0)) exitWith {};
|
|
|
|
// If still a spectator then re-enter the interface
|
|
[QGVAR(escape),false] call FUNC(interrupt);
|
|
|
|
[_this select 1] call CBA_fnc_removePerFrameHandler;
|
|
},0,_dlg] call CBA_fnc_addPerFrameHandler;
|
|
};
|
|
case "zeus": {
|
|
openCuratorInterface;
|
|
|
|
[{
|
|
// PFH to re-open display when menu closes
|
|
[{
|
|
if !((isNull curatorCamera) && {isNull (GETMVAR(bis_fnc_moduleRemoteControl_unit,objNull))}) exitWith {};
|
|
|
|
// If still a spectator then re-enter the interface
|
|
[QGVAR(zeus),false] call FUNC(interrupt);
|
|
|
|
[_this select 1] call CBA_fnc_removePerFrameHandler;
|
|
},0] call CBA_fnc_addPerFrameHandler;
|
|
},[],5] call CBA_fnc_waitAndExecute;
|
|
|
|
true
|
|
};
|
|
};
|