diff --git a/addons/laser/XEH_PREP.hpp b/addons/laser/XEH_PREP.hpp index 2d26ff81f25..27e043c63f3 100644 --- a/addons/laser/XEH_PREP.hpp +++ b/addons/laser/XEH_PREP.hpp @@ -17,5 +17,4 @@ PREP(seekerFindLaserSpot); PREP(setLaserCode); PREP(shootCone); PREP(shootRay); -PREP(showVehicleHud); PREP(toggleLST); diff --git a/addons/laser/XEH_postInit.sqf b/addons/laser/XEH_postInit.sqf index 768752bee2e..7b47e75d44b 100644 --- a/addons/laser/XEH_postInit.sqf +++ b/addons/laser/XEH_postInit.sqf @@ -4,29 +4,12 @@ if (hasInterface) then { #include "initKeybinds.inc.sqf" - GVAR(pfID) = -1; - ["CBA_settingsInitialized", { // Handle Map Drawing GVAR(mapLaserSource) = objNull; ["ACE_controlledUAV", LINKFUNC(addMapHandler)] call CBA_fnc_addEventHandler; ["turret", LINKFUNC(addMapHandler), false] call CBA_fnc_addPlayerEventHandler; ["unit", LINKFUNC(addMapHandler), true] call CBA_fnc_addPlayerEventHandler; - - // Laser code display - ["turret", LINKFUNC(showVehicleHud), false] call CBA_fnc_addPlayerEventHandler; - ["vehicle", LINKFUNC(showVehicleHud), true] call CBA_fnc_addPlayerEventHandler; // only one of these needs the retro flag - - // Add UAV Control Compatibility - ["ACE_controlledUAV", { - params ["_UAV", "_seatAI", "_turret", "_position"]; - TRACE_4("ACE_controlledUAV EH",_UAV,_seatAI,_turret,_position); - if (!isNull _seatAI) then { - [_seatAI] call FUNC(showVehicleHud); - } else { - [ace_player] call FUNC(showVehicleHud); - }; - }] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler; }; diff --git a/addons/laser/functions/fnc_showVehicleHud.sqf b/addons/laser/functions/fnc_showVehicleHud.sqf deleted file mode 100644 index 856030bf8cb..00000000000 --- a/addons/laser/functions/fnc_showVehicleHud.sqf +++ /dev/null @@ -1,114 +0,0 @@ -#include "..\script_component.hpp" -/* - * Author: PabstMirror - * Shows the laser hud when vehicle is equiped with the weapon. - * Shows laser code, fire mode and seeker status. - * - * Arguments: - * 0: Player - * - * Return Value: - * Nothing - * - * Example: - * [player] call ace_laser_fnc_showVehicleHud - * - * Public: No - */ - -params ["_player"]; -TRACE_1("showHud",_player); - -private _enabled = false; -private _vehicle = vehicle _player; -private _turretPath = [-1]; - -if ((alive _player) && {_player != _vehicle}) then { - if (_player != (driver _vehicle)) then { - _turretPath = _player call CBA_fnc_turretPath - }; - { - if ((getNumber (configFile >> "CfgWeapons" >> _x >> QGVAR(showHud))) == 1) then { - TRACE_1("showHud",_x); - _enabled = true; - }; - } forEach (_vehicle weaponsTurret _turretPath); -}; - -if ((!_enabled) && (GVAR(pfID) < 0)) exitWith {TRACE_2("Disabled - No Change",_enabled,GVAR(pfID));}; - -TRACE_2("Cleaning up old pfeh and display",_enabled,GVAR(pfID)); -[GVAR(pfID)] call CBA_fnc_removePerFrameHandler; -if (!isNull (uiNamespace getVariable [QGVAR(display), displayNull])) then { - ([QGVAR(modeDisplay)] call BIS_fnc_rscLayer) cutText ["", "PLAIN"]; -}; -GVAR(pfID) = -1; - -if (!_enabled) exitWith {TRACE_2("Disabled - Now Off",_enabled,GVAR(pfID));}; - -TRACE_2("Enabled - Adding PFEH",_enabled,GVAR(pfID)); - -private _adjustDown = false; // Flares display will block ours, if present just move ours down a bit -{ - if ((getText (configFile >> "CfgWeapons" >> _x >> "simulation")) == "cmlauncher") exitWith {_adjustDown = true}; -} forEach (_vehicle weaponsTurret _turretPath); - -private _turretConfig = [_vehicle, _turretPath] call CBA_fnc_getTurret; -private _seekerSource = getText (_turretConfig >> "memoryPointGunnerOptics"); -TRACE_3("",_adjustDown,_seekerSource,_vehicle selectionPosition _seekerSource); - -GVAR(pfID) = [{ - params ["_args", "_pfID"]; - _args params ["_vehicle", "_turretPath", "_seekerSource", "_adjustDown"]; - - // Restart display if null (not just at start, this will happen periodicly) - if (isNull (uiNamespace getVariable [QGVAR(display), displayNull])) then { - TRACE_1("creating display",_this); - ([QGVAR(modeDisplay)] call BIS_fnc_rscLayer) cutRsc [QGVAR(modeDisplay), "PLAIN", 1, false]; - if (_adjustDown) then { - private _ctrl = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl IDC_MODECONTROLGROUP; - private _pos = ctrlPosition _ctrl; - _pos set [1, (_pos select 1) + ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)]; - _ctrl ctrlSetPosition _pos; - _ctrl ctrlCommit 0; - }; - }; - - private _currentWeapon = _vehicle currentWeaponTurret _turretPath; - private _showLockMode = (getNumber (configFile >> "CfgWeapons" >> _currentWeapon >> QGVAR(showHud))) == 1; - - private _ctrlGroup = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl 1000; - - if (!_showLockMode) exitWith { - _ctrlGroup ctrlShow false; - }; - _ctrlGroup ctrlShow true; - - private _ctrlText = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl IDC_ATTACKMODE; - private _ctrlCode = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl IDC_LASERCODE; - private _ctrlIcon = (uiNamespace getVariable [QGVAR(display), displayNull]) displayCtrl IDC_LASERICON; - - // Do Laser Scan: - private _ammo = getText (configFile >> "CfgMagazines" >> _vehicle currentMagazineTurret _turretPath >> "ammo"); - private _laserSource = _vehicle modelToWorldWorld (_vehicle selectionPosition _seekerSource); - private _laserCode = _vehicle getVariable [QGVAR(code), ACE_DEFAULT_LASER_CODE]; - private _seekerAngle = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ace_missileguidance" >> "seekerAngle"); - private _seekerMaxRange = getNumber (configFile >> "CfgAmmo" >> _ammo >> "ace_missileguidance" >> "seekerMaxRange"); - private _laserResult = [_laserSource, vectorDir _vehicle, _seekerAngle, _seekerMaxRange, [ACE_DEFAULT_LASER_WAVELENGTH,ACE_DEFAULT_LASER_WAVELENGTH], _laserCode, _vehicle] call EFUNC(laser,seekerFindLaserSpot); - private _foundTargetPos = _laserResult select 0; - private _haveLock = !isNil "_foundTargetPos"; - - private _defaultAttackProfile = getText (configFile >> "CfgAmmo" >> _ammo >> "ace_missileguidance" >> "defaultAttackProfile"); - private _vehicleLockMode = _vehicle getVariable [QEGVAR(missileguidance,attackProfile), _defaultAttackProfile]; - - _modeShort = if (_haveLock) then { - getText (configFile >> QEGVAR(missileguidance,AttackProfiles) >> _vehicleLockMode >> "nameLocked"); - } else { - getText (configFile >> QEGVAR(missileguidance,AttackProfiles) >> _vehicleLockMode >> "name"); - }; - - _ctrlIcon ctrlSetTextColor ([[0,0,0,0.25],[1,0,0,0.75]] select _haveLock); - _ctrlText ctrlSetText _modeShort; - _ctrlCode ctrlSetText format ["CODE: %1", _laserCode]; - -}, 0.1, [_vehicle, _turretPath, _seekerSource, _adjustDown]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/missile_hud/$PBOPREFIX$ b/addons/missile_hud/$PBOPREFIX$ new file mode 100644 index 00000000000..caccfc6f644 --- /dev/null +++ b/addons/missile_hud/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\missile_hud \ No newline at end of file diff --git a/addons/missile_hud/ACE_GuidanceConfig.hpp b/addons/missile_hud/ACE_GuidanceConfig.hpp new file mode 100644 index 00000000000..5e632bb1f8d --- /dev/null +++ b/addons/missile_hud/ACE_GuidanceConfig.hpp @@ -0,0 +1,5 @@ +class EGVAR(missileguidance,SeekerTypes) { + class SALH { + hudInfo = QFUNC(info_salh); + }; +}; \ No newline at end of file diff --git a/addons/missile_hud/CfgEventHandlers.hpp b/addons/missile_hud/CfgEventHandlers.hpp new file mode 100644 index 00000000000..957d6badcb7 --- /dev/null +++ b/addons/missile_hud/CfgEventHandlers.hpp @@ -0,0 +1,17 @@ +class Extended_PreStart_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); + }; +}; + +class Extended_PreInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_preInit)); + }; +}; + +class Extended_PostInit_EventHandlers { + class ADDON { + init = QUOTE(call COMPILE_SCRIPT(XEH_postInit)); + }; +}; diff --git a/addons/missile_hud/README.md b/addons/missile_hud/README.md new file mode 100644 index 00000000000..e17bd2e0c5a --- /dev/null +++ b/addons/missile_hud/README.md @@ -0,0 +1,4 @@ +ace_missile_hud +=================== + +Displays information about missile to player through their in-game HUD diff --git a/addons/missile_hud/RscTitles.hpp b/addons/missile_hud/RscTitles.hpp new file mode 100644 index 00000000000..3f2492103a0 --- /dev/null +++ b/addons/missile_hud/RscTitles.hpp @@ -0,0 +1,40 @@ +class RscTitles { + class GVAR(infoDisplay) { + idd = -1; + onLoad = QUOTE(with uiNameSpace do { GVAR(display) = _this select 0 };); + movingEnable = 0; + duration = 60; + fadeIn = "false"; + fadeOut = "false"; + class controls {}; + class controlPrefabs { + class line: RscControlsGroupNoScrollbars { + idc = -1; + x = "3.8 * (((safeZoneW / safeZoneH) min 1.2) / 40) + (profilenamespace getvariable ['IGUI_GRID_WEAPON_X',((safeZoneX + safeZoneW) - (10 * (((safeZoneW / safeZoneH) min 1.2) / 40)) - 4.3 * (((safeZoneW / safeZoneH) min 1.2) / 40))])"; + y = "2.5 * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25) + (profilenamespace getVariable ['IGUI_GRID_WEAPON_Y', (safeZoneY + 0.5 * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25))])"; + w = "10 * (((safeZoneW / safeZoneH) min 1.2) / 40)"; + h = "1 * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)"; + }; + class text: RscText { + idc = -1; + colorText[] = {1, 1, 1, 1}; + colorBackground[] = {0, 0, 0, 0}; + x = "0"; + y = "0"; + w = "1 * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)"; + h = "1 * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)"; + sizeEx = "0.8 * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)"; + }; + class icon: RscPictureKeepAspect { + idc = -1; + colorText[] = {1, 1, 1, 1}; + colorBackground[] = {0, 0, 0, 0}; + text = "\a3\Ui_F_Curator\Data\CfgCurator\laser_ca.paa"; + x = "0"; + y = "0"; + w = "(1) * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)"; + h = "(1) * ((((safeZoneW / safeZoneH) min 1.2) / 1.2) / 25)"; + }; + }; + }; +}; diff --git a/addons/missile_hud/XEH_PREP.hpp b/addons/missile_hud/XEH_PREP.hpp new file mode 100644 index 00000000000..2f512a261b8 --- /dev/null +++ b/addons/missile_hud/XEH_PREP.hpp @@ -0,0 +1,8 @@ +PREP(createCtrlFromElement); +PREP(getCurrentWeapon); +PREP(info_salh); +PREP(isElementValid); +PREP(registerDefaultHud); +PREP(registerElement); +PREP(shouldAdjustHud); +PREP(showVehicleHud); diff --git a/addons/missile_hud/XEH_postInit.sqf b/addons/missile_hud/XEH_postInit.sqf new file mode 100644 index 00000000000..5bb0f4b8164 --- /dev/null +++ b/addons/missile_hud/XEH_postInit.sqf @@ -0,0 +1,31 @@ +#include "script_component.hpp" + +if (hasInterface) then { + GVAR(pfID) = -1; + GVAR(generators) = []; + + GVAR(config) = configFile >> "RscTitles" >> QGVAR(infoDisplay) >> "controlPrefabs"; + GVAR(config_line) = GVAR(config) >> "line"; + GVAR(lineHeight) = getNumber (GVAR(config_line) >> "h"); + GVAR(lineWidth) = getNumber (GVAR(config_line) >> "w"); + GVAR(itemWidth) = getNumber (GVAR(config) >> "icon" >> "w") / 1.25; + + ["CBA_settingsInitialized", { + ["turret", LINKFUNC(showVehicleHud), false] call CBA_fnc_addPlayerEventHandler; + ["vehicle", LINKFUNC(showVehicleHud), true] call CBA_fnc_addPlayerEventHandler; // only one of these needs the retro flag + + // Add UAV Control Compatibility + ["ACE_controlledUAV", { + params ["_UAV", "_seatAI", "_turret", "_position"]; + TRACE_4("ACE_controlledUAV EH",_UAV,_seatAI,_turret,_position); + if (!isNull _seatAI) then { + [_seatAI] call FUNC(showVehicleHud); + } else { + [ace_player] call FUNC(showVehicleHud); + }; + }] call CBA_fnc_addEventHandler; + + [] call FUNC(registerDefaultHud); + }] call CBA_fnc_addEventHandler; +}; + diff --git a/addons/missile_hud/XEH_preInit.sqf b/addons/missile_hud/XEH_preInit.sqf new file mode 100644 index 00000000000..b47cf6628db --- /dev/null +++ b/addons/missile_hud/XEH_preInit.sqf @@ -0,0 +1,9 @@ +#include "script_component.hpp" + +ADDON = false; + +PREP_RECOMPILE_START; +#include "XEH_PREP.hpp" +PREP_RECOMPILE_END; + +ADDON = true; diff --git a/addons/missile_hud/XEH_preStart.sqf b/addons/missile_hud/XEH_preStart.sqf new file mode 100644 index 00000000000..022888575ed --- /dev/null +++ b/addons/missile_hud/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/missile_hud/config.cpp b/addons/missile_hud/config.cpp new file mode 100644 index 00000000000..473766d70cd --- /dev/null +++ b/addons/missile_hud/config.cpp @@ -0,0 +1,24 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_common", "ace_missileguidance"}; + author = ECSTRING(common,ACETeam); + authors[] = {"tcvm"}; + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "CfgEventHandlers.hpp" +#include "ACE_GuidanceConfig.hpp" + +class RscText; +class RscControlsGroupNoScrollbars; +class RscPictureKeepAspect; + +#include "RscTitles.hpp" \ No newline at end of file diff --git a/addons/missile_hud/functions/fnc_createCtrlFromElement.sqf b/addons/missile_hud/functions/fnc_createCtrlFromElement.sqf new file mode 100644 index 00000000000..b398cf2ddb2 --- /dev/null +++ b/addons/missile_hud/functions/fnc_createCtrlFromElement.sqf @@ -0,0 +1,49 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Create a UI control to be added to the display. + * + * Arguments: + * 0: Display + * 1: Line + * 2: Element + * + * Return Value: + * Control + * + * Example: + * [findDisplay 46, ["TEXT", "Hello, world!", [1, 1, 0]]] call ace_missile_hud_fnc_createCtrlFromElement + * + * Public: No + */ + +params ["_display", "_line", "_element"]; +TRACE_1("createCtrlFromElement",_this); + +private _ctrl = controlNull; +switch (_element select 0) do { + case "TEXT": { + _element params ["", "_text", "_color"]; + private _controlConfig = GVAR(config) >> "text"; + _ctrl = _display ctrlCreate [_controlConfig, -1, _line]; + _ctrl ctrlSetText _text; + if (3 == count _color) then { _color pushBack 1; }; + _ctrl ctrlSetTextColor _color; + }; + case "ICON": { + _element params ["", "_path", "_color"]; + private _controlConfig = GVAR(config) >> "icon"; + _ctrl = _display ctrlCreate [_controlConfig, -1, _line]; + _ctrl ctrlSetText _path; + if (3 == count _color) then { _color pushBack 1; }; + _ctrl ctrlSetTextColor _color; + }; + case "SPACER": { + private _controlConfig = GVAR(config) >> "icon"; + _ctrl = _display ctrlCreate [_controlConfig, -1, _line]; + _ctrl ctrlSetText "\A3\ui_f\data\map\markers\system\empty_ca.paa"; + _ctrl ctrlSetTextColor [0, 0, 0, 0]; + }; +}; + +_ctrl \ No newline at end of file diff --git a/addons/missile_hud/functions/fnc_getCurrentWeapon.sqf b/addons/missile_hud/functions/fnc_getCurrentWeapon.sqf new file mode 100644 index 00000000000..64984507af2 --- /dev/null +++ b/addons/missile_hud/functions/fnc_getCurrentWeapon.sqf @@ -0,0 +1,29 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Get the current weapon of the unit. + * + * Arguments: + * 0: Unit + * 1: Vehicle + * 2: Turret path + * + * Return Value: + * Current weapon + * + * Example: + * [player, vehicle player, [0]] call ace_missile_hud_fnc_getCurrentWeapon + * + * Public: No + */ + +params ["_unit", "_vehicle", "_turretPath"]; +TRACE_2("registerElement",_condition,_generator); + +private _currentWeapon = if (_unit isEqualTo _vehicle) then { + currentWeapon _unit +} else { + _vehicle currentWeaponTurret _turretPath +}; + +_currentWeapon \ No newline at end of file diff --git a/addons/missile_hud/functions/fnc_info_salh.sqf b/addons/missile_hud/functions/fnc_info_salh.sqf new file mode 100644 index 00000000000..dda08969e78 --- /dev/null +++ b/addons/missile_hud/functions/fnc_info_salh.sqf @@ -0,0 +1,55 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Generates HUD info for SALH seeker. + * + * Arguments: + * 0: Idle display Text + * 1: Locked display text + * 2: Unit + * 3: Vehicle + * 4: Ammo Config + * + * Return Value: + * Element array + * + * Example: + * [["TEXT", "My Test", [1, 0.4, 5]]] call ace_missile_hud_fnc_info_salh + * + * Public: No + */ + +params ["_idleText", "_lockedText", "_unit", "_vehicle", "_ammoConfig"]; + +private _turretPath = _unit call CBA_fnc_turretPath; +private _turretConfig = [_vehicle, _turretPath] call CBA_fnc_getTurret; +private _laserSource = _vehicle modelToWorldWorld (_vehicle selectionPosition getText (_turretConfig >> "memoryPointGunnerOptics")); +private _laserCode = _vehicle getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE]; +private _seekerAngle = getNumber (_ammoConfig >> "seekerAngle"); +private _seekerMaxRange = getNumber (_ammoConfig >> "seekerMaxRange"); + +private _laserResult = [_laserSource, vectorDir _vehicle, _seekerAngle, _seekerMaxRange, [ACE_DEFAULT_LASER_WAVELENGTH,ACE_DEFAULT_LASER_WAVELENGTH], _laserCode, _vehicle] call EFUNC(laser,seekerFindLaserSpot); +private _foundTargetPos = _laserResult select 0; +private _haveLock = !isNil "_foundTargetPos"; + +private _displayText = [_idleText, _lockedText] select (_haveLock && _lockedText != ""); +private _laserColor = [[1, 0, 0, 0.25], [1, 0, 0, 0.75]] select _haveLock; + +if (_displayText == "") then { + [ + ["SPACER", "", []], + ["SPACER", "", []], + ["SPACER", "", []], + ["SPACER", "", []], + ["TEXT", format ["CODE: %1", _laserCode], [1, 1, 1]], + ["ICON", "\a3\Ui_F_Curator\Data\CfgCurator\laser_ca.paa", _laserColor] + ] +} else { + [ + ["TEXT", _displayText, [1, 1, 1]], + ["SPACER", "", []], + ["TEXT", format ["CODE: %1", _laserCode], [1, 1, 1]], + ["ICON", "\a3\Ui_F_Curator\Data\CfgCurator\laser_ca.paa", _laserColor] + ] +} + diff --git a/addons/missile_hud/functions/fnc_isElementValid.sqf b/addons/missile_hud/functions/fnc_isElementValid.sqf new file mode 100644 index 00000000000..e51263c639e --- /dev/null +++ b/addons/missile_hud/functions/fnc_isElementValid.sqf @@ -0,0 +1,33 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Returns if an element array is valid. + * + * Arguments: + * 0: Element array + * + * Return Value: + * If array is valid format + * + * Example: + * [["TEXT", "My Test", [1, 0.4, 5]]] call ace_missile_hud_fnc_isElementValid + * + * Public: Yes + */ + +params ["_elementArray"]; +TRACE_1("isElementValid",_elementArray); + +if !(_elementArray isEqualTypeArray ["", "", []]) exitWith { TRACE_1("Invalid - Types not equal",_elementArray); false }; +_elementArray params ["_type", "_str", "_color"]; +if !(_type in ["TEXT", "ICON", "SPACER"]) exitWith { TRACE_1("Invalid - Element Type not supported",_type); false }; +private _success = if (_type != "SPACER") then { + if !((_color isEqualTypeArray [0, 0, 0]) || (_color isEqualTypeArray [0, 0, 0, 0])) exitWith { TRACE_1("Invalid - Color not number",_color); false }; + if (-1 != _color findIf { _x > 1 || _x < 0 }) exitWith { TRACE_1("Invalid - Color not in range [0, 1]",_color); false }; + true +}; +if !(_success) exitWith { false }; + +TRACE_3("Valid - All checks pass",_type,_str,_color); + +true diff --git a/addons/missile_hud/functions/fnc_registerDefaultHud.sqf b/addons/missile_hud/functions/fnc_registerDefaultHud.sqf new file mode 100644 index 00000000000..23abb129ec7 --- /dev/null +++ b/addons/missile_hud/functions/fnc_registerDefaultHud.sqf @@ -0,0 +1,94 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Register default HUD for most missiles. + * + * Arguments: + * Nothing + * + * Return Value: + * Nothing + * + * Example: + * [] call ace_missile_hud_fnc_registerDefaultHud + * + * Public: No + */ + +[{ + params ["_unit", "_vehicle", "_weapon"]; + private _turretPath = _unit call CBA_fnc_turretPath; + if (_unit == driver _vehicle) then { + _turretPath = [-1]; + }; + private _pylons = (getAllPylonsInfo _vehicle) select { (_x select 2) isEqualTo _turretPath }; + private _hasAttackMode = false; + scopeName "cond"; + { + _x params ["", "", "", "_magazine"]; + private _ammo = getText (configFile >> "CfgMagazines" >> _magazine >> "ammo"); + private _ammoConfig = configFile >> "CfgAmmo" >> _ammo >> "ace_missileguidance"; + private _attackProfiles = getArray (_ammoConfig >> "attackProfiles"); + private _seeker = getText (_ammoConfig >> "defaultSeekerType"); + private _hudFnc = getText (configFile >> QEGVAR(missileguidance,SeekerTypes) >> _seeker >> "hudInfo"); + if (_hudFnc != "") exitWith { _hasAttackMode = true; }; + + { + private _config = configFile >> QEGVAR(missileguidance,AttackProfiles) >> _x; + if (getText (_config >> "name") != "" || getText (_config >> "lockedName") != "" || _hudFnc != "") exitWith { + _hasAttackMode = true; + breakTo "cond"; + } + } forEach _attackProfiles; + } forEach _pylons; + _hasAttackMode +}, { + params ["_unit", "_vehicle", "_weapon"]; + private _magazineDetails = createHashMap; + + private _turretPath = _unit call CBA_fnc_turretPath; + if (_unit == driver _vehicle) then { + _turretPath = [-1]; + }; + private _pylons = (getAllPylonsInfo _vehicle) select { (_x select 2) isEqualTo _turretPath }; + { + _x params ["", "", "", "_magazine"]; + private _ammo = getText (configFile >> "CfgMagazines" >> _magazine >> "ammo"); + private _ammoConfig = configFile >> "CfgAmmo" >> _ammo >> "ace_missileguidance"; + private _defaultAttackProfile = getText (_ammoConfig >> "defaultAttackProfile"); + private _attackProfiles = getArray (_ammoConfig >> "attackProfiles"); + private _seeker = getText (_ammoConfig >> "defaultSeekerType"); + private _hudFnc = getText (configFile >> QEGVAR(missileguidance,SeekerTypes) >> _seeker >> "hudInfo"); + private _modes = createHashMap; + { + private _config = configFile >> QEGVAR(missileguidance,AttackProfiles) >> _x; + _modes set [_x, [getText (_config >> "name"), getText (_config >> "lockedName")]]; + } forEach _attackProfiles; + + _magazineDetails set [_magazine, [_modes, _defaultAttackProfile, _hudFnc, _ammoConfig]]; + } forEach _pylons; + + [_magazineDetails] +}, { + params ["_unit", "_vehicle", "_weapon", "_params"]; + _params params ["_magazineDetails"]; + private _turretPath = _unit call CBA_fnc_turretPath; + if (_unit == driver _vehicle) then { + _turretPath = [-1]; + }; + private _magazine = _vehicle currentMagazineTurret _turretPath; + if !(_magazine in _magazineDetails) exitWith { [] }; + (_magazineDetails get _magazine) params ["_modes", "_defaultAttackProfile", "_hudFnc", "_ammoConfig"]; + + private _mode = _vehicle getVariable [QEGVAR(missileguidance,attackProfile), _defaultAttackProfile]; + (_modes getOrDefault [_mode, ["", ""]]) params ["_idleDisplay", "_lockedDisplay"]; + if (_idleDisplay == "" && _hudFnc == "") exitWith { [] }; + + private _hud = []; + if (_hudFnc != "") then { + _hud = [_idleDisplay, _lockedDisplay, _unit, _vehicle, _ammoConfig] call (missionNamespace getVariable [_hudFnc, { [] }]); + } else { + _hud = ["TEXT", _idleDisplay, [1, 1, 1]]; + }; + _hud +}] call FUNC(registerElement); \ No newline at end of file diff --git a/addons/missile_hud/functions/fnc_registerElement.sqf b/addons/missile_hud/functions/fnc_registerElement.sqf new file mode 100644 index 00000000000..091a30e5c5e --- /dev/null +++ b/addons/missile_hud/functions/fnc_registerElement.sqf @@ -0,0 +1,31 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Register an element which will be drawn when the HUD is displayed. + * + * Setup and condition function are called every time the HUD appears + * Arguments to condition and setup function are `[player, vehicle, weapon]` + * Arguments to generator function are `[player, vehicle, weapon, additional]` where `additional` is whatever was returned from the setup function + * Generator function creates elements of type ["TEXT", "My Text", [r, g, b]] or ["ICON", "/path/to/icon", [r, g, b]] + * Generator function returns array of elements which will be grouped on the same line. If the line overflows, the line will break to fit. + * + * Arguments: + * 0: Setup Condition + * 1: Setup Function + * 2: Generator function + * + * Return Value: + * None + * + * Example: + * [{ params ["_unit", "_vehicle"]; _unit == gunner _vehicle }, { [_this, 123] }, { params ["_vars", "_myVar"]; ["TEXT", format ["Hello, world! %1", _myVar], [1, 0, 0]] }] call ace_missile_hud_fnc_registerElement + * + * Public: Yes + */ + +params ["_condition", "_setup", "_generator"]; +TRACE_2("registerElement",_condition,_generator); + +GVAR(generators) pushBack [_condition, _setup, _generator]; +[ACE_PLAYER] call FUNC(showVehicleHud); + diff --git a/addons/missile_hud/functions/fnc_shouldAdjustHud.sqf b/addons/missile_hud/functions/fnc_shouldAdjustHud.sqf new file mode 100644 index 00000000000..119437fc83f --- /dev/null +++ b/addons/missile_hud/functions/fnc_shouldAdjustHud.sqf @@ -0,0 +1,27 @@ +#include "..\script_component.hpp" +/* + * Author: tcvm + * Whether or not we should adjust the HUD element down. + * + * Arguments: + * 0: Player + * 1: Vehicle + * 2: Turret Path (Optional) + * + * Return Value: + * Whether or not to adjust hud + * + * Example: + * [player, player, [0]] call ace_missile_hud_fnc_shouldAdjustHud + * + * Public: No + */ +params ["_player", "_vehicle", ["_turretPath", [-1]]]; + +private _adjustDown = false; +// Flares display will block ours, if present just move ours down a bit +{ + if ((getText (configFile >> "CfgWeapons" >> _x >> "simulation")) == "cmlauncher") exitWith {_adjustDown = true}; +} forEach (_vehicle weaponsTurret _turretPath); + +_adjustDown \ No newline at end of file diff --git a/addons/missile_hud/functions/fnc_showVehicleHud.sqf b/addons/missile_hud/functions/fnc_showVehicleHud.sqf new file mode 100644 index 00000000000..1468924d691 --- /dev/null +++ b/addons/missile_hud/functions/fnc_showVehicleHud.sqf @@ -0,0 +1,148 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror, tcvm + * Shows the missile info hud when data is available to be shown. + * + * Arguments: + * 0: Player + * + * Return Value: + * Nothing + * + * Example: + * [player] call ace_missile_hud_fnc_showVehicleHud + * + * Public: No + */ + +params ["_player"]; +TRACE_1("showHud",_player); + +if !(alive _player) exitWith {TRACE_1("Disabled - Not Alive",_player);}; + +private _vehicle = vehicle _player; +private _turretPath = [-1]; +if (_player != driver _vehicle) then { + _turretPath = _player call CBA_fnc_turretPath; +}; +private _weapon = [_player, _vehicle, _turretPath] call FUNC(getCurrentWeapon); +private _enabled = -1 != GVAR(generators) findIf { [_player, _vehicle, _weapon] call (_x select 0) }; + +if ((!_enabled) && (GVAR(pfID) < 0)) exitWith {TRACE_2("Disabled - No Change",_enabled,GVAR(pfID));}; + +TRACE_2("Cleaning up old pfeh and display",_enabled,GVAR(pfID)); +[GVAR(pfID)] call CBA_fnc_removePerFrameHandler; +if (!isNull (uiNamespace getVariable [QGVAR(display), displayNull])) then { + ([QGVAR(infoDisplay)] call BIS_fnc_rscLayer) cutText ["", "PLAIN"]; +}; +GVAR(pfID) = -1; + +if (!_enabled) exitWith {TRACE_2("Disabled - Now Off",_enabled,GVAR(pfID));}; + +TRACE_2("Enabled - Adding PFEH",_enabled,GVAR(pfID)); + +private _adjustDown = [_player, _vehicle, _turretPath] call FUNC(shouldAdjustHud); + +TRACE_4("",_adjustDown,_player,_vehicle,_turretPath); + +private _generators = GVAR(generators) select { [_player, _vehicle] call (_x select 0) }; +_generators = _generators apply { + _x params ["", "_setup", "_generator"]; + [_generator, [_player, _vehicle] call _setup] +}; + +TRACE_2("Running - Some generators are valid",count _generators,count GVAR(generators)); + +private _linePosition = [ + getNumber (GVAR(config_line) >> "x"), + getNumber (GVAR(config_line) >> "y") + GVAR(lineHeight) +]; + +GVAR(pfID) = [{ + params ["_args", "_pfID"]; + _args params ["_generators", "_adjustDown", "_player", "_vehicle", "_weapon", "_basePosition"]; + + // Restart display if null (not just at start, this will happen periodicly) + if (isNull (uiNamespace getVariable [QGVAR(display), displayNull])) then { + TRACE_1("creating display",_this); + ([QGVAR(infoDisplay)] call BIS_fnc_rscLayer) cutRsc [QGVAR(infoDisplay), "PLAIN", 1, false]; + if (_adjustDown) then { + _basePosition set [1, (_basePosition select 1) + GVAR(lineHeight)]; + _args set [5, _basePosition]; + }; + }; + private _display = uiNamespace getVariable [QGVAR(display), displayNull]; + if (isNull _display) exitWith { + TRACE_1("Aborting - Display is null, somehow?",_display); + [_pfID] call CBA_fnc_removePerFrameHandler; + }; + private _lines = _display getVariable [QGVAR(lines), []]; + { + ctrlDelete _x; + } forEach _lines; + + private _elements = []; + { + _x params ["_generator", "_params"]; + private _group = [_player, _vehicle, _weapon, _params] call _generator; + + if (isNil "_group") then { TRACE_1("Skipping - generator returned null group",_generator); continue; }; + if !(_group isEqualType []) then { TRACE_1("Skipping - generator did not return array",_group); continue; }; + if (_group isEqualTo []) then { TRACE_1("Skipping - generator did not return any elements",_group); continue; }; + if ((_group select 0) isEqualType "") then { + if !([_group] call FUNC(isElementValid)) then { TRACE_1("Skipping - Some element is not valid",_group); continue; }; + _elements pushBack [_group]; + } else { + if (-1 != _group findIf { !([_x] call FUNC(isElementValid)) }) then { TRACE_1("Skipping - Some element is not valid",_group); continue; }; + _elements pushBack _group; + }; + } forEach _generators; + + _lines = []; + private _linePosition = +_basePosition; + { + // Create new line + private _line = _display ctrlCreate [GVAR(config_line), -1]; + _line ctrlShow true; + _line ctrlSetPosition _linePosition; + _line ctrlCommit 0; + + private _drawPosition = [0, 0]; + private _nonOverflowIndex = 0; + { + private _control = [_display, _line, _x] call FUNC(createCtrlFromElement); + private _width = ctrlTextWidth _control; + _width = ceil (_width / GVAR(itemWidth)) * GVAR(itemWidth); + + // If we overflow, create a new line for next element + // If we are the first element being added, add us to the row. Otherwise, dont + if (_forEachIndex != _nonOverflowIndex && (_drawPosition select 0) + _width > GVAR(lineWidth)) then { + ctrlDelete _control; + + _linePosition = _linePosition vectorAdd [0, GVAR(lineHeight)]; + _lines pushBack _line; + + _line = _display ctrlCreate [GVAR(config_line), -1]; + _line ctrlShow true; + _line ctrlSetPosition _linePosition; + _line ctrlCommit 0; + + _control = [_display, _line, _x] call FUNC(createCtrlFromElement); + _width = ctrlTextWidth _control; + _nonOverflowIndex = _forEachIndex + 1; + + _drawPosition = [0, 0]; + }; + _control ctrlSetPosition _drawPosition; + _control ctrlSetPositionW _width; + _control ctrlShow true; + _control ctrlCommit 0; + _drawPosition = _drawPosition vectorAdd [_width, 0]; + } forEach _x; + _lines pushBack _line; + + _linePosition = _linePosition vectorAdd [0, GVAR(lineHeight)]; + } forEach _elements; + + _display setVariable [QGVAR(lines), _lines]; +}, (HUD_UPDATE_RATE), [_generators, _adjustDown, _player, _vehicle, _weapon, _linePosition]] call CBA_fnc_addPerFrameHandler; diff --git a/addons/missile_hud/script_component.hpp b/addons/missile_hud/script_component.hpp new file mode 100644 index 00000000000..8c5792931e1 --- /dev/null +++ b/addons/missile_hud/script_component.hpp @@ -0,0 +1,20 @@ +#define COMPONENT missile_hud +#define COMPONENT_BEAUTIFIED Missile HUD +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_PERFORMANCE_COUNTERS + +#ifdef DEBUG_ENABLED_MISSILE_HUD + #define DEBUG_MODE_FULL +#endif + +#ifdef DEBUG_SETTINGS_MISSILE_HUD + #define DEBUG_SETTINGS DEBUG_SETTINGS_MISSILE_HUD +#endif + +#include "\z\ace\addons\main\script_macros.hpp" +#include "\a3\ui_f\hpp\defineResincl.inc" + +#define HUD_UPDATE_RATE 0.1 \ No newline at end of file