diff --git a/AUTHORS.txt b/AUTHORS.txt index 9b6493b632..6b51c1990a 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -51,6 +51,7 @@ Dharma Bellamkonda Dimaslg eRazeri evromalarkey +F3 Project Falke75 Ferenczi Ferenzi @@ -66,6 +67,7 @@ Hamburger SV Harakhti havena Hawkins +Head jokoho482 ` Jonpas Karneck diff --git a/addons/spectator/ACE_Settings.hpp b/addons/spectator/ACE_Settings.hpp index 88f4ebfad6..5e7907d19f 100644 --- a/addons/spectator/ACE_Settings.hpp +++ b/addons/spectator/ACE_Settings.hpp @@ -1,26 +1,30 @@ class ACE_Settings { - class GVAR(enabled) { - value = 0; + class GVAR(onDeath) { typeName = "BOOL"; - }; - class GVAR(limitSide) { value = 0; - typeName = "BOOL"; }; - class GVAR(AI) { + class GVAR(filterUnits) { + typeName = "SCALAR"; + value = 1; + values[] = {CSTRING(units_none), CSTRING(units_players), CSTRING(units_all)}; + }; + class GVAR(filterSides) { + typeName = "SCALAR"; value = 0; - typeName = "BOOL"; + values[] = {CSTRING(sides_player), CSTRING(sides_friendly), CSTRING(sides_hostile), CSTRING(sides_all)}; }; - class GVAR(tracking) { + class GVAR(restrictModes) { + typeName = "SCALAR"; value = 0; - typeName = "BOOL"; + values[] = {CSTRING(modes_all), CSTRING(modes_unit), CSTRING(modes_free), CSTRING(modes_internal), CSTRING(modes_external)}; }; - class GVAR(modulePos) { + class GVAR(restrictVisions) { + typeName = "SCALAR"; value = 0; - typeName = "BOOL"; + values[] = {CSTRING(modes_all), CSTRING(visions_nv), CSTRING(visions_ti), "$STR_Special_None"}; }; - class GVAR(endMission) { - value = 0; + class GVAR(unitIcons) { typeName = "BOOL"; + value = 1; }; -}; \ No newline at end of file +}; diff --git a/addons/spectator/CfgVehicles.hpp b/addons/spectator/CfgVehicles.hpp index 8faee1dca7..7067257f23 100644 --- a/addons/spectator/CfgVehicles.hpp +++ b/addons/spectator/CfgVehicles.hpp @@ -1,53 +1,125 @@ class CfgVehicles { class ACE_Module; - class ACE_ModuleSpectator: ACE_Module { - author = ECSTRING(common,ACETeam); - category = "ACE"; - displayName = CSTRING(Module_DisplayName); - function = QFUNC(moduleSpectator); + class GVAR(moduleSettings): ACE_Module { scope = 2; - isGlobal = 1; + displayName = CSTRING(Settings_DisplayName); icon = PATHTOF(UI\Icon_Module_Spectator_ca.paa); + category = "ACE"; + function = QFUNC(moduleSpectatorSettings); + isGlobal = 1; + author = ECSTRING(common,ACETeam); class Arguments { - class SpectatorEnabled { - displayName = CSTRING(Enabled_DisplayName); - description = CSTRING(Enabled_Description); + class systemEnable { + displayName = CSTRING(system_DisplayName); + description = CSTRING(system_Description); typeName = "BOOL"; defaultValue = 0; }; - class SpectatorPlayerSide { - displayName = CSTRING(PlayerSide_DisplayName); - description = CSTRING(PlayerSide_Description); - typeName = "BOOL"; - defaultValue = 0; - }; - class SpectatorAI { - displayName = CSTRING(AI_DisplayName); - description = CSTRING(AI_Description); - typeName = "BOOL"; - defaultValue = 0; - }; - class SpectatorTracking { - displayName = CSTRING(Tracking_DisplayName); - description = CSTRING(Tracking_Description); - typeName = "BOOL"; - defaultValue = 0; + class unitsFilter { + displayName = CSTRING(units_DisplayName); + description = CSTRING(units_Description); + typeName = "NUMBER"; + class values { + class none { + name = CSTRING(units_none); + value = 0; + }; + class players { + name = CSTRING(units_players); + value = 1; + default = 1; + }; + class all { + name = CSTRING(units_all); + value = 2; + }; + }; }; - class SpectatorPos { - displayName = CSTRING(Pos_DisplayName); - description = CSTRING(Pos_Description); - typeName = "BOOL"; - defaultValue = 0; + class sidesFilter { + displayName = CSTRING(sides_DisplayName); + description = CSTRING(sides_Description); + typeName = "NUMBER"; + class values { + class player { + name = CSTRING(sides_player); + value = 0; + default = 1; + }; + class friendly { + name = CSTRING(sides_friendly); + value = 1; + }; + class hostile { + name = CSTRING(sides_hostile); + value = 2; + }; + class all { + name = CSTRING(sides_all); + value = 3; + }; + }; }; - class SpectatorEnd { - displayName = CSTRING(End_DisplayName); - description = CSTRING(End_Description); + class cameraModes { + displayName = CSTRING(modes_DisplayName); + description = CSTRING(modes_Description); + typeName = "NUMBER"; + class values { + class all { + name = CSTRING(modes_all); + value = 0; + default = 1; + }; + class unit { + name = CSTRING(modes_unit); + value = 1; + }; + class free { + name = CSTRING(modes_free); + value = 2; + }; + class internal { + name = CSTRING(modes_internal); + value = 3; + }; + class external { + name = CSTRING(modes_external); + value = 4; + }; + }; + }; + class visionModes { + displayName = CSTRING(visions_DisplayName); + description = CSTRING(visions_Description); + typeName = "NUMBER"; + class values { + class all { + name = CSTRING(modes_all); + value = 0; + default = 1; + }; + class nv { + name = CSTRING(visions_nv); + value = 1; + }; + class ti { + name = CSTRING(visions_ti); + value = 2; + }; + class none { + name = "$STR_Special_None"; + value = 3; + }; + }; + }; + class unitIcons { + displayName = CSTRING(icons_DisplayName); + description = CSTRING(icons_Description); typeName = "BOOL"; - defaultValue = 0; + defaultValue = 1; }; }; class ModuleDescription { - description = CSTRING(Module_Description); + description = CSTRING(Settings_Description); }; }; -}; \ No newline at end of file +}; diff --git a/addons/spectator/README.md b/addons/spectator/README.md index 180f21c57c..b3e586149b 100644 --- a/addons/spectator/README.md +++ b/addons/spectator/README.md @@ -7,4 +7,4 @@ Spectator. Includes features from Splendid Cam, and much more. The people responsible for merging changes to this component or answering potential questions. -- [voiper](https://github.com/voiperr) \ No newline at end of file +- [SilentSpike](https://github.com/SilentSpike) diff --git a/addons/spectator/UI.hpp b/addons/spectator/UI.hpp deleted file mode 100644 index eec38066f9..0000000000 --- a/addons/spectator/UI.hpp +++ /dev/null @@ -1,640 +0,0 @@ -#define PIXEL_X (safeZoneWAbs / (getResolution select 0)) -#define PIXEL_Y (safeZoneH / (getResolution select 1)) -#define XHAIR RESUNITS_X * 4 -#define COMPASS_W RESUNITS_X * 20 -#define COMPASS_H COMPASS_W / 15 -#define COMPASS_X RESCENTRE_X - COMPASS_W / 2 -#define HELP_W RESUNITS_X * 75 -#define HELP_H RESUNITS_Y * 75 - -class ace_spectator_overlay { - - idd = 12200; - enableSimulation = 1; - movingEnable = 1; - enableDisplay = 1; - onLoad = "uiNamespace setVariable ['ace_spectator_overlay', _this select 0]; ['Init', _this] call ace_spectator_fnc_overlay"; - - class controls { - - class Unitlist { - - access = 0; - idc = 0; - type = CT_TREE; - style = ST_LEFT; - default = 0; - blinkingPeriod = 0; - - x = QUOTE(safeZoneX); - y = QUOTE(safeZoneY + RESUNITS_X * 4/3); - w = QUOTE(RESUNITS_X * 30); - h = QUOTE(RESUNITS_Y * 50); - - colorBorder[] = {1,1,1,1}; - - colorBackground[] = {0.1,0.1,0.1,1}; - colorSelect[] = {1,0.5,0,1}; - colorMarked[] = {1,0.5,0,0.5}; - colorMarkedSelected[] = {1,0.5,0,1}; - - sizeEx = QUOTE(RESUNITS_Y * 2); - font = GUI_FONT_NORMAL; - shadow = 1; - colorText[] = {1,1,1,1}; - colorSelectText[] = {1,1,1,1}; - colorMarkedText[] = {1,1,1,1}; - - tooltip = ""; - tooltipColorShade[] = {0,0,0,1}; - tooltipColorText[] = {1,1,1,1}; - tooltipColorBox[] = {1,1,1,1}; - - multiselectEnabled = 0; - expandOnDoubleclick = 0; - hiddenTexture = "A3\ui_f\data\gui\rsccommon\rsctree\hiddenTexture_ca.paa"; - expandedTexture = "A3\ui_f\data\gui\rsccommon\rsctree\expandedTexture_ca.paa"; - maxHistoryDelay = 1; - - class ScrollBar { - width = 0; - height = 0; - scrollSpeed = 0.01; - - arrowEmpty = "\A3\ui_f\data\gui\cfg\scrollbar\arrowEmpty_ca.paa"; - arrowFull = "\A3\ui_f\data\gui\cfg\scrollbar\arrowFull_ca.paa"; - border = "\A3\ui_f\data\gui\cfg\scrollbar\border_ca.paa"; - thumb = "\A3\ui_f\data\gui\cfg\scrollbar\thumb_ca.paa"; - - color[] = {1,1,1,1}; - }; - - colorDisabled[] = {0,0,0,0}; - colorArrow[] = {0,0,0,0}; - - onDestroy = QUOTE(GVAR(mouseBusy) = false; false); - onMouseEnter = QUOTE(GVAR(mouseBusy) = true; false); - onMouseExit = QUOTE(GVAR(mouseBusy) = false; false); - - onTreeDblClick = "['Select', _this] call ace_spectator_fnc_overlay; false"; - }; - }; -}; - -class ace_spectator_vd { - idd = 12201; - enableSimulation = 1; - enableDisplay = 0; - movingEnable = 0; - - onLoad = "uiNamespace setVariable ['ace_spectator_vd', _this select 0]; ['Init', _this] call ace_spectator_fnc_viewDistance"; - - class Controls { - - class BG: vip_rsc_box { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30); - y = QUOTE(safeZoneY + COMPASS_H); - w = QUOTE(RESUNITS_X * 30); - h = QUOTE(COMPASS_H); - colorBackground[] = {0.1,0.1,0.1,1}; - onDestroy = QUOTE(GVAR(mouseBusy) = false; false); - }; - - class TitleFrame: vip_rsc_frame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30); - y = QUOTE(safeZoneY + COMPASS_H); - w = QUOTE(RESUNITS_X * 8); - h = QUOTE(COMPASS_H); - shadow = 2; - colorText[]={1,1,1,1}; - }; - - class Title: vip_rsc_text { - style = ST_CENTER; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30); - y = QUOTE(safeZoneY + COMPASS_H); - w = QUOTE(RESUNITS_X * 8); - h = QUOTE(COMPASS_H); - sizeEx = QUOTE(RESUNITS_Y * 2); - font = GUI_FONT_NORMAL; - shadow = 2; - colorText[]={1,1,1,1}; - text = CSTRING(VD_Title); - }; - - class DistanceFrame: TitleFrame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5); - w = QUOTE(RESUNITS_X * 5); - }; - - class Distance: Title { - idc = 1; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5); - w = QUOTE(RESUNITS_X * 5); - text = ""; - }; - - class ButtonExit: vip_rsc_button { - idc = 0; - style = ST_CENTER; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 5); - y = QUOTE(safeZoneY + COMPASS_H); - w = QUOTE(RESUNITS_X * 5); - h = QUOTE(COMPASS_H); - - colorBackground[] = {1,1,1,1}; - sizeEx = QUOTE(RESUNITS_Y * 2); - font = GUI_FONT_NORMAL; - - text = CSTRING(VD_Button); - - onButtonClick = "closeDialog 0; false"; - onMouseButtonDown = QUOTE(GVAR(mouseBusy) = true; false); - onMouseButtonUp = QUOTE(GVAR(mouseBusy) = false; false); - }; - - class Slider { - idc = 2; - - type = CT_XSLIDER; - style = SL_HORZ; - shadow = 2; - - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 21.5); - y = QUOTE(safeZoneY + COMPASS_H); - w = QUOTE(RESUNITS_X * 9.5); - h = QUOTE(COMPASS_H); - color[] = {1,1,1,1}; - colorActive[] = {1,1,1,1}; - colorDisabled[] = {1,1,1,0.2}; - arrowEmpty = "\A3\ui_f\data\gui\cfg\slider\arrowEmpty_ca.paa"; - arrowFull = "\A3\ui_f\data\gui\cfg\slider\arrowFull_ca.paa"; - border = "\A3\ui_f\data\gui\cfg\slider\border_ca.paa"; - thumb = "\A3\ui_f\data\gui\cfg\slider\thumb_ca.paa"; - - text = ""; - onSliderPosChanged = "['Slider', _this] call ace_spectator_fnc_viewDistance"; - onMouseButtonDown = QUOTE(GVAR(mouseBusy) = true; false); - onMouseButtonUp = QUOTE(GVAR(mouseBusy) = false; false); - }; - }; -}; - -class ace_spectator_map { - - idd = 12202; - enableSimulation = 1; - enableDisplay = 0; - onLoad = "uiNameSpace setVariable ['ace_spectator_map', _this select 0]; ['Init', _this select 0] call ace_spectator_fnc_map"; - onUnload = "['Close', _this select 0] call ace_spectator_fnc_map"; - onKeyDown = "['KeyDown', _this] call ace_spectator_fnc_map"; - - class controls { - //changes stolen from ACE_map - class Map { - access = 0; - idc = 1; - type = CT_MAP_MAIN; - style = ST_PICTURE; - default = 0; - blinkingPeriod = 0; - - x = safeZoneXAbs; - y = safeZoneY; - w = safeZoneWAbs; - h = safeZoneH; - - sizeEx = GUI_GRID_CENTER_H; - font = GUI_FONT_NORMAL; - colorText[] = {0,0,0,1}; - text = "#(argb,8,8,3)color(1,1,1,1)"; - - moveOnEdges = 1; - - ptsPerSquareSea = 5; - ptsPerSquareTxt = 20; - ptsPerSquareCLn = 10; - ptsPerSquareExp = 10; - ptsPerSquareCost = 10; - - ptsPerSquareFor = 9; - ptsPerSquareForEdge = 9; - ptsPerSquareRoad = 6; - ptsPerSquareObj = 9; - - scaleMin = 0.001; - scaleMax = 1.0; - scaleDefault = 0.16; - - alphaFadeStartScale = 2; - alphaFadeEndScale = 2; - maxSatelliteAlpha = 0.5; - - colorBackground[] = {0.929412, 0.929412, 0.929412, 1.0}; - colorOutside[] = {0.929412, 0.929412, 0.929412, 1.0}; - colorSea[] = {0.4,0.6,0.8,0.5}; - colorForest[] = {0.6, 0.8, 0.2, 0.25}; - colorForestBorder[] = {0.6,0.8,0.4,1}; - colorRocks[] = {0.50, 0.50, 0.50, 0.50}; - colorRocksBorder[] = {0,0,0,1}; - colorLevels[] = {0.0, 0.0, 0.0, 1.0}; - colorMainCountlines[] = {0.858824, 0, 0,1}; - colorCountlines[] = {0.647059, 0.533333, 0.286275, 1}; - colorMainCountlinesWater[] = {0.5,0.6,0.7,0.6}; - colorCountlinesWater[] = {0.5,0.6,0.7,0.3}; - colorPowerLines[] = {0.1,0.1,0.1,1}; - colorRailWay[] = {0.8,0.2,0,1}; - colorNames[] = {1.1,0.1,1.1,0.9}; - colorInactive[] = {1,1,0,0.5}; - colorTracks[] = {0.2,0.13,0,1}; - colorTracksFill[] = {1,0.88,0.65,0.3}; - colorRoads[] = {0.2,0.13,0,1}; - colorRoadsFill[] = {1,0.88,0.65,1}; - colorMainRoads[] = {0.0,0.0,0.0,1}; - colorMainRoadsFill[] = {0.94,0.69,0.2,1}; - colorGrid[] = {0.05,0.1,0,0.6}; - colorGridMap[] = {0.05,0.1,0,0.4}; - - fontLabel="PuristaMedium"; - sizeExLabel="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - fontGrid="TahomaB"; - sizeExGrid = 0.032; - fontUnits="TahomaB"; - sizeExUnits="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - fontNames="EtelkaNarrowMediumPro"; - sizeExNames="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8) * 2"; - fontInfo="PuristaMedium"; - sizeExInfo="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - fontLevel="TahomaB"; - sizeExLevel=0.03; - showCountourInterval = 1; - - class Task { - icon = "#(argb,8,8,3)color(1,1,1,1)"; - color[] = {1,1,0,1}; - - iconCreated = "#(argb,8,8,3)color(1,1,1,1)"; - colorCreated[] = {0,0,0,1}; - - iconCanceled = "#(argb,8,8,3)color(1,1,1,1)"; - colorCanceled[] = {0,0,0,0.5}; - - iconDone = "#(argb,8,8,3)color(1,1,1,1)"; - colorDone[] = {0,1,0,1}; - - iconFailed = "#(argb,8,8,3)color(1,1,1,1)"; - colorFailed[] = {1,0,0,1}; - - size = 8; - importance = 1; - coefMin = 1; - coefMax = 1; - }; - class ActiveMarker { //includes icons spawned by drawIcon - color[] = {0,0,0,1}; - size = 2; - coefMin = 1; //make sure icon doesnt scale - }; - class Waypoint { - coefMax = 1; - coefMin = 4; - color[] = {0,0,0,1}; - icon = "#(argb,8,8,3)color(0,0,0,1)"; - importance = 1; - size = 2; - }; - class WaypointCompleted: Waypoint{}; - class CustomMark: Waypoint{}; - class Command: Waypoint{}; - class Bush { - icon = ""; - color[] = {0.450000, 0.640000, 0.330000, 0.0}; - size = 14; - importance = "0.2 * 14 * 0.05"; - coefMin = 0.250000; - coefMax = 4; - }; - class Rock: Waypoint{color[]={0.45,0.64,0.33,0.4}; importance="0.5 * 12 * 0.05";}; - class SmallTree { - icon = ""; - color[] = {0.450000, 0.640000, 0.330000, 0.0}; - size = 12; - importance = "0.6 * 12 * 0.05"; - coefMin = 0.250000; - coefMax = 4; - }; - class Tree { - icon = ""; - color[] = {0.450000, 0.640000, 0.330000, 0.0}; - size = 12; - importance = "0.9 * 16 * 0.05"; - coefMin = 0.250000; - coefMax = 4; - }; - class Legend { - x = SafeZoneX+SafeZoneW-.340; - y = SafeZoneY+SafeZoneH-.152; - font = "PuristaMedium"; - w = .340; - h = .152; - sizeEx = 0.039210; - colorBackground[] = {0.906000, 0.901000, 0.880000, 0.5}; - color[] = {0, 0, 0, 0.75}; - }; - class BusStop: Waypoint{}; - class FuelStation: Waypoint{}; - class Hospital: Waypoint{}; - class Church: Waypoint{}; - class Lighthouse: Waypoint{}; - class Power: Waypoint{}; - class PowerSolar: Waypoint{}; - class PowerWave: Waypoint{}; - class PowerWind: Waypoint{}; - class Quay: Waypoint{}; - class Transmitter: Waypoint{}; - class Watertower: Waypoint{}; - class Cross: Waypoint{}; - class Chapel: Waypoint{}; - class Shipwreck: Waypoint{}; - class Bunker: Waypoint{}; - class Fortress: Waypoint{}; - class Fountain: Waypoint{}; - class Ruin: Waypoint{}; - class Stack: Waypoint{}; - class Tourism: Waypoint{}; - class ViewTower: Waypoint{}; - }; - }; -}; - -class RscTitles { - class ace_spectator_crosshair { - - onLoad = "uiNamespace setVariable ['ace_spectator_crosshair', _this select 0]"; - - idd=-1; - movingEnable=0; - fadein=0; - fadeout=0; - duration=1e+011; - - class controls { - - class X: vip_rsc_picture { - idc = 0; - x = QUOTE(RESCENTRE_X - XHAIR / 2); - y = QUOTE(RESCENTRE_Y - XHAIR * 4/3 / 2); - w = QUOTE(XHAIR); - h = QUOTE(XHAIR * 4/3); - text = "\a3\ui_f\data\IGUI\Cfg\Cursors\select_target_ca.paa"; - colorText[] = {1,1,1,0.8}; - }; - }; - }; - - class ace_spectator_status { - - onLoad = "uiNamespace setVariable ['ace_spectator_status', _this select 0]; [_this select 0] call ace_spectator_fnc_status"; - idd = -1; - movingEnable=0; - fadein=0; - fadeout=0; - duration=1e+011; - - class controls { - - class BGRight: vip_rsc_box { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30); - y = QUOTE(safeZoneY); - w = QUOTE(RESUNITS_X * 30); - h = QUOTE(COMPASS_H); - colorBackground[] = {0.1,0.1,0.1,1}; - }; - - class BGLeft: BGRight { - x = QUOTE(safeZoneX); - }; - - class SpeedFrame: vip_rsc_frame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 5); - y = QUOTE(safeZoneY); - w = QUOTE(RESUNITS_X * 5); - h = QUOTE(COMPASS_H); - shadow = 2; - colorText[]={1,1,1,1}; - }; - - class Speed: vip_rsc_text { - idc = 0; - style = ST_CENTER; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 5); - y = QUOTE(safeZoneY); - w = QUOTE(RESUNITS_X * 5); - h = QUOTE(COMPASS_H); - colorText[]={1,1,1,1}; - sizeEx = QUOTE(RESUNITS_Y * 2); - font = GUI_FONT_NORMAL; - text = ""; - }; - - class FovFrame: SpeedFrame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5); - }; - - class Fov: Speed { - idc = 4; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 10.5); - }; - - class TimeAccFrame: SpeedFrame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 21.5); - }; - - class TimeAcc: Speed { - idc = 5; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 21.5); - }; - - class FocusFrame: SpeedFrame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 16); - }; - - class Focus: Speed { - idc = 6; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 16); - }; - - class NameFrame: SpeedFrame { - x = QUOTE(safeZoneX); - w = QUOTE(RESUNITS_X * 24.5); - }; - - class Name: Speed { - idc = 1; - x = QUOTE(safeZoneX); - w = QUOTE(RESUNITS_X * 24.5); - }; - - class ModeFrame: SpeedFrame { - x = QUOTE(safeZoneX + RESUNITS_X * 25); - }; - - class Mode: Speed { - idc = 2; - x = QUOTE(safeZoneX + RESUNITS_X * 25); - }; - - class TimeFrame: SpeedFrame { - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30); - w = QUOTE(RESUNITS_X * 8); - }; - - class Time: Speed { - idc = 3; - x = QUOTE(safeZoneX + safeZoneW - RESUNITS_X * 30); - w = QUOTE(RESUNITS_X * 8); - }; - }; - }; - - class ace_spectator_compass { - - onLoad = "uiNamespace setVariable ['ace_spectator_compass', _this select 0]"; - onUnload = ""; - idd=-1; - movingEnable=0; - fadein=0; - fadeout=0; - duration=1e+011; - - class controls { - - class BG: vip_rsc_box { - x = QUOTE(COMPASS_X); - y = QUOTE(safeZoneY); - w = QUOTE(COMPASS_W); - h = QUOTE(COMPASS_H); - colorBackground[] = {0.1,0.1,0.1,1}; - }; - - class 0_90: vip_rsc_picture { - idc = 1; - x = QUOTE(RESCENTRE_X); - y = QUOTE(safeZoneY); - w = QUOTE(COMPASS_W / 2); - h = QUOTE(COMPASS_H); - text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture180_ca.paa"; - }; - - class 90_180: 0_90 { - idc = 2; - x = QUOTE(RESCENTRE_X + COMPASS_W / 2); - text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture270_ca.paa"; - }; - - class 180_270: 0_90 { - idc = 3; - x = QUOTE(RESCENTRE_X + COMPASS_W); - text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture0_ca.paa"; - }; - - class 270_0: 0_90 { - idc = 4; - x = QUOTE(RESCENTRE_X + COMPASS_W * 1.5); - text = "A3\ui_f_curator\data\cfgIngameUI\compass\texture90_ca.paa"; - }; - - class Post: vip_rsc_box { - x = QUOTE(COMPASS_X + COMPASS_W / 2); - y = QUOTE(safeZoneY); - w = QUOTE(PIXEL_X * 2); - h = QUOTE(COMPASS_H); - colorBackground[]={1,0,0,1}; - }; - - class LeftBlocker: vip_rsc_box { - x = QUOTE(COMPASS_X - COMPASS_W / 2); - y = QUOTE(safeZoneY); - w = QUOTE(COMPASS_W / 2); - h = QUOTE(COMPASS_H); - colorBackground[] = {0.1,0.1,0.1,1}; - }; - - class RightBlocker: LeftBlocker { - x = QUOTE(COMPASS_X + COMPASS_W); - }; - - class Frame: vip_rsc_frame { - x = QUOTE(COMPASS_X); - y = QUOTE(safeZoneY); - w = QUOTE(COMPASS_W); - h = QUOTE(COMPASS_H); - shadow=2; - colorText[]={1,1,1,1}; - }; - }; - }; - - class ace_spectator_help { - - onLoad = "uiNamespace setVariable ['ace_spectator_help', _this select 0]; ['Help', _this select 0] call ace_spectator_fnc_camera"; - idd = -1; - movingEnable=0; - fadein=0; - fadeout=0; - duration=1e+011; - - class controls { - - class BG: vip_rsc_box { - idc = -1; - x = QUOTE(RESCENTRE_X - HELP_W / 2); - y = QUOTE(RESCENTRE_Y - HELP_H / 2); - w = QUOTE(HELP_W); - h = QUOTE(HELP_H); - colorBackground[] = {0.1,0.1,0.1,1}; - }; - - class Title: vip_rsc_text { - idc = 0; - style = ST_CENTER; - x = QUOTE(RESCENTRE_X - RESUNITS_X * 25); - y = QUOTE(RESCENTRE_Y - (HELP_H / 2) + RESUNITS_Y * 3); - w = QUOTE(RESUNITS_X * 50); - h = QUOTE(RESUNITS_Y * 4); - colorText[]={1,1,1,1}; - sizeEx = QUOTE(RESUNITS_Y * 4); - font = GUI_FONT_NORMAL; - text = "ACE Spectator Controls"; - }; - - class LeftColumn1 { - idc = 1; - type = CT_STRUCTURED_TEXT; - style = ST_LEFT; - x = QUOTE(RESCENTRE_X - HELP_W / 2 + RESUNITS_X * 3); - y = QUOTE(RESCENTRE_Y - (HELP_H / 2) + RESUNITS_Y * 10); - w = QUOTE(RESUNITS_X * 16.75); - h = QUOTE(RESUNITS_Y * 63); - text = ""; - size = QUOTE(RESUNITS_Y * 2.5); - colorBackground[] = {0,0,0,0}; - }; - - class LeftColumn2: LeftColumn1 { - idc = 2; - x = QUOTE(RESCENTRE_X - HELP_W / 2 + RESUNITS_X * 19.75); - }; - - class RightColumn1: LeftColumn1 { - idc = 3; - x = QUOTE(RESCENTRE_X + HELP_W / 2 - RESUNITS_X * 3 - RESUNITS_X * 29.5); - }; - - class RightColumn2: LeftColumn1 { - idc = 4; - x = QUOTE(RESCENTRE_X + HELP_W / 2 - RESUNITS_X * 3 - RESUNITS_X * 11.75); - }; - }; - }; -}; \ No newline at end of file diff --git a/addons/spectator/UI/Icon_Module_Spectator_ca.paa b/addons/spectator/UI/Icon_Module_Spectator_ca.paa index a4d784cea6..97258bb0d0 100644 Binary files a/addons/spectator/UI/Icon_Module_Spectator_ca.paa and b/addons/spectator/UI/Icon_Module_Spectator_ca.paa differ diff --git a/addons/spectator/UI/interface.hpp b/addons/spectator/UI/interface.hpp new file mode 100644 index 0000000000..e8df31c280 --- /dev/null +++ b/addons/spectator/UI/interface.hpp @@ -0,0 +1,210 @@ +class RscButtonMenu; +class RscControlsGroupNoScrollbars; +class RscFrame; +class RscListNBox; +class RscMapControl; +class RscPicture; +class RscText; +class RscTree; + +class GVAR(interface) { + idd = 12249; + enableSimulation = 1; + movingEnable = 0; + onLoad = QUOTE([ARR_2('onLoad',_this)] call FUNC(handleInterface)); + onUnload = QUOTE([ARR_2('onUnload',_this)] call FUNC(handleInterface)); + onKeyDown = QUOTE([ARR_2('onKeyDown',_this)] call FUNC(handleInterface)); + onKeyUp = QUOTE([ARR_2('onKeyUp',_this)] call FUNC(handleInterface)); + class controlsBackground { + class mouseHandler: RscControlsGroupNoScrollbars { + x = safeZoneXAbs; + y = safeZoneY; + w = safeZoneWAbs; + h = safeZoneH; + onMouseButtonDown = QUOTE([ARR_2('onMouseButtonDown',_this)] call FUNC(handleInterface)); + onMouseButtonUp = QUOTE([ARR_2('onMouseButtonUp',_this)] call FUNC(handleInterface)); + onMouseZChanged = QUOTE([ARR_2('onMouseZChanged',_this)] call FUNC(handleInterface)); + onMouseMoving = QUOTE([ARR_2('onMouseMoving',_this)] call FUNC(handleInterface)); + onMouseHolding = QUOTE([ARR_2('onMouseMoving',_this)] call FUNC(handleInterface)); + }; + }; + class controls { + class compass: RscControlsGroupNoScrollbars { + idc = IDC_COMP; + x = COMPASS_X; + y = safeZoneY; + w = COMPASS_W; + h = TOOL_H; + class controls { + class compassBack: RscText { + x = 0; + y = 0; + w = COMPASS_W; + h = TOOL_H; + colorBackground[] = {COL_BACK}; + }; + class compass0_90: RscPicture { + idc = IDC_COMP_0; + x = COMPASS_W * 0.5; + y = 0; + w = COMPASS_W * 0.5; + h = TOOL_H; + text = "A3\UI_F_Curator\Data\CfgIngameUI\compass\texture180_ca.paa"; + }; + class compass90_180: compass0_90 { + idc = IDC_COMP_90; + x = COMPASS_W; + text = "A3\UI_F_Curator\Data\CfgIngameUI\compass\texture270_ca.paa"; + }; + class compass180_270: compass0_90 { + idc = IDC_COMP_180; + x = 0; + text = "A3\UI_F_Curator\Data\CfgIngameUI\compass\texture0_ca.paa"; + }; + class compass270_0: compass0_90 { + idc = IDC_COMP_270; + x = COMPASS_W * -0.5; + text = "A3\UI_F_Curator\Data\CfgIngameUI\compass\texture90_ca.paa"; + }; + class compassCaret: RscFrame { + x = COMPASS_W * 0.5; + y = 0; + w = 0; + h = TOOL_H; + colorText[] = {COL_FORE}; + }; + class compassFrame: compassBack { + style = 64; + shadow=2; + colorText[] = {COL_FORE}; + }; + }; + }; + class toolbar: RscControlsGroupNoScrollbars { + idc = IDC_TOOL; + x = safeZoneX; + y = safeZoneY + safeZoneH - TOOL_H; + w = safeZoneW; + h = TOOL_H; + class controls { + class nameTool: RscText { + idc = IDC_TOOL_NAME; + style = 2; + x = 0; + y = 0; + w = TOOL_W * 2; + h = TOOL_H; + shadow = 2; + colorText[]={COL_FORE}; + colorBackground[] = {COL_BACK}; + sizeEx = H_PART(1); + }; + class nameFrame: nameTool { + idc = -1; + style = 64; + }; + class viewTool: nameTool { + idc = IDC_TOOL_VIEW; + x = TOOL_W * 2 + MARGIN; + w = TOOL_W; + }; + class viewFrame: viewTool { + idc = -1; + style = 64; + }; + class fovTool: viewTool { + idc = IDC_TOOL_FOV; + x = TOOL_W * 3 + MARGIN * 2; + }; + class fovFrame: fovTool { + idc = -1; + style = 64; + }; + class clockTool: viewTool { + idc = IDC_TOOL_CLOCK; + x = safeZoneW - TOOL_W * 3 - MARGIN * 2; + }; + class clockFrame: clockTool { + idc = -1; + style = 64; + }; + class visionTool: viewTool { + idc = IDC_TOOL_VISION; + x = safeZoneW - TOOL_W * 2 - MARGIN; + }; + class visionFrame: visionTool { + idc = -1; + style = 64; + }; + class speedTool: viewTool { + idc = IDC_TOOL_SPEED; + x = safeZoneW - TOOL_W; + }; + class speedFrame: speedTool { + idc = -1; + style = 64; + }; + }; + }; + class unitTree: RscTree { + idc = IDC_UNIT; + x = safeZoneX; + y = safeZoneY + TOOL_H * 2; + w = TOOL_W * 2; + h = safeZoneH - TOOL_H * 4; + sizeEx = H_PART(0.8); + borderSize = 1; + colorBorder[] = {COL_FORE}; + colorBackground[] = {COL_BACK}; + colorSelect[] = { + "(profilenamespace getvariable ['GUI_BCG_RGB_R',0.77])", + "(profilenamespace getvariable ['GUI_BCG_RGB_G',0.51])", + "(profilenamespace getvariable ['GUI_BCG_RGB_B',0.08])", + 1 + }; + multiselectEnabled = 0; + onTreeDblClick = QUOTE([ARR_2('onTreeDblClick',_this)] call FUNC(handleInterface)); + }; + class mapOverlay: RscMapControl { + idc = IDC_MAP; + x = safeZoneX; + y = safeZoneY; + w = safeZoneW; + h = safeZoneH; + onMouseButtonDblClick = QUOTE([ARR_2('onMapDblClick',_this)] call FUNC(handleInterface)); + onDraw = QUOTE([ARR_2('onDraw',_this)] call FUNC(handleInterface)); + }; + class helpSplash: RscControlsGroupNoScrollbars { + idc = IDC_HELP; + x = 0.5 - W_PART(12); + y = 0.5 - H_PART(12); + w = W_PART(24); + h = H_PART(24); + class controls { + class helpBack: RscText { + x = 0; + y = 0; + w = W_PART(24); + h = H_PART(24); + colorBackground[] = {COL_BACK}; + }; + class helpTitle: helpBack { + h = H_PART(1); + colorText[]={COL_FORE}; + colorBackground[] = {COL_FORE_D}; + sizeEx = H_PART(1); + text = CSTRING(HelpTitle); + }; + class helpContent: RscListNBox { + idc = IDC_HELP_LIST; + x = W_PART(1); + y = H_PART(2); + W = W_PART(22); + H = H_PART(21); + default = 1; + columns[] = {0.01,0.5}; + }; + }; + }; + }; +}; diff --git a/addons/spectator/XEH_postInit.sqf b/addons/spectator/XEH_postInit.sqf index b57d08ac7b..bad3758c19 100644 --- a/addons/spectator/XEH_postInit.sqf +++ b/addons/spectator/XEH_postInit.sqf @@ -1,96 +1,17 @@ -/* - Author: - voiper -*/ - #include "script_component.hpp" +//#include "initKeybinds.sqf"; + +// Add interaction menu exception +["isNotSpectating", {!((_this select 0) getVariable [QGVAR(isSpectator), false])}] call EFUNC(common,addCanInteractWithCondition); ["SettingsInitialized", { - if !GVAR(enabled) exitWith {}; - - //check if respawn is set up properly - _fail = if (getNumber (missionConfigFile >> "respawn") != 3 && getText (missionConfigFile >> "respawn") != "Base") then {true} else {false}; - if (_fail) exitWith { - _text = "[ACE_Spectator] ERROR: This mission does not have respawn set up properly. Add 'respawn=3' or 'respawn=""BASE""' to description.ext."; - systemChat _text; - diag_log text _text; + GVAR(availableModes) = [[0,1,2], [1,2], [0], [1], [2]] select GVAR(restrictModes); + GVAR(availableVisions) = [[-2,-1,0,1], [-2,-1], [-2,0,1], [-2]] select GVAR(restrictVisions); + + if !(hasInterface) exitWith {}; + + if (GVAR(onDeath)) then { + player addEventHandler ["Killed",FUNC(handleKilled)]; + player addEventHandler ["Respawn",FUNC(handleRespawn)]; }; - - if GVAR(endMission) then { - [{ - if (player distance GVAR(penPos) < 200) then { - if ({isPlayer _x && alive _x && (_x distance GVAR(penPos)) > 200} count allUnits == 0) then { - [["endDeath", false], "BIS_fnc_endMission"] call BIS_fnc_MP; - [_this select 1] call CBA_fnc_removePerFrameHandler; - }; - }; - }, 2] call CBA_fnc_addPerFrameHandler; - }; - - if (isDedicated) exitWith {}; - - call FUNC(penPos); - - { - if (getMarkerPos _x isEqualTo [0,0,0]) then { - _marker = createMarkerLocal [_x, [0,0]]; - _marker setMarkerShapeLocal "ICON"; - }; - - _x setMarkerPosLocal GVAR(penPos); - } forEach ["respawn_west", "respawn_east", "respawn_guerrila", "respawn_civilian"]; - - GVAR(playerSide) = side (group player); - - if GVAR(tracking) then { - [FUNC(checkUnits), 2] call CBA_fnc_addPerFrameHandler; - [FUNC(trackUnits), 20] call CBA_fnc_addPerFrameHandler; - }; - - player addEventHandler ["Killed", { - [player] joinSilent grpNull; - if (isClass (configFile >> "CfgPatches" >> "ace_hearing")) then {EGVAR(hearing,disableVolumeUpdate) = true}; - _delay = getNumber (missionConfigFile >> "respawnDelay"); - _delay fadeSound 0; - 999999 cutText ["", "BLACK", _delay]; - }]; - - player addEventHandler ["Respawn", { - if (!isNil QGVAR(cam)) then {["Exit"] call FUNC(camera)}; - if (isClass (configFile >> "CfgPatches" >> "ace_hearing")) then {EGVAR(hearing,disableVolumeUpdate) = true}; - if (isClass (configFile >> "CfgPatches" >> "acre_sys_radio")) then {[true] call acre_api_fnc_setSpectator}; - if (isClass (configFile >> "CfgPatches" >> "task_force_radio")) then {[player, true] call TFAR_fnc_forceSpectator}; - - if !GVAR(modulePos) then { - _corpse = _this select 1; - if (!isNil "_corpse") then { - if (!isNull _corpse) then { - GVAR(startingPos) = getPosATL _corpse; - }; - }; - }; - - player addEventHandler ["HandleDamage", {0}]; - [player] joinSilent grpNull; - removeAllWeapons player; - removeAllItems player; - removeAllAssignedItems player; - removeUniform player; - removeVest player; - player linkItem "ItemMap"; - player linkItem "ItemRadio"; - hideObjectGlobal player; - - if (surfaceisWater GVAR(penPos)) then { - player forceAddUniform "U_B_Wetsuit"; - player addVest "V_RebreatherB"; - }; - - player setPosATL GVAR(penPos); - - 0 fadeSound 0; - 999999 cutText ["", "BLACK FADED", 0]; - ["Init", [true]] call FUNC(camera); - }]; - -}] call EFUNC(common,addEventHandler); \ No newline at end of file +}] call EFUNC(common,addEventHandler); diff --git a/addons/spectator/XEH_preInit.sqf b/addons/spectator/XEH_preInit.sqf index 41b24e8fcc..e5872c3272 100644 --- a/addons/spectator/XEH_preInit.sqf +++ b/addons/spectator/XEH_preInit.sqf @@ -2,30 +2,51 @@ ADDON = false; -PREP(camera); -PREP(cameraIntro); -PREP(canSpectateUnit); -PREP(checkUnits); -PREP(compass); -PREP(crosshair); -PREP(draw3D); -PREP(drawMines2D); -PREP(drawMines3D); -PREP(drawTracks2D); -PREP(drawUnits2D); -PREP(drawUnits3D); -PREP(killed); -PREP(map); -PREP(moduleSpectator); -PREP(overlay); -PREP(penPos); -PREP(respawn); -PREP(sideColour); -PREP(status); -PREP(trackUnits); -PREP(unitInfo); -PREP(unitSide); -PREP(unitVar); -PREP(viewDistance); +PREP(cacheUnitInfo); +PREP(cycleCamera); +PREP(handleCamera); +PREP(handleCompass); +PREP(handleIcons); +PREP(handleInterface); +PREP(handleKilled); +PREP(handleMouse); +PREP(handleRespawn); +PREP(handleToolbar); +PREP(handleUnits); +PREP(moduleSpectatorSettings); +PREP(setCameraAttributes); +PREP(setSpectator); +PREP(transitionCamera); +PREP(toggleInterface); +PREP(updateCameraModes); +PREP(updateSpectatableSides); +PREP(updateUnits); +PREP(updateVisionModes); -ADDON = true; \ No newline at end of file +// Permanent variables +GVAR(availableModes) = [0,1,2]; +GVAR(availableSides) = [west,east,resistance,civilian]; +GVAR(availableVisions) = [-2,-1,0,1]; + +GVAR(camMode) = 0; +GVAR(camPan) = 0; +GVAR(camPos) = ATLtoASL [worldSize * 0.5, worldSize * 0.5, 20]; +GVAR(camSpeed) = 1; +GVAR(camTilt) = -10; +GVAR(camUnit) = objNull; +GVAR(camVision) = -2; +GVAR(camZoom) = 1.25; + +GVAR(showComp) = true; +GVAR(showHelp) = true; +GVAR(showIcons) = true; +GVAR(showInterface) = true; +GVAR(showMap) = false; +GVAR(showTool) = true; +GVAR(showUnit) = true; + +GVAR(unitList) = []; +GVAR(unitBlacklist) = []; +GVAR(unitWhitelist) = []; + +ADDON = true; diff --git a/addons/spectator/config.cpp b/addons/spectator/config.cpp index 89b0b814b5..e686c75294 100644 --- a/addons/spectator/config.cpp +++ b/addons/spectator/config.cpp @@ -6,8 +6,8 @@ class CfgPatches { weapons[] = {}; requiredVersion = REQUIRED_VERSION; requiredAddons[] = {"ace_common"}; - author[] = {"voiper"}; - authorUrl = "https://github.com/voiperr/"; + author[] = {"F3 Project","Head","SilentSpike","voiper"}; + authorUrl = "https://github.com/acemod"; VERSION_CONFIG; }; }; @@ -15,5 +15,4 @@ class CfgPatches { #include "ACE_Settings.hpp" #include "CfgEventHandlers.hpp" #include "CfgVehicles.hpp" -#include "rsc_defines.hpp" -#include "UI.hpp" \ No newline at end of file +#include "ui\interface.hpp" diff --git a/addons/spectator/functions/fnc_cacheUnitInfo.sqf b/addons/spectator/functions/fnc_cacheUnitInfo.sqf new file mode 100644 index 0000000000..13977bf398 --- /dev/null +++ b/addons/spectator/functions/fnc_cacheUnitInfo.sqf @@ -0,0 +1,33 @@ +/* + * Author: SilentSpike + * Caches the units information for quick retrevial in spectator interface PFHs + * + * Arguments: + * 0: Unit to have info cached for + * + * Return Value: + * None + * + * Example: + * [vehicle player] call ace_spectator_fnc_cacheUnitInfo + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_unit"]; +private ["_color","_icon","_name"]; + +_color = [side group _unit] call BIS_fnc_sideColor; +_icon = getText (configFile >> "CfgVehicles" >> typeOf _unit >> "Icon"); +_name = [_unit,false] call EFUNC(common,getName); + +// Handle CfgVehicleIcons +if isText (configFile >> "CfgVehicleIcons" >> _icon) then { + _icon = getText (configFile >> "CfgVehicleIcons" >> _icon); +}; + +SETVAR(_unit,GVAR(uColor),_color); +SETVAR(_unit,GVAR(uIcon),_icon); +SETVAR(_unit,GVAR(uName),_name); diff --git a/addons/spectator/functions/fnc_camera.sqf b/addons/spectator/functions/fnc_camera.sqf deleted file mode 100644 index bc4cea88cc..0000000000 --- a/addons/spectator/functions/fnc_camera.sqf +++ /dev/null @@ -1,1081 +0,0 @@ -/* - Author: - voiper, derived in part from BIS_fnc_camera by Karel Moricky - - Description: - Spectator camera and UI. - - Arguments: - 0: Mode: "Init" is the only mission relevant one - 1: (optional): - 0: Whether player can escape from camera (false for MP spectator; true for SP photography) - - Example: - ["Init", [false]] call ace_spectator_fnc_camera; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" -#include "\a3\editor_f\Data\Scripts\dikCodes.h" - -disableSerialization; -_mode = _this select 0; -_this = _this select 1; - -switch _mode do { - - case "Init": { - - GVAR(noEscape) = if (count _this > 0) then {_this select 0} else {false}; - - call FUNC(penPos); - - _camPos = if (!isNil QGVAR(startingPos)) then { - GVAR(startingPos) - } else { - getPos cameraOn - }; - - _camDir = if (!isNil QGVAR(startingDir)) then { - GVAR(startingDir) - } else { - 0 - }; - - _camPos set [2, (_camPos select 2) + 2]; - _cam = "camera" camCreate _camPos; - _cam setDir _camDir; - _cam cameraEffect ["internal", "back"]; - _cam camSetFocus [-1, -1]; - _cam camCommit 0; - showCinemaBorder false; - cameraEffectEnableHUD true; - setViewDistance 3000; - - //variables - GVAR(cam) = _cam; - GVAR(LMB) = false; - GVAR(RMB) = false; - GVAR(vector) = [_camDir, 0, 0]; - GVAR(fov) = 0.7; - GVAR(vision) = 0; - GVAR(moveScale) = 0.1; - GVAR(cameraOn) = true; - GVAR(focus) = [-1, -1]; - GVAR(lock) = [-1]; - GVAR(attach) = objNull; - GVAR(unit) = objNull; - GVAR(mouseBusy) = false; - GVAR(markers) = 3; - GVAR(accTime) = 1; - GVAR(third) = false; - - //define only if doesn't exist (to preserve saved spots from a previous camera) - if (isNil QGVAR(savedSpots)) then { - GVAR(savedSpots) = []; - for "_i" from 0 to 11 do {GVAR(savedSpots) set [_i, []]}; - }; - - if (isNil QGVAR(savedUnits)) then { - GVAR(savedUnits) = []; - for "_i" from 0 to 9 do {GVAR(savedUnits) set [_i, objNull]}; - }; - - GVAR(keys) = []; - _DIKcodes = true call BIS_fnc_keyCode; - _DIKlast = _DIKcodes select (count _DIKcodes - 1); - for "_i" from 0 to (_DIKlast - 1) do { - GVAR(keys) set [_i, false]; - }; - - _display = findDisplay 46; - - GVAR(ehDraw3D) = addMissionEventhandler ["Draw3D", {['Draw3D', _this] call FUNC(draw3D)}]; - addMissionEventHandler ["Ended", {if (!isNil QGVAR(cam)) then {["Exit"] call FUNC(camera)}}]; - GVAR(ehKeyDown) = _display displayAddEventHandler ["keyDown", {['KeyDown', _this] call FUNC(camera)}]; - GVAR(ehKeyUp) = _display displayAddEventHandler ["keyUp", {['KeyUp', _this] call FUNC(camera)}]; - GVAR(ehMouseButtonDown) = _display displayAddEventHandler ["mouseButtonDown", {['MouseButtonDown', _this] call FUNC(camera)}]; - GVAR(ehMouseButtonUp) = _display displayAddEventHandler ["mouseButtonUp", {['MouseButtonUp',_this] call FUNC(camera)}]; - GVAR(ehMouseZChanged) = _display displayAddEventHandler ["mouseZChanged", {['MouseZChanged',_this] call FUNC(camera)}]; - GVAR(ehMouseMoving) = _display displayAddEventHandler ["mouseMoving", {['Mouse',_this] call FUNC(camera)}]; - GVAR(ehMouseHolding) =_display displayAddEventHandler ["mouseHolding", {['Mouse',_this] call FUNC(camera)}]; - - //remove mission layer - _displayMission = call (uiNamespace getVariable "BIS_fnc_displayMission"); - _control = _displayMission displayCtrl 11400; - _control ctrlSetFade 1; - _control ctrlCommit 0; - - //kill layers - cutText ["", "Plain"]; - _layers = missionNamespace getVariable ["BIS_fnc_rscLayer_list", []]; - for "_i" from 1 to (count _layers - 1) step 2 do { - (_layers select _i) cutText ["", "Plain"]; - }; - - clearRadio; - - //crosshair - _layer = [QGVAR(crosshair)] call BIS_fnc_rscLayer; - _layer cutRsc [QGVAR(crosshair), "PLAIN", 2, true]; - - //compass - _layer = [QGVAR(compass)] call BIS_fnc_rscLayer; - _layer cutRsc [QGVAR(compass), "PLAIN", 2, true]; - - //status - _layer = [QGVAR(status)] call BIS_fnc_rscLayer; - _layer cutRsc [QGVAR(status), "PLAIN", 2, true]; - - //help - _layer = [QGVAR(help)] call BIS_fnc_rscLayer; - preloadTitleRsc [QGVAR(help), "PLAIN", 0, true]; - - if (isClass (configFile >> "CfgPatches" >> "ace_nametags")) then { - GVAR(tags) = [EGVAR(nametags,showPlayerNames), EGVAR(nametags,showNamesForAI)]; - EGVAR(nametags,showPlayerNames) = 0; - EGVAR(nametags,showNamesForAI) = false; - }; - - if (isClass (configFile >> "CfgPatches" >> "ace_interact_menu")) then { - [QGVAR(interactCondition), {false}] call EFUNC(common,addCanInteractWithCondition); - }; - - //add unit check, since if tracking were on it would already be present - if !GVAR(tracking) then { - [FUNC(checkUnits), 2] call CBA_fnc_addPerFrameHandler - }; - - [FUNC(cameraIntro), 1] call CBA_fnc_addPerFrameHandler; - }; - - ////////////////////////////////////////// - case "Mouse": { - _mapOn = uiNamespace getVariable QGVAR(map); - if (!isNull _mapOn) exitWith {}; - - _keys = GVAR(keys); - _cam = GVAR(cam); - _dir = GVAR(vector) select 0; - _pitch = GVAR(vector) select 1; - _bank = GVAR(vector) select 2; - _camPos = getPosASL _cam; - _coef = (GVAR(moveScale) * (((getPosATL _cam) select 2) / 2)) min 50 max 0.001; - - _move = { - _inPos = _this; - if !GVAR(cameraOn) exitWith {}; - if (_inPos select 2 > 20000) then {_inPos set [2, 20000]}; - _obj = GVAR(attach); - if !(isNull _obj) then { - if ((GVAR(lock) select 0) < 0) then { - _modelPos = _obj worldToModel (ASLtoATL _inPos); - _cam attachTo [_obj, _modelPos]; - }; - } else { - _cam setPosASL _inPos; - }; - }; - - if (GVAR(LMB) || GVAR(RMB)) then { - if GVAR(mouseBusy) exitWith {}; - _mX = (_this select 1) * (GVAR(accTime) max 0.05); - _mY = (_this select 2) * (GVAR(accTime) max 0.05); - - if GVAR(RMB) then { - - _dX = _mX; - _dY = -_mY; - - _camPos = [_camPos, _dY, getDir _cam] call BIS_fnc_relPos; - _camPos = [_camPos, _dX, getDir _cam + 90] call BIS_fnc_relPos; - - _camPos call _move; - - } else { - if (GVAR(lock) select 0 > -1) exitWith {}; - _dX = _mX / 50 * 180 * GVAR(fov); - _dY = -_mY / 50 * 180 * GVAR(fov); - - if (_keys select DIK_LSHIFT) then { - _pitch = (_pitch + _dY) max -180 min 180; - _bank = (_bank + _dX) max -181 min 181; - if (_bank <= -181) then {_bank = 180} else {if (_bank >= 181) then {_bank = -180}}; - } else { - _dir = _dir + _dX; - _pitch = (_pitch + _dY) max -90 min 90; - }; - GVAR(vector) = [_dir, _pitch, _bank]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - }; - }; - - _camMove = { - _dX = _this select 0; - _dY = _this select 1; - _dZ = _this select 2; - _pos = getPosASL _cam; - _moveDir = (getDir _cam) + _dX * 90; - _camPos = [ - (_pos select 0) + ((sin (_moveDir)) * _coef * _dY), - (_pos select 1) + ((cos (_moveDir)) * _coef * _dY), - (_pos select 2) + _dZ * _coef / 1.5 - ]; - //for some reason, at visual height = 0, cameras report 10cm higher than they actually are - _camPos set [2, (_camPos select 2) max (getTerrainHeightASL _camPos + 0.1)]; - - _camPos call _move; - }; - - _camRotate = { - if ((GVAR(lock) select 0) > -1) exitWith {}; - _dX = (_this select 0) * GVAR(fov) * _rotMod; - _dY = (_this select 1) * GVAR(fov) * _rotMod; - _pitch = ((GVAR(vector) select 1) + _dY) max -90 min 90; - _bank = GVAR(vector) select 2; - _dir = _dir + _dX; - GVAR(vector) = [_dir, _pitch, _bank]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - }; - - _camBank = { - if ((GVAR(lock) select 0) > -1) exitWith {}; - _dZ = (_this select 0) * _rotMod; - _pitch = GVAR(vector) select 1; - _bank = ((GVAR(vector) select 2) + _dZ) max -181 min 181; - if (_bank == -181) then {_bank = 180} else {if (_bank == 181) then {_bank = -180}}; - GVAR(vector) = [_dir, _pitch, _bank]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - }; - - _numPad0 = _keys select DIK_NUMPAD0; - _numPadDel = _keys select DIK_DECIMAL; - _rotMod = if (_numPad0 && !_numPadDel) then { - 5 - } else { - if (!_numPad0 && _numPadDel) then {0.1} else {1}; - }; - - if (_keys select DIK_W) then {[0,1,0] call _camMove}; - if (_keys select DIK_S) then {[0,-1,0] call _camMove}; - if (_keys select DIK_A) then {[-1,1,0] call _camMove}; - if (_keys select DIK_D) then {[1,1,0] call _camMove}; - - if (_keys select DIK_Q) then {[0,0,1] call _camMove}; - if (_keys select DIK_Z) then {[0,0,-1] call _camMove}; - - if (_keys select DIK_NUMPAD1) then {[-1,-1,0] call _camRotate}; - if (_keys select DIK_NUMPAD2) then {[+0,-1,0] call _camRotate}; - if (_keys select DIK_NUMPAD3) then {[+1,-1,0] call _camRotate}; - if (_keys select DIK_NUMPAD4) then {[-1,+0,0] call _camRotate}; - if (_keys select DIK_NUMPAD6) then {[+1,+0,0] call _camRotate}; - if (_keys select DIK_NUMPAD7) then {[-1,+1,0] call _camRotate}; - if (_keys select DIK_NUMPAD8) then {[+0,+1,0] call _camRotate}; - if (_keys select DIK_NUMPAD9) then {[+1,+1,0] call _camRotate}; - if (_keys select DIK_DIVIDE) then {[-1] call _camBank}; - if (_keys select DIK_MULTIPLY) then {[+1] call _camBank}; - - if (_keys select DIK_ADD) then { - GVAR(fov) = GVAR(fov) - (GVAR(fov) / 50 * _rotMod) max 0.01; - _cam camPrepareFOV GVAR(fov); - _cam camCommitPrepared 0; - }; - if (_keys select DIK_SUBTRACT) then { - GVAR(fov) = GVAR(fov) + (GVAR(fov) / 50 * _rotMod) min 2; - _cam camPrepareFOV GVAR(fov); - _cam camCommitPrepared 0; - }; - - if (_keys select DIK_NUMPADENTER) then { - GVAR(fov) = 0.7; - _cam camPrepareFOV GVAR(fov); - _cam camCommitPrepared 0; - }; - - if (_keys select DIK_MINUS) then { - _cur = GVAR(focus) select 0; - if (_cur < 0) then {_cur = 1}; - _cur = _cur - (_cur / 25) max 0.25; - GVAR(focus) = [_cur, 1.5]; - _cam camSetFocus GVAR(focus); - _cam camCommit 0; - }; - - if (_keys select DIK_EQUALS) then { - _cur = GVAR(focus) select 0; - if (_cur < 0) then {_cur = 1}; - _cur = _cur + (_cur / 25) min 5000; - GVAR(focus) = [_cur, 1.5]; - _cam camSetFocus GVAR(focus); - _cam camCommit 0; - }; - - if (_keys select DIK_LBRACKET)then { - if (!isMultiplayer) then { - _cur = GVAR(accTime); - _cur = _cur - (_cur / 25) max 0; - GVAR(accTime) = _cur; - setAccTime GVAR(accTime); - }; - }; - - if (_keys select DIK_RBRACKET)then { - if (!isMultiplayer) then { - _cur = GVAR(accTime); - _cur = _cur + (_cur / 25) min 4; - GVAR(accTime) = _cur; - setAccTime GVAR(accTime); - }; - }; - }; - - ////////////////////////////////////////// - case "MouseButtonDown": { - _mapOn = uiNamespace getVariable QGVAR(map); - if (!isNull _mapOn) exitWith {}; - - _button = _this select 1; - _mX = _this select 2; - _mY = _this select 3; - _shift = _this select 4; - _ctrl = _this select 5; - _alt = _this select 6; - - switch (_button) do { - case 0: {GVAR(LMB) = true}; - case 1: {GVAR(RMB) = true}; - }; - }; - - ////////////////////////////////////////// - case "MouseButtonUp": { - _mapOn = uiNamespace getVariable QGVAR(map); - if (!isNull _mapOn) exitWith {}; - - _button = _this select 1; - switch (_button) do { - case 0: {GVAR(LMB) = false}; - case 1: {GVAR(RMB) = false}; - }; - }; - - ////////////////////////////////////////// - case "MouseZChanged": { - _mapOn = uiNamespace getVariable QGVAR(map); - if (!isNull _mapOn) exitWith {}; - - _diff = _this select 1; - if (_diff > 0) then { - GVAR(moveScale) = GVAR(moveScale) + (GVAR(moveScale) / 10) min 1; - } else { - GVAR(moveScale) = GVAR(moveScale) - (GVAR(moveScale) / 10) max 0.001; - }; - }; - - ////////////////////////////////////////// - case "KeyDown": { - _key = _this select 1; - _shift = _this select 2; - _ctrl = _this select 3; - _alt = _this select 4; - _return = false; - - GVAR(keys) set [_key, true]; - - _cam = GVAR(cam); - _camOn = GVAR(cameraOn); - _unit = GVAR(unit); - _lock = GVAR(lock) select 0; - - _camPos = [getPos _cam, GVAR(vector), GVAR(fov), GVAR(focus)]; - - _camSaveSpot = { - _num = _this select 0; - if (!isNull GVAR(attach)) then { - _vector = _camPos select 1; - _dir = _vector select 0; - _vector set [0, _dir - (getDir GVAR(attach))]; - _camPos set [1, _vector]; - }; - GVAR(savedSpots) set [_num, _camPos]; - }; - - _camLoadSpot = { - _num = _this select 0; - _arr = GVAR(savedSpots) select _num; - if (count (_arr) > 0) then { - if (!_camOn) then { - ["Camera", ["Free"]] call FUNC(camera) - }; - call _detach; - _cam setPos (_arr select 0); - _vector = _arr select 1; - [_cam, _vector] call BIS_fnc_setObjectRotation; - _cam camPrepareFOV (_arr select 2); - _cam camPrepareFocus (_arr select 3); - _cam camCommitPrepared 0; - GVAR(vector) = _vector; - }; - }; - - _camSaveUnit = { - _num = _this select 0; - - if (!isNull _unit) then { - _alreadySaved = GVAR(savedUnits) find _unit; - if (_alreadySaved > -1) then { - GVAR(savedUnits) set [_alreadySaved, objNull]; - }; - GVAR(savedUnits) set [_num, _unit] - }; - }; - - _camLoadUnit = { - _num = _this select 0; - _unit = GVAR(savedUnits) select _num; - if (!isNull _unit) then { - if (_lock > -1) then { - ["Camera", ["Lock"]] call FUNC(camera) - }; - if (GVAR(unit) == _unit) then { - call _detach; - if (_camOn) then { - ["Camera", ["Third"]] call FUNC(camera); - } else { - ["Camera", ["SwitchUnit"]] call FUNC(camera); - }; - } else { - GVAR(unit) = _unit; - if ((GVAR(lock) select 0) > -1) then {["Camera", ["Lock"]] call FUNC(camera)}; - if (!_camOn) then { - call _detach; - ["Camera", ["SwitchUnit"]] call FUNC(camera); - }; - }; - }; - }; - - _detach = { - if (!isNull GVAR(attach)) then { - ["Camera", ["Attach"]] call FUNC(camera); - }; - }; - - switch (_key) do { - - case (DIK_F1): {if (_ctrl) then {[0] call _camSaveSpot} else {[0] call _camLoadSpot}; _return = true}; - case (DIK_F2): {if (_ctrl) then {[1] call _camSaveSpot} else {[1] call _camLoadSpot}; _return = true}; - case (DIK_F3): {if (_ctrl) then {[2] call _camSaveSpot} else {[2] call _camLoadSpot}; _return = true}; - case (DIK_F4): {if (_ctrl) then {[3] call _camSaveSpot} else {[3] call _camLoadSpot}; _return = true}; - case (DIK_F5): {if (_ctrl) then {[4] call _camSaveSpot} else {[4] call _camLoadSpot}; _return = true}; - case (DIK_F6): {if (_ctrl) then {[5] call _camSaveSpot} else {[5] call _camLoadSpot}; _return = true}; - case (DIK_F7): {if (_ctrl) then {[6] call _camSaveSpot} else {[6] call _camLoadSpot}; _return = true}; - case (DIK_F8): {if (_ctrl) then {[7] call _camSaveSpot} else {[7] call _camLoadSpot}; _return = true}; - case (DIK_F9): {if (_ctrl) then {[8] call _camSaveSpot} else {[8] call _camLoadSpot}; _return = true}; - case (DIK_F10): {if (_ctrl) then {[9] call _camSaveSpot} else {[9] call _camLoadSpot}; _return = true}; - case (DIK_F11): {if (_ctrl) then {[10] call _camSaveSpot} else {[10] call _camLoadSpot}; _return = true}; - case (DIK_F12): {if (_ctrl) then {[11] call _camSaveSpot} else {[11] call _camLoadSpot}; _return = true}; - - case (DIK_1): {if (_ctrl) then {[0] call _camSaveUnit} else {[0] call _camLoadUnit}; _return = true}; - case (DIK_2): {if (_ctrl) then {[1] call _camSaveUnit} else {[1] call _camLoadUnit}; _return = true}; - case (DIK_3): {if (_ctrl) then {[2] call _camSaveUnit} else {[2] call _camLoadUnit}; _return = true}; - case (DIK_4): {if (_ctrl) then {[3] call _camSaveUnit} else {[3] call _camLoadUnit}; _return = true}; - case (DIK_5): {if (_ctrl) then {[4] call _camSaveUnit} else {[4] call _camLoadUnit}; _return = true}; - case (DIK_6): {if (_ctrl) then {[5] call _camSaveUnit} else {[5] call _camLoadUnit}; _return = true}; - case (DIK_7): {if (_ctrl) then {[6] call _camSaveUnit} else {[6] call _camLoadUnit}; _return = true}; - case (DIK_8): {if (_ctrl) then {[7] call _camSaveUnit} else {[7] call _camLoadUnit}; _return = true}; - case (DIK_9): {if (_ctrl) then {[8] call _camSaveUnit} else {[8] call _camLoadUnit}; _return = true}; - case (DIK_0): {if (_ctrl) then {[9] call _camSaveUnit} else {[9] call _camLoadUnit}; _return = true}; - - case (DIK_NUMPAD5): { - _dir = getDir _cam; - if (!isNull GVAR(attach)) then {_dir = _dir - getDir GVAR(attach)}; - GVAR(vector) = [_dir, 0, 0]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - GVAR(fov) = 0.7; - _cam camPrepareFOV GVAR(fov); - _cam camCommitPrepared 0; - }; - - case (DIK_NUMPADENTER): {_return = true}; - - case (DIK_NUMPAD0): {_return = true}; - - case (DIK_DECIMAL): {_return = true}; - - case (DIK_BACKSPACE): { - GVAR(focus) = if (!_shift) then { - [-1, 1]; - } else { - [-1, -1]; - }; - _cam camPrepareFocus GVAR(focus); - _cam camCommitPrepared 0; - _return = true; - }; - - case (DIK_BACKSLASH): { - if (!isMultiplayer) then { - GVAR(accTime) = 1; - setAccTime GVAR(accTime); - }; - }; - - case (DIK_GRAVE): {_return = true}; - - case (DIK_SPACE): { - if (!_camOn) exitWith {}; - if (_ctrl) then { - ["Camera", ["Attach"]] call FUNC(camera); - } else { - ["Camera", ["Lock"]] call FUNC(camera); - }; - }; - - case (DIK_LEFT): { - ["Camera", ["NewUnit", -1]] call FUNC(camera) - }; - - case (DIK_RIGHT): { - ["Camera", ["NewUnit", 1]] call FUNC(camera) - }; - - case (DIK_UP): { - if (isNull GVAR(unit)) exitWith {}; - if (_lock > -1) then {["Camera", ["Lock"]] call FUNC(camera)}; - call _detach; - if (_camOn) then { - ["Camera", ["Third"]] call FUNC(camera); - } else { - if GVAR(third) then { - ["Camera", ["First"]] call FUNC(camera); - }; - }; - }; - - case (DIK_DOWN): { - if (isNull GVAR(unit)) exitWith {}; - if (_lock > -1) then {["Camera", ["Lock"]] call FUNC(camera)}; - call _detach; - if (!_camOn) then { - if !GVAR(third) then { - ["Camera", ["Third"]] call FUNC(camera); - } else { - ["Camera", ["Free"]] call FUNC(camera); - }; - }; - }; - - case (DIK_T): { - GVAR(markers) = GVAR(markers) + 1; - if (GVAR(markers) > 3) then {GVAR(markers) = 0}; - if (GVAR(markers) == 0) then {clearRadio}; - }; - - case (DIK_U): { - _map = uiNameSpace getVariable [QGVAR(map), findDisplay 12202]; - if (!isNull _map) exitWith {}; - - _overlay = uiNamespace getVariable [QGVAR(overlay), findDisplay 12200]; - if (isNull _overlay) then { - createDialog QGVAR(overlay); - } else { - closeDialog 0; - }; - }; - - case (DIK_X): { - _layer = [QGVAR(crosshair)] call BIS_fnc_rscLayer; - _xhair = uiNamespace getVariable QGVAR(crosshair); - if (isNull _xhair) then { - _layer cutRsc [QGVAR(crosshair), "PLAIN", 0, true]; - call FUNC(crosshair); - } else { - _layer cutText ["", "PLAIN"]; - }; - }; - - case (DIK_C): { - _layer = [QGVAR(compass)] call BIS_fnc_rscLayer; - if (isNull (uiNamespace getVariable QGVAR(compass))) then { - _layer cutRsc [QGVAR(compass), "PLAIN", 0, true]; - } else { - _layer cutText ["", "PLAIN"]; - }; - - _layer = [QGVAR(status)] call BIS_fnc_rscLayer; - if (isNull (uiNamespace getVariable QGVAR(status))) then { - _layer cutRsc [QGVAR(status), "PLAIN", 0, true]; - } else { - _layer cutText ["", "PLAIN"]; - }; - }; - - case (DIK_G): { - _vd = uiNamespace getVariable [QGVAR(vd), findDisplay 12201]; - if (isNull _vd) then { - createDialog QGVAR(vd); - } else { - closeDialog 0; - } - }; - - case (DIK_H): { - _layer = [QGVAR(help)] call BIS_fnc_rscLayer; - if (isNull (uiNamespace getVariable QGVAR(help))) then { - _layer cutRsc [QGVAR(help), "PLAIN", 0, true]; - } else { - _layer cutText ["", "PLAIN"]; - }; - }; - - case (DIK_M): { - _map = uiNameSpace getVariable [QGVAR(map), findDisplay 12202]; - if (isNull _map) then { - createDialog QGVAR(map); - } else { - closeDialog 0; - }; - }; - - case (DIK_N): { - GVAR(vision) = GVAR(vision) + 1; - if (GVAR(vision) > 4) then {GVAR(vision) = 0}; - switch GVAR(vision) do { - case 0: { - camUseNVG false; - false SetCamUseTi 0; - }; - case 1: { - camUseNVG true; - false SetCamUseTi 0; - }; - case 2: { - camUseNVG false; - true SetCamUseTi 0; - }; - case 3: { - camUseNVG false; - true SetCamUseTi 1; - }; - - case 4: { - camUseNVG false; - true SetCamUseTi 4; - }; - }; - }; - - case (DIK_ESCAPE): { - if !GVAR(noEscape) then { - _return = true; - _this spawn { - disableSerialization; - _display = _this select 0; - _message = ["Do you want to exit spectator?", "ACE Spectator", nil, true, _display] call BIS_fnc_guiMessage; - if (_message) then {["Exit"] call FUNC(camera)}; - }; - }; - }; - default {}; - }; - - _return - }; - - ////////////////////////////////////////// - case "KeyUp": { - GVAR(keys) set [_this select 1, false]; - }; - - ////////////////////////////////////////// - case "Camera": { - - _mode = _this select 0; - - _cam = GVAR(cam); - _camOn = GVAR(cameraOn); - _unit = GVAR(unit); - _lock = GVAR(lock) select 0; - - _findTarget = { - - _ret = []; - _screenPos = screenToWorld [0.5,0.5]; - _camPosASL = getPosASL _cam; - _camPosReal = getPos _cam; - _endPosASL = [_screenPos select 0, _screenPos select 1, getTerrainHeightASL _screenPos]; - _endPosReal = if (surfaceIsWater _endPosASL) then {_endPosASL} else {ASLtoATL _endPosASL}; - _objs = lineIntersectsWith [_camPosASL, _endPosASL, objNull, objNull, true]; - - if (count _objs > 0) then { //if vehicle/object found - _obj = _objs select (count _objs - 1); - _ret = _obj; - } else { //check for units near endpoint instead - _units = allUnits; - if (count _units > 0) then { - _nearestUnit = _units select 0; - {if (_endPosReal distance _x < _endPosReal distance _nearestUnit) then {_nearestUnit = _x}} forEach _units; - _intersect = [_nearestUnit, "FIRE"] intersect [_camPosReal, _endPosReal]; - if (count (_intersect) > 0) then { - _ret = _nearestUnit; - } else { //check for units near camera instead - _nearestUnit = _units select 0; - {if (_cam distance _x < _cam distance _nearestUnit) then {_nearestUnit = _x}} forEach _units; - _intersect = [_nearestUnit, "FIRE"] intersect [_camPosReal, _endPosReal]; - if (count _intersect > 0) then { - _ret = _nearestUnit; - } else { //if nothing else, point at ground position - _ret = _endPosReal; - }; - }; - }; - }; - _ret - }; - - switch (_mode) do { - - case "Free": { - GVAR(cameraOn) = true; - GVAR(third) = false; - detach _cam; - player switchCamera "Internal"; - _cam cameraEffect ["Internal", "Back"]; - cameraEffectEnableHUD true; - _dir = getDir _unit; - _pos = [_unit, -5, _dir] call BIS_fnc_relPos; - _pos set [2, ((getPos _unit) select 2) + 2]; - _cam setPos _pos; - GVAR(vector) set [0, _dir]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - }; - - case "First": { - if (_unit == player) exitWith {}; - GVAR(cameraOn) = false; - GVAR(third) = false; - _cam attachTo [vehicle _unit, [0,0.1,0]]; - _cam cameraEffect ["Terminate", "Back"]; - vehicle _unit switchCamera "Internal"; - }; - - case "Third": { - if (_unit == player) exitWith {}; - GVAR(third) = true; - GVAR(cameraOn) = false; - if (!difficultyEnabled "3rdPersonView") then { - player switchCamera "Internal"; - _cam cameraEffect ["Internal", "Back"]; - cameraEffectEnableHUD true; - if (vehicle _unit == _unit) then { - _cam attachTo [_unit, [0.1, -2.4, 0.6], "head"]; - } else { - _cam attachTo [vehicle _unit, [0, -7, 1.5]]; - }; - } else { - _cam attachTo [vehicle _unit, [0,0.1,0]]; - _cam cameraEffect ["Terminate", "Back"]; - vehicle _unit switchCamera "External"; - }; - }; - - case "NewUnit": { - - _increment = _this select 1; - _units = []; - { - if (alive _x) then {_units pushBack _x}; - } forEach GVAR(units); - - _count = count _units; - - if (_count > 0) then { - - _index = _units find _unit; - _index = _index + _increment; - if (_index < 0) then {_index = _count - 1}; - if (_index > (_count - 1)) then {_index = 0}; - - GVAR(unit) = _units select _index; - if (!_camOn) then {["Camera", ["SwitchUnit"]] call FUNC(camera)}; - }; - }; - - case "SwitchUnit": { - if !GVAR(third) then { - ["Camera", ["First"]] call FUNC(camera); - } else { - ["Camera", ["Third"]] call FUNC(camera); - }; - }; - - case "Lock": { - if (_lock < 0) then { - - _target = call _findTarget; - - if (typeName _target == "OBJECT") then { - GVAR(lock) = [1, _target]; - } else { - if (count _target > 0) then { - GVAR(lock) = [1, _target]; - }; - }; - - _cam camPrepareTarget (GVAR(lock) select 1); - _cam camCommitPrepared 0; - call FUNC(crosshair); - } else { - - _dir = getDir _cam; - _pitchBank = _cam call BIS_fnc_getPitchBank; - GVAR(lock) = [-1]; - _cam cameraEffect ["Terminate", "Back"]; - camDestroy _cam; - _cam = "camera" camCreate (_camPos select 0); - [_cam, _camPos select 1] call BIS_fnc_setObjectRotation; - _cam camPrepareFOV (_camPos select 2); - _cam camPrepareFocus GVAR(focus); - _cam camCommitPrepared 0; - _cam cameraEffect ["Internal", "Back"]; - cameraEffectEnableHUD true; - GVAR(cam) = _cam; - _obj = GVAR(attach); - if !(isNull _obj) then { - _modelPos = _obj worldToModel (_camPos select 0); - _cam attachTo [_obj, _modelPos]; - _dir = _dir - getDir _obj; - }; - GVAR(vector) = [_dir, _pitchBank select 0, 0]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - call FUNC(crosshair); - }; - }; - - case "Attach": { - _dir = getDir _cam; - _pitchBank = _cam call BIS_fnc_getPitchBank; - if (isNull GVAR(attach)) then { - _target = call _findTarget; - if (typeName _target == "OBJECT") then { - if (_target isKindOf "AllVehicles") then { - _dir = _dir - getDir _target; - _cam attachTo [_target]; - GVAR(attach) = _target; - call FUNC(crosshair); - }; - }; - } else { - detach _cam; - GVAR(attach) = objNull; - call FUNC(crosshair); - }; - GVAR(vector) = [_dir, _pitchBank select 0, _pitchBank select 1]; - [_cam, GVAR(vector)] call BIS_fnc_setObjectRotation; - }; - }; - - call FUNC(crosshair); - }; - - ////////////////////////////////////////// - case "Help": { - - _dialog = _this; - -_c1Action = parseText " -Camera:
-
-Move
-Pitch, Yaw
-Roll
-Slide
-Speed Multiplier
-Camera Mode
-Track Pos or Object
-Lock to Object
-Save Pos
-Recall Pos
-Optic Mode
-Focus
-Autofocus
-Disable Focus
-Pitch and Yaw
-Roll
-Pitch/Roll Reset
-Zoom
-Reset Zoom
-Pitch/Yaw/Roll/Zoom Fast
-Pitch/Yaw/Roll/Zoom Slow
-
-"; - -_c1Control = parseText " -
-
-W, A, S, D
-LMB + Mouse
-Shift + LMB + Mouse
-RMB + Mouse
-MouseWheel Up, Down
-Arrow Up, Down
-Space
-Ctrl + Space
-Ctrl + F1...F12
-F1...F12
-N
-Keyboard - and +
-Backspace
-Shift + Backspace
-Numpad 1...9
-Numpad / and *
-Numpad 5
-Numpad - and +
-Numpad Enter
-Numpad 0
-Numpad Decimal
-
-"; - -_c2Action = parseText " -Units:
-
-Cycle Unit
-Save Unit
-Recall Unit
-Unit List
-
-Display:
-
-Toggle Crosshair
-Toggle Status Bar
-View Distance Dialog
-Cycle Marker Mode
-Toggle Help
-
-"; - -_c2Control = parseText " -
-
-Arrow Left, Right
-Ctrl + 1...10
-1...10
-U
-
-
-
-X
-C
-G
-T
-H
-
-"; - -if (!isMultiplayer) then { - -_add1 = parseText " -
-Time:
-
-Faster, Slower
-Reset -
-"; - -_add2 = parseText " -
-
-
-[ and ]
-\
-
-"; - - _c2Action = composeText [_c2Action, _add1]; - _c2Control = composeText [_c2Control, _add2]; -}; - - (_dialog displayCtrl 1) ctrlSetStructuredText _c1Action; - (_dialog displayCtrl 2) ctrlSetStructuredText _c1Control; - (_dialog displayCtrl 3) ctrlSetStructuredText _c2Action; - (_dialog displayCtrl 4) ctrlSetStructuredText _c2Control; - }; - - ////////////////////////////////////////// - case "Exit": { - - if (isClass (configFile >> "CfgPatches" >> "ace_nametags")) then { - EGVAR(nametags,showPlayerNames) = GVAR(tags) select 0; - EGVAR(nametags,showNamesForAI) = GVAR(tags) select 1; - GVAR(tags) = nil; - }; - - if (isClass (configFile >> "CfgPatches" >> "ace_hearing")) then { - EGVAR(hearing,disableVolumeUpdate) = false; - }; - - if (isClass (configFile >> "CfgPatches" >> "ace_interact_menu")) then { - [QGVAR(interactCondition)] call EFUNC(common,removeCanInteractWithCondition); - }; - - GVAR(cam) cameraEffect ["terminate", "back"]; - camUseNVG false; - false SetCamUseTi 0; - camDestroy GVAR(cam); - clearRadio; - - GVAR(noEscape) = nil; - GVAR(cam) = nil; - GVAR(LMB) = nil; - GVAR(RMB) = nil; - GVAR(vector) = nil; - GVAR(fov) = nil; - GVAR(vision) = nil; - GVAR(moveScale) = nil; - GVAR(cameraOn) = nil; - GVAR(focus) = nil; - GVAR(lock) = nil; - GVAR(attach) = nil; - GVAR(unit) = nil; - GVAR(mouseBusy) = nil; - GVAR(markers) = nil; - GVAR(keys) = nil; - GVAR(accTime) = nil; - - _display = findDisplay 46; - - removeMissionEventHandler ["Draw3D", GVAR(ehDraw3D)]; - _display displayRemoveEventHandler ["keyDown", GVAR(ehKeyDown)]; - _display displayRemoveEventHandler ["keyUp", GVAR(ehKeyUp)]; - _display displayRemoveEventHandler ["mouseButtonDown", GVAR(ehMouseButtonDown)]; - _display displayRemoveEventHandler ["mouseButtonUp", GVAR(ehMouseButtonUp)]; - _display displayRemoveEventHandler ["mouseZChanged", GVAR(ehMouseZChanged)]; - _display displayRemoveEventHandler ["mouseMoving", GVAR(ehMouseMoving)]; - _display displayRemoveEventHandler ["mouseHolding", GVAR(ehMouseHolding)]; - GVAR(ehDraw3D) = nil; - GVAR(ehKeyDown) = nil; - GVAR(ehKeyUp) = nil; - GVAR(ehMouseButtonDown) = nil; - GVAR(ehMouseButtonUp) = nil; - GVAR(ehMouseZChanged) = nil; - GVAR(ehMouseMoving) = nil; - GVAR(ehMouseHolding) = nil; - - _layers = missionNamespace getVariable ["BIS_fnc_rscLayer_list", []]; - - for "_i" from 1 to (count _layers - 1) step 2 do { - (_layers select _i) cutText ["", "Plain"]; - }; - - if (!isMultiplayer) then {setAccTime 1}; - ACE_player switchCamera "Internal"; - }; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_cameraIntro.sqf b/addons/spectator/functions/fnc_cameraIntro.sqf deleted file mode 100644 index 22bfa27d57..0000000000 --- a/addons/spectator/functions/fnc_cameraIntro.sqf +++ /dev/null @@ -1,28 +0,0 @@ -/* - Author: - voiper - - Description: - Curtain, sound, and text intro when camera starts. - - Arguments: - None - - Example: - call ace_spectator_fnc_camIntro; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -999999 cutText ["", "BLACK IN", 2]; -2 fadeSound 1; - -["Press H for spectator controls", 2] call EFUNC(common,displaytextstructured); - -[_this select 1] call CBA_fnc_removePerFrameHandler; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_canSpectateUnit.sqf b/addons/spectator/functions/fnc_canSpectateUnit.sqf deleted file mode 100644 index 1ce9f32d97..0000000000 --- a/addons/spectator/functions/fnc_canSpectateUnit.sqf +++ /dev/null @@ -1,30 +0,0 @@ -/* - Author: - voiper - - Description: - Check if a unit is suitable to spectate. - - Arguments: - 0: Unit to check - - Example: - [unit] call ace_spectator_canSpectateUnit; - - Return Value: - Whether is suitable to spectate - - Public: - No -*/ - -#include "script_component.hpp" - -_unit = _this select 0; - -if (_unit distance GVAR(penPos) < 200) exitWith {false}; -if (_unit distance [0,0,0] < 100) exitWith {false}; -if (!GVAR(AI) && !isPlayer _unit) exitWith {false}; -if (GVAR(limitSide) && (([_unit] call FUNC(unitSide)) != GVAR(playerSide))) exitWith {false}; - -true \ No newline at end of file diff --git a/addons/spectator/functions/fnc_checkUnits.sqf b/addons/spectator/functions/fnc_checkUnits.sqf deleted file mode 100644 index 5d62aeed12..0000000000 --- a/addons/spectator/functions/fnc_checkUnits.sqf +++ /dev/null @@ -1,37 +0,0 @@ -/* - Author: - voiper - - Description: - Compile array of units to spectate. - - Arguments: - None. - - Example: - call ace_spectator_fnc_checkUnits; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_units = allUnits; -_units append allDead; -GVAR(units) = []; - -{ - _listed = _x getVariable [QGVAR(listed), false]; - if (!_listed) then { - [_x] call FUNC(unitVar); - _x addEventHandler ["Killed", {_this call FUNC(killed)}]; - _x addEventHandler ["Respawn", {_this call FUNC(respawn)}]; - _x setVariable [QGVAR(listed), true]; - }; - - if ([_x] call FUNC(canSpectateUnit)) then {GVAR(units) pushback _x}; -} forEach _units; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_compass.sqf b/addons/spectator/functions/fnc_compass.sqf deleted file mode 100644 index 4120cd996f..0000000000 --- a/addons/spectator/functions/fnc_compass.sqf +++ /dev/null @@ -1,59 +0,0 @@ -/* - Author: - voiper - - Description: - Orient and set compass. - - Arguments: - 0: Compass - - Example: - [display] call ace_spectator_fnc_compass; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -#define RESUNITS_X safeZoneW / 100 -#define CENTRE safeZoneX + safeZoneW / 2 -#define COMPASS_W RESUNITS_X * 20 -#define COMPASS_X CENTRE - COMPASS_W / 2 -#define ARC_W COMPASS_W / 2 -#define DEGUNIT COMPASS_W / 180 - -_dialog = _this select 0; - -_Q1 = _dialog displayCtrl 1; -_Q2 = _dialog displayCtrl 2; -_Q3 = _dialog displayCtrl 3; -_Q4 = _dialog displayCtrl 4; -_qOrder = []; - -_dir = if GVAR(cameraOn) then {getDir GVAR(cam)} else {getDir GVAR(unit)}; -_angleFromCentre = _dir - floor(_dir / 90) * 90; -_leftEdgePos = _angleFromCentre * DEGUNIT; - -_positions = [ - [CENTRE - _leftEdgePos - ARC_W, safeZoneY], - [CENTRE - _leftEdgePos, safeZoneY], - [CENTRE - _leftEdgePos + ARC_W, safeZoneY], - [0, safeZoneY - 1] -]; - -_qOrder = switch (true) do { - case ((_dir >= 0) && (_dir < 90)): {[_Q4, _Q1, _Q2, _Q3]}; - case ((_dir >= 90) && (_dir < 180)): {[_Q1, _Q2, _Q3, _Q4]}; - case ((_dir >= 180) && (_dir < 270)): {[_Q2, _Q3, _Q4, _Q1]}; - case (_dir >= 270): {[_Q3, _Q4, _Q1, _Q2]}; -}; - -{ - _x ctrlSetPosition (_positions select _forEachIndex); - _x ctrlCommit 0; -} forEach _qOrder; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_crosshair.sqf b/addons/spectator/functions/fnc_crosshair.sqf deleted file mode 100644 index 80a12cd668..0000000000 --- a/addons/spectator/functions/fnc_crosshair.sqf +++ /dev/null @@ -1,29 +0,0 @@ -/* - Author: - voiper - - Description: - Automatically set crosshair colour. - - Arguments: - None - - Example: - call ace_spectator_fnc_crosshair; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_xhair = uiNamespace getVariable QGVAR(crosshair); -if (!isNull _xhair) then { - _colour = if ((GVAR(lock) select 0) > -1) then {[1,0,0,0.8]} else { - if (!isNull GVAR(attach)) then {[1,1,0,0.8]} else {[1,1,1,0.8]}; - }; - (_xhair displayCtrl 0) ctrlSetTextColor _colour; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_cycleCamera.sqf b/addons/spectator/functions/fnc_cycleCamera.sqf new file mode 100644 index 0000000000..474d25cd0c --- /dev/null +++ b/addons/spectator/functions/fnc_cycleCamera.sqf @@ -0,0 +1,58 @@ +/* + * Author: SilentSpike + * Cycle through the spectator camera vision/view/units in steps + * + * Arguments: + * 0: Camera mode steps + * 1: Camera unit steps + * 2: Vision mode steps + * + * Return Value: + * None + * + * Example: + * [0, -1] call ace_spectator_fnc_cycleCamera + * + * Public: No + */ + +#include "script_component.hpp" + +params [["_stepMode",0], ["_stepUnit",0], ["_stepVision",0]]; +private ["_modes","_visions","_iMode","_iVision","_countModes","_countVisions","_newMode","_newVision","_newUnit"]; + +_modes = GVAR(availableModes); +_units = GVAR(unitList); +_visions = GVAR(availableVisions); + +// Get current index +_iMode = (_modes find GVAR(camMode)) max 0; +_iUnit = (_units find GVAR(camUnit)) max 0; +_iVision = (_visions find GVAR(camVision)) max 0; + +_countModes = count _modes; +_countUnits = count _units; +_countVisions = count _visions; + +// Step index by step number (loop at ends) +if (_countModes != 0) then { + _iMode = (_iMode + _stepMode) % _countModes; + if (_iMode < 0) then { _iMode = _countModes + _iMode; }; +}; + +if (_countUnits != 0) then { + _iUnit = (_iUnit + _stepUnit) % _countUnits; + if (_iUnit < 0) then { _iUnit = _countUnits + _iUnit; }; +}; + +if (_countVisions != 0) then { + _iVision = (_iVision + _stepVision) % _countVisions; + if (_iVision < 0) then { _iVision = _countVisions + _iVision; }; +}; + +// Get value at new index +_newMode = _modes select _iMode; +_newUnit = _units select _iUnit; +_newVision = _visions select _iVision; + +[_newMode, _newUnit, _newVision] call FUNC(transitionCamera); diff --git a/addons/spectator/functions/fnc_draw3D.sqf b/addons/spectator/functions/fnc_draw3D.sqf deleted file mode 100644 index 26eb319f73..0000000000 --- a/addons/spectator/functions/fnc_draw3D.sqf +++ /dev/null @@ -1,34 +0,0 @@ -/* - Author: - voiper - - Description: - Draw3D EH for spectator. - - Arguments: - None - - Example: - call ace_spectator_fnc_draw3D; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_map = uiNameSpace getVariable QGVAR(map); -if (!isNull _map) exitWith {}; - -_compass = uiNamespace getVariable QGVAR(compass); -_status = uiNamespace getVariable QGVAR(status); -if (!isNull _compass) then {[_compass] call FUNC(compass)}; -if (!isNull _status) then {[_status] call FUNC(status)}; - -if (GVAR(markers) > 0) then { - call FUNC(drawMines3D); - call FUNC(drawUnits3D); -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_drawMines2D.sqf b/addons/spectator/functions/fnc_drawMines2D.sqf deleted file mode 100644 index c77c589529..0000000000 --- a/addons/spectator/functions/fnc_drawMines2D.sqf +++ /dev/null @@ -1,43 +0,0 @@ -/* - Author: - voiper - - Description: - Draw mines on spectator map. - - Arguments: - 0: Map control - 1: Zoom level - - Example: - [map, zoomlevel] call ace_spectator_fnc_drawMines2D; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -#define SCALE 5 * safeZoneH / 100 -#define MIN 300 * SCALE -#define TEXTURE "\A3\ui_f\data\map\markers\military\triangle_CA.paa" - -_map = _this select 0; -_zoom = _this select 1; - -_size = SCALE / _zoom; -_textSize = ((1/4 * _size) max (SCALE / 2) min (SCALE / 1.5)) / 2; -_iconSize = (20 * _size) max SCALE min MIN; -_showText = (GVAR(markers) > 1); - -{ - _name = ""; - if (_showText) then { - _magName = getText (configFile >> "CfgAmmo" >> (typeOf _x) >> "defaultMagazine"); - _name = getText (configFile >> "CfgMagazines" >> _magName >> "displayName"); - }; - _map drawIcon [TEXTURE, [1,0.5,0,1], getPos _x, _iconSize, _iconSize, getDir _x, _name, 1, _textSize, "PuristaMedium"]; -} forEach allMines; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_drawMines3D.sqf b/addons/spectator/functions/fnc_drawMines3D.sqf deleted file mode 100644 index 7183db574f..0000000000 --- a/addons/spectator/functions/fnc_drawMines3D.sqf +++ /dev/null @@ -1,55 +0,0 @@ -/* - Author: - voiper - - Description: - Draw mines in 3D. - - Arguments: - None - - Example: - call ace_spectator_fnc_drawMines3D; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -#define SCALE safeZoneH / 100 -#define TEXTMAX (1.5 * SCALE) -#define TEXTMIN 6 * SCALE -#define ICONMAX (30 * SCALE) -#define ICONMIN (120 * SCALE) -#define TEXTURE "\A3\ui_f\data\map\markers\military\triangle_CA.paa" - -_cam = GVAR(cam); -_showText = (GVAR(markers) > 1); - -{ - _pos = getPos _x; - _dist = (_cam distance _pos) + 0.1; - - if (_dist < 2000) then { - - _distScaled = SCALE / sqrt(_dist); - _iconScale = 300 * _distScaled; - //_iconSize = (20 * _size) max _scale min _min; - _iconSize = _iconScale max ICONMAX min ICONMIN; - _textSize = 0; - - if (_showText) then { - _textScale = 10 * _distScaled; - _textSize = _textScale max TEXTMAX min TEXTMIN; - }; - - _magName = getText (configFile >> "CfgAmmo" >> (typeOf _x) >> "defaultMagazine"); - _name = getText (configFile >> "CfgMagazines" >> _magName >> "displayName"); - - drawIcon3D [TEXTURE, [1,0.5,0,1], _pos, _iconSize, _iconSize, 0, _name, 1, _textSize, "PuristaMedium"]; - }; -} forEach allMines; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_drawTracks2D.sqf b/addons/spectator/functions/fnc_drawTracks2D.sqf deleted file mode 100644 index 32b6d58ae8..0000000000 --- a/addons/spectator/functions/fnc_drawTracks2D.sqf +++ /dev/null @@ -1,56 +0,0 @@ -/* - Author: - voiper - - Description: - Draw unit tracks in spectator map. - - Arguments: - 0: Map control - 1: Zoom level - - Example: - [map, zoomlevel] call ace_spectator_fnc_drawTracks2D; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_map = _this select 0; -_zoom = _this select 1; - -{ - _unit = _x select 0; - - _info = [_unit] call FUNC(unitInfo); - _colour = _info select 2; - - if (_unit == GVAR(unit)) then {_colour = [1,1,0,_colour select 3]}; - - _positions = _x select 1; - _count = count _positions; - _step = floor (10 * _zoom) min 3 max 1; - _lastIndex = 0; - - if (_count > 1) then { - for "_i" from 0 to (_count - 1) step _step do {; - if (_i > 0 && _i < _count) then { - _pos1 = _positions select _i; - _pos2 = _positions select (_i - _step); - _lastIndex = _i; - _map drawLine [_pos1, _pos2, _colour]; - }; - }; - }; - - //((_count - _step + _count mod _step) max 0) - if (alive _unit) then { - _map drawLine [_positions select _lastIndex, getPosVisual _unit, _colour]; - }; - -} forEach GVAR(trackingArray); \ No newline at end of file diff --git a/addons/spectator/functions/fnc_drawUnits2D.sqf b/addons/spectator/functions/fnc_drawUnits2D.sqf deleted file mode 100644 index 858b418c2f..0000000000 --- a/addons/spectator/functions/fnc_drawUnits2D.sqf +++ /dev/null @@ -1,81 +0,0 @@ -/* - Author: - voiper - - Description: - Draw unit icons on spectator map. - - Arguments: - 0: Map control - 1: Zoom level - - Example: - [map, zoomlevel] call ace_spectator_fnc_drawUnits2D; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -#define SCALE 5 * safeZoneH / 100 -#define MIN 300 * SCALE - -_map = _this select 0; -_zoom = _this select 1; - -_topIcon = []; - -_size = SCALE / _zoom; -_showText = (GVAR(markers) > 1); -_textSize = (0.25 * _size) max (SCALE / 2) min (SCALE / 1.5); - -{ - _unit = _x; - _isTarget = (_unit == GVAR(unit)); - - if (true) then { - - _veh = vehicle _unit; - _inVeh = (_veh != _unit); - if (!_isTarget && _inVeh && !(_unit == ((crew _veh) select 0))) exitWith {}; - if (!_isTarget && _inVeh && (GVAR(unit) in (crew _veh))) exitWith {}; - - _obj = if (_inVeh) then {_veh} else {_unit}; - _pos = getPosVisual _obj; - _dir = getDir _obj; - - _info = [_unit] call FUNC(unitInfo); - _name = _info select 0; - _colour = _info select 2; - - _icon = getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "Icon"); - _iconSize = 0; - _iconText = ""; - - if (_inVeh) then { - _iconSize = (50 * _size) max SCALE min (MIN * 2); - if (_showText) then { - _iconText = "[" + (getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "displayName")) + "] " + _name; - }; - } else { - _iconSize = (50 * _size) max SCALE min MIN; - if (_showText) then { - _iconText = _name; - }; - }; - - if (_isTarget) exitWith { - _topIcon = [_icon, [1,1,0,1], _pos, _iconSize, _iconSize, _dir, _iconText, 1, _textSize, "PuristaBold", "RIGHT"]; - }; - - _map drawIcon [_icon, _colour, _pos, _iconSize, _iconSize, _dir, _iconText, 1, _textSize, "PuristaMedium", "RIGHT"] - }; -} forEach GVAR(units); - -if (count _topIcon > 0) then { - _map drawIcon _topIcon; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_drawUnits3D.sqf b/addons/spectator/functions/fnc_drawUnits3D.sqf deleted file mode 100644 index 709e7d8fff..0000000000 --- a/addons/spectator/functions/fnc_drawUnits3D.sqf +++ /dev/null @@ -1,97 +0,0 @@ -/* - Author: - voiper - - Description: - Draw unit icons in 3D. - - Arguments: - None - - Example: - call ace_spectator_fnc_drawUnits3D; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -#define SCALE safeZoneH / 100 -#define TEXTMAX (1.5 * SCALE) -#define TEXTMIN 6 * SCALE -#define ICONMAX (30 * SCALE) -#define ICONMIN (120 * SCALE) - -_cam = GVAR(cam); -_showText = (GVAR(markers) > 1); -_topIcon = []; - -{ - _unit = _x; - - if (true) then { - _veh = vehicle _unit; - _inVeh = (_veh != _unit); - _cmdr = if (_inVeh && (_unit == ((crew _veh) select 0))) then {true} else {false}; - - _obj = if (_inVeh && _cmdr) then {_veh} else {_unit}; - _pos = if (surfaceIsWater getPos _obj) then {getPosASLVisual _obj} else {getPosATLVisual _obj}; - _dist = (_cam distance _pos) + 0.1; - - _isTarget = (_unit == GVAR(unit)); - - //exit if too far - if (_dist > 2000 && !_isTarget) exitWith {}; - - //exit if target not on screen - if ((count (worldToScreen _pos) < 1) && !_isTarget) exitWith {}; - - _info = [_unit] call FUNC(unitInfo); - _name = _info select 0; - _colour = _info select 2; - - _pos set [2, (_pos select 2) + 3]; - _distScaled = SCALE / sqrt(_dist); - - _icon = ""; - _iconScale = 300 * _distScaled; - _iconSize = _iconScale max ICONMAX min ICONMIN; - - _text = if (_showText) then {_name} else {""}; - _textScale = 10 * _distScaled; - _textSize = _textScale max TEXTMAX min TEXTMIN; - - if (_inVeh) then { - if (_cmdr) then { - _icon = getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "Icon"); - _text = if (_showText) then { - "[" + (getText (configFile >> "CfgVehicles" >> (typeOf _veh) >> "displayName")) + "] " + _text - } else {""}; - _pos set [2, (_pos select 2) + 3]; - } else { - _iconSize = 0; - _textSize = if (_dist < 25) then {_textSize / 1.5} else {0}; - }; - } else { - _icon = getText (configFile >> "CfgVehicles" >> (typeOf _unit) >> "Icon"); - }; - - if (GVAR(markers) > 2) then { - _text = _text + " [" + str ceil(_dist) + "]"; - }; - - if (_isTarget) exitWith { - _topIcon = [_icon, [1,1,0,1], _pos, _iconSize, _iconSize, 0, _text, 2, _textSize, "PuristaBold", "CENTER", true]; - }; - - drawIcon3D [_icon, _colour, _pos, _iconSize, _iconSize, 0, _text, 2, _textSize, "PuristaMedium"]; - }; -} forEach GVAR(units); - -if ((count _topIcon > 0) && GVAR(cameraOn)) then { - drawIcon3D _topIcon; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_handleCamera.sqf b/addons/spectator/functions/fnc_handleCamera.sqf new file mode 100644 index 0000000000..7f53b59009 --- /dev/null +++ b/addons/spectator/functions/fnc_handleCamera.sqf @@ -0,0 +1,41 @@ +/* + * Author: F3 Project, Head, SilentSpike + * Handles free camera manipulation according to input + * + * Arguments: + * 0: Parameters + * 1: PFH handle + * + * Return Value: + * None + * + * Example: + * [ace_spectator_fnc_handleCamera, 0] call CBA_fnc_addPerFrameHandler; + * + * Public: No + */ + +#include "script_component.hpp" + +// Kill PFH when not in free cam (or display is closed) +if (isNil QGVAR(camHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; + +private ["_oldPos","_mX","_mY","_mZ","_pan","_x","_y","_z"]; + +_oldPos = getPosASL GVAR(camera); +_mX = GVAR(camDolly) select 0; +_mY = GVAR(camDolly) select 1; +_mZ = GVAR(camBoom); + +_pan = (GVAR(camPan) + 360) % 360; +_x = (_oldPos select 0) + (_mX * cos(_pan)) + (_mY * sin(_pan)); +_y = (_oldPos select 1) - (_mX * sin(_pan)) + (_mY * cos(_pan)); +_z = (_oldPos select 2) + _mZ; + +// Prevent camera going under terrain +GVAR(camPos) = [_x,_y,_z max (getTerrainHeightASL [_x,_y])]; + +// Update camera position and rotation +GVAR(camera) setPosASL GVAR(camPos); +GVAR(camera) setDir GVAR(camPan); +[GVAR(camera), GVAR(camTilt), 0] call BIS_fnc_setPitchBank; diff --git a/addons/spectator/functions/fnc_handleCompass.sqf b/addons/spectator/functions/fnc_handleCompass.sqf new file mode 100644 index 0000000000..a65cc9ddce --- /dev/null +++ b/addons/spectator/functions/fnc_handleCompass.sqf @@ -0,0 +1,67 @@ +/* + * Author: SilentSpike, voiper + * Handles the spectator UI compass + * + * Arguments: + * 0: Parameters + * 1: PFH handle + * + * Return Value: + * None + * + * Example: + * [ace_spectator_fnc_handleCompass, 0, _display] call CBA_fnc_addPerFrameHandler; + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_display"]; + +// Kill PFH when compass hidden (or display is closed) +if (isNil QGVAR(compHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; + +private ["_compass","_NE","_ES","_SW","_WN","_compassW","_degree","_heading","_offset","_positions","_sequence"]; + +_compass = _display displayCtrl IDC_COMP; + +_NE = _compass controlsGroupCtrl IDC_COMP_0; +_ES = _compass controlsGroupCtrl IDC_COMP_90; +_SW = _compass controlsGroupCtrl IDC_COMP_180; +_WN = _compass controlsGroupCtrl IDC_COMP_270; + +_compassW = (ctrlPosition _compass) select 2; +_degree = _compassW / 180; + +// Get direction of screen rather than object (accounts for unit freelook) +_heading = (positionCameraToWorld [0,0,1]) vectorDiff (positionCameraToWorld [0,0,0]); +_heading = (((_heading select 0) atan2 (_heading select 1)) + 360) % 360; +_offset = -(_heading % 90) * _degree; + +_positions = [ + [_compassW * -0.5 + _offset, 0], + [_offset, 0], + [_compassW * 0.5 + _offset, 0], + [_compassW + _offset, 0] +]; + +_sequence = if (_heading < 90) then { + [_SW, _WN, _NE, _ES] +} else { + if (_heading < 180) then { + [_WN, _NE, _ES, _SW] + } else { + if (_heading < 270) then { + [_NE, _ES, _SW, _WN] + } else { + [_ES, _SW, _WN, _NE] + }; + }; +}; + + +{ + _x ctrlSetPosition (_positions select _forEachIndex); + _x ctrlCommit 0; +} forEach _sequence; diff --git a/addons/spectator/functions/fnc_handleIcons.sqf b/addons/spectator/functions/fnc_handleIcons.sqf new file mode 100644 index 0000000000..c52943ad10 --- /dev/null +++ b/addons/spectator/functions/fnc_handleIcons.sqf @@ -0,0 +1,57 @@ +/* + * Author: SilentSpike + * Handles rendering the spectator 3D unit icons + * + * Arguments: + * 0: Parameters + * 1: PFH handle + * + * Return Value: + * None + * + * Example: + * [ace_spectator_fnc_handleIcons, 0] call CBA_fnc_addPerFrameHandler; + * + * Public: No + */ + +#include "script_component.hpp" + +// Kill PFH when not in free cam (or display is closed) +if (isNil QGVAR(iconHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; + +if !(GVAR(showIcons)) exitWith {}; + +private ["_cachedVehicles","_unit","_cameraPos","_cameraDir","_lambda","_uPos","_cmd","_txt"]; +_cachedVehicles = []; +{ + _unit = vehicle _x; + + // Only try each vehicle once + if !(_unit in _cachedVehicles) then { + _cachedVehicles pushBack _unit; + + // Within 200m + if ((GVAR(camera) distanceSqr _unit) < 40000) then { + _cameraPos = (positionCameraToWorld [0, 0, 0]) call EFUNC(common,positionToASL); + _cameraDir = ((positionCameraToWorld [0, 0, 1]) call EFUNC(common,positionToASL)) vectorDiff _cameraPos; + + // Quick oclussion test (taken from interact_menu) + _lambda = ((getPosASL _x) vectorDiff _cameraPos) vectorDotProduct _cameraDir; + if (_lambda > -1) then { + _uPos = worldToScreen (visiblePosition _unit); + + // Only draw if onscreen + if ((_uPos select 0 > safeZoneXAbs) && (_uPos select 0 < safeZoneXAbs + safeZoneWAbs)) then { + if ((_uPos select 1 > safeZoneY) && (_uPos select 1 < safeZoneY + safeZoneH)) then { + // Use commander's info if available + _cmd = [_x, effectiveCommander _unit] select ((effectiveCommander _unit) in GVAR(unitList)); + _txt = ["", GETVAR(_cmd,GVAR(uName),"")] select (isPlayer _cmd); + + drawIcon3D ["\A3\ui_f\data\map\markers\military\dot_CA.paa", GETVAR(_cmd,GVAR(uColor),[ARR_4(0,0,0,0)]), _unit modelToWorldVisual [0,0,3], 0.7, 0.7, 0, _txt, 1, 0.02]; + }; + }; + }; + }; + }; +} forEach GVAR(unitList); diff --git a/addons/spectator/functions/fnc_handleInterface.sqf b/addons/spectator/functions/fnc_handleInterface.sqf new file mode 100644 index 0000000000..864ae32adc --- /dev/null +++ b/addons/spectator/functions/fnc_handleInterface.sqf @@ -0,0 +1,485 @@ +/* + * Author: SilentSpike + * Handles spectator interface events + * + * Arguments: + * 0: Event name + * 1: Event arguments + * + * Return Value: + * None + * + * Example: + * ["onLoad",_this] call ace_spectator_fnc_handleInterface + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_mode",["_args",[]]]; + +switch (toLower _mode) do { + // Safely open/close the interface + case "open": { + // Prevent reopening + if !(isNull (GETUVAR(GVAR(display),displayNull))) exitWith {}; + + // Initalize camera variables + GVAR(camBoom) = 0; + GVAR(camDolly) = [0,0]; + GVAR(camGun) = false; + + // Initalize display variables + GVAR(ctrlKey) = false; + GVAR(heldKeys) = []; + GVAR(mouse) = [false,false]; + GVAR(mousePos) = [0.5,0.5]; + + // Initalize the camera view + GVAR(camera) = "Camera" camCreate (ASLtoATL GVAR(camPos)); + [] call FUNC(transitionCamera); + + // Close all existing dialogs + while {dialog} do { + closeDialog 0; + }; + + // Create the dialog + createDialog QGVAR(interface); + + // Cache and disable nametag settings + if (["ace_nametags"] call EFUNC(common,isModLoaded)) then { + GVAR(nametagSettingCache) = [EGVAR(nametags,showPlayerNames), EGVAR(nametags,showNamesForAI)]; + EGVAR(nametags,showPlayerNames) = 0; + EGVAR(nametags,showNamesForAI) = false; + }; + }; + case "close": { + // Can't close a second time + if (isNull (GETUVAR(GVAR(display),displayNull))) exitWith {}; + + // Terminate interface + while {dialog} do { + closeDialog 0; + }; + GETUVAR(GVAR(display),displayNull) closeDisplay 0; + + // Terminate camera + GVAR(camera) cameraEffect ["terminate", "back"]; + camDestroy GVAR(camera); + + // Return to player view + ACE_Player switchCamera "internal"; + + // Cleanup camera variables + GVAR(camera) = nil; + GVAR(camBoom) = nil; + GVAR(camDolly) = nil; + GVAR(camGun) = nil; + + // Cleanup display variables + GVAR(ctrlKey) = nil; + GVAR(heldKeys) = nil; + GVAR(mouse) = nil; + GVAR(mousePos) = nil; + + // Reset nametag settings + if (["ace_nametags"] call EFUNC(common,isModLoaded)) then { + EGVAR(nametags,showPlayerNames) = GVAR(nametagSettingCache) select 0; + EGVAR(nametags,showNamesForAI) = GVAR(nametagSettingCache) select 1; + GVAR(nametagSettingCache) = nil; + }; + }; + // Dialog events + case "onload": { + _args params ["_display"]; + + with uiNamespace do { + GVAR(display) = _display; + }; + + // Always show interface and hide map upon opening + [_display,nil,nil,!GVAR(showInterface),GVAR(showMap)] call FUNC(toggleInterface); + + // Keep unit list and tree up to date + [FUNC(handleUnits), 21, _display] call CBA_fnc_addPerFrameHandler; + + // Populate the help splash + private "_help"; + _help = (_display displayCtrl IDC_HELP) controlsGroupCtrl IDC_HELP_LIST; + { + // Add space before category titles + if (count _x == 1) then { + _help lnbAddRow [""]; + }; + + _help lnbAddRow _x; + } forEach [ + [localize LSTRING(uiControls),""], + [localize LSTRING(uiToggleHelp),"H"], + [localize LSTRING(uiToggleMap),"M"], + [localize LSTRING(uiToggleUnits),"1"], + [localize LSTRING(uiToggleTools),"2"], + [localize LSTRING(uiToggleCompass),"3"], + [localize LSTRING(uiToggleIcons),"4"], + [localize LSTRING(uiToggleInterface),"Backspace"], + + [localize LSTRING(freeCamControls)], + [localize LSTRING(freeCamForward),"W"], + [localize LSTRING(freeCamBackward),"S"], + [localize LSTRING(freeCamLeft),"A"], + [localize LSTRING(freeCamRight),"D"], + [localize LSTRING(freeCamUp),"Q"], + [localize LSTRING(freeCamDown),"Z"], + [localize LSTRING(freeCamPan),"RMB (Hold)"], + [localize LSTRING(freeCamDolly),"LMB (Hold)"], + [localize LSTRING(freeCamSpeed),"Scrollwheel"], + [localize LSTRING(freeCamZoom),"Ctrl + Scrollwheel"], + [localize LSTRING(freeCamNextVis),"N"], + [localize LSTRING(freeCamPrevVis),"Ctrl + N"], + + [localize LSTRING(otherControls)], + [localize LSTRING(nextCam),"Up Arrow"], + [localize LSTRING(prevCam),"Down Arrow"], + [localize LSTRING(nextUnit),"Right Arrow"], + [localize LSTRING(prevUnit),"Left Arrow"] + ]; + + // Hacky way to enable keybindings + //_display displayAddEventHandler ["KeyUp", {[_this,'keyup'] call CBA_events_fnc_keyHandler}]; + //_display displayAddEventHandler ["KeyDown", {[_this,'keydown'] call CBA_events_fnc_keyHandler}]; + }; + case "onunload": { + with uiNamespace do { + GVAR(display) = nil; + }; + + GVAR(camHandler) = nil; + GVAR(compHandler) = nil; + GVAR(iconHandler) = nil; + GVAR(toolHandler) = nil; + }; + // 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 change speed, modifier for zoom + if (GVAR(ctrlKey)) then { + [nil,nil,nil,nil,nil,nil, GVAR(camZoom) + _zChange * 0.1] call FUNC(setCameraAttributes); + } else { + [nil,nil,nil,nil,nil,nil,nil, GVAR(camSpeed) + _zChange * 0.2] call FUNC(setCameraAttributes); + }; + }; + case "onmousemoving": { + _args params ["_ctrl","_x","_y"]; + + [_x,_y] call FUNC(handleMouse); + }; + // Keyboard events + case "onkeydown": { + _args params ["_display","_dik","_shift","_ctrl","_alt"]; + + // Handle held keys (prevent repeat calling) + if (_dik in GVAR(heldKeys)) exitwith {}; + // Exclude movement keys so that speed can be adjusted on fly + if !(_dik in [17,30,31,32]) then { + GVAR(heldKeys) pushBack _dik; + }; + + switch (_dik) do { + case 1: { // Esc + ["escape", [_display]] call FUNC(handleInterface); + }; + case 2: { // 1 + [_display,nil,nil,nil,nil,nil,true] call FUNC(toggleInterface); + }; + case 3: { // 2 + [_display,nil,nil,nil,nil,true] call FUNC(toggleInterface); + }; + case 4: { // 3 + [_display,true] call FUNC(toggleInterface); + }; + case 5: { // 4 + GVAR(showIcons) = !GVAR(showIcons); + }; + case 14: { // Backspace + [_display,nil,nil,true] call FUNC(toggleInterface); + }; + case 16: { // Q + GVAR(camBoom) = 0.5; + }; + case 17: { // W + GVAR(camDolly) set [1, GVAR(camSpeed)]; + }; + case 29: { // Ctrl + GVAR(ctrlKey) = true; + }; + case 30: { // A + GVAR(camDolly) set [0, -GVAR(camSpeed)]; + }; + case 31: { // S + GVAR(camDolly) set [1, -GVAR(camSpeed)]; + }; + case 32: { // D + GVAR(camDolly) set [0, GVAR(camSpeed)]; + }; + case 35: { // H + [_display,nil,true] call FUNC(toggleInterface); + }; + case 44: { // Z + GVAR(camBoom) = -0.5; + }; + case 49: { // N + 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 + // Freecam attachment here, if in external then set cam pos and attach + }; + 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) = GVAR(heldKeys) - [_dik]; + + 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 ["_curSelData","_cachedGrps","_cachedSides","_grp","_side","_sNode","_gNode","_uNode"]; + + // Cache current selection + _curSelData = _tree tvData (tvCurSel _tree); + + // Clear the tree + tvClear _tree; + + // Update the tree from the unit list + _cachedGrps = []; + _cachedSides = []; + { + _grp = group _x; + _side = [side _grp] call BIS_fnc_sideName; + + // Use correct side node + if !(_side in _cachedSides) then { + // Add side node + _sNode = _tree tvAdd [[], _side]; + + _cachedSides pushBack _side; + _cachedSides pushBack _sNode; + } else { + // If side already processed, use existing node + _sNode = _cachedSides select ((_cachedSides find _side) + 1); + }; + + // Use correct group node + if !(_grp in _cachedGrps) then { + // Add group node + _gNode = _tree tvAdd [[_sNode], groupID _grp]; + + _cachedGrps pushBack _grp; + _cachedGrps pushBack _gNode; + } else { + // If group already processed, use existing node + _gNode = _cachedGrps select ((_cachedGrps find _grp) + 1); + }; + + _uNode = _tree tvAdd [[_sNode,_gNode], GETVAR(_x,GVAR(uName),"")]; + _tree tvSetData [[_sNode,_gNode,_uNode], netID _x]; + + // Preserve the previous selection + if (_curSelData == (_tree tvData [_sNode,_gNode,_uNode])) then { + _tree tvSetCurSel [_sNode,_gNode,_uNode]; + }; + + _tree tvSort [[_sNode,_gNode],false]; + _tree tvExpand [_sNode,_gNode]; + } forEach GVAR(unitList); + + { + if (typeName _x == "SCALAR") then { + _tree tvSort [[_x],false]; + _tree tvExpand [_x]; + }; + } forEach _cachedSides; + + _tree tvSort [[],false]; + }; + // Map events + case "onmapdblclick": { + _args params ["_map","_button","_x","_y"]; + 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); + }; + }; + case "ondraw": { + _args params ["_map"]; + + if (GVAR(camMode) == 0) then { + _map drawIcon ["\A3\UI_F\Data\GUI\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa",[0,0,0,1],GVAR(camera),24,24,GVAR(camPan)]; + }; + + if !(GVAR(showIcons)) exitWith {}; + + private ["_cachedVehicles","_unit","_color","_icon"]; + _cachedVehicles = []; + { + _unit = vehicle _x; + + if !(_unit in _cachedVehicles) then { + _cachedVehicles pushBack _unit; + + // Use previously cached info where possible + if (isNil { GETVAR(_unit,GVAR(uIcon),nil) }) then { + [_unit] call FUNC(cacheUnitInfo); + }; + + _color = GETVAR(_unit,GVAR(uColor),[ARR_4(0,0,0,0)]); + _icon = GETVAR(_unit,GVAR(uIcon),""); + _map drawIcon [_icon, _color, _unit, 24, 24, getDir _unit]; + }; + } forEach GVAR(unitList); + }; + // Other + case "escape": { + _args params ["_display"]; + private ["_dlg","_key","_index","_ctrl","_config"]; + + // Kill display + _display closeDisplay 0; + + // Reset cam/UI vars + GVAR(camBoom) = 0; + GVAR(camDolly) = [0,0]; + + GVAR(ctrlKey) = false; + GVAR(heldKeys) = []; + GVAR(mouse) = [false,false]; + GVAR(mousePos) = [0.5,0.5]; + + // Below is from EFUNC(common,disableUserInput) + createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select isMultiplayer); + + disableSerialization; + _dlg = finddisplay 49; + _dlg displayAddEventHandler ["KeyDown", { + _key = _this select 1; + !(_key == 1) + }]; + + for "_index" from 100 to 2000 do { + (_dlg displayCtrl _index) ctrlEnable false; + }; + + _ctrl = _dlg displayctrl 103; + _ctrl ctrlSetEventHandler ["buttonClick", QUOTE(while {dialog} do {closeDialog 0}; failMission 'LOSER';)]; + _ctrl ctrlEnable true; + _ctrl ctrlSetText "ABORT"; + _ctrl ctrlSetTooltip "Abort."; + + _ctrl = _dlg displayctrl ([104, 1010] select isMultiplayer); + _ctrl ctrlSetEventHandler ["buttonClick", QUOTE(closeDialog 0; player setDamage 1;)]; + _ctrl ctrlEnable (call {_config = missionConfigFile >> "respawnButton"; !isNumber _config || {getNumber _config == 1}}); + _ctrl ctrlSetText "RESPAWN"; + _ctrl ctrlSetTooltip "Respawn."; + + // PFH to re-open display when menu closes + [{ + if !(isNull (findDisplay 49)) exitWith {}; + + createDialog QGVAR(interface); + [] call FUNC(transitionCamera); + + [_this select 1] call CBA_fnc_removePerFrameHandler; + },0] call CBA_fnc_addPerFrameHandler; + }; +}; diff --git a/addons/spectator/functions/fnc_handleKilled.sqf b/addons/spectator/functions/fnc_handleKilled.sqf new file mode 100644 index 0000000000..67c556cc3f --- /dev/null +++ b/addons/spectator/functions/fnc_handleKilled.sqf @@ -0,0 +1,27 @@ +/* + * Author: SilentSpike + * Cache necessary details and process unit for spectator on death + * Part of the basic spectator system + * + * Arguments: + * 0: Corpse + * 1: Killer + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_unit","_killer"]; + +// Remove from group to prevent appearing on HUD upon respawn +[_unit, true, QGVAR(isSpectator), side group _unit] call EFUNC(common,switchToGroupSide); + +if (isNull _killer) then { + [2,_unit] call FUNC(setCameraAttributes); +} else { + [2,_killer] call FUNC(setCameraAttributes); +}; diff --git a/addons/spectator/functions/fnc_handleMouse.sqf b/addons/spectator/functions/fnc_handleMouse.sqf new file mode 100644 index 0000000000..8158ba95b5 --- /dev/null +++ b/addons/spectator/functions/fnc_handleMouse.sqf @@ -0,0 +1,43 @@ +/* + * Author: F3 Project, Head, SilentSpike + * Processes the change in mouse position for the spectator camera + * + * Arguments: + * 0: Mouse x coord + * 1: Mouse y coord + * + * Return Value: + * None + * + * Example: + * [0.5, 0.5] call ace_spectator_fnc_handleMouse; + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_x","_y"]; +private ["_leftButton","_rightButton","_oldX","_oldY","_deltaX","_deltaY"]; + +_leftButton = GVAR(mouse) select 0; +_rightButton = GVAR(mouse) select 1; + +_oldX = GVAR(mousePos) select 0; +_oldY = GVAR(mousePos) select 1; + +// Get change in pos +_deltaX = _oldX - _x; +_deltaY = _oldY - _y; + +if (_leftButton) then { + GVAR(camDolly) set [0, _deltaX * -100 * GVAR(camSpeed)]; + GVAR(camDolly) set [1, _deltaY * 100 * GVAR(camSpeed)]; +} else { + if (_rightButton) then { + GVAR(camPan) = GVAR(camPan) - (_deltaX * 360); + GVAR(camTilt) = ((GVAR(camTilt) + (_deltaY * 180)) min 89) max -89; + }; +}; + +GVAR(mousePos) = [_x,_y]; diff --git a/addons/spectator/functions/fnc_handleRespawn.sqf b/addons/spectator/functions/fnc_handleRespawn.sqf new file mode 100644 index 0000000000..9b6b0bb802 --- /dev/null +++ b/addons/spectator/functions/fnc_handleRespawn.sqf @@ -0,0 +1,18 @@ +/* + * Author: SilentSpike + * Start the interface on respawn + * Part of the basic spectator system + * + * Arguments: + * 0: New unit + * 1: Old unit + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +[_this select 0] call FUNC(setSpectator); diff --git a/addons/spectator/functions/fnc_handleToolbar.sqf b/addons/spectator/functions/fnc_handleToolbar.sqf new file mode 100644 index 0000000000..fd29ca532e --- /dev/null +++ b/addons/spectator/functions/fnc_handleToolbar.sqf @@ -0,0 +1,54 @@ +/* + * Author: Karel Moricky, SilentSpike + * Handles the spectator UI toolbar values and applies them to the camera + * + * Arguments: + * 0: Parameters + * 1: PFH handle + * + * Return Value: + * None + * + * Example: + * [ace_spectator_fnc_handleToolbar, 0, _display] call CBA_fnc_addPerFrameHandler; + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_display"]; + +// Kill PFH when toolbar hidden (or display is closed) +if (isNil QGVAR(toolHandler)) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; + +private ["_name","_vision","_fov","_speed","_mode","_time","_toolbar"]; +_toolbar = _display displayCtrl IDC_TOOL; + +// Find all tool values +if (GVAR(camMode) == 0) then { + _vision = if (GVAR(camVision) >= 0) then {localize LSTRING(VisionThermal)} else { [localize LSTRING(VisionNight), localize LSTRING(VisionNormal)] select (GVAR(camVision) < -1) }; + _fov = format ["%1x", floor(GVAR(camZoom) * 100) * 0.01]; + _speed = format ["%1 m/s", floor(GVAR(camSpeed) * 100) * 0.01]; +} else { + _vision = format ["%1 m", floor(getPosASL GVAR(camUnit) select 2)]; + _fov = [side group GVAR(camUnit)] call BIS_fnc_sideName; + _speed = format ["%1 km/h", floor(speed GVAR(camUnit)) max 0]; +}; + +if (isNull GVAR(camUnit)) then { + _name = localize "STR_Special_None"; +} else { + _name = GETVAR(GVAR(camUnit),GVAR(uName),""); +}; + +_mode = [localize LSTRING(ViewFree),localize LSTRING(ViewInternal),localize LSTRING(ViewExternal)] select GVAR(camMode); +_time = [daytime,"HH:MM"] call BIS_fnc_timeToString; + +// Update the UI tools +(_toolbar controlsGroupCtrl IDC_TOOL_CLOCK) ctrlSetText _time; +(_toolbar controlsGroupCtrl IDC_TOOL_VISION) ctrlSetText _vision; +(_toolbar controlsGroupCtrl IDC_TOOL_FOV) ctrlSetText _fov; +(_toolbar controlsGroupCtrl IDC_TOOL_NAME) ctrlSetText _name; +(_toolbar controlsGroupCtrl IDC_TOOL_SPEED) ctrlSetText _speed; +(_toolbar controlsGroupCtrl IDC_TOOL_VIEW) ctrlSetText _mode; diff --git a/addons/spectator/functions/fnc_handleUnits.sqf b/addons/spectator/functions/fnc_handleUnits.sqf new file mode 100644 index 0000000000..b64a1a2717 --- /dev/null +++ b/addons/spectator/functions/fnc_handleUnits.sqf @@ -0,0 +1,38 @@ +/* + * Author: SilentSpike + * Maintains the spectatable unit list and updates the unit tree accordingly + * Also updates current camera unit when status changes + * + * Arguments: + * 0: Parameters + * 1: PFH handle + * + * Return Value: + * None + * + * Example: + * [ace_spectator_fnc_handleUnits, 10, _display] call CBA_fnc_addPerFrameHandler; + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_display"]; + +// Kill PFH when display is closed +if (isNull _display) exitWith { [_this select 1] call CBA_fnc_removePerFrameHandler; }; + +// Remove all dead and null units from the list +[] call FUNC(updateUnits); + +// Camera shouldn't stay on unit that isn't in the list +if !(GVAR(camUnit) in GVAR(unitList)) then { + [nil,1] call FUNC(cycleCamera); +}; + +// Reduce overhead when unit tree is hidden +if (ctrlShown (_display displayCtrl IDC_UNIT)) then { + // Reduce overhead by spreading across frames + [FUNC(handleInterface),["onUnitsUpdate",[_display displayCtrl IDC_UNIT]],1] call EFUNC(common,waitAndExecute); +}; diff --git a/addons/spectator/functions/fnc_killed.sqf b/addons/spectator/functions/fnc_killed.sqf deleted file mode 100644 index 4774476be4..0000000000 --- a/addons/spectator/functions/fnc_killed.sqf +++ /dev/null @@ -1,65 +0,0 @@ -/* - Author: - voiper - - Description: - Killed EH for remote units. - - Arguments: - 0: Unit - 1: Killer - - Example: - [unit, killer] call ace_spectator_fnc_killed; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_unit = _this select 0; -_killer = _this select 1; - -if (isNil "_unit") exitWith {}; -if (isNil QGVAR(cam)) exitWith {}; -if (isNull _unit) exitWith {}; - -if (!isNull _killer) then { - if (GVAR(markers) > 2 && !difficultyEnabled "deathMessages") then { - _nameUnit = name _unit; - _nameKiller = name _killer; - - _text = if (_killer == _unit) then { - format ["%1 died", _nameUnit] - } else { - format ["%2 killed by %1", _nameUnit, _nameKiller] - }; - systemChat _text; - }; -}; - -if (_unit == GVAR(unit) && !GVAR(cameraOn)) then { - ["Camera", ["Free"]] call FUNC(camera); - GVAR(unit) = objNull; -}; - -_savedUnit = GVAR(savedUnits) find _unit; -if (_savedUnit > -1) then { - GVAR(savedUnits) set [_savedUnit, objNull]; -}; - -if (!isNil QGVAR(trackingArray)) then { - _pos = getPos _unit; - _pos resize 2; - _index = -1; - {if ((_x select 0) == _unit) then {_index = _forEachIndex}} forEach GVAR(trackingArray); - _unitArray = GVAR(trackingArray) select _index; - _tracks = _unitArray select 1; - _tracks pushBack _pos; - _unitArray set [1, _tracks]; - GVAR(trackingArray) set [_index, _unitArray]; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_map.sqf b/addons/spectator/functions/fnc_map.sqf deleted file mode 100644 index b58fa8ce2b..0000000000 --- a/addons/spectator/functions/fnc_map.sqf +++ /dev/null @@ -1,156 +0,0 @@ -/* - Author: - voiper - - Description: - Manage spectator map. - - Arguments: - 0: Mode - 1: Elements (depending on situation) - - Example: - ["Init", [map]] call ace_spectator_fnc_map; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" -#include "\a3\editor_f\Data\Scripts\dikCodes.h" - -_mode = _this select 0; -_this = _this select 1; - -switch _mode do { - - case "Init": { - _map = _this displayCtrl 1; - - if (isNil QGVAR(mapPos)) then { - GVAR(mapPos) = [(GVAR(penPos) select 0) / 4, (GVAR(penPos) select 1) / 4]; - }; - - if (isNil QGVAR(mapZoom)) then { - GVAR(mapZoom) = 0.75; - }; - - _map ctrlMapAnimAdd [0, GVAR(mapZoom), GVAR(mapPos)]; - ctrlMapAnimCommit _map; - setMousePosition [0.5, 0.5]; - - _map ctrlAddEventHandler ["Draw", {['Draw', _this] call FUNC(map)}]; - _map ctrlAddEventHandler ["MouseButtonDblClick", {['Click', _this] call FUNC(map)}]; - }; - - case "Close": { - _map = _this displayCtrl 1; - GVAR(mapPos) = _map ctrlMapScreenToWorld [0.5,0.5]; - GVAR(mapZoom) = ctrlMapScale _map; - }; - - case "Draw": { - _map = _this select 0; - _zoom = ctrlMapScale _map; - - if (GVAR(markers) > 0) then { - if ((GVAR(markers) > 2) && GVAR(tracking)) then { - [_map, _zoom] call FUNC(drawTracks2D); - }; - [_map, _zoom] call FUNC(drawMines2D); - [_map, _zoom] call FUNC(drawUnits2D); - }; - - if (GVAR(cameraOn)) then { - _scale = 5 * safeZoneH / 100; - _map drawIcon ["\A3\ui_f\data\gui\Rsc\RscDisplayMissionEditor\iconcamera_ca.paa", [1,1,1,1], getPos GVAR(cam), 500 * _scale, 500 * _scale, getDir GVAR(cam), "", 0, 0, "PuristaMedium"]; - }; - }; - - case "Click": { - _map = _this select 0; - _button = _this select 1; - _shift = _this select 4; - _mapPos = _map ctrlMapScreenToWorld [_this select 2, _this select 3]; - - if (_shift) then { - if (GVAR(cameraOn)) then { - _dir = [getPos GVAR(cam), _mapPos] call BIS_fnc_dirTo; - GVAR(vector) set [0, _dir]; - [GVAR(cam), GVAR(vector)] call BIS_fnc_setObjectRotation; - }; - } else { - - _newUnit = objNull; - - _scale = ctrlMapScale _map; - _radius = _scale * 250; - _units = []; - - //find units near spot, ignoring height (necessary since nearestObjects takes height into account) - { - if (alive _x) then { - _pos = getPos _x; - _pos set [2, 0]; - if (_pos distance _mapPos <= _radius) then { - _units pushBack _x; - }; - }; - } forEach GVAR(units); - - //find closest unit to spot - if (count _units > 0) then { - _nearest = 0; - for "_i" from 1 to (count _units - 1) do { - if (((_units select _i) distance _mapPos) < ((_units select _nearest) distance _mapPos)) then { - _nearest = _i; - }; - }; - _newUnit = _units select _nearest; - }; - - if (!isNull _newUnit) then { - - if (vehicle _newUnit != _newUnit) then { - _crew = crew (vehicle _newUnit); - _newUnit = _crew select 0; - }; - - GVAR(unit) = _newUnit; - if (GVAR(cameraOn)) then { - ["Camera", ["Third"]] call FUNC(camera); - } else { - if (GVAR(third)) then { - ["Camera", ["Third"]] call FUNC(camera); - } else { - ["Camera", ["First"]] call FUNC(camera); - }; - }; - } else { - - if (!GVAR(cameraOn)) then { - ["Camera", ["Free"]] call FUNC(camera); - }; - _mapPos set [2, 10]; - GVAR(cam) setPosATL _mapPos; - }; - }; - }; - - case "KeyDown": { - _key = _this select 1; - _shift = _this select 2; - _ctrl = _this select 3; - _alt = _this select 4; - _return = false; - - switch (_key) do { - case (DIK_DELETE): {_return = true}; - }; - - _return - }; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_moduleSpectator.sqf b/addons/spectator/functions/fnc_moduleSpectator.sqf deleted file mode 100644 index a371327b23..0000000000 --- a/addons/spectator/functions/fnc_moduleSpectator.sqf +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Author: esteldunedain - * Initializes the addon module. - * - * Arguments: - * Whatever the module provides. - * - * Return Value: - * None - */ - -#include "script_component.hpp" - -PARAMS_3(_logic,_units,_activated); - -if !(_activated) exitWith {}; - -[_logic, QGVAR(enabled), "SpectatorEnabled"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(limitSide), "SpectatorPlayerSide"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(AI), "SpectatorAI"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(tracking), "SpectatorTracking"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(modulePos), "SpectatorPos"] call EFUNC(common,readSettingFromModule); -[_logic, QGVAR(endMission), "SpectatorEnd"] call EFUNC(common,readSettingFromModule); - -if GVAR(modulePos) then { - GVAR(startingPos) = getPosATL _logic; - GVAR(startingDir) = getDir _logic; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_moduleSpectatorSettings.sqf b/addons/spectator/functions/fnc_moduleSpectatorSettings.sqf new file mode 100644 index 0000000000..1fd20f50e4 --- /dev/null +++ b/addons/spectator/functions/fnc_moduleSpectatorSettings.sqf @@ -0,0 +1,27 @@ +/* + * Author: SilentSpike + * Read spectator settings from module + * + * Arguments: + * 0: The module logic + * 1: units + * 2: activated + * + * Return Value: + * None + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_logic", "_units", "_activated"]; + +if !(_activated) exitWith {}; + +[_logic, QGVAR(onDeath), "systemEnable"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(filterUnits), "unitsFilter"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(filterSides), "sidesFilter"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(restrictModes), "cameraModes"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(restrictVisions), "visionModes"] call EFUNC(common,readSettingFromModule); +[_logic, QGVAR(unitIcons), "unitIcons"] call EFUNC(common,readSettingFromModule); diff --git a/addons/spectator/functions/fnc_overlay.sqf b/addons/spectator/functions/fnc_overlay.sqf deleted file mode 100644 index d998b9a3b2..0000000000 --- a/addons/spectator/functions/fnc_overlay.sqf +++ /dev/null @@ -1,106 +0,0 @@ -/* - Author: - voiper - - Description: - Spectator unit list. - - Arguments: - 0: Specific function to use - 1: Function params - - Example: - ["Init", [display]] call ace_spectator_fnc_overlay; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_mode = _this select 0; -_this = _this select 1; - -switch _mode do { - - case "Init": { - - _display = _this select 0; - _ctrl = _display displayCtrl 0; - _count = _ctrl tvCount []; - for "_i" from 0 to _count do { - _ctrl tvDelete [_x]; - }; - - _ctrl tvAdd [[], "Blufor"]; - _ctrl tvAdd [[], "Opfor"]; - _ctrl tvAdd [[], "Independent"]; - _ctrl tvAdd [[], "Civilian"]; - - _unitList = []; - - { - _units = units _x; - private ["_groupNum"]; - { - if ((GVAR(units) find _x > -1) && alive _x) then { - _info = [_x] call FUNC(unitInfo); - _text = _info select 0; - _team = _info select 1; - _side = switch (_team) do { - case BLUFOR: {0}; - case OPFOR: {1}; - case INDEPENDENT: {2}; - case CIVILIAN: {3}; - }; - - _icon = getText (configFile >> "CfgVehicles" >> (typeOf _x) >> "Icon"); - _picture = "\a3\ui_f\data\map\VehicleIcons\" + _icon + "_ca.paa"; - _treeIndex = []; - _unitList pushBack _x; - - _savedUnit = GVAR(savedUnits) find _x; - if (_savedUnit > -1) then {_text = _text + " (#" + str (_savedUnit + 1) + ")"}; - - if (_forEachIndex == 0) then { - _groupNum = _ctrl tvAdd [[_side], _text]; - _treeIndex = [_side, _groupNum]; - } else { - _num = _ctrl tvAdd [[_side, _groupNum], _text]; - _treeIndex = [_side, _groupNum, _num]; - }; - - _ctrl tvSetPicture [_treeIndex, _picture]; - _ctrl tvSetData [_treeIndex, [_x] call FUNC(unitVar)]; - _unitList pushBack _treeIndex; - }; - } forEach _units; - } forEach allGroups; - - if (!isNull GVAR(unit)) then { - if (alive GVAR(unit)) then { - _treeIndex = _unitList select ((_unitList find GVAR(unit)) + 1); - _ctrl tvSetCurSel _treeIndex; - }; - }; - }; - - case "Select": { - - _ctrl = _this select 0; - _selection = _this select 1; - if (count _selection < 2) exitWith {}; - - _str = _ctrl tvData _selection; - _unit = missionNamespace getVariable _str; - GVAR(unit) = _unit; - if (GVAR(cameraOn)) then { - ["Camera", ["Third"]] call FUNC(camera); - } else { - ["Camera", ["SwitchUnit"]] call FUNC(camera); - }; - }; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_penPos.sqf b/addons/spectator/functions/fnc_penPos.sqf deleted file mode 100644 index a176d3e811..0000000000 --- a/addons/spectator/functions/fnc_penPos.sqf +++ /dev/null @@ -1,33 +0,0 @@ -/* - Author: - voiper - - Description: - Determine spec pen position. - - Arguments: - None - - Example: - call ace_spectator_fnc_penPos; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_mapSize = (configFile >> "CfgWorlds" >> worldName >> "mapSize"); -_worldEdge = if (isNumber _mapSize) then {getNumber _mapSize} else {32768}; -_pos = [_worldEdge * 2, _worldEdge * 2]; - -if (surfaceisWater _pos) then { - _pos set [2, -1.4]; - GVAR(penPos) = ASLtoATL _pos; -} else { - _pos set [2, 0]; - GVAR(penPos) = _pos; -}; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_respawn.sqf b/addons/spectator/functions/fnc_respawn.sqf deleted file mode 100644 index dba2f6a850..0000000000 --- a/addons/spectator/functions/fnc_respawn.sqf +++ /dev/null @@ -1,25 +0,0 @@ -/* - Author: - voiper - - Description: - Respawn EH for remote clients. - - Arguments: - 0: Unit - - Example: - ["Init", [false]] call ace_spectator_fnc_camera; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_unit = _this select 0; -_unit setVariable [QGVAR(name), name _unit, true]; -//_unit setVariable [QGVAR(listed), false]; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_setCameraAttributes.sqf b/addons/spectator/functions/fnc_setCameraAttributes.sqf new file mode 100644 index 0000000000..da2373318d --- /dev/null +++ b/addons/spectator/functions/fnc_setCameraAttributes.sqf @@ -0,0 +1,66 @@ +/* + * Author: SilentSpike + * Sets the spectator camera attributes as desired + * + * Arguments: + * 0: Camera mode + * - 0: Free + * - 1: Internal + * - 2: External + * 1: Camera unit (objNull for random) + * 2: Camera vision + * - -2: Normal + * - -1: Night vision + * - 0: Thermal white hot + * - 1: Thermal black hot + * 3: Camera position (ATL) + * 4: Camera pan (0 - 360) + * 5: Camera tilt (-90 - 90) + * 6: Camera zoom (0.01 - 2) + * 7: Camera speed in m/s (0.05 - 10) + * + * Return Value: + * None + * + * Example: + * [1, objNull] call ace_spectator_fnc_setCameraAttributes + * + * Public: Yes + */ + +#include "script_component.hpp" + +params [ + ["_mode",GVAR(camMode),[0]], + ["_unit",GVAR(camUnit),[objNull]], + ["_vision",GVAR(camVision),[0]], + ["_position",ASLtoATL GVAR(camPos),[[]],3], + ["_heading",GVAR(camPan),[0]], + ["_tilt",GVAR(camTilt),[0]], + ["_zoom",GVAR(camZoom),[0]], + ["_speed",GVAR(camSpeed),[0]] +]; + +// Normalize input +if !(_mode in GVAR(availableModes)) then { + _mode = GVAR(availableModes) select ((GVAR(availableModes) find GVAR(camMode)) max 0); +}; + +if !(_vision in GVAR(availableVisions)) then { + _vision = GVAR(availableVisions) select ((GVAR(availableVisions) find GVAR(camVision)) max 0); +}; + +GVAR(camPan) = _heading % 360; +GVAR(camPosition) = (ATLtoASL _position); +GVAR(camSpeed) = (_speed max 0.05) min 10; +GVAR(camTilt) = (_tilt max -89) min 89; +GVAR(camUnit) = _unit; +GVAR(camVision) = _vision; +GVAR(camZoom) = (_zoom min 2) max 0.01; + +// Apply if camera exists +if !(isNil QGVAR(camera)) then { + [_mode,_unit,_vision] call FUNC(transitionCamera); +} else { + GVAR(camMode) = _mode; +}; diff --git a/addons/spectator/functions/fnc_setSpectator.sqf b/addons/spectator/functions/fnc_setSpectator.sqf new file mode 100644 index 0000000000..fd3dd9861c --- /dev/null +++ b/addons/spectator/functions/fnc_setSpectator.sqf @@ -0,0 +1,77 @@ +/* + * Author: SilentSpike + * Sets target unit to the given spectator state + * + * Arguments: + * 0: Unit to put into spectator state + * 1: New spectator state + * + * Return Value: + * None + * + * Example: + * [player, true] call ace_spectator_fnc_setSpectator + * + * Public: Yes + */ + +#include "script_component.hpp" + +params ["_unit",["_set",true,[true]],["_target",objNull,[objNull]]]; + +// No change, no service (but allow spectators who respawn to be reset) +if !(_set || (_unit getVariable [QGVAR(isSpectator), false])) exitWith {}; + +// Only run for player units +if !(isPlayer _unit) exitWith {}; + +if !(local _unit) exitwith { + [[_unit, _set, _target], QFUNC(setSpectator), _unit] call EFUNC(common,execRemoteFnc); +}; + +// Prevent player falling into water +_unit enableSimulation !_set; + +// Move to/from group as appropriate +[_unit, _set, QGVAR(isSpectator), side group _unit] call EFUNC(common,switchToGroupSide); + +if (_set) then { + // Move and hide the player ASAP to avoid being seen + _unit setPos (getMarkerPos QGVAR(respawn)); + + // Ghosts can't talk + [_unit, QGVAR(isSpectator)] call EFUNC(common,hideUnit); + [_unit, QGVAR(isSpectator)] call EFUNC(common,muteUnit); + + ["open"] call FUNC(handleInterface); +} else { + ["close"] call FUNC(handleInterface); + + // Physical beings can talk + [_unit, QGVAR(isSpectator)] call EFUNC(common,unhideUnit); + [_unit, QGVAR(isSpectator)] call EFUNC(common,unmuteUnit); + + private "_marker"; + _marker = ["respawn_west","respawn_east","respawn_guerrila","respawn_civilian"] select ([west,east,resistance,civilian] find (side group _unit)); + _unit setPos (getMarkerPos _marker); +}; + +// Enable/disable input as appropriate +//[QGVAR(isSpectator), _set] call EFUNC(common,setDisableUserInputStatus); + +// Handle common addon audio +if (["ace_hearing"] call EFUNC(common,isModLoaded)) then {EGVAR(hearing,disableVolumeUpdate) = _set}; +if (["acre_sys_radio"] call EFUNC(common,isModLoaded)) then {[_set] call acre_api_fnc_setSpectator}; +if (["task_force_radio"] call EFUNC(common,isModLoaded)) then {[_unit, _set] call TFAR_fnc_forceSpectator}; + +// Spectators ignore damage (vanilla and ace_medical) +_unit allowDamage !_set; +_unit setVariable [QEGVAR(medical,allowDamage), !_set]; + +// No theoretical change if an existing spectator was reset +if !(_set && (_unit getVariable [QGVAR(isSpectator), false])) then { + // Mark spectator state for reference + _unit setVariable [QGVAR(isSpectator), _set, true]; + + ["spectatorChanged",[_set]] call EFUNC(common,localEvent); +}; diff --git a/addons/spectator/functions/fnc_sideColour.sqf b/addons/spectator/functions/fnc_sideColour.sqf deleted file mode 100644 index 1262ae5b07..0000000000 --- a/addons/spectator/functions/fnc_sideColour.sqf +++ /dev/null @@ -1,66 +0,0 @@ -/* - Author: - voiper - - Description: - Determine side colour for spectator GUI. - - Arguments: - 0: Side - - Example: - [0 call ace_spectator_fnc_sideColour; - - Return Value: - Colour - - Public: - No -*/ - -#include "script_component.hpp" -#define FACTOR 1.3 -#define GETCOLOUR(a,b) (profileNameSpace getVariable [QUOTE(a), b]) - -PARAMS_1(_side); - -_colour = switch _side do { - case BLUFOR: { - [ - GETCOLOUR('Map_BLUFOR_R', 0), - GETCOLOUR('Map_BLUFOR_G', 0.3), - GETCOLOUR('Map_BLUFOR_B', 0.6) - ] - }; - - case OPFOR: { - [ - GETCOLOUR('Map_OPFOR_R', 0.5), - GETCOLOUR('Map_OPFOR_G', 0), - GETCOLOUR('Map_OPFOR_B', 0) - ] - }; - - case INDEPENDENT: { - [ - GETCOLOUR('Map_Independent_R', 0), - GETCOLOUR('Map_Independent_G', 0.5), - GETCOLOUR('Map_Independent_B', 0) - ] - }; - - case CIVILIAN: { - [ - GETCOLOUR('Map_Civilian_R', 0.4), - GETCOLOUR('Map_Civilian_G', 0), - GETCOLOUR('Map_Civilian_B', 0.5) - ] - }; -}; - -_colour set [0, (_colour select 0) * FACTOR]; -_colour set [1, (_colour select 1) * FACTOR]; -_colour set [2, (_colour select 2) * FACTOR]; -_colour set [3, 1]; - -_colour \ No newline at end of file diff --git a/addons/spectator/functions/fnc_status.sqf b/addons/spectator/functions/fnc_status.sqf deleted file mode 100644 index 4207ef9c00..0000000000 --- a/addons/spectator/functions/fnc_status.sqf +++ /dev/null @@ -1,60 +0,0 @@ -/* - Author: - voiper - - Description: - Render status. - - Arguments: - 0: Status element - - Example: - [display] call ace_spectator_fnc_status; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_display = _this select 0; - -_speedText = (str ([GVAR(moveScale), 4] call BIS_fnc_cutDecimals)) + "v"; -(_display displayCtrl 0) ctrlSetText _speedText; - -_name = ""; -_colour = [1,1,1,1]; - -if (!isNull GVAR(unit)) then { - _info = [GVAR(unit)] call FUNC(unitInfo); - _name = _info select 0; - _side = _info select 1; - _colour = _info select 2; - _colour set [3, 1]; -}; -(_display displayCtrl 1) ctrlSetText _name; -(_display displayCtrl 1) ctrlSetTextColor _colour; - -_mode = if (GVAR(cameraOn)) then { - if (isNull GVAR(attach)) then {"FREE"} else {"ATTACH"}; -} else { - if (GVAR(third)) then {"THIRD"} else {"FIRST"}; -}; -(_display displayCtrl 2) ctrlSetText _mode; - -_timeText = [dayTime] call BIS_fnc_timeToString; -(_display displayCtrl 3) ctrlSetText _timeText; - -_fovText = (str ([GVAR(fov), 3] call BIS_fnc_cutDecimals)) + "a"; -(_display displayCtrl 4) ctrlSetText _fovText; - -_timeAccText = (str ([GVAR(accTime), 4] call BIS_fnc_cutDecimals)) + "x"; -(_display displayCtrl 5) ctrlSetText _timeAccText; - -_focusDist = [GVAR(focus) select 0, 1] call BIS_fnc_cutDecimals; -_focusBlur = GVAR(focus) select 1; -_focusText = if (_focusDist == -1 && _focusBlur == 1) then {"Auto"} else {if (_focusDist < 0) then {toString [8734]} else {str _focusDist + "m"}}; -(_display displayCtrl 6) ctrlSetText _focusText; \ No newline at end of file diff --git a/addons/spectator/functions/fnc_toggleInterface.sqf b/addons/spectator/functions/fnc_toggleInterface.sqf new file mode 100644 index 0000000000..609c7cd757 --- /dev/null +++ b/addons/spectator/functions/fnc_toggleInterface.sqf @@ -0,0 +1,89 @@ +/* + * Author: SilentSpike + * Correctly handles toggling of spectator interface elements for clean UX + * + * Arguments: + * 0: Display + * 1: Toogle compass + * 2: Toogle help + * 3: Toogle interface + * 4: Toogle map + * 5: Toogle toolbar + * 6: Toogle unit list + * + * Return Value: + * None + * + * Example: + * [_dsiplay, nil, true] call ace_spectator_fnc_toggleInterface + * + * Public: No + */ + +#include "script_component.hpp" + +params ["_display", ["_toggleComp",false], ["_toggleHelp",false], ["_toggleInterface",false], ["_toggleMap",false], ["_toggleTool",false], ["_toggleUnit",false]]; + +private ["_comp","_help","_map","_tool","_unit"]; +_comp = _display displayCtrl IDC_COMP; +_help = _display displayCtrl IDC_HELP; +_map = _display displayCtrl IDC_MAP; +_tool = _display displayCtrl IDC_TOOL; +_unit = _display displayCtrl IDC_UNIT; + +// Map and help operate outside of interface +GVAR(showHelp) = [GVAR(showHelp), !GVAR(showHelp)] select _toggleHelp; +GVAR(showMap) = [GVAR(showMap), !GVAR(showMap)] select _toggleMap; + +// When help changes with map open, minimise the map +if (GVAR(showMap) && _toggleHelp) then { + GVAR(showHelp) = true; + GVAR(showMap) = false; +}; + +_help ctrlShow GVAR(showHelp); +_map ctrlShow GVAR(showMap); + +if (GVAR(showMap)) then { + // When map is shown, temporarily hide interface to stop overlapping + { + _x ctrlShow false; + } forEach [_comp,_help,_tool,_unit]; + + // Centre map on camera/unit upon opening + if (_toggleMap) then { + _map ctrlMapAnimAdd [0, 0.5, [GVAR(camUnit),GVAR(camera)] select (GVAR(camMode) == 0)]; + ctrlMapAnimCommit _map; + }; +} else { + // Can only toggle interface with map minimised + GVAR(showInterface) = [GVAR(showInterface), !GVAR(showInterface)] select _toggleInterface; + + if (GVAR(showInterface)) then { + // Can only toggle interface elements with interface shown + GVAR(showComp) = [GVAR(showComp), !GVAR(showComp)] select _toggleComp; + GVAR(showTool) = [GVAR(showTool), !GVAR(showTool)] select _toggleTool; + GVAR(showUnit) = [GVAR(showUnit), !GVAR(showUnit)] select _toggleUnit; + + _comp ctrlShow GVAR(showComp); + _tool ctrlShow GVAR(showTool); + _unit ctrlShow GVAR(showUnit); + } else { + { + _x ctrlShow false; + } forEach [_comp,_tool,_unit]; + }; +}; + +// Only run PFHs when respective control is shown, otherwise kill +if (ctrlShown _comp) then { + if (isNil QGVAR(compHandler)) then { GVAR(compHandler) = [FUNC(handleCompass), 0, _display] call CBA_fnc_addPerFrameHandler; }; +} else { + GVAR(compHandler) = nil; +}; + +if (ctrlShown _tool) then { + if (isNil QGVAR(toolHandler)) then { GVAR(toolHandler) = [FUNC(handleToolbar), 0, _display] call CBA_fnc_addPerFrameHandler; }; +} else { + GVAR(toolHandler) = nil; +}; diff --git a/addons/spectator/functions/fnc_trackUnits.sqf b/addons/spectator/functions/fnc_trackUnits.sqf deleted file mode 100644 index 28da75a554..0000000000 --- a/addons/spectator/functions/fnc_trackUnits.sqf +++ /dev/null @@ -1,54 +0,0 @@ -/* - Author: - voiper - - Description: - Check and record tracking for all units. - - Arguments: - None - - Example: - call ace_spectator_fnc_trackUnits; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -if (isNil QGVAR(trackingArray)) then { - GVAR(trackingArray) = []; -}; - -if (count GVAR(units) < 1) exitWith {}; - -{ - _unit = _x; - _pos = getPos _unit; - _pos resize 2; - - _index = -1; - - {if ((_x select 0) == _unit) then {_index = _forEachIndex}} forEach GVAR(trackingArray); - if (_index == -1) then { - GVAR(trackingArray) pushBack [_unit, [_pos]] - } else { - _unitArray = GVAR(trackingArray) select _index; - _trackingArray = _unitArray select 1; - _latestIndex = (count _trackingArray) - 1; - _latestPos = _trackingArray select _latestIndex; - _diffX = abs((_latestPos select 0) - (_pos select 0)); - _diffY = abs((_latestPos select 1) - (_pos select 1)); - - if !((_diffX < 20) && (_diffY < 20)) then { - _trackingArray pushBack _pos; - _unitArray set [1, _trackingArray]; - GVAR(trackingArray) set [_index, _unitArray]; - }; - }; - -} forEach GVAR(units); \ No newline at end of file diff --git a/addons/spectator/functions/fnc_transitionCamera.sqf b/addons/spectator/functions/fnc_transitionCamera.sqf new file mode 100644 index 0000000000..07abbc94ab --- /dev/null +++ b/addons/spectator/functions/fnc_transitionCamera.sqf @@ -0,0 +1,112 @@ +/* + * Author: SilentSpike + * Transitions the spectator camera vision/view/unit + * + * Arguments: + * 0: Camera mode + * - 0: Free + * - 1: Internal + * - 2: External + * 1: Camera unit + * 2: Vision mode + * - -2: Normal + * - -1: NV + * - 0: White hot + * - 1: Black hot + * + * Return Value: + * None + * + * Example: + * [0,objNull] call ace_spectator_fnc_transitionCamera + * + * Public: No + */ + +#include "script_component.hpp" + +params [["_newMode",GVAR(camMode)], ["_newUnit",GVAR(camUnit)], ["_newVision",GVAR(camVision)]]; + +// If new mode isn't available then keep current (unless current also isn't) +if !(_newMode in GVAR(availableModes)) then { + _newMode = GVAR(availableModes) select ((GVAR(availableModes) find GVAR(camMode)) max 0); +}; + +// When no units available to spectate, exit to freecam +if (GVAR(unitList) isEqualTo []) then { + _newMode = 0; + _newUnit = objNull; +}; + +// Reset gun cam if not internal +if (_newMode != 1) then { + GVAR(camGun) = false; +}; + +if (_newMode == 0) then { // Free + // Preserve camUnit value for consistency when manually changing view + GVAR(camera) cameraEffect ["internal", "back"]; + showCinemaBorder false; + cameraEffectEnableHUD true; + + // Apply the camera zoom + GVAR(camera) camSetFov -(linearConversion [0.01,2,GVAR(camZoom),-2,-0.01,true]); + GVAR(camera) camCommit 0; + + // Switch to camera to stop AI group chat + ACE_Player switchCamera "internal"; + clearRadio; + + // If new vision isn't available then keep current (unless current also isn't) + if !(_newVision in GVAR(availableVisions)) then { + _newVision = GVAR(availableVisions) select ((GVAR(availableVisions) find GVAR(camVision)) max 0); + }; + + // Vision mode only applies to free cam + if (_newVision < 0) then { + false setCamUseTi 0; + camUseNVG (_newVision >= -1); + } else { + true setCamUseTi _newVision; + }; + GVAR(camVision) = _newVision; + + // Handle camera movement + if (isNil QGVAR(camHandler)) then { GVAR(camHandler) = [FUNC(handleCamera), 0] call CBA_fnc_addPerFrameHandler; }; + + // Handle unit icons + if (GVAR(unitIcons)) then { + if (isNil QGVAR(iconHandler)) then { GVAR(iconHandler) = [FUNC(handleIcons), 0] call CBA_fnc_addPerFrameHandler; }; + }; +} else { + // When null unit is given choose random + if (isNull _newUnit) then { + _newUnit = GVAR(unitList) select floor(random(count GVAR(unitList))); + }; + + if (_newMode == 1) then { // Internal + // Handle gun cam + if (GVAR(camGun)) then { + _newUnit switchCamera "gunner"; + } else { + _newUnit switchCamera "internal"; + }; + } else { // External + _newUnit switchCamera "external"; + }; + + // Clear radio if group changed + if (group _newUnit != group GVAR(camUnit)) then { + clearRadio; + }; + + GVAR(camUnit) = _newUnit; + + // Terminate camera view + GVAR(camera) cameraEffect ["terminate", "back"]; + GVAR(camHandler) = nil; + GVAR(iconHandler) = nil; + cameraEffectEnableHUD true; +}; + +GVAR(camMode) = _newMode; diff --git a/addons/spectator/functions/fnc_unitInfo.sqf b/addons/spectator/functions/fnc_unitInfo.sqf deleted file mode 100644 index a377cabf31..0000000000 --- a/addons/spectator/functions/fnc_unitInfo.sqf +++ /dev/null @@ -1,34 +0,0 @@ -/* - Author: - voiper - - Description: - Retrieve unit name, side, and colour. - - Arguments: - 0: Unit - - Example: - [player] call ace_spectator_fnc_unitInfo; - - Return Value: - Name , Side , Colour - - Public: - No -*/ - -#include "script_component.hpp" - -PARAMS_1(_unit); - -_name = [_unit] call EFUNC(common,getName); -_side = [_unit] call FUNC(unitSide); -_colour = [_side] call FUNC(sideColour); - -if (!alive _unit) then { - {_colour set [_forEachIndex, _x / 2.5]} forEach _colour; - _colour set [3, 0.8]; -}; - -[_name, _side, _colour] \ No newline at end of file diff --git a/addons/spectator/functions/fnc_unitSide.sqf b/addons/spectator/functions/fnc_unitSide.sqf deleted file mode 100644 index d33520d5ec..0000000000 --- a/addons/spectator/functions/fnc_unitSide.sqf +++ /dev/null @@ -1,39 +0,0 @@ -/* - Author: - voiper - - Description: - Retrieve unit's side, even after they join grpNull. - - Arguments: - 0: Unit to check - - Example: - [unit] call ace_spectator_unitSide; - - Return Value: - Side - - Public: - No -*/ - -#include "script_component.hpp" - -PARAMS_1(_unit); - -private ["_side"]; - -if (alive _unit) then { - _side = side (group _unit); -} else { - _sideNum = getNumber (configFile >> "CfgVehicles" >> (typeOf _unit) >> "side"); - _side = switch _sideNum do { - case 0: {OPFOR}; - case 1: {BLUFOR}; - case 2: {INDEPENDENT}; - case 3: {CIVILIAN}; - }; -}; - -_side \ No newline at end of file diff --git a/addons/spectator/functions/fnc_unitVar.sqf b/addons/spectator/functions/fnc_unitVar.sqf deleted file mode 100644 index 6d072ae171..0000000000 --- a/addons/spectator/functions/fnc_unitVar.sqf +++ /dev/null @@ -1,38 +0,0 @@ -/* - Author: Karel Moricky, modified by voiper - - Description: - Set or return an unique object variable (client only). - - Arguments: - 0: Unit - - Returns: - Variable -*/ - -#include "script_component.hpp" - -private ["_object","_var"]; - -_object = [_this, 0, objnull, [objnull]] call BIS_fnc_param; - -if (isNull _object) exitwith {""}; - -_var = _object getVariable [QGVAR(objectVar), ""]; - -if (_var == "") then { - _var = vehicleVarname _object; - - if (_var == "") then { - _var = [_this, 1, QGVAR(obj), [""]] call BIS_fnc_param; - _varID = [_var, 1] call BIS_fnc_counter; - _var = _var + str _varID; - }; - - _object setVariable [QGVAR(objectVar), _var]; - missionNamespace setVariable [_var, _object]; - _object setVehicleVarname _var; -}; - -_var \ No newline at end of file diff --git a/addons/spectator/functions/fnc_updateCameraModes.sqf b/addons/spectator/functions/fnc_updateCameraModes.sqf new file mode 100644 index 0000000000..ec2837ffb8 --- /dev/null +++ b/addons/spectator/functions/fnc_updateCameraModes.sqf @@ -0,0 +1,48 @@ +/* + * Author: SilentSpike + * Adds or removes spectator camera modes from the selection available to the local player. + * Possible camera modes are: + * - 0: Free + * - 1: Internal + * - 2: External + * + * Arguments: + * 0: Camera modes to add + * 1: Camera modes to remove + * + * Return Value: + * Available camera modes + * + * Example: + * [[0], [1,2]] call ace_spectator_fnc_updateCameraModes + * + * Public: Yes + */ + +#include "script_component.hpp" + +params [["_addModes",[],[[]]], ["_removeModes",[],[[]]]]; +private ["_newModes","_currentModes"]; + +_currentModes = GVAR(availableModes); + +// Restrict additions to only possible values +_newModes = _addModes arrayIntersect [0,1,2]; +_newModes append (_currentModes - _removeModes); + +_newModes arrayIntersect _newModes; +_newModes sort true; + +// Can't become an empty array +if (_newModes isEqualTo []) then { + ["Cannot remove all camera modes (%1)", QFUNC(updateCameraModes)] call BIS_fnc_error; +} else { + GVAR(availableModes) = _newModes; +}; + +// Update camera in case of change +if !(isNil QGVAR(camera)) then { + [] call FUNC(transitionCamera); +}; + +_newModes diff --git a/addons/spectator/functions/fnc_updateSpectatableSides.sqf b/addons/spectator/functions/fnc_updateSpectatableSides.sqf new file mode 100644 index 0000000000..e4f359b4d1 --- /dev/null +++ b/addons/spectator/functions/fnc_updateSpectatableSides.sqf @@ -0,0 +1,33 @@ +/* + * Author: SilentSpike + * Adds or removes sides from the selection available to spectate by the local player. + * Note that the side filter setting is applied to the available sides dynamically. + * + * Default selection is [west,east,resistance,civilian] + * + * Arguments: + * 0: Sides to add + * 1: Sides to remove + * + * Return Value: + * Spectatable sides + * + * Example: + * [[west], [east,civilian]] call ace_spectator_fnc_updateSpectatableSides + * + * Public: Yes + */ + +#include "script_component.hpp" + +params [["_addSides",[],[[]]], ["_removeSides",[],[[]]]]; + +// Add and remove sides +_addSides append (GVAR(availableSides) - _removeSides); + +// Only need array of unique sides +_addSides arrayIntersect _addSides; + +GVAR(availableSides) = _addSides; + +_addSides diff --git a/addons/spectator/functions/fnc_updateUnits.sqf b/addons/spectator/functions/fnc_updateUnits.sqf new file mode 100644 index 0000000000..0393fa0e36 --- /dev/null +++ b/addons/spectator/functions/fnc_updateUnits.sqf @@ -0,0 +1,72 @@ +/* + * Author: SilentSpike + * Adds units to spectator whitelist/blacklist and refreshes the filter units + * + * Arguments: + * 0: Units to add to the whitelist + * 1: Use blacklist + * + * Return Value: + * None + * + * Example: + * [allUnits,true] call ace_spectator_fnc_updateUnits + * + * Public: Yes + */ + +#include "script_component.hpp" + +params [["_newUnits",[],[[]]],["_blacklist",false,[false]]]; + +// Function only matters on player clients +if !(hasInterface) exitWith {}; + +// If adding to a list we can exit here, since it won't show up until the UI refreshes anyway +if !(_newUnits isEqualTo []) exitWith { + if (_blacklist) then { + GVAR(unitWhitelist) = GVAR(unitWhitelist) - _newUnits; + GVAR(unitBlacklist) append _newUnits; + } else { + GVAR(unitBlacklist) = GVAR(unitBlacklist) - _newUnits; + GVAR(unitWhitelist) append _newUnits; + }; +}; + +private ["_sides","_cond","_filteredUnits","_color","_icon"]; + +// Unit setting filter +_newUnits = [[],allPlayers,allUnits] select GVAR(filterUnits); + +// Side setting filter +_sides = []; +_cond = [{_this == (side group player)},{(_this getFriend (side group player)) >= 0.6},{(_this getFriend (side group player)) < 0.6},{true}] select GVAR(filterSides); +{ + if (_x call _cond) then { + _sides pushBack _x; + }; +} forEach GVAR(availableSides); + +// Filter units and append to list +_filteredUnits = []; +{ + if ( + (alive _x) && + {(_x isKindOf "CAManBase")} && + {(side group _x) in _sides} && // Side filter + {simulationEnabled _x} && + {!(_x getVariable [QGVAR(isSpectator), false])} // Who watches the watchmen? + ) then { + _filteredUnits pushBack _x; + }; +} forEach (_newUnits - GVAR(unitBlacklist)); +_filteredUnits append GVAR(unitWhitelist); + +// Cache icons and colour for drawing +{ + // Intentionally re-applied to units in case their status changes + [_x] call FUNC(cacheUnitInfo); +} forEach _filteredUnits; + +// Replace previous list entirely (removes any no longer valid) +GVAR(unitList) = _filteredUnits arrayIntersect _filteredUnits; diff --git a/addons/spectator/functions/fnc_updateVisionModes.sqf b/addons/spectator/functions/fnc_updateVisionModes.sqf new file mode 100644 index 0000000000..b2b2cd75d6 --- /dev/null +++ b/addons/spectator/functions/fnc_updateVisionModes.sqf @@ -0,0 +1,56 @@ +/* + * Author: SilentSpike + * Adds or removes spectator vision modes from the selection available to the local player. + * The default selection is [-2,-1,0,1]. + * Possible vision modes are: + * - -2: Normal + * - -1: Night vision + * - 0: White hot + * - 1: Black hot + * - 2: Light Green Hot / Darker Green cold + * - 3: Black Hot / Darker Green cold + * - 4: Light Red Hot / Darker Red Cold + * - 5: Black Hot / Darker Red Cold + * - 6: White Hot / Darker Red Cold + * - 7: Thermal (Shade of Red and Green, Bodies are white) + * + * Arguments: + * 0: Vision modes to add + * 1: Vision modes to remove + * + * Return Value: + * Available vision modes + * + * Example: + * [[0], [1,2]] call ace_spectator_fnc_updateVisionModes + * + * Public: Yes + */ + +#include "script_component.hpp" + +params [["_addModes",[],[[]]], ["_removeModes",[],[[]]]]; +private ["_newModes","_currentModes"]; + +_currentModes = GVAR(availableVisions); + +// Restrict additions to only possible values +_newModes = _addModes arrayIntersect [-2,-1,0,1,2,3,4,5,6,7]; +_newModes append (_currentModes - _removeModes); + +_newModes arrayIntersect _newModes; +_newModes sort true; + +// Can't become an empty array +if (_newModes isEqualTo []) then { + ["Cannot remove all vision modes (%1)", QFUNC(updateVisionModes)] call BIS_fnc_error; +} else { + GVAR(availableVisions) = _newModes; +}; + +// Update camera in case of change +if !(isNil QGVAR(camera)) then { + [] call FUNC(transitionCamera); +}; + +_newModes diff --git a/addons/spectator/functions/fnc_viewDistance.sqf b/addons/spectator/functions/fnc_viewDistance.sqf deleted file mode 100644 index 4112ed2a62..0000000000 --- a/addons/spectator/functions/fnc_viewDistance.sqf +++ /dev/null @@ -1,47 +0,0 @@ -/* - Author: - voiper - - Description: - View distance dialog. - - Arguments: - 0: Mode - 1: Arguemnts - - Example: - ["Init", [dialog]] call ace_spectator_fnc_viewDistance; - - Return Value: - None - - Public: - No -*/ - -#include "script_component.hpp" - -_mode = _this select 0; -_this = _this select 1; - -switch _mode do { - - case "Init": { - _dialog = _this select 0; - _dist = -1; - _text = _dialog displayCtrl 1; - _slider = _dialog displayCtrl 2; - _slider slidersetRange [1000,20000]; - _slider sliderSetSpeed [1000,1000,1000]; - _slider sliderSetPosition viewDistance; - _text ctrlSetText str viewDistance; - }; - - case "Slider": { - _dialog = ctrlParent (_this select 0); - _dist = _this select 1; - _text = _dialog displayCtrl 1; - setViewDistance _dist; - _text ctrlSetText str viewDistance; - }; -}; \ No newline at end of file diff --git a/addons/spectator/rsc_defines.hpp b/addons/spectator/rsc_defines.hpp deleted file mode 100644 index e7cb7178c3..0000000000 --- a/addons/spectator/rsc_defines.hpp +++ /dev/null @@ -1,646 +0,0 @@ -// Control types -#define CT_STATIC 0 -#define CT_BUTTON 1 -#define CT_EDIT 2 -#define CT_SLIDER 3 -#define CT_COMBO 4 -#define CT_LISTBOX 5 -#define CT_TOOLBOX 6 -#define CT_CHECKBOXES 7 -#define CT_PROGRESS 8 -#define CT_HTML 9 -#define CT_STATIC_SKEW 10 -#define CT_ACTIVETEXT 11 -#define CT_TREE 12 -#define CT_STRUCTURED_TEXT 13 -#define CT_CONTEXT_MENU 14 -#define CT_CONTROLS_GROUP 15 -#define CT_SHORTCUTBUTTON 16 -#define CT_HITZONES 17 -#define CT_XKEYDESC 40 -#define CT_XBUTTON 41 -#define CT_XLISTBOX 42 -#define CT_XSLIDER 43 -#define CT_XCOMBO 44 -#define CT_ANIMATED_TEXTURE 45 -#define CT_OBJECT 80 -#define CT_OBJECT_ZOOM 81 -#define CT_OBJECT_CONTAINER 82 -#define CT_OBJECT_CONT_ANIM 83 -#define CT_LINEBREAK 98 -#define CT_USER 99 -#define CT_MAP 100 -#define CT_MAP_MAIN 101 -#define CT_LISTNBOX 102 -#define CT_ITEMSLOT 103 -#define CT_CHECKBOX 77 - -// Static styles -#define ST_POS 0x0F -#define ST_HPOS 0x03 -#define ST_VPOS 0x0C -#define ST_LEFT 0x00 -#define ST_RIGHT 0x01 -#define ST_CENTER 0x02 -#define ST_DOWN 0x04 -#define ST_UP 0x08 -#define ST_VCENTER 0x0C - -#define ST_TYPE 0xF0 -#define ST_SINGLE 0x00 -#define ST_MULTI 0x10 -#define ST_TITLE_BAR 0x20 -#define ST_PICTURE 0x30 -#define ST_FRAME 0x40 -#define ST_BACKGROUND 0x50 -#define ST_GROUP_BOX 0x60 -#define ST_GROUP_BOX2 0x70 -#define ST_HUD_BACKGROUND 0x80 -#define ST_TILE_PICTURE 0x90 -#define ST_WITH_RECT 0xA0 -#define ST_LINE 0xB0 -#define ST_UPPERCASE 0xC0 -#define ST_LOWERCASE 0xD0 - -#define ST_SHADOW 0x100 -#define ST_NO_RECT 0x200 -#define ST_KEEP_ASPECT_RATIO 0x800 - -#define ST_TITLE ST_TITLE_BAR + ST_CENTER - -// Slider styles -#define SL_DIR 0x400 -#define SL_VERT 0 -#define SL_HORZ 0x400 - -#define SL_TEXTURES 0x10 - -// progress bar -#define ST_VERTICAL 0x01 -#define ST_HORIZONTAL 0 - -// Listbox styles -#define LB_TEXTURES 0x10 -#define LB_MULTI 0x20 - -// Tree styles -#define TR_SHOWROOT 1 -#define TR_AUTOCOLLAPSE 2 - -// MessageBox styles -#define MB_BUTTON_OK 1 -#define MB_BUTTON_CANCEL 2 -#define MB_BUTTON_USER 4 -#define MB_ERROR_DIALOG 8 - -// Fonts -#define GUI_FONT_NORMAL PuristaMedium -#define GUI_FONT_BOLD PuristaSemibold -#define GUI_FONT_THIN PuristaLight -#define GUI_FONT_MONO EtelkaMonospacePro -#define GUI_FONT_NARROW EtelkaNarrowMediumPro -#define GUI_FONT_CODE LucidaConsoleB -#define GUI_FONT_SYSTEM TahomaB - -//colours - -#define COLOUR_GUI_TEXT {"profilenamespace getvariable ['GUI_TITLETEXT_RGB_R',1]", "profilenamespace getvariable ['GUI_TITLETEXT_RGB_G',1]", "profilenamespace getvariable ['GUI_TITLETEXT_RGB_B',1]", "profilenamespace getvariable ['GUI_TITLETEXT_RGB_A',1]"} - -#define COLOUR_GUI_BG {"profilenamespace getvariable ['GUI_BCG_RGB_R',0.8]", "profilenamespace getvariable ['GUI_BCG_RGB_G',0.8]","profilenamespace getvariable ['GUI_BCG_RGB_B',0.8]","profilenamespace getvariable ['GUI_BCG_RGB_A',0.8]"} - -#define COLOUR_IGUI_TEXT {"profilenamespace getvariable ['IGUI_TEXT_RGB_R',1]", "profilenamespace getvariable ['IGUI_TEXT_RGB_G',1]", "profilenamespace getvariable ['IGUI_TEXT_RGB_B',1]", "profilenamespace getvariable ['IGUI_TEXT_RGB_A',1]"} - -#define COLOUR_IGUI_BG {"profilenamespace getvariable ['IGUI_BCG_RGB_R',0.8]", "profilenamespace getvariable ['IGUI_BCG_RGB_G',0.5]","profilenamespace getvariable ['IGUI_BCG_RGB_B',0]","profilenamespace getvariable ['IGUI_BCG_RGB_A',0.8]"} - -#define COLOUR_IGUI_WARN {"profilenamespace getvariable ['IGUI_TEXT_WARNING_R',0.8]", "profilenamespace getvariable ['IGUI_TEXT_WARNING_G',0.5]", "profilenamespace getvariable ['IGUI_TEXT_WARNING_B',0]", "profilenamespace getvariable ['IGUI_TEXT_WARNING_A',0.8]"} - -// Grids -#define GUI_GRID_CENTER_WAbs ((safezoneW / safezoneH) min 1.2) -#define GUI_GRID_CENTER_HAbs (GUI_GRID_CENTER_WAbs / 1.2) -#define GUI_GRID_CENTER_W (GUI_GRID_CENTER_WAbs / 40) -#define GUI_GRID_CENTER_H (GUI_GRID_CENTER_HAbs / 25) -#define GUI_GRID_CENTER_X (safezoneX + (safezoneW - GUI_GRID_CENTER_WAbs)/2) -#define GUI_GRID_CENTER_Y (safezoneY + (safezoneH - GUI_GRID_CENTER_HAbs)/2) - -#define RESUNITS_X (safeZoneW / 100) -#define RESUNITS_Y (safeZoneH / 100) -#define RESCENTRE_X safeZoneX + safeZoneW / 2 -#define RESCENTRE_Y safeZoneY + safeZoneH / 2 - -#define Q(s) #s - -class vip_rsc_picture { - - access = 0; - idc = -1; - type = CT_STATIC; - style = ST_PICTURE; - colorBackground[] = {0,0,0,0}; - colorText[] = {1,1,1,1}; - font = "TahomaB"; - sizeEx = 0; - lineSpacing = 0; - text = ""; - fixedWidth = 0; - shadow = 0; -}; - -class vip_rsc_text { - - access = 0; - idc = -1; - type = CT_STATIC; - style = ST_LEFT; - colorBackground[] = {0,0,0,0}; - colorText[] = {1,1,1,1}; - font = "PuristaMedium"; - sizeEx = 0.08; - lineSpacing = 1; - text = ""; - fixedWidth = 0; - moving = 0; -}; - -class vip_rsc_box { - - idc=-1; - type = CT_STATIC; - style = ST_CENTER; - text = ""; - font = "TahomaB"; - sizeEx = 0.04; - - colorBackground[] = {0,0,0,1}; - colorText[] = {1,1,1,1}; -}; - -class vip_rsc_button { - - access = 0; - type = CT_BUTTON; - style = ST_LEFT; - default = 0; - blinkingPeriod = 0; - - x = 0 * GUI_GRID_CENTER_W + GUI_GRID_CENTER_X; - y = 0 * GUI_GRID_CENTER_H + GUI_GRID_CENTER_Y; - w = 6 * GUI_GRID_CENTER_W; - h = 1 * GUI_GRID_CENTER_H; - - colorBackground[] = {0.8,0.8,0.8,1}; - colorBackgroundDisabled[] = {0.8,0.8,0.8, 0.25}; - colorBackgroundActive[] = {1,1,1,1}; - colorFocused[] = {0.8,0.8,0.8,1}; - - text = ""; - sizeEx = 1 * GUI_GRID_CENTER_H; - font = GUI_FONT_NORMAL; - shadow = 1; - colorText[] = {0,0,0,1}; - colorDisabled[] = {0,0,0,0.25}; - - borderSize = 0.0; - colorBorder[] = {1,1,1,1}; - - colorShadow[] = {0,0,0,0.0}; - offsetX = 0.0075; - offsetY = 0.01; - offsetPressedX = 0.000; - offsetPressedY = 0.00; - - period = 0; - periodFocus = 0; - periodOver = 0.5; - - soundClick[] = {"\A3\ui_f\data\sound\RscButton\soundClick",0.09,1}; - soundEnter[] = {"\A3\ui_f\data\sound\RscButton\soundEnter",0.09,1}; - soundPush[] = {"\A3\ui_f\data\sound\RscButton\soundPush",0.09,1}; - soundEscape[] = {"\A3\ui_f\data\sound\RscButton\soundEscape",0.09,1}; - - //onButtonClick = "false"; -}; - -class vip_rsc_listbox { - - access = 0; - idc = 25; - type = CT_COMBO; - style = ST_LEFT + LB_TEXTURES; - default = 0; - blinkingPeriod = 0; - - x = 12 * GUI_GRID_CENTER_W + GUI_GRID_CENTER_X; - y = 4 * GUI_GRID_CENTER_H + GUI_GRID_CENTER_Y; - w = 9 * GUI_GRID_CENTER_W; - h = 1 * GUI_GRID_CENTER_H; - - colorBackground[] = {0.2,0.2,0.2,1}; - colorSelectBackground[] = {1,0.5,0,1}; - - sizeEx = GUI_GRID_CENTER_H; - font = GUI_FONT_NORMAL; - shadow = 0; - colorText[] = {1,1,1,1}; - colorDisabled[] = {1,1,1,0.5}; - colorSelect[] = {1,1,1,1}; - - pictureColor[] = {1,0.5,0,1}; - pictureColorSelect[] = {1,1,1,1}; - pictureColorDisabled[] = {1,1,1,0.5}; - - arrowEmpty = "\A3\ui_f\data\GUI\RscCommon\rsccombo\arrow_combo_ca.paa"; - arrowFull = "\A3\ui_f\data\GUI\RscCommon\rsccombo\arrow_combo_active_ca.paa"; - - wholeHeight = 8 * GUI_GRID_CENTER_H; - maxHistoryDelay = 1; - - soundExpand[] = {"\A3\ui_f\data\sound\RscCombo\soundExpand",0.1,1}; - soundCollapse[] = {"\A3\ui_f\data\sound\RscCombo\soundCollapse",0.1,1}; - soundSelect[] = {"\A3\ui_f\data\sound\RscCombo\soundSelect",0.1,1}; - - class ComboScrollBar - { - width = 0; - height = 0; - scrollSpeed = 0.01; - - arrowEmpty = "\A3\ui_f\data\gui\cfg\scrollbar\arrowEmpty_ca.paa"; - arrowFull = "\A3\ui_f\data\gui\cfg\scrollbar\arrowFull_ca.paa"; - border = "\A3\ui_f\data\gui\cfg\scrollbar\border_ca.paa"; - thumb = "\A3\ui_f\data\gui\cfg\scrollbar\thumb_ca.paa"; - - color[] = {1,1,1,1}; - }; - - onLBSelChanged = ""; -}; - -class vip_rsc_frame { - type = 0; - idc = -1; - style=ST_FRAME; - shadow=2; - colorBackground[]={0,0,0,0}; - colorText[]={1,1,1,1}; - font="PuristaMedium"; - sizeEx=0.02; - text=""; -}; - -class vip_rsc_map { - moveOnEdges=1; - x="SafeZoneXAbs"; - y="SafeZoneY + 1.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; - w="SafeZoneWAbs"; - h="SafeZoneH - 1.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; - shadow=0; - ptsPerSquareSea=5; - ptsPerSquareTxt=20; - ptsPerSquareCLn=10; - ptsPerSquareExp=10; - ptsPerSquareCost=10; - ptsPerSquareFor=9; - ptsPerSquareForEdge=9; - ptsPerSquareRoad=6; - ptsPerSquareObj=9; - showCountourInterval=0; - scaleMin=0.001; - scaleMax=1; - scaleDefault=0.16; - maxSatelliteAlpha=0.85000002; - alphaFadeStartScale=2; - alphaFadeEndScale=2; - colorBackground[]={0.96899998,0.95700002,0.949,1}; - colorSea[]={0.46700001,0.63099998,0.85100001,0.5}; - colorForest[]={0.62400001,0.77999997,0.38800001,0.5}; - colorForestBorder[]={0,0,0,0}; - colorRocks[]={0,0,0,0.30000001}; - colorRocksBorder[]={0,0,0,0}; - colorLevels[]={0.28600001,0.177,0.093999997,0.5}; - colorMainCountlines[]={0.57200003,0.354,0.18799999,0.5}; - colorCountlines[]={0.57200003,0.354,0.18799999,0.25}; - colorMainCountlinesWater[]={0.491,0.57700002,0.70200002,0.60000002}; - colorCountlinesWater[]={0.491,0.57700002,0.70200002,0.30000001}; - colorPowerLines[]={0.1,0.1,0.1,1}; - colorRailWay[]={0.80000001,0.2,0,1}; - colorNames[]={0.1,0.1,0.1,0.89999998}; - colorInactive[]={1,1,1,0.5}; - colorOutside[]={0,0,0,1}; - colorTracks[]={0.83999997,0.75999999,0.64999998,0.15000001}; - colorTracksFill[]={0.83999997,0.75999999,0.64999998,1}; - colorRoads[]={0.69999999,0.69999999,0.69999999,1}; - colorRoadsFill[]={1,1,1,1}; - colorMainRoads[]={0.89999998,0.5,0.30000001,1}; - colorMainRoadsFill[]={1,0.60000002,0.40000001,1}; - colorGrid[]={0.1,0.1,0.1,0.60000002}; - colorGridMap[]={0.1,0.1,0.1,0.60000002}; - fontLabel="PuristaMedium"; - sizeExLabel="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - fontGrid="TahomaB"; - sizeExGrid=0.02; - fontUnits="TahomaB"; - sizeExUnits="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - fontNames="EtelkaNarrowMediumPro"; - sizeExNames="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8) * 2"; - fontInfo="PuristaMedium"; - sizeExInfo="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - fontLevel="TahomaB"; - sizeExLevel=0.02; - text="#(argb,8,8,3)color(1,1,1,1)"; - class Legend - { - x="SafeZoneX + ( ((safezoneW / safezoneH) min 1.2) / 40)"; - y="SafeZoneY + safezoneH - 4.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; - w="10 * ( ((safezoneW / safezoneH) min 1.2) / 40)"; - h="3.5 * ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; - font="PuristaMedium"; - sizeEx="( ( ( ((safezoneW / safezoneH) min 1.2) / 1.2) / 25) * 0.8)"; - colorBackground[]={1,1,1,0.5}; - color[]={0,0,0,1}; - }; - class Task - { - icon="\A3\ui_f\data\map\mapcontrol\taskIcon_CA.paa"; - iconCreated="\A3\ui_f\data\map\mapcontrol\taskIconCreated_CA.paa"; - iconCanceled="\A3\ui_f\data\map\mapcontrol\taskIconCanceled_CA.paa"; - iconDone="\A3\ui_f\data\map\mapcontrol\taskIconDone_CA.paa"; - iconFailed="\A3\ui_f\data\map\mapcontrol\taskIconFailed_CA.paa"; - color[]= - { - "(profilenamespace getvariable ['IGUI_TEXT_RGB_R',0])", - "(profilenamespace getvariable ['IGUI_TEXT_RGB_G',1])", - "(profilenamespace getvariable ['IGUI_TEXT_RGB_B',1])", - "(profilenamespace getvariable ['IGUI_TEXT_RGB_A',0.8])" - }; - colorCreated[]={1,1,1,1}; - colorCanceled[]={0.69999999,0.69999999,0.69999999,1}; - colorDone[]={0.69999999,1,0.30000001,1}; - colorFailed[]={1,0.30000001,0.2,1}; - size=27; - importance=1; - coefMin=1; - coefMax=1; - }; - class Waypoint - { - icon="\A3\ui_f\data\map\mapcontrol\waypoint_ca.paa"; - color[]={0,0,0,1}; - }; - class WaypointCompleted - { - icon="\A3\ui_f\data\map\mapcontrol\waypointCompleted_ca.paa"; - color[]={0,0,0,1}; - }; - class CustomMark - { - icon="\A3\ui_f\data\map\mapcontrol\custommark_ca.paa"; - size=24; - importance=1; - coefMin=1; - coefMax=1; - color[]={0,0,0,1}; - }; - class Command - { - icon="\A3\ui_f\data\map\mapcontrol\waypoint_ca.paa"; - size=18; - importance=1; - coefMin=1; - coefMax=1; - color[]={1,1,1,1}; - }; - class Bush - { - icon="\A3\ui_f\data\map\mapcontrol\bush_ca.paa"; - color[]={0.44999999,0.63999999,0.33000001,0.40000001}; - size="14/2"; - importance="0.2 * 14 * 0.05 * 0.05"; - coefMin=0.25; - coefMax=4; - }; - class Rock - { - icon="\A3\ui_f\data\map\mapcontrol\rock_ca.paa"; - color[]={0.1,0.1,0.1,0.80000001}; - size=12; - importance="0.5 * 12 * 0.05"; - coefMin=0.25; - coefMax=4; - }; - class SmallTree - { - icon="\A3\ui_f\data\map\mapcontrol\bush_ca.paa"; - color[]={0.44999999,0.63999999,0.33000001,0.40000001}; - size=12; - importance="0.6 * 12 * 0.05"; - coefMin=0.25; - coefMax=4; - }; - class Tree - { - icon="\A3\ui_f\data\map\mapcontrol\bush_ca.paa"; - color[]={0.44999999,0.63999999,0.33000001,0.40000001}; - size=12; - importance="0.9 * 16 * 0.05"; - coefMin=0.25; - coefMax=4; - }; - class busstop - { - icon="\A3\ui_f\data\map\mapcontrol\busstop_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class fuelstation - { - icon="\A3\ui_f\data\map\mapcontrol\fuelstation_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class hospital - { - icon="\A3\ui_f\data\map\mapcontrol\hospital_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class church - { - icon="\A3\ui_f\data\map\mapcontrol\church_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class lighthouse - { - icon="\A3\ui_f\data\map\mapcontrol\lighthouse_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class power - { - icon="\A3\ui_f\data\map\mapcontrol\power_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class powersolar - { - icon="\A3\ui_f\data\map\mapcontrol\powersolar_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class powerwave - { - icon="\A3\ui_f\data\map\mapcontrol\powerwave_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class powerwind - { - icon="\A3\ui_f\data\map\mapcontrol\powerwind_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class quay - { - icon="\A3\ui_f\data\map\mapcontrol\quay_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class transmitter - { - icon="\A3\ui_f\data\map\mapcontrol\transmitter_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class watertower - { - icon="\A3\ui_f\data\map\mapcontrol\watertower_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={1,1,1,1}; - }; - class Cross - { - icon="\A3\ui_f\data\map\mapcontrol\Cross_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={0,0,0,1}; - }; - class Chapel - { - icon="\A3\ui_f\data\map\mapcontrol\Chapel_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={0,0,0,1}; - }; - class Shipwreck - { - icon="\A3\ui_f\data\map\mapcontrol\Shipwreck_CA.paa"; - size=24; - importance=1; - coefMin=0.85000002; - coefMax=1; - color[]={0,0,0,1}; - }; - class Bunker - { - icon="\A3\ui_f\data\map\mapcontrol\bunker_ca.paa"; - size=14; - importance="1.5 * 14 * 0.05"; - coefMin=0.25; - coefMax=4; - color[]={0,0,0,1}; - }; - class Fortress - { - icon="\A3\ui_f\data\map\mapcontrol\bunker_ca.paa"; - size=16; - importance="2 * 16 * 0.05"; - coefMin=0.25; - coefMax=4; - color[]={0,0,0,1}; - }; - class Fountain - { - icon="\A3\ui_f\data\map\mapcontrol\fountain_ca.paa"; - size=11; - importance="1 * 12 * 0.05"; - coefMin=0.25; - coefMax=4; - color[]={0,0,0,1}; - }; - class Ruin - { - icon="\A3\ui_f\data\map\mapcontrol\ruin_ca.paa"; - size=16; - importance="1.2 * 16 * 0.05"; - coefMin=1; - coefMax=4; - color[]={0,0,0,1}; - }; - class Stack - { - icon="\A3\ui_f\data\map\mapcontrol\stack_ca.paa"; - size=20; - importance="2 * 16 * 0.05"; - coefMin=0.89999998; - coefMax=4; - color[]={0,0,0,1}; - }; - class Tourism - { - icon="\A3\ui_f\data\map\mapcontrol\tourism_ca.paa"; - size=16; - importance="1 * 16 * 0.05"; - coefMin=0.69999999; - coefMax=4; - color[]={0,0,0,1}; - }; - class ViewTower - { - icon="\A3\ui_f\data\map\mapcontrol\viewtower_ca.paa"; - size=16; - importance="2.5 * 16 * 0.05"; - coefMin=0.5; - coefMax=4; - color[]={0,0,0,1}; - }; -}; \ No newline at end of file diff --git a/addons/spectator/script_component.hpp b/addons/spectator/script_component.hpp index c445dc4cdd..a726c6c67f 100644 --- a/addons/spectator/script_component.hpp +++ b/addons/spectator/script_component.hpp @@ -9,4 +9,48 @@ #define DEBUG_SETTINGS DEBUG_SETTINGS_SPECTATOR #endif -#include "\z\ace\addons\main\script_macros.hpp" \ No newline at end of file +#include "\z\ace\addons\main\script_macros.hpp" + +// UI grid +#define SIZEX ((safezoneW / safezoneH) min 1.2) +#define SIZEY (SIZEX / 1.2) +#define W_PART(num) (num * (SIZEX / 40)) +#define H_PART(num) (num * (SIZEY / 25)) +#define X_PART(num) (W_PART(num) + (safezoneX + (safezoneW - SIZEX)/2)) +#define Y_PART(num) (H_PART(num) + (safezoneY + (safezoneH - SIZEY)/2)) + +// UI tools +#define TOOL_H H_PART(1) +#define TOOL_W W_PART(5) +#define MARGIN TOOL_W * 0.05 + +// UI compass +#define COMPASS_W (TOOL_W * 4) +#define COMPASS_X (safeZoneX + safeZoneW * 0.5 - COMPASS_W * 0.5) + +// UI IDCs +#define IDC_COMP 4490 +#define IDC_COMP_0 5000 +#define IDC_COMP_90 5090 +#define IDC_COMP_180 5180 +#define IDC_COMP_270 5270 + +#define IDC_HELP 7631 +#define IDC_HELP_LIST 7622 + +#define IDC_MAP 6791 + +#define IDC_TOOL 3000 +#define IDC_TOOL_CLOCK 3003 +#define IDC_TOOL_FOV 3005 +#define IDC_TOOL_NAME 3001 +#define IDC_TOOL_SPEED 3006 +#define IDC_TOOL_VIEW 3002 +#define IDC_TOOL_VISION 3004 + +#define IDC_UNIT 6002 + +// UI colours +#define COL_BACK 0.1,0.1,0.1,0.8 +#define COL_FORE 1,1,1,1 +#define COL_FORE_D 0.1,0.1,0.1,1 diff --git a/addons/spectator/stringtable.xml b/addons/spectator/stringtable.xml index 5cd585108a..8b91608981 100644 --- a/addons/spectator/stringtable.xml +++ b/addons/spectator/stringtable.xml @@ -1,95 +1,197 @@  - - Spectator - Obserwator - Pozorovatel - Espectador + + Spectator Settings - - Enable Spectator - Aktywuj obserwatora - Povolit pozorovatele - Activar espectador + + Configure how the spectator system will operate by default. - - Begin spectating on player death? - Włącz obserwatora po śmierci gracza? - Přepnout do pozorovatele po hráčově smrti? - ¿Comenzar como espectador al morir el jugador? + + Spectate on death - - Player Side Only - Tylko strona gracza - Pouze strana hráče - Sólo bando del jugador + + Enables spectator upon death. - - Only spectate units belonging to player's side? - Pozwól obserwować jednostki będące tylko po stronie gracza? - Pozorovat pouze jednotky patřící k hráčově straně? - ¿Sólo observar unidades que pertenecen al bando del jugador? + + Unit filter - - Spectate AI - Obserwacja AI - Pozorovat AI - Observar IA + + Method of filtering spectatable units. - - Allow spectating of AI units? - Pozwól obserwować jednostki AI? - Umožnit pozorovat AI jednotky? - ¿Permitir observar unidades de la IA? + + No units - - Track Units - Śledź jednostki - Sledovat jednotky - Seguir unidades + + Only players - - Track units' movements throughout mission? - Śledź ruch jednostek w trakcie misji? - Sledovat pohyby jednotek napříč misí? - ¿Seguimiento de movimientos de unidades a lo largo de la misión? + + All units - - Start Position - Pozycja startowa - Počáteční pozice - Posición de inicio + + Side filter - - Use this module as a starting position for spectator camera? - Użyj pozycji modułu jako pozycje startową dla kamery obserwatora? - Použít tento modul jako počáteční pozici pro pozorovací kameru? - ¿Utiliza este módulo como una posición de inicio para la cámara de espectador? + + Method of filtering spectatable sides. - - End Mission - Zakończ misję - Konec mise - Finalizar misión + + Player side - - End mission when all players dead (default BIS behaviour)? - Zakończ misję kiedy wszyscy gracze będą martwi (domyślne zachowanie BIS)? - Ukončit misi když umřou všichni hráči (výchozí BIS chování)? - ¿Finalizar misión cuando todos los jugadores mueran (comportamiento por defecto de BIS)? + + Friendly sides - - View Distance - Zasięg widzenia - Dohlednost - Distancia de visión + + Hostile sides - - OK - OK - OK - Aceptar + + All sides + + + Camera modes + + + Camera modes that can be used. + + + All + + + Free only + + + Internal only + + + External only + + + Internal and external + + + Vision modes + + + Vision modes that can be used. + + + Night vision + + + Thermal imaging + + + Unit icons + + + Render icons above spectatable units. + + + + + Spectator Controls + + + Free + + + Internal + + + External + + + Normal + + + Night + + + Thermal + + + + + Free Camera Controls + + + Camera Forward + + + Camera Backward + + + Camera Left + + + Camera Right + + + Camera Up + + + Camera Down + + + Pan Camera + + + Dolly Camera + + + Lock Camera to Target + + + Zoom In/Out + + + Speed Up/Down + + + Next Vision Mode + + + Previous Vision Mode + + + + Interface Controls + + + Toggle Interface + + + Toggle Unit Icons + + + Toggle Unit List + + + Toggle Toolbar + + + Toggle Compass + + + Toggle Map + + + Toggle Help + + + + Other Controls + + + Next Camera + + + Previous Camera + + + Next Unit + + + Previous Unit - \ No newline at end of file + diff --git a/extras/assets/icons/Icons_Modules.psd b/extras/assets/icons/Icons_Modules.psd index c586b18eef..553449898a 100644 Binary files a/extras/assets/icons/Icons_Modules.psd and b/extras/assets/icons/Icons_Modules.psd differ