From 91c8c89e87d9ef08efb30d1faf98b6fa542e5a72 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Tue, 14 Apr 2015 20:47:07 -0500 Subject: [PATCH 1/6] Only sync A3 VON status over network --- .../nametags/functions/fnc_initIsSpeaking.sqf | 49 ++++++++----------- 1 file changed, 21 insertions(+), 28 deletions(-) diff --git a/addons/nametags/functions/fnc_initIsSpeaking.sqf b/addons/nametags/functions/fnc_initIsSpeaking.sqf index 56c5cfc2f1..95403e0894 100644 --- a/addons/nametags/functions/fnc_initIsSpeaking.sqf +++ b/addons/nametags/functions/fnc_initIsSpeaking.sqf @@ -20,8 +20,8 @@ if (isServer) then { //If someone disconnects while speaking, reset their variable addMissionEventHandler ["HandleDisconnect", { PARAMS_1(_disconnectedPlayer); - if (_disconnectedPlayer getVariable [QGVAR(isSpeaking), false]) then { - _disconnectedPlayer setVariable [QGVAR(isSpeaking), false, true]; + if (_disconnectedPlayer getVariable [QGVAR(isSpeakingInGame), false]) then { + _disconnectedPlayer setVariable [QGVAR(isSpeakingInGame), false, true]; }; }]; }; @@ -31,46 +31,39 @@ if (!hasInterface) exitWith {}; ["playerChanged", { //When player changes, make sure to reset old unit's variable PARAMS_2(_newUnit,_oldUnit); - if (_oldUnit getVariable [QGVAR(isSpeaking), false]) then { - _oldUnit setVariable [QGVAR(isSpeaking), false, true]; + if ((!isNull _oldUnit) && {_oldUnit getVariable [QGVAR(isSpeakingInGame), false]}) then { + _oldUnit setVariable [QGVAR(isSpeakingInGame), false, true]; }; }] call EFUNC(common,addEventHandler); +//PFEH to watch the internal VON icon +//Note: class RscDisplayVoiceChat {idd = 55}; //only present when talking +[{ + _oldSetting = ACE_player getVariable [QGVAR(isSpeakingInGame), false]; + _newSetting = (!(isNull findDisplay 55)); + if (!(_oldSetting isEqualTo _newSetting)) then { + ACE_player setVariable [QGVAR(isSpeakingInGame), _newSetting, true]; + }; +} , 0.1, []] call CBA_fnc_addPerFrameHandler; -//For performance, chose different code paths at mission start based on installed mods (once, instead of checking each time) -_pfEHCode = switch (true) do { + +DFUNC(isSpeaking) = switch (true) do { case (isClass (configFile >> "cfgPatches" >> "acre_api")): { { - _oldSetting = ACE_player getVariable [QGVAR(isSpeaking), false]; - _newSetting = ([ACE_player] call acre_api_fnc_isSpeaking) || ([ACE_player] call acre_api_fnc_isBroadcasting) || {!(isNull findDisplay 55)}; - if (!(_oldSetting isEqualTo _newSetting)) then { - ACE_player setVariable [QGVAR(isSpeaking), _newSetting, true]; - }; + PARAMS_1(_unit); + (_unit getVariable [QGVAR(isSpeakingInGame), false]) || ([_unit] call acre_api_fnc_isSpeaking) || ([ACE_player] call acre_api_fnc_isBroadcasting) }; }; case (isClass (configFile >> "cfgPatches" >> "task_force_radio")): { - //Note: TFAR has a TFAR_fnc_isSpeaking function, but it has a fairly costly `callExtension` - //I think it's much faster to use the internal "tf_isSpeaking" variable - //If we don't care about the built-in VON, we could switch this to a pure event driven system { - _oldSetting = ACE_player getVariable [QGVAR(isSpeaking), false]; - _newSetting = (ACE_player getVariable ["tf_isSpeaking", false]) || {!(isNull findDisplay 55)}; - if (!(_oldSetting isEqualTo _newSetting)) then { - ACE_player setVariable [QGVAR(isSpeaking), _newSetting, true]; - }; + PARAMS_1(_unit); + (_unit getVariable [QGVAR(isSpeakingInGame), false]) || (_unit getVariable ["tf_isSpeaking", false]) }; }; default { - //Note: class RscDisplayVoiceChat {idd = 55}; //only present when talking { - _oldSetting = ACE_player getVariable [QGVAR(isSpeaking), false]; - _newSetting = (!(isNull findDisplay 55)); - if (!(_oldSetting isEqualTo _newSetting)) then { - ACE_player setVariable [QGVAR(isSpeaking), _newSetting, true]; - }; + PARAMS_1(_unit); + (_unit getVariable [QGVAR(isSpeakingInGame), false]) }; }; }; - -//Is 0.05sec precision enough?? -[_pfEHCode, 0.05, []] call CBA_fnc_addPerFrameHandler; From 00b9e2d72ca7584268b78636d49a842ab39ebab5 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Tue, 14 Apr 2015 20:49:44 -0500 Subject: [PATCH 2/6] draw3d --- addons/nametags/XEH_postInit.sqf | 1 + addons/nametags/XEH_preInit.sqf | 2 -- addons/nametags/functions/fnc_onDraw3d.sqf | 10 +++++----- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/addons/nametags/XEH_postInit.sqf b/addons/nametags/XEH_postInit.sqf index ab3cd03391..1df20e45e7 100644 --- a/addons/nametags/XEH_postInit.sqf +++ b/addons/nametags/XEH_postInit.sqf @@ -5,6 +5,7 @@ if (!hasInterface) exitWith {}; +GVAR(ShowNamesTime) = -10; // Add keybinds ["ACE3", QGVAR(showNameTags), localize "STR_ACE_NameTags_ShowNames", diff --git a/addons/nametags/XEH_preInit.sqf b/addons/nametags/XEH_preInit.sqf index 80c06cff1f..9fae94fd08 100644 --- a/addons/nametags/XEH_preInit.sqf +++ b/addons/nametags/XEH_preInit.sqf @@ -12,6 +12,4 @@ PREP(onDraw3d); PREP(onMouseZChanged); PREP(setText); -GVAR(ShowNamesTime) = -10; - ADDON = true; diff --git a/addons/nametags/functions/fnc_onDraw3d.sqf b/addons/nametags/functions/fnc_onDraw3d.sqf index 8aa503d377..d35cef0d67 100644 --- a/addons/nametags/functions/fnc_onDraw3d.sqf +++ b/addons/nametags/functions/fnc_onDraw3d.sqf @@ -50,9 +50,9 @@ if ((GVAR(showPlayerNames) in [2,4]) && {_onKeyPressAlphaMax > 0}) then { _alpha = _alpha min _onKeyPressAlphaMax; _icon = ICON_NONE; if (GVAR(showSoundWaves) == 2) then { //icon will be drawn below, so only show name here - _icon = if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target}) then {ICON_NAME} else {_defaultIcon}; + _icon = if (([_target] call FUNC(isSpeaking)) && {(vehicle _target) == _target}) then {ICON_NAME} else {_defaultIcon}; } else { - _icon = if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target} && {GVAR(showSoundWaves) > 0}) then {ICON_NAME_SPEAK} else {_defaultIcon}; + _icon = if (([_target] call FUNC(isSpeaking)) && {(vehicle _target) == _target} && {GVAR(showSoundWaves) > 0}) then {ICON_NAME_SPEAK} else {_defaultIcon}; }; [_player, _target, _alpha, _distance * 0.026, _icon] call FUNC(drawNameTagIcon); @@ -77,10 +77,10 @@ if (((GVAR(showPlayerNames) in [1,3]) && {_onKeyPressAlphaMax > 0}) || {GVAR(sho _icon = ICON_NONE; if ((GVAR(showPlayerNames) in [1,3]) && {_onKeyPressAlphaMax > 0}) then { - if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target} && {GVAR(showSoundWaves) > 0}) then {_icon = ICON_NAME_SPEAK;} else {_icon = _defaultIcon}; + if (([_target] call FUNC(isSpeaking)) && {(vehicle _target) == _target} && {GVAR(showSoundWaves) > 0}) then {_icon = ICON_NAME_SPEAK;} else {_icon = _defaultIcon}; } else { //showSoundWaves must be 2, only draw speak icon - if ((_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target}) then {_icon = ICON_SPEAK;}; + if (([_target] call FUNC(isSpeaking)) && {(vehicle _target) == _target}) then {_icon = ICON_SPEAK;}; }; if ((_icon != ICON_NONE) && @@ -96,7 +96,7 @@ if (((GVAR(showPlayerNames) in [1,3]) && {_onKeyPressAlphaMax > 0}) || {GVAR(sho _alpha = ((1 - 0.2 * (_distance - GVAR(PlayerNamesViewDistance))) min (1 - 0.15 * (_projDist * 5 - _distance - 3)) min 1) * GVAR(PlayerNamesMaxAlpha); - if ((GVAR(showSoundWaves) == 2) && {(_target getVariable [QGVAR(isSpeaking), false]) && {(vehicle _target) == _target}}) then { + if ((GVAR(showSoundWaves) == 2) && {([_target] call FUNC(isSpeaking)) && {(vehicle _target) == _target}}) then { _alpha = 1; } else { _alpha = _alpha min _onKeyPressAlphaMax; From 1f51a3fc8ac5fd27275621244c300dd997d318b5 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Tue, 14 Apr 2015 23:10:05 -0500 Subject: [PATCH 3/6] Never use this func anywhere --- addons/nametags/XEH_preInit.sqf | 1 - .../nametags/functions/fnc_onMouseZChanged.sqf | 18 ------------------ 2 files changed, 19 deletions(-) delete mode 100644 addons/nametags/functions/fnc_onMouseZChanged.sqf diff --git a/addons/nametags/XEH_preInit.sqf b/addons/nametags/XEH_preInit.sqf index 9fae94fd08..f3c9a97cba 100644 --- a/addons/nametags/XEH_preInit.sqf +++ b/addons/nametags/XEH_preInit.sqf @@ -9,7 +9,6 @@ PREP(getVehicleData); PREP(initIsSpeaking); PREP(moduleNameTags); PREP(onDraw3d); -PREP(onMouseZChanged); PREP(setText); ADDON = true; diff --git a/addons/nametags/functions/fnc_onMouseZChanged.sqf b/addons/nametags/functions/fnc_onMouseZChanged.sqf deleted file mode 100644 index 8892f201bc..0000000000 --- a/addons/nametags/functions/fnc_onMouseZChanged.sqf +++ /dev/null @@ -1,18 +0,0 @@ -/* - Author: aeroson - - Description: - Callback for mouse wheel change - - Parameters: - None - - Returns: - Nothing -*/ - -#include "script_component.hpp" - -if(call FUNC(canShow)) then { - call FUNC(doShow); -}; From 6ea38a9946a8fd2201989a4ffb568177e7b55e78 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Wed, 15 Apr 2015 11:34:27 -0500 Subject: [PATCH 4/6] Only check A3 VON if no radio mods running --- .../nametags/functions/fnc_initIsSpeaking.sqf | 49 ++++++++++--------- 1 file changed, 25 insertions(+), 24 deletions(-) diff --git a/addons/nametags/functions/fnc_initIsSpeaking.sqf b/addons/nametags/functions/fnc_initIsSpeaking.sqf index 95403e0894..d8ffda756c 100644 --- a/addons/nametags/functions/fnc_initIsSpeaking.sqf +++ b/addons/nametags/functions/fnc_initIsSpeaking.sqf @@ -36,32 +36,33 @@ if (!hasInterface) exitWith {}; }; }] call EFUNC(common,addEventHandler); -//PFEH to watch the internal VON icon -//Note: class RscDisplayVoiceChat {idd = 55}; //only present when talking -[{ - _oldSetting = ACE_player getVariable [QGVAR(isSpeakingInGame), false]; - _newSetting = (!(isNull findDisplay 55)); - if (!(_oldSetting isEqualTo _newSetting)) then { - ACE_player setVariable [QGVAR(isSpeakingInGame), _newSetting, true]; - }; -} , 0.1, []] call CBA_fnc_addPerFrameHandler; +if (isClass (configFile >> "cfgPatches" >> "acre_api")) then { + diag_log text format ["[ACE_nametags] - ACRE Detected"]; + DFUNC(isSpeaking) = { + PARAMS_1(_unit); + ([_unit] call acre_api_fnc_isSpeaking) || ([ACE_player] call acre_api_fnc_isBroadcasting) + }; +} else { + if (isClass (configFile >> "cfgPatches" >> "task_force_radio")) then { + diag_log text format ["[ACE_nametags] - TFR Detected"]; + DFUNC(isSpeaking) = { + PARAMS_1(_unit); + (_unit getVariable ["tf_isSpeaking", false]) + }; + } else { + //No Radio Mod - Start a PFEH to watch the internal VON icon + //Note: class RscDisplayVoiceChat {idd = 55} - only present when talking -DFUNC(isSpeaking) = switch (true) do { -case (isClass (configFile >> "cfgPatches" >> "acre_api")): { - { - PARAMS_1(_unit); - (_unit getVariable [QGVAR(isSpeakingInGame), false]) || ([_unit] call acre_api_fnc_isSpeaking) || ([ACE_player] call acre_api_fnc_isBroadcasting) - }; - }; -case (isClass (configFile >> "cfgPatches" >> "task_force_radio")): { - { - PARAMS_1(_unit); - (_unit getVariable [QGVAR(isSpeakingInGame), false]) || (_unit getVariable ["tf_isSpeaking", false]) - }; - }; - default { - { + [{ + _oldSetting = ACE_player getVariable [QGVAR(isSpeakingInGame), false]; + _newSetting = (!(isNull findDisplay 55)); + if (!(_oldSetting isEqualTo _newSetting)) then { + ACE_player setVariable [QGVAR(isSpeakingInGame), _newSetting, true]; + }; + } , 0.1, []] call CBA_fnc_addPerFrameHandler; + + DFUNC(isSpeaking) = { PARAMS_1(_unit); (_unit getVariable [QGVAR(isSpeakingInGame), false]) }; From e54d8dc827f05362d3b25b34a56ea48c97bd0355 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Wed, 15 Apr 2015 12:55:16 -0500 Subject: [PATCH 5/6] ProgressBar - Fixed Alignment --- addons/common/ProgressScreen.hpp | 135 ++++++++++---------- addons/common/functions/fnc_progressBar.sqf | 19 +-- 2 files changed, 76 insertions(+), 78 deletions(-) diff --git a/addons/common/ProgressScreen.hpp b/addons/common/ProgressScreen.hpp index 751d48af9f..df07e5ca2f 100644 --- a/addons/common/ProgressScreen.hpp +++ b/addons/common/ProgressScreen.hpp @@ -1,77 +1,74 @@ - class GVAR(ProgressBar_Dialog) { - idd = -1; - movingEnable = false; - onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(ctrlProgressBar)),(_this select 0) displayCtrl 1)]; uiNamespace setVariable [ARR_2(QUOTE(QGVAR(ctrlProgressBarTitle)),(_this select 0) displayCtrl 2)];); - objects[] = {}; + idd = -1; + movingEnable = false; + onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(ctrlProgressBar)),(_this select 0) displayCtrl 1)]; uiNamespace setVariable [ARR_2(QUOTE(QGVAR(ctrlProgressBarTitle)),(_this select 0) displayCtrl 2)];); + objects[] = {}; - class controlsBackground { - class Background { - idc = -1; - moving = 0; - font = "TahomaB"; - text = ""; - sizeEx = 0; - lineSpacing = 0; - access = 0; - type = 0; - style = 0; - size = 1; - colorBackground[] = {0, 0, 0, 0.0}; - colorText[] = {0, 0, 0, 0}; - x = "safezoneX"; - y = "safezoneY"; - w = "safezoneW"; - h = "safezoneH"; + class controlsBackground { + class Background { + idc = -1; + moving = 0; + font = "TahomaB"; + text = ""; + sizeEx = 0; + lineSpacing = 0; + access = 0; + type = 0; + style = 0; + size = 1; + colorBackground[] = {0, 0, 0, 0.0}; + colorText[] = {0, 0, 0, 0}; + x = "safezoneX"; + y = "safezoneY"; + w = "safezoneW"; + h = "safezoneH"; + }; + class Progress: ACE_gui_RscProgress { + idc = 1; + x = "1.2 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "0.1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "37.8 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = ".8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + colorFrame[] = {0,0,0,0.0}; + colorBar[] = {0.27,0.5,0.31,0.8}; + texture = "#(argb,8,8,3)color(1,1,1,0.7)"; + }; + class Title_Bar : ACE_gui_staticBase { + idc = 2; + style = 0x22; + colorBackground[] = {0, 0, 0, 0}; + colorText[] = {1, 1, 1, 1}; + x = "1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; + y = "0 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; + w = "38 * (((safezoneW / safezoneH) min 1.2) / 40)"; + h = "1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; + }; }; - - class Progress: ACE_gui_RscProgress { - idc = 1; - x = "1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; - y = "0.1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; - w = "38 * (((safezoneW / safezoneH) min 1.2) / 40)"; - h = ".8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; - colorFrame[] = {0,0,0,0.0}; - colorBar[] = {0.27,0.5,0.31,0.8}; - texture = "#(argb,8,8,3)color(1,1,1,0.7)"; - }; - - class Title_Bar : ACE_gui_staticBase { - idc = 2; - style = 0x22; - colorBackground[] = {0, 0, 0, 0}; - colorText[] = {1, 1, 1, 1}; - x = "1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2)"; - y = "0 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2)"; - w = "38 * (((safezoneW / safezoneH) min 1.2) / 40)"; - h = "1 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)"; - }; - }; }; class GVAR(DisableMouse_Dialog) { - idd = -1; - movingEnable = false; - onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(dlgDisableMouse)),_this select 0)];); - objects[] = {}; - class controlsBackground { - class Background { - idc = -1; - moving = 0; - font = "TahomaB"; - text = ""; - sizeEx = 0; - lineSpacing = 0; - access = 0; - type = 0; - style = 0; - size = 1; - colorBackground[] = {0, 0, 0, 0};//0.5 - colorText[] = {0, 0, 0, 0}; - x = "safezoneX"; - y = "safezoneY"; - w = "safezoneW"; - h = "safezoneH"; + idd = -1; + movingEnable = false; + onLoad = QUOTE(uiNamespace setVariable [ARR_2(QUOTE(QGVAR(dlgDisableMouse)),_this select 0)];); + objects[] = {}; + class controlsBackground { + class Background { + idc = -1; + moving = 0; + font = "TahomaB"; + text = ""; + sizeEx = 0; + lineSpacing = 0; + access = 0; + type = 0; + style = 0; + size = 1; + colorBackground[] = {0, 0, 0, 0};//0.5 + colorText[] = {0, 0, 0, 0}; + x = "safezoneX"; + y = "safezoneY"; + w = "safezoneW"; + h = "safezoneH"; + }; }; - }; }; diff --git a/addons/common/functions/fnc_progressBar.sqf b/addons/common/functions/fnc_progressBar.sqf index 3191a57d72..03c56398c4 100644 --- a/addons/common/functions/fnc_progressBar.sqf +++ b/addons/common/functions/fnc_progressBar.sqf @@ -26,7 +26,7 @@ PARAMS_4(_totalTime,_args,_onFinish,_onFail); DEFAULT_PARAM(4,_localizedTitle,""); DEFAULT_PARAM(5,_condition,{true}); DEFAULT_PARAM(6,_exceptions,[]); -private ["_player", "_perFrameFunction"]; +private ["_player", "_perFrameFunction", "_ctrlPos"]; _player = ACE_player; @@ -35,14 +35,15 @@ closeDialog 0; createDialog QGVAR(ProgressBar_Dialog); (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlSetText _localizedTitle; -if (GVAR(SettingProgressBarLocation) == 1) then { - private "_ctrlPos"; - _ctrlPos = [1 * (((safezoneW / safezoneH) min 1.2) / 40) + (safezoneX + (safezoneW - ((safezoneW / safezoneH) min 1.2))/2), 29 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2), 38 * (((safezoneW / safezoneH) min 1.2) / 40), 0.8 * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25)]; - (uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlSetPosition _ctrlPos; - (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlSetPosition _ctrlPos; - (uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlCommit 0; - (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlCommit 0; -}; +//Adjust position based on user setting: +_ctrlPos = ctrlPosition (uiNamespace getVariable QGVAR(ctrlProgressBarTitle)); +_ctrlPos set [1, ((0 + 29 * GVAR(SettingProgressBarLocation)) * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2))]; +(uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlSetPosition _ctrlPos; +(uiNamespace getVariable QGVAR(ctrlProgressBarTitle)) ctrlCommit 0; +_ctrlPos = ctrlPosition (uiNamespace getVariable QGVAR(ctrlProgressBar)); +_ctrlPos set [1, ((0.1 + 29 * GVAR(SettingProgressBarLocation)) * ((((safezoneW / safezoneH) min 1.2) / 1.2) / 25) + (safezoneY + (safezoneH - (((safezoneW / safezoneH) min 1.2) / 1.2))/2))]; +(uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlSetPosition _ctrlPos; +(uiNamespace getVariable QGVAR(ctrlProgressBar)) ctrlCommit 0; _perFrameFunction = { From 1a117a58932989057b63994d8b7e3406467f7748 Mon Sep 17 00:00:00 2001 From: jaynus Date: Wed, 15 Apr 2015 11:04:37 -0700 Subject: [PATCH 6/6] AMG documentation update. --- .../framework/advanced-missile-guidance.md | 101 +++++++++++++++++- 1 file changed, 99 insertions(+), 2 deletions(-) diff --git a/documentation/framework/advanced-missile-guidance.md b/documentation/framework/advanced-missile-guidance.md index e67bfbe0f3..3029b7b3bd 100644 --- a/documentation/framework/advanced-missile-guidance.md +++ b/documentation/framework/advanced-missile-guidance.md @@ -6,5 +6,102 @@ order: 5 parent: wiki --- -## 1. Overview -Blah blah blah \ No newline at end of file +# 1. Overview + +The ACE Advanced Missile Guidance Framework provides a setup of configuration settings, functions and a execution framework for addon makers to integrate with the missile guidance and targeting mechanisms of ACE. It also provides for mod makers to create their own custom guidance methods within the framework. + +The framework provides all the functionality needed for guidance; from laser locking, target specification and selection, to handling the fired events and tracking and steering the vehicle based on provided parameters. This way, all that needs to be defined in addons is the appropriate CfgAmmo entries for the missile. + +The framework also provides addon makers and scripters with the ability to configure custom seeker types and attack profiles, which are defined below. This allows for complete control of the guidance, locking and flight of a missile at the discretion of the addon maker. + +ACE3 provides a full suite of base concepts and guidance for the majority of modern missile weaponry avialable today; these includes all basic types of seekers (SALH/SACLOS/Optic/Thermal/etc) - as well as the different common attack profiles utilized with guided munitions (such as top-down attacks). + +Finally, flight profiles and mechanics for realistic missile simulations are also implemented; allowing for lock-steering bump guidance flight such as with the M47 Dragon or GBU steering fins, or finely tuned direct flight guidance which is currently avialable with other missile types. + +# 2. Details + +The framework is broken up into 3 major components: Locking Types, Seeker Types and Attack Profiles. In combination, these components build out the entire process of launching, locking and going terminal flight against targets. + +### Components + +##### 1. Locking Types +Locking types provide the basic functionality of targeting which will be based to a seeker type, providing target aquisition for seekers. This provides the basic functionality for providing pre-determined targets for a seeker, or allowing the seeker to perform its own target aquisition and locking. Additionally, the seeker may reference back into the locking type in order to re-perform target aquisition. + +##### 2. Seeker Types +Each seeker is generally assumed to be the logic for the seeker head unit within any given munition. Seekers within this framework provide the basic targeting functionality for the entire framework. The locking type will provide a generic target to the seeker, or the seeker may aquire a target on its own. The seeker then provides a target, either an object or a ASL position, which is then passed further into the framework. This target (or position) should be the actual current target position for the missiles flight. Seekers are required to perform all limitations and checks within their systems, although various limitations have been provided in this framework such as LOS FOV, laser guidance, etc. + +##### 3. Attack Profiles + +An attack profile adjusts the current target flight location to create the actual flight path of the missile. The attack profile is provided with all parameters of the system, including the returned target of the seeker. Using this information, the attack profile then will adjust the *direct flight target position* to specifically direct where and how the missile shall flight. + +## How it all ties together + +The system is executed in a linear series of calls to each step of the process, and feeding back the return from that step to the next step. Execution is conducted using Locking->Seeker->Profile, iteratively every frame of execution. Flight times are adjusted to accTime values and FPS lag, giving consistent flight. + +On each step of execution, a target specification array [targetObj, targetPos] is passed to the locking type, which then will return a possible modified target array. Next, this modified data is passed to the seeker type - which then, in turn, returns a position vector to the current "seeked" target position (ASL). Last, this target position is passed to the attack profile, who then returns an "adjusted attack position (ASL)", which is the location the missile should *currently* be homing on for flight. + +In the simplest sense, the entire system provides the flight trajectory of the missile homing directly on the "adjusted attack position"; thus, an attack profile would ajust this position to direct the missile. For example, Top down attacks return the adjusted attack position high above the target, until entering their terminal stages, which then changes the position to be directly ontop of the target - thus "walking the missile" along its flight path and to the kill. + +# 2. Adding AMG to a missile + +## Enabling guidance on Ammo Types +``` +class CfgAmmo { + class MissileBase; + class MyMissileType : MissileBase { + // Turn off arma crosshair-guidance + manualControl = 0; + + // Begin ACE guidance Configs + class ace_missileguidance { + enabled = 1; + + minDeflection = 0.00025; // Minium flap deflection for guidance + maxDeflection = 0.001; // Maximum flap deflection for guidance + incDeflection = 0.0005; // The incrmeent in which deflection adjusts. + + canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet modes. All 'recruit' games use vanilla locking + + // Seeker type and settings for munitions + defaultSeekerType = "SALH"; + seekerTypes[] = { "SALH", "LIDAR", "SARH", "Optic", "Thermal", "GPS", "SACLOS", "MCLOS" }; + + defaultSeekerLockMode = "LOAL"; + seekerLockModes[] = { "LOAL", "LOBL" }; + + seekerAngle = 90; // Angle in front of the missile which can be searched + seekerAccuracy = 1; // seeker accuracy multiplier + + seekerMinRange = 1; + seekerMaxRange = 2500; // Range from the missile which the seeker can visually search + + // Attack profile type selection + defaultAttackProfile = "LIN"; + attackProfiles[] = { "LIN", "DIR", "MID", "HI" }; + }; +``` + +# 2. Creating your own custom seekers and attack profiles + +## Adding seeker types and attack profiles + +``` +class ace_missileguidance_attackProfiles{ + class MyAttackProfile { + name = ""; + visualName = ""; + description = ""; + + functionName = "my_fnc_doAttackProfile"; + }; +}; +class ace_missileguidance_seekerTypes { + class MySeekerType { + name = ""; + visualName = ""; + description = ""; + + functionName = "my_fnc_doSeekerType"; + }; +}; +``` \ No newline at end of file