From 2bfb226b86d41a59d2d2bd3008817ba1920c6718 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Mon, 13 Jan 2025 14:01:44 -0600 Subject: [PATCH 1/7] Common - Check extensions hash (#10144) Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com> Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com> --- addons/common/ACE_ExtensionsHashes.hpp | 6 +++ addons/common/config.cpp | 2 + addons/common/functions/fnc_checkFiles.sqf | 45 ++++++++++++++++------ addons/common/initSettings.inc.sqf | 9 +++++ addons/common/stringtable.xml | 3 ++ extension/Makefile.toml | 10 ++++- tools/.vscode/tasks.json | 4 +- tools/getExtensionHash.py | 36 +++++++++++++++++ 8 files changed, 100 insertions(+), 15 deletions(-) create mode 100644 addons/common/ACE_ExtensionsHashes.hpp create mode 100644 tools/getExtensionHash.py diff --git a/addons/common/ACE_ExtensionsHashes.hpp b/addons/common/ACE_ExtensionsHashes.hpp new file mode 100644 index 00000000000..74fe4defab1 --- /dev/null +++ b/addons/common/ACE_ExtensionsHashes.hpp @@ -0,0 +1,6 @@ +class ACE_ExtensionsHashes { + class ace { + dll = "b83c2c9c7c989eaf888c885d13a2fdf4a61d1c5f"; + dll_x64 = "356a61c4bd2aa13556a8ba0b467c819b3b438d6c"; + }; +}; diff --git a/addons/common/config.cpp b/addons/common/config.cpp index f7b27ce3749..f94b1d376cd 100644 --- a/addons/common/config.cpp +++ b/addons/common/config.cpp @@ -75,3 +75,5 @@ class ACE_Tests { mapConfigs = QPATHTOF(dev\test_mapConfigs.sqf); cfgPatches = QPATHTOF(dev\test_cfgPatches.sqf); }; + +#include "ACE_ExtensionsHashes.hpp" diff --git a/addons/common/functions/fnc_checkFiles.sqf b/addons/common/functions/fnc_checkFiles.sqf index 13ad27a7cb5..8ae67eb04a0 100644 --- a/addons/common/functions/fnc_checkFiles.sqf +++ b/addons/common/functions/fnc_checkFiles.sqf @@ -116,31 +116,52 @@ if (_oldCompats isNotEqualTo []) then { /////////////// // Check extensions /////////////// -private _platform = toLowerANSI (productVersion select 6); +if (hasInterface) then { + private _platform = toLowerANSI (productVersion select 6); -if (_platform in ["linux", "osx"]) then { - // Linux and OSX client ports do not support extensions at all - if (hasInterface) then { + // Check for presence + if (_platform in ["linux", "osx"]) exitWith { + // Linux and OSX client ports do not support extensions at all WARNING("Operating system does not support extensions"); - } else { - INFO("Operating system does not support extensions"); }; -} else { + ("ace" callExtension ["version", []]) params [["_versionEx", "", [""]], ["_returnCode", -1, [-1]]]; if (_returnCode != 0 || {_versionEx == ""}) then { private _errorMsg = format ["Extension not found. [Return Code: %1]", _returnCode]; ERROR(_errorMsg); - - if (hasInterface) then { - ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage); - }; + ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage); } else { _versionEx = _versionEx select [0, 8]; // git hash INFO_1("Extension [Version: %1]",_versionEx); }; -}; + // Check for correct hash + if (GVAR(checkExtensions)) then { + private _allExtensions = allExtensions; + + { + private _extName = configName _x; + private _extensionType = "dll"; + if (productVersion select 7 == "x64") then { _extensionType = format ["%1_x64", _extensionType]; }; + private _expectedHash = getText (_x >> _extensionType); + + private _extensionHash = ""; + { + if ((_x getOrDefault ["name", ""]) == _extName) exitWith { + _extensionHash = _x getOrDefault ["hash", ""]; + }; + } forEach _allExtensions; + TRACE_3("",_extName,_expectedHash,_extensionHash); + + if (_extensionHash != _expectedHash) then { + private _errorMsg = format ["Extension %1 wrong version [%2 vs %3].", _extName, _extensionHash, _expectedHash]; + ERROR(_errorMsg); + ["[ACE] ERROR", _errorMsg] call FUNC(errorMessage); + }; + } forEach ("true" configClasses (configFile >> "ACE_ExtensionsHashes")); + }; +}; /////////////// // Check server version/addons diff --git a/addons/common/initSettings.inc.sqf b/addons/common/initSettings.inc.sqf index 4b3a2fd9c9d..a0a495b094e 100644 --- a/addons/common/initSettings.inc.sqf +++ b/addons/common/initSettings.inc.sqf @@ -29,6 +29,15 @@ private _categorySway = [_category, LSTRING(subcategory_sway)]; 1 ] call CBA_fnc_addSetting; +[ + QGVAR(checkExtensions), + "CHECKBOX", + [LSTRING(checkExtensions_DisplayName)], + _category, + false, + 1 +] call CBA_fnc_addSetting; + [ QGVAR(settingFeedbackIcons), "LIST", diff --git a/addons/common/stringtable.xml b/addons/common/stringtable.xml index fa26901e46b..ece8ece410d 100644 --- a/addons/common/stringtable.xml +++ b/addons/common/stringtable.xml @@ -409,6 +409,9 @@ 检查 PBO PBO-k ellenőrzése + + Check Extensions + What addons are allowed regardless? Jaké addony jsou povoleny? diff --git a/extension/Makefile.toml b/extension/Makefile.toml index 3002e34dccf..22f16e3ee18 100644 --- a/extension/Makefile.toml +++ b/extension/Makefile.toml @@ -55,5 +55,13 @@ dependencies = ["build_x32_release"] [tasks.debug] dependencies = ["move_x32_debug", "move_x64_debug"] -[tasks.release] +[tasks.updateSigs] +script_runner = "python" +script_extension = "py" +script_runner_args = ["../tools/getExtensionHash.py"] +script = ''' +''' dependencies = ["move_x32_release", "move_x64_release"] + +[tasks.release] +dependencies = ["updateSigs"] diff --git a/tools/.vscode/tasks.json b/tools/.vscode/tasks.json index 277d4bcc85b..ef04bb50f57 100644 --- a/tools/.vscode/tasks.json +++ b/tools/.vscode/tasks.json @@ -119,7 +119,7 @@ } }, { - "label": "Extension: x64", + "label": "Extension: make move_x64_release", "command": "cargo", "options": { "cwd": "${workspaceFolder}" @@ -133,7 +133,7 @@ } }, { - "label": "Extension: Release", + "label": "Extension: make release", "command": "cargo", "options": { "cwd": "${workspaceFolder}" diff --git a/tools/getExtensionHash.py b/tools/getExtensionHash.py new file mode 100644 index 00000000000..fa990218c44 --- /dev/null +++ b/tools/getExtensionHash.py @@ -0,0 +1,36 @@ +import pathlib +import os +import hashlib + +addon_base_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) + +extensions = {} + +for file in os.listdir(addon_base_path): + path = pathlib.Path(addon_base_path, file) + extension_type = "dll" + if path.suffix == ".dll": + key = path.stem + if key.endswith("_x64"): + key = key.removesuffix("_x64") + extension_type += "_x64" + print(f"looking at {path}") + with open(path, 'rb') as file_read: + sha1 = hashlib.sha1() + data = file_read.read() + sha1.update(data) + arr = extensions.get(key, {}) + arr[extension_type] = sha1.hexdigest() + extensions[key] = arr + +file_out = pathlib.Path(addon_base_path, "addons", "common", "ACE_ExtensionsHashes.hpp") +with open(file_out, 'w') as file_write: + print(f"class ACE_ExtensionsHashes {{", file=file_write) + for key, values in extensions.items(): + print(f" class {key} {{", file=file_write) + for type, hash in values.items(): + print(f" {type} = \"{hash}\";", file=file_write) + print(f" }};", file=file_write) + print(f"}};", file=file_write) + +print(f"Wrote {len(extensions)} to {file_out}") From 064e1eb3889aa9ad803cddccfbb9a761f0dfe1c7 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 13 Jan 2025 12:28:31 -0800 Subject: [PATCH 2/7] Sitting - Various improvements (#10644) * Misc improvements to sitting * Unclaim, then claim * Update addons/sitting/XEH_clientInit.sqf Co-authored-by: PabstMirror * Update addons/sitting/XEH_preStart.sqf Co-authored-by: PabstMirror * Update fnc_canSit.sqf --------- Co-authored-by: PabstMirror --- addons/sitting/XEH_clientInit.sqf | 9 ++--- addons/sitting/XEH_preStart.sqf | 5 +++ .../sitting/functions/fnc_addSitActions.sqf | 6 +++ addons/sitting/functions/fnc_canSit.sqf | 13 +++--- addons/sitting/functions/fnc_sit.sqf | 40 ++++++++++++------- addons/sitting/functions/fnc_stand.sqf | 19 +++++---- docs/wiki/framework/sitting-framework.md | 8 +--- 7 files changed, 61 insertions(+), 39 deletions(-) diff --git a/addons/sitting/XEH_clientInit.sqf b/addons/sitting/XEH_clientInit.sqf index bb2b1e2e681..4b3ea3fbadf 100644 --- a/addons/sitting/XEH_clientInit.sqf +++ b/addons/sitting/XEH_clientInit.sqf @@ -9,13 +9,10 @@ if (!hasInterface) exitWith {}; // If not enabled, then do not add CanInteractWith Condition or event handlers if (!XGVAR(enable)) exitWith {}; - // Initialize classes as they spawn - ["ThingX", "init", LINKFUNC(addSitActions), nil, nil, true] call CBA_fnc_addClassEventHandler; - - // Initialize statically defined benches (also appear as world objects, no class EH thrown) + // Initialize all seats { - [_x] call FUNC(addSitActions); - } forEach [BENCHES]; + _x call FUNC(addSitActions); + } forEach keys (uiNamespace getVariable [QGVAR(seats), []]); // Add interaction menu exception ["isNotSitting", {isNil {(_this select 0) getVariable QGVAR(sittingStatus)}}] call EFUNC(common,addCanInteractWithCondition); diff --git a/addons/sitting/XEH_preStart.sqf b/addons/sitting/XEH_preStart.sqf index 022888575ed..0cc72dc4912 100644 --- a/addons/sitting/XEH_preStart.sqf +++ b/addons/sitting/XEH_preStart.sqf @@ -1,3 +1,8 @@ #include "script_component.hpp" #include "XEH_PREP.hpp" + +private _seats = QUOTE(getNumber (_x >> QQXGVAR(canSit)) == 1) configClasses (configFile >> "CfgVehicles"); +_seats = _seats apply {configName _x}; + +uiNamespace setVariable [QGVAR(seats), compileFinal (_seats createHashMapFromArray [])]; diff --git a/addons/sitting/functions/fnc_addSitActions.sqf b/addons/sitting/functions/fnc_addSitActions.sqf index a705ca21e69..d9264af1027 100644 --- a/addons/sitting/functions/fnc_addSitActions.sqf +++ b/addons/sitting/functions/fnc_addSitActions.sqf @@ -15,6 +15,11 @@ * Public: No */ +// Only run this after the settings are initialized +if !(EGVAR(common,settingsInitFinished)) exitWith { + EGVAR(common,runAtSettingsInitialized) pushBack [FUNC(addSitActions), _this]; +}; + params ["_seat"]; private _type = _seat; @@ -69,3 +74,4 @@ if !((_sitPosition select 0) isEqualType []) then { [_type, 0, _menuType, _sitAction] call EFUNC(interact_menu,addActionToClass); } forEach _sitPosition; +nil // return diff --git a/addons/sitting/functions/fnc_canSit.sqf b/addons/sitting/functions/fnc_canSit.sqf index 609bcea6828..5c8ea3be549 100644 --- a/addons/sitting/functions/fnc_canSit.sqf +++ b/addons/sitting/functions/fnc_canSit.sqf @@ -21,10 +21,13 @@ params ["_seat", "_player", ["_seatPos", 0]]; // Sitting enabled, not occupied and standing up (or not on a big slope) XGVAR(enable) && -{[_player, _seat] call EFUNC(common,canInteractWith)} && {isNil {_player getVariable QGVAR(sittingStatus)}} && -{ +{round (vectorUp _seat select 0) == 0 && {round (vectorUp _seat select 1) == 0} && {round (vectorUp _seat select 2) == 1}} && { private _seatsClaimed = _seat getVariable [QGVAR(seatsClaimed), []]; - _seatsClaimed isEqualTo [] || {!(_seatsClaimed select _seatPos)} -} && -{round (vectorUp _seat select 0) == 0 && {round (vectorUp _seat select 1) == 0} && {round (vectorUp _seat select 2) == 1}} + + (_seatsClaimed isEqualTo [] || {isNull (_seatsClaimed select _seatPos)}) && { + ([_player, _seat] call EFUNC(common,canInteractWith)) || // not claimed (common case) + // Can self-interact and chair claimed by another sitter + {([_player, objNull] call EFUNC(common,canInteractWith)) && {(_seatsClaimed findIf {!isNull _x}) != -1}} + } +} diff --git a/addons/sitting/functions/fnc_sit.sqf b/addons/sitting/functions/fnc_sit.sqf index d359083c44a..29da603c64f 100644 --- a/addons/sitting/functions/fnc_sit.sqf +++ b/addons/sitting/functions/fnc_sit.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: Jonpas, vabene1111 - * Sits down the player. + * Makes the player sit down. * * Arguments: * 0: Seat @@ -65,16 +65,9 @@ _player setVariable [QGVAR(sittingStatus), [_seat, _actionID, _seatPos]]; private _seatsClaimed = _seat getVariable [QGVAR(seatsClaimed), []]; // Initialize claimed seats if first time sitting on it if (_seatsClaimed isEqualTo []) then { - if (_multiSitting) then { - for "_i" from 0 to ((count _sitPositionAll) - 1) do { - _seatsClaimed pushBack (_i == _seatPos); - }; - } else { - _seatsClaimed = [true]; - }; -} else { - _seatsClaimed set [_seatPos, true]; + _seatsClaimed resize [count _sitPositionAll, objNull]; }; +_seatsClaimed set [_seatPos, _player]; _seat setVariable [QGVAR(seatsClaimed), _seatsClaimed, true]; // Also prevent dragging/carrying @@ -82,27 +75,44 @@ if !([_seat] call EFUNC(common,owned)) then { [_player, _seat] call EFUNC(common,claim); }; -// Add automatical stand PFH in case of interruptions +// Automatically stand up if interrupted private _seatPosOrig = getPosASL _seat; private _seatDistOrig = (getPosASL _player) distance _seat; [{ params ["_args", "_pfhId"]; - _args params ["_player", "_seat", "_seatPosOrig", "_seatDistOrig"]; + _args params ["_player", "_seat", "_seatPos", "_seatPosOrig", "_seatDistOrig"]; // Remove PFH if not sitting any more if (isNil {_player getVariable QGVAR(sittingStatus)}) exitWith { [_pfhId] call CBA_fnc_removePerFrameHandler; TRACE_1("Remove PFH",_player getVariable [ARR_2(QGVAR(sittingStatus),false)]); + + if (!alive _seat) exitWith {}; + + // Allow sitting on this seat again + private _seatsClaimed = _seat getVariable [QGVAR(seatsClaimed), []]; + _seatsClaimed set [_seatPos, objNull]; + _seat setVariable [QGVAR(seatsClaimed), _seatsClaimed, true]; + + // Unclaim... + [objNull, _seat] call EFUNC(common,claim); + + // ...but have a remaining unit reclaim ownership immediately + private _index = _seatsClaimed findIf {!isNull _x}; + + if (_index == -1) exitWith {}; + + [_seatsClaimed select _index, _seat] call EFUNC(common,claim); }; - // Stand up if chair gets deleted or moved - if (isNull _seat || + // Stand up if chair gets deleted or moved + if (!alive _seat || {getPosASL _player distance _seatPosOrig > _seatDistOrig + 0.5} || {((getPosASL _seat) vectorDistance _seatPosOrig) > 0.01} ) exitWith { _player call FUNC(stand); TRACE_2("Chair moved",getPosASL _seat,_seatPosOrig); }; -}, 0, [_player, _seat, _seatPosOrig, _seatDistOrig]] call CBA_fnc_addPerFrameHandler; +}, 0, [_player, _seat, _seatPos, _seatPosOrig, _seatDistOrig]] call CBA_fnc_addPerFrameHandler; ["ace_satDown", [_player, _seat, _seatPos]] call CBA_fnc_localEvent; diff --git a/addons/sitting/functions/fnc_stand.sqf b/addons/sitting/functions/fnc_stand.sqf index b25c7a5ee1e..26fb4fd6191 100644 --- a/addons/sitting/functions/fnc_stand.sqf +++ b/addons/sitting/functions/fnc_stand.sqf @@ -1,7 +1,7 @@ #include "..\script_component.hpp" /* * Author: Jonpas - * Stands up the player. + * Makes the player stand up. * * Arguments: * Player @@ -39,14 +39,19 @@ _player setVariable [QGVAR(sittingStatus), nil]; ["ace_stoodUp", [_player, _seat, _seatPos]] call CBA_fnc_localEvent; -if (isNull _seat) exitWith {}; +if (!alive _seat) exitWith {}; // Allow sitting on this seat again private _seatsClaimed = _seat getVariable [QGVAR(seatsClaimed), []]; -_seatsClaimed set [_seatPos, false]; +_seatsClaimed set [_seatPos, objNull]; _seat setVariable [QGVAR(seatsClaimed), _seatsClaimed, true]; -// Unclaim if no one else sitting on it -if (_seatsClaimed find true == -1) then { - [objNull, _seat] call EFUNC(common,claim); -}; +// Unclaim... +[objNull, _seat] call EFUNC(common,claim); + +// ...but have a remaining unit reclaim ownership immediately +private _index = _seatsClaimed findIf {!isNull _x}; + +if (_index == -1) exitWith {}; + +[_seatsClaimed select _index, _seat] call EFUNC(common,claim); diff --git a/docs/wiki/framework/sitting-framework.md b/docs/wiki/framework/sitting-framework.md index b8f8ff37b08..7478976a572 100644 --- a/docs/wiki/framework/sitting-framework.md +++ b/docs/wiki/framework/sitting-framework.md @@ -1,7 +1,7 @@ --- layout: wiki title: Sitting Framework -description: Explains how to set-up sitting objects (eg. chairs) with ACE sitting system. +description: Explains how to set-up sitting objects (e.g. chairs) with ACE sitting system. group: framework order: 5 parent: wiki @@ -15,10 +15,7 @@ redirect_from: "/wiki/frameworkx/sitting-framework.md" ## 1. Requirements -Object must inherit from `ThingX` or any of its sub-classes. - -Object must have Extended Event Handler (XEH) enabled (this is not the case for the majority of vanilla objects in `ThingX` class), configuration entry on how to do that is shown below. - +Object must have `acex_sitting_canSit = 1` defined. ## 2. Config Values @@ -30,7 +27,6 @@ class CfgVehicles { acex_sitting_sitPosition[] = {0, -0.1, -0.45}; // Position relative to object (may behave weird with certain objects) acex_sitting_interactPosition[] = {0, -0.1, -0.45}; ace_sitting_animations[] = {"ace_sitting_HubSittingChairA_idle1"}; // Overwrite random animation pool - XEH_ENABLED; // Enable XEH (only necessary if XEH is not yet enabled for this class or the one this inherits from) }; }; ``` From 6e6ad93b126b61d628924c3c4aad8b5ab32abc5d Mon Sep 17 00:00:00 2001 From: Dart <59131299+DartRuffian@users.noreply.github.com> Date: Mon, 13 Jan 2025 14:36:03 -0600 Subject: [PATCH 3/7] Medical Treatment - Allow creating litter from classes (#10649) --- .../functions/fnc_createLitterServer.sqf | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/addons/medical_treatment/functions/fnc_createLitterServer.sqf b/addons/medical_treatment/functions/fnc_createLitterServer.sqf index afeba0eb36b..b19ddc9baa5 100644 --- a/addons/medical_treatment/functions/fnc_createLitterServer.sqf +++ b/addons/medical_treatment/functions/fnc_createLitterServer.sqf @@ -24,15 +24,22 @@ if (isNil QGVAR(litterObjects)) then { GVAR(litterCleanup) = false; }; -private _model = getText (configFile >> "CfgVehicles" >> _litterClass >> "model"); -if (_model == "") exitWith {}; +private _config = configFile >> "CfgVehicles" >> _litterClass; +private _modelOrClass = if (getNumber (_config >> QGVAR(useClass)) == 1) then { + _litterClass +} else { + getText (_config >> "model"); +}; + + +if (_modelOrClass == "") exitWith {}; // createSimpleObject expects a path without the leading slash -if (_model select [0, 1] == "\") then { - _model = _model select [1]; +if (_modelOrClass select [0, 1] == "\") then { + _modelOrClass = _modelOrClass select [1]; }; -private _object = createSimpleObject [_model, [0, 0, 0]]; +private _object = createSimpleObject [_modelOrClass, [0, 0, 0]]; _object setPosASL _position; _object setDir _direction; From c038494c6784215f2f94f18ebe95812a186dc1f7 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 13 Jan 2025 12:42:05 -0800 Subject: [PATCH 4/7] Compat EF - Remove `ace_hearing` hard dependency (#10646) --- addons/compat_ef/CfgWeapons.hpp | 19 ------------------- .../compat_ef_hearing/CfgWeapons.hpp | 19 +++++++++++++++++++ addons/compat_ef/compat_ef_hearing/config.cpp | 19 +++++++++++++++++++ .../compat_ef_hearing/script_component.hpp | 3 +++ addons/compat_ef/config.cpp | 1 - 5 files changed, 41 insertions(+), 20 deletions(-) create mode 100644 addons/compat_ef/compat_ef_hearing/CfgWeapons.hpp create mode 100644 addons/compat_ef/compat_ef_hearing/config.cpp create mode 100644 addons/compat_ef/compat_ef_hearing/script_component.hpp diff --git a/addons/compat_ef/CfgWeapons.hpp b/addons/compat_ef/CfgWeapons.hpp index 1b2cd4c3fe5..33fa1c41d2d 100644 --- a/addons/compat_ef/CfgWeapons.hpp +++ b/addons/compat_ef/CfgWeapons.hpp @@ -7,25 +7,6 @@ class CfgWeapons { EGVAR(nightvision,border) = QPATHTOEF(nightvision,data\nvg_mask_binos_4096.paa); }; - // -- ace_hearing -- - class HelmetBase; - class EF_H_Protecta: HelmetBase { - HEARING_PROTECTION_PELTOR; - }; - class EF_H_MCH; // this does not have peltor - class EF_H_MCH_Basic: EF_H_MCH { - HEARING_PROTECTION_PELTOR; - }; - class EF_H_MCH_BasicNet_Des: EF_H_MCH { - HEARING_PROTECTION_PELTOR; - }; - class EF_H_MCH_Full: EF_H_MCH { - HEARING_PROTECTION_PELTOR; - }; - class EF_H_MCH_FullCamo_Des: EF_H_MCH { - HEARING_PROTECTION_PELTOR; - }; - // -- ace_overpressure -- class autocannon_30mm; class EF_autocannon_50mm_AAV9: autocannon_30mm { diff --git a/addons/compat_ef/compat_ef_hearing/CfgWeapons.hpp b/addons/compat_ef/compat_ef_hearing/CfgWeapons.hpp new file mode 100644 index 00000000000..ece1f54c252 --- /dev/null +++ b/addons/compat_ef/compat_ef_hearing/CfgWeapons.hpp @@ -0,0 +1,19 @@ +class CfgWeapons { + class HelmetBase; + class EF_H_Protecta: HelmetBase { + HEARING_PROTECTION_PELTOR; + }; + class EF_H_MCH; // this does not have peltor + class EF_H_MCH_Basic: EF_H_MCH { + HEARING_PROTECTION_PELTOR; + }; + class EF_H_MCH_BasicNet_Des: EF_H_MCH { + HEARING_PROTECTION_PELTOR; + }; + class EF_H_MCH_Full: EF_H_MCH { + HEARING_PROTECTION_PELTOR; + }; + class EF_H_MCH_FullCamo_Des: EF_H_MCH { + HEARING_PROTECTION_PELTOR; + }; +}; diff --git a/addons/compat_ef/compat_ef_hearing/config.cpp b/addons/compat_ef/compat_ef_hearing/config.cpp new file mode 100644 index 00000000000..c091a27c8fd --- /dev/null +++ b/addons/compat_ef/compat_ef_hearing/config.cpp @@ -0,0 +1,19 @@ +#include "script_component.hpp" +#include "\z\ace\addons\hearing\script_macros_hearingProtection.hpp" + +class CfgPatches { + class SUBADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"EF_Weapons", "EF_Marines", "ace_hearing"}; + skipWhenMissingDependencies = 1; + author = ECSTRING(common,ACETeam); + url = ECSTRING(main,URL); + VERSION_CONFIG; + addonRootClass = QUOTE(ADDON); + }; +}; + +#include "CfgWeapons.hpp" diff --git a/addons/compat_ef/compat_ef_hearing/script_component.hpp b/addons/compat_ef/compat_ef_hearing/script_component.hpp new file mode 100644 index 00000000000..8edb825af34 --- /dev/null +++ b/addons/compat_ef/compat_ef_hearing/script_component.hpp @@ -0,0 +1,3 @@ +#define SUBCOMPONENT hearing +#define SUBCOMPONENT_BEAUTIFIED Hearing +#include "..\script_component.hpp" diff --git a/addons/compat_ef/config.cpp b/addons/compat_ef/config.cpp index 9f701b7083f..0a8eea8c41c 100644 --- a/addons/compat_ef/config.cpp +++ b/addons/compat_ef/config.cpp @@ -1,5 +1,4 @@ #include "script_component.hpp" -#include "\z\ace\addons\hearing\script_macros_hearingProtection.hpp" class CfgPatches { class ADDON { From f83bd560b198bd4f15536616bbfd2e08c1c97d21 Mon Sep 17 00:00:00 2001 From: johnb432 <58661205+johnb432@users.noreply.github.com> Date: Mon, 13 Jan 2025 12:50:08 -0800 Subject: [PATCH 5/7] Compat SPE - Remove hard hearing dependency (#10652) --- addons/compat_spe/CfgWeapons.hpp | 1 - addons/compat_spe/CfgWeapons/helmets.hpp | 142 ----------------- .../compat_spe_hearing/CfgWeapons.hpp | 145 ++++++++++++++++++ .../compat_spe/compat_spe_hearing/config.cpp | 27 ++++ .../compat_spe_hearing/script_component.hpp | 3 + addons/compat_spe/config.cpp | 1 - 6 files changed, 175 insertions(+), 144 deletions(-) delete mode 100644 addons/compat_spe/CfgWeapons/helmets.hpp create mode 100644 addons/compat_spe/compat_spe_hearing/CfgWeapons.hpp create mode 100644 addons/compat_spe/compat_spe_hearing/config.cpp create mode 100644 addons/compat_spe/compat_spe_hearing/script_component.hpp diff --git a/addons/compat_spe/CfgWeapons.hpp b/addons/compat_spe/CfgWeapons.hpp index f6b1532bdad..35d04a36dcd 100644 --- a/addons/compat_spe/CfgWeapons.hpp +++ b/addons/compat_spe/CfgWeapons.hpp @@ -1,5 +1,4 @@ class CfgWeapons { - #include "CfgWeapons\helmets.hpp" #include "CfgWeapons\launchers.hpp" #include "CfgWeapons\weapons.hpp" }; diff --git a/addons/compat_spe/CfgWeapons/helmets.hpp b/addons/compat_spe/CfgWeapons/helmets.hpp deleted file mode 100644 index 54cbfd15b86..00000000000 --- a/addons/compat_spe/CfgWeapons/helmets.hpp +++ /dev/null @@ -1,142 +0,0 @@ -class H_SPE_HelmetB; -class H_SPE_Hat: H_SPE_HelmetB {}; - -//ALLIED PILOT -class H_SPE_US_Helmet_Pilot: H_SPE_Hat { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_Op: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_Glasses_Up: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_Glasses_Down: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_Respirator: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_Respirator_Glasses_Up: H_SPE_US_Helmet_Pilot_Respirator { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_Respirator_Glasses_Down: H_SPE_US_Helmet_Pilot_Respirator { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_SWDG_Respirator: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Pilot_SWDG_low_Respirator: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15: H_SPE_US_Helmet_Pilot { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_Op: H_SPE_US_Helmet_H15 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_SWDG: H_SPE_US_Helmet_H15 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_SWDG_low: H_SPE_US_Helmet_H15 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_O2: H_SPE_US_Helmet_H15 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_B7_O2: H_SPE_US_Helmet_H15_O2 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_B7_low_O2: H_SPE_US_Helmet_H15_O2 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_SWDG_O2: H_SPE_US_Helmet_H15_O2 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_H15_SWDG_low_O2: H_SPE_US_Helmet_H15_O2 { - HEARING_PROTECTION_EARMUFF; -}; - -//ALLIED TANKER -class H_SPE_US_Helmet_Tank: H_SPE_HelmetB { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_NG: H_SPE_US_Helmet_Tank { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_Nun: H_SPE_US_Helmet_Tank { - HEARING_PROTECTION_OPEN; -}; -class H_SPE_US_Helmet_Tank_M1_OS: H_SPE_US_Helmet_Tank { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_M1_NS: H_SPE_US_Helmet_Tank_M1_OS { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_M1_Scrim: H_SPE_US_Helmet_Tank_M1_OS { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_polar: H_SPE_US_Helmet_Tank { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_polar_tapes: H_SPE_US_Helmet_Tank_polar { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_polar_low: H_SPE_US_Helmet_Tank_polar { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_US_Helmet_Tank_tapes: H_SPE_US_Helmet_Tank { - HEARING_PROTECTION_EARMUFF; -}; - -//AXIS PILOT -class H_SPE_GER_LW_PilotHelmet_base: H_SPE_Hat { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_LW_PilotHelmet: H_SPE_GER_LW_PilotHelmet_base { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_LW_S_PilotHelmet: H_SPE_GER_LW_PilotHelmet_base { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_LW_PilotHelmet_Mask_base: H_SPE_Hat { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_LW_PilotHelmet_Mask: H_SPE_GER_LW_PilotHelmet_Mask_base { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_LW_PilotHelmet_S_Mask: H_SPE_GER_LW_PilotHelmet_Mask_base { - HEARING_PROTECTION_EARMUFF; -}; - -//AXIS TANKER -class H_SPE_GER_TankPrivateCap: H_SPE_Hat { - HEARING_PROTECTION_OPEN; -}; -class H_SPE_GER_TankOfficerCap: H_SPE_Hat { - HEARING_PROTECTION_OPEN; -}; -class H_SPE_GER_Fieldcap: H_SPE_Hat { - HEARING_PROTECTION_OPEN; -}; -class H_SPE_GER_Fieldcap2: H_SPE_GER_Fieldcap { - HEARING_PROTECTION_OPEN; -}; -class H_SPE_GER_TankPrivateCap2: H_SPE_GER_TankPrivateCap { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_TankOffzCap2: H_SPE_GER_TankPrivateCap { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_TankOfficerCap2: H_SPE_GER_TankOfficerCap { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_SPGPrivateCap: H_SPE_Hat { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_ST_Tanker_Cap2: H_SPE_GER_Fieldcap2 { - HEARING_PROTECTION_EARMUFF; -}; -class H_SPE_GER_ST_Tanker_Cap: H_SPE_GER_Fieldcap { - HEARING_PROTECTION_EARMUFF; -}; diff --git a/addons/compat_spe/compat_spe_hearing/CfgWeapons.hpp b/addons/compat_spe/compat_spe_hearing/CfgWeapons.hpp new file mode 100644 index 00000000000..a1e1fcc3b99 --- /dev/null +++ b/addons/compat_spe/compat_spe_hearing/CfgWeapons.hpp @@ -0,0 +1,145 @@ +class CfgWeapons { + class H_SPE_HelmetB; + class H_SPE_Hat: H_SPE_HelmetB {}; + + //ALLIED PILOT + class H_SPE_US_Helmet_Pilot: H_SPE_Hat { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_Op: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_Glasses_Up: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_Glasses_Down: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_Respirator: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_Respirator_Glasses_Up: H_SPE_US_Helmet_Pilot_Respirator { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_Respirator_Glasses_Down: H_SPE_US_Helmet_Pilot_Respirator { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_SWDG_Respirator: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Pilot_SWDG_low_Respirator: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15: H_SPE_US_Helmet_Pilot { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_Op: H_SPE_US_Helmet_H15 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_SWDG: H_SPE_US_Helmet_H15 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_SWDG_low: H_SPE_US_Helmet_H15 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_O2: H_SPE_US_Helmet_H15 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_B7_O2: H_SPE_US_Helmet_H15_O2 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_B7_low_O2: H_SPE_US_Helmet_H15_O2 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_SWDG_O2: H_SPE_US_Helmet_H15_O2 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_H15_SWDG_low_O2: H_SPE_US_Helmet_H15_O2 { + HEARING_PROTECTION_EARMUFF; + }; + + //ALLIED TANKER + class H_SPE_US_Helmet_Tank: H_SPE_HelmetB { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_NG: H_SPE_US_Helmet_Tank { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_Nun: H_SPE_US_Helmet_Tank { + HEARING_PROTECTION_OPEN; + }; + class H_SPE_US_Helmet_Tank_M1_OS: H_SPE_US_Helmet_Tank { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_M1_NS: H_SPE_US_Helmet_Tank_M1_OS { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_M1_Scrim: H_SPE_US_Helmet_Tank_M1_OS { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_polar: H_SPE_US_Helmet_Tank { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_polar_tapes: H_SPE_US_Helmet_Tank_polar { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_polar_low: H_SPE_US_Helmet_Tank_polar { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_US_Helmet_Tank_tapes: H_SPE_US_Helmet_Tank { + HEARING_PROTECTION_EARMUFF; + }; + + //AXIS PILOT + class H_SPE_GER_LW_PilotHelmet_base: H_SPE_Hat { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_LW_PilotHelmet: H_SPE_GER_LW_PilotHelmet_base { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_LW_S_PilotHelmet: H_SPE_GER_LW_PilotHelmet_base { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_LW_PilotHelmet_Mask_base: H_SPE_Hat { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_LW_PilotHelmet_Mask: H_SPE_GER_LW_PilotHelmet_Mask_base { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_LW_PilotHelmet_S_Mask: H_SPE_GER_LW_PilotHelmet_Mask_base { + HEARING_PROTECTION_EARMUFF; + }; + + //AXIS TANKER + class H_SPE_GER_TankPrivateCap: H_SPE_Hat { + HEARING_PROTECTION_OPEN; + }; + class H_SPE_GER_TankOfficerCap: H_SPE_Hat { + HEARING_PROTECTION_OPEN; + }; + class H_SPE_GER_Fieldcap: H_SPE_Hat { + HEARING_PROTECTION_OPEN; + }; + class H_SPE_GER_Fieldcap2: H_SPE_GER_Fieldcap { + HEARING_PROTECTION_OPEN; + }; + class H_SPE_GER_TankPrivateCap2: H_SPE_GER_TankPrivateCap { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_TankOffzCap2: H_SPE_GER_TankPrivateCap { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_TankOfficerCap2: H_SPE_GER_TankOfficerCap { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_SPGPrivateCap: H_SPE_Hat { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_ST_Tanker_Cap2: H_SPE_GER_Fieldcap2 { + HEARING_PROTECTION_EARMUFF; + }; + class H_SPE_GER_ST_Tanker_Cap: H_SPE_GER_Fieldcap { + HEARING_PROTECTION_EARMUFF; + }; + +}; diff --git a/addons/compat_spe/compat_spe_hearing/config.cpp b/addons/compat_spe/compat_spe_hearing/config.cpp new file mode 100644 index 00000000000..b2b55e9ff42 --- /dev/null +++ b/addons/compat_spe/compat_spe_hearing/config.cpp @@ -0,0 +1,27 @@ +#include "script_component.hpp" +#include "\z\ace\addons\hearing\script_macros_hearingProtection.hpp" + +class CfgPatches { + class SUBADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = { + "ww2_spe_assets_c_weapons_infantryweapons_c", + "ww2_spe_assets_c_vehicles_staticweapons_c", + "ww2_spe_assets_c_vehicles_weapons_c", + "ww2_spe_core_f_system_staticweapons_f", + "ww2_spe_core_c_core_c_eventhandlers", + "ace_hearing" + }; + skipWhenMissingDependencies = 1; + author = ECSTRING(common,ACETeam); + url = ECSTRING(main,URL); + VERSION_CONFIG; + + addonRootClass = QUOTE(ADDON); + }; +}; + +#include "CfgWeapons.hpp" diff --git a/addons/compat_spe/compat_spe_hearing/script_component.hpp b/addons/compat_spe/compat_spe_hearing/script_component.hpp new file mode 100644 index 00000000000..8edb825af34 --- /dev/null +++ b/addons/compat_spe/compat_spe_hearing/script_component.hpp @@ -0,0 +1,3 @@ +#define SUBCOMPONENT hearing +#define SUBCOMPONENT_BEAUTIFIED Hearing +#include "..\script_component.hpp" diff --git a/addons/compat_spe/config.cpp b/addons/compat_spe/config.cpp index 5c1ba718d68..13bd24f53dd 100644 --- a/addons/compat_spe/config.cpp +++ b/addons/compat_spe/config.cpp @@ -1,5 +1,4 @@ #include "script_component.hpp" -#include "\z\ace\addons\hearing\script_macros_hearingProtection.hpp" class CfgPatches { class ADDON { From 416845b1ed6041ff65c3fd520069588f1db2815c Mon Sep 17 00:00:00 2001 From: OverlordZorn <56258612+OverlordZorn@users.noreply.github.com> Date: Mon, 13 Jan 2025 22:05:57 +0100 Subject: [PATCH 6/7] Medical Treatment - Change default adv. diagnose setting (#10548) Co-authored-by: Mr. Zorn <56258612+PulsarNeutronStar@users.noreply.github.com> --- addons/medical_treatment/initSettings.inc.sqf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/medical_treatment/initSettings.inc.sqf b/addons/medical_treatment/initSettings.inc.sqf index b5297e7f34b..11166f8002e 100644 --- a/addons/medical_treatment/initSettings.inc.sqf +++ b/addons/medical_treatment/initSettings.inc.sqf @@ -3,7 +3,7 @@ "LIST", [LSTRING(AdvancedDiagnose_DisplayName), LSTRING(AdvancedDiagnose_Description)], LSTRING(Category), - [[0, 1, 2, 3], [ELSTRING(common,Disabled), ELSTRING(common,Enabled), LSTRING(AdvancedDiagnose_DiagnoseCardiacArrest), LSTRING(AdvancedDiagnose_DiagnoseCardiacArrestDirect)], 1], + [[0, 1, 2, 3], [ELSTRING(common,Disabled), ELSTRING(common,Enabled), LSTRING(AdvancedDiagnose_DiagnoseCardiacArrest), LSTRING(AdvancedDiagnose_DiagnoseCardiacArrestDirect)], 2], true ] call CBA_fnc_addSetting; From 5c6b7c124ec95c4c9864699afdfa7b000c86c7fe Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Mon, 13 Jan 2025 15:08:36 -0600 Subject: [PATCH 7/7] Pike - Laser guided 40mm grenade (#6731) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jouni Järvinen --- .../artillerytables/functions/fnc_firedEH.sqf | 3 + addons/missile_clgp/$PBOPREFIX$ | 1 + addons/missile_clgp/ACE_GuidanceConfig.hpp | 0 addons/missile_clgp/CfgAmmo.hpp | 89 +++++++ addons/missile_clgp/CfgEventhandlers.hpp | 15 ++ addons/missile_clgp/CfgMagazineWells.hpp | 5 + addons/missile_clgp/CfgMagazines.hpp | 15 ++ addons/missile_clgp/CfgWeapons.hpp | 0 addons/missile_clgp/GUI.hpp | 0 addons/missile_clgp/README.md | 4 + addons/missile_clgp/XEH_PREP.hpp | 5 + addons/missile_clgp/XEH_postInit.sqf | 5 + addons/missile_clgp/XEH_preInit.sqf | 9 + addons/missile_clgp/XEH_preStart.sqf | 3 + addons/missile_clgp/config.cpp | 22 ++ addons/missile_clgp/data/ace_pike_ammo.p3d | Bin 0 -> 16967 bytes addons/missile_clgp/dev/quickTesting.sqf | 77 +++++++ .../functions/fnc_submunition_ammoFired.sqf | 49 ++++ .../functions/fnc_submunition_applyDrag.sqf | 39 ++++ .../fnc_submunition_submunitionCreated.sqf | 42 ++++ addons/missile_clgp/script_component.hpp | 12 + addons/missile_clgp/stringtable.xml | 14 ++ addons/missile_clgp/ui/gear_pike_ca.paa | Bin 0 -> 25111 bytes addons/missileguidance/XEH_PREP.hpp | 1 + .../missileguidance/functions/fnc_onFired.sqf | 209 +---------------- .../functions/fnc_onFiredGetArgs.sqf | 218 ++++++++++++++++++ docs/wiki/framework/clgp-framework.md | 56 +++++ 27 files changed, 689 insertions(+), 204 deletions(-) create mode 100644 addons/missile_clgp/$PBOPREFIX$ create mode 100644 addons/missile_clgp/ACE_GuidanceConfig.hpp create mode 100644 addons/missile_clgp/CfgAmmo.hpp create mode 100644 addons/missile_clgp/CfgEventhandlers.hpp create mode 100644 addons/missile_clgp/CfgMagazineWells.hpp create mode 100644 addons/missile_clgp/CfgMagazines.hpp create mode 100644 addons/missile_clgp/CfgWeapons.hpp create mode 100644 addons/missile_clgp/GUI.hpp create mode 100644 addons/missile_clgp/README.md create mode 100644 addons/missile_clgp/XEH_PREP.hpp create mode 100644 addons/missile_clgp/XEH_postInit.sqf create mode 100644 addons/missile_clgp/XEH_preInit.sqf create mode 100644 addons/missile_clgp/XEH_preStart.sqf create mode 100644 addons/missile_clgp/config.cpp create mode 100644 addons/missile_clgp/data/ace_pike_ammo.p3d create mode 100644 addons/missile_clgp/dev/quickTesting.sqf create mode 100644 addons/missile_clgp/functions/fnc_submunition_ammoFired.sqf create mode 100644 addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf create mode 100644 addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf create mode 100644 addons/missile_clgp/script_component.hpp create mode 100644 addons/missile_clgp/stringtable.xml create mode 100644 addons/missile_clgp/ui/gear_pike_ca.paa create mode 100644 addons/missileguidance/functions/fnc_onFiredGetArgs.sqf create mode 100644 docs/wiki/framework/clgp-framework.md diff --git a/addons/artillerytables/functions/fnc_firedEH.sqf b/addons/artillerytables/functions/fnc_firedEH.sqf index 5aa46c69690..853dd39debb 100644 --- a/addons/artillerytables/functions/fnc_firedEH.sqf +++ b/addons/artillerytables/functions/fnc_firedEH.sqf @@ -62,6 +62,9 @@ if (_newMuzzleVelocityCoefficent != 1) then { if (_airFriction > 0) exitWith {}; // positive value indicates it has vanilla airFriction, so we can just exit +// For compatiblity with other addons +_projectile setVariable [QGVAR(kFactor), _kFactor]; + [{ params ["_projectile", "_kFactor", "_time"]; diff --git a/addons/missile_clgp/$PBOPREFIX$ b/addons/missile_clgp/$PBOPREFIX$ new file mode 100644 index 00000000000..433858d3351 --- /dev/null +++ b/addons/missile_clgp/$PBOPREFIX$ @@ -0,0 +1 @@ +z\ace\addons\missile_clgp diff --git a/addons/missile_clgp/ACE_GuidanceConfig.hpp b/addons/missile_clgp/ACE_GuidanceConfig.hpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/missile_clgp/CfgAmmo.hpp b/addons/missile_clgp/CfgAmmo.hpp new file mode 100644 index 00000000000..12b153dccc7 --- /dev/null +++ b/addons/missile_clgp/CfgAmmo.hpp @@ -0,0 +1,89 @@ +class CfgAmmo { + class SubmunitionBase; + + + + class GVAR(pike_launch): SubmunitionBase { + model = QPATHTOF(data\ace_pike_ammo.p3d); + submunitionAmmo = QGVAR(pike_guidance); + submunitionCount = 1; + submunitionConeAngle = 0; + triggerTime = 0.1; + class Eventhandlers { + fired = QUOTE(call FUNC(submunition_ammoFired)); + }; + }; + + class MissileBase; + class GVAR(pike_guidance): MissileBase { + irLock = 0; + laserLock = 0; + airLock = 0; + manualControl = 0; + timeToLive = 22; + + model = QPATHTOF(data\ace_pike_ammo.p3d); + maxSpeed = 150; // ~2km in 15sec + thrust = 19; + thrustTime = 14; + initTime = 0; + airFriction = 0.1; + sideAirFriction = 0.1; + + hit = 120; + indirectHit = 10; + indirectHitRange = 10; + warheadName = "HE"; + + EGVAR(frag,enabled) = 1; + EGVAR(frag,force) = 1; + EGVAR(frag,classes)[] = {QEGVAR(frag,tiny_HD)}; + EGVAR(frag,metal) = 200; + EGVAR(frag,charge) = 270; // ~8x a normal 40mm + EGVAR(frag,gurney_c) = 2700; + EGVAR(frag,gurney_k) = "1/2"; + + CraterEffects="ExploAmmoCrater"; + explosionEffects="ExploAmmoExplosion"; + effectsMissileInit = ""; + effectsMissile = "missile2"; + + SoundSetExplosion[] = {"GrenadeHe_Exp_SoundSet", "GrenadeHe_Tail_SoundSet", "Explosion_Debris_SoundSet"}; + soundHit1[] = { "A3\Sounds_F\arsenal\explosives\Grenades\Explosion_gng_grenades_01", 3.1622777, 1, 1500}; + soundHit2[] = { "A3\Sounds_F\arsenal\explosives\Grenades\Explosion_gng_grenades_02", 3.1622777, 1, 1500}; + soundHit3[] = { "A3\Sounds_F\arsenal\explosives\Grenades\Explosion_gng_grenades_03", 3.1622777, 1, 1500}; + soundHit4[] = { "A3\Sounds_F\arsenal\explosives\Grenades\Explosion_gng_grenades_04", 3.1622777, 1, 1500}; + multiSoundHit[] = {"soundHit1", 0.25, "soundHit2", 0.25, "soundHit3", 0.25, "soundHit4", 0.25}; + whistleDist=16; + + // Begin ACE guidance Configs + class ace_missileguidance { + enabled = 2; + + pitchRate = 15; + yawRate = 20; + + canVanillaLock = 0; // Can this default vanilla lock? Only applicable to non-cadet mode + + // Guidance type for munitions + defaultSeekerType = "SALH"; + seekerTypes[] = {"SALH"}; + + defaultSeekerLockMode = "LOAL"; + seekerLockModes[] = {"LOAL"}; + + defaultNavigationType = "Direct"; + navigationTypes[] = { "Direct" }; + + seekerAngle = 90; // Angle in front of the missile which can be searched + seekerAccuracy = 1; // seeker accuracy multiplier + + seekerMinRange = 1; + seekerMaxRange = 3000; // Range from the missile which the seeker can visually search + + // Attack profile type selection + defaultAttackProfile = "LIN"; + attackProfiles[] = {"LIN"}; + }; + }; +}; diff --git a/addons/missile_clgp/CfgEventhandlers.hpp b/addons/missile_clgp/CfgEventhandlers.hpp new file mode 100644 index 00000000000..2a3f71f852d --- /dev/null +++ b/addons/missile_clgp/CfgEventhandlers.hpp @@ -0,0 +1,15 @@ +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_clgp/CfgMagazineWells.hpp b/addons/missile_clgp/CfgMagazineWells.hpp new file mode 100644 index 00000000000..e5ccc8b0749 --- /dev/null +++ b/addons/missile_clgp/CfgMagazineWells.hpp @@ -0,0 +1,5 @@ +class CfgMagazineWells { + class CBA_40mm_EGLM { // for longer grenades that can only fit side breech-loading + ADDON[] = {"ACE_40mm_Pike"}; + }; +}; diff --git a/addons/missile_clgp/CfgMagazines.hpp b/addons/missile_clgp/CfgMagazines.hpp new file mode 100644 index 00000000000..99886a2a938 --- /dev/null +++ b/addons/missile_clgp/CfgMagazines.hpp @@ -0,0 +1,15 @@ +class CfgMagazines { + class 1Rnd_HE_Grenade_shell; + class ACE_40mm_Pike: 1Rnd_HE_Grenade_shell { + author = ECSTRING(common,ACETeam); + displayName = CSTRING(pike_magazine_displayName); + displayNameShort = CSTRING(pike_magazine_displayNameShort); + descriptionShort = CSTRING(pike_magazine_descriptionShort); + picture = QPATHTOF(ui\gear_pike_ca.paa); + ammo = QGVAR(pike_launch); + count = 1; + // model = QPATHTOF(data\ace_pike_ammo.p3d); // just use default pouch + initSpeed = 50; + mass = 12; // ~1.7 Pounds, but high density + }; +}; diff --git a/addons/missile_clgp/CfgWeapons.hpp b/addons/missile_clgp/CfgWeapons.hpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/missile_clgp/GUI.hpp b/addons/missile_clgp/GUI.hpp new file mode 100644 index 00000000000..e69de29bb2d diff --git a/addons/missile_clgp/README.md b/addons/missile_clgp/README.md new file mode 100644 index 00000000000..9e1065a9f00 --- /dev/null +++ b/addons/missile_clgp/README.md @@ -0,0 +1,4 @@ +ace_missile_clgp +=================== + +Cannon Launched Guided Projectiles diff --git a/addons/missile_clgp/XEH_PREP.hpp b/addons/missile_clgp/XEH_PREP.hpp new file mode 100644 index 00000000000..c6d509b520a --- /dev/null +++ b/addons/missile_clgp/XEH_PREP.hpp @@ -0,0 +1,5 @@ +LOG("prep"); + +PREP(submunition_ammoFired); +PREP(submunition_applyDrag); +PREP(submunition_submunitionCreated); diff --git a/addons/missile_clgp/XEH_postInit.sqf b/addons/missile_clgp/XEH_postInit.sqf new file mode 100644 index 00000000000..603af8fcd11 --- /dev/null +++ b/addons/missile_clgp/XEH_postInit.sqf @@ -0,0 +1,5 @@ +#include "script_component.hpp" + +#ifdef ENABLE_QUICK_TESTING +call compileScript [QPATHTOF(dev\quickTesting.sqf)]; +#endif diff --git a/addons/missile_clgp/XEH_preInit.sqf b/addons/missile_clgp/XEH_preInit.sqf new file mode 100644 index 00000000000..b47cf6628db --- /dev/null +++ b/addons/missile_clgp/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_clgp/XEH_preStart.sqf b/addons/missile_clgp/XEH_preStart.sqf new file mode 100644 index 00000000000..022888575ed --- /dev/null +++ b/addons/missile_clgp/XEH_preStart.sqf @@ -0,0 +1,3 @@ +#include "script_component.hpp" + +#include "XEH_PREP.hpp" diff --git a/addons/missile_clgp/config.cpp b/addons/missile_clgp/config.cpp new file mode 100644 index 00000000000..9221b0b9c99 --- /dev/null +++ b/addons/missile_clgp/config.cpp @@ -0,0 +1,22 @@ +#include "script_component.hpp" + +class CfgPatches { + class ADDON { + name = COMPONENT_NAME; + units[] = {}; + weapons[] = {}; + requiredVersion = REQUIRED_VERSION; + requiredAddons[] = {"ace_missileguidance"}; + author = ECSTRING(common,ACETeam); + url = ECSTRING(main,URL); + VERSION_CONFIG; + }; +}; + +#include "ACE_GuidanceConfig.hpp" +#include "CfgAmmo.hpp" +#include "CfgEventhandlers.hpp" +#include "CfgMagazines.hpp" +#include "CfgMagazineWells.hpp" +#include "CfgWeapons.hpp" +#include "GUI.hpp" diff --git a/addons/missile_clgp/data/ace_pike_ammo.p3d b/addons/missile_clgp/data/ace_pike_ammo.p3d new file mode 100644 index 0000000000000000000000000000000000000000..9a60996295df1a501441562028c3c8632c30af12 GIT binary patch literal 16967 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 literal 0 HcmV?d00001 diff --git a/addons/missile_clgp/dev/quickTesting.sqf b/addons/missile_clgp/dev/quickTesting.sqf new file mode 100644 index 00000000000..0bb998648c2 --- /dev/null +++ b/addons/missile_clgp/dev/quickTesting.sqf @@ -0,0 +1,77 @@ +#include "..\script_component.hpp" + +["recompile", "recompile", "recompile", { + private _start = diag_tickTime; + [] call ACE_PREP_RECOMPILE; + [] call ace_common_fnc_dumpPerformanceCounters; + private _end = diag_tickTime; + systemChat format ["recompile took [%1 ms]", (1000 * (_end - _start)) toFixed 1]; + + if (productVersion #4 == "Diag") then { + call compile "diag_mergeConfigFile ['P:\z\ace\addons\missile_clgp\config.cpp']"; + }; + false +}, {false}, [59, [false, false, false]], false] call CBA_fnc_addKeybind; // F1 Key + +DFUNC(dev_trackShell) = { + params ["_projectile"]; + [{ + params ["_projectile", "_time", "_lastVel"]; + if (isNull _projectile) exitWith { true }; + + private _ammo = typeOf _projectile; + if (_ammo isKindOf "SubmunitionBase") then { + private _projectilePos = getPosASL _projectile; + private _forwardPosition = _projectilePos vectorAdd ((vectorNormalized (velocity _projectile)) vectorMultiply 15); + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [1,0,0,1], ASLToAGL _projectilePos, 0.75, 0.75, 0, _ammo, 1, 0.025, "TahomaB"]; + drawIcon3D ["\a3\ui_f\data\IGUI\Cfg\Cursors\selectover_ca.paa", [0.5,0,1,1], ASLToAGL _forwardPosition, 0.75, 0.75, 0, + format ["V: %1 (%2)", round vectorMagnitude velocity _projectile, round ((velocity _projectile) # 2)], 1, 0.025, "TahomaB"]; + drawLine3D [ASLToAGL _projectilePos, ASLToAGL _forwardPosition, [0.5,0,1,1]]; + }; + + private _deltaT = CBA_missionTime - _time; + if (_deltaT < 0.25) exitWith { false }; + + private _curVelocity = velocity _projectile; + private _avgSpeed = 0.5 * vectorMagnitude (_curVelocity vectorAdd _lastVel); + systemChat format ["Vel %1 (%2)", _curVelocity, _avgSpeed]; + + private _diff = _curVelocity vectorDiff _lastVel; + _diff = _diff vectorMultiply (1/_deltaT); + _diff = _diff vectorAdd [0,0,GRAVITY]; + private _drag = (vectorMagnitude _diff) / ((_avgSpeed max 1) ^ 2); + systemChat format ["Drag %1", (100000 * _drag) toFixed 2]; + + // systemChat format ["E %1", (GRAVITY * ((getposasl _projectile) # 2)) + (_avgSpeed ^2)]; + + _this set[1, CBA_missionTime]; + _this set[2, _curVelocity]; + false + }, {}, [_projectile, CBA_missionTime, velocity _projectile]] call CBA_fnc_waitUntilAndExecute; +}; + + +// ["turret", { +// params ["_player", "_turret"]; +// private _veh = vehicle _player; +// if (currentWeapon _veh == "mortar_155mm_AMOS" && {_veh getVariable [QGVAR(needSetup), true]}) then { +// _veh setVariable [QGVAR(needSetup), false]; +// systemChat "Setting up..."; +// for "_i" from 0 to 9 do { _veh addMagazineTurret ["ace_1rnd_155mm_m712", [0], 1]; }; +// _veh loadMagazine [[0], "mortar_155mm_AMOS", "ace_1rnd_155mm_m712"]; +// }; +// }, true] call CBA_fnc_addPlayerEventHandler; + +{ + _x addEventHandler ["Fired", { + params ["", "", "", "", "", "", "_projectile"]; + _projectile call FUNC(dev_trackShell); + _projectile addEventHandler ["SubmunitionCreated", { + params ["_projectile", "_submunitionProjectile"]; + hint format ["sub\n%1\n=%2 %3\n\n%4\n%5 %6", + velocity _projectile, vectorMagnitude velocity _projectile, local _projectile, + velocity _submunitionProjectile, vectorMagnitude velocity _submunitionProjectile, local _submunitionProjectile]; + _submunitionProjectile call FUNC(dev_trackShell); + }]; + }]; +} forEach (vehicles + [player]); diff --git a/addons/missile_clgp/functions/fnc_submunition_ammoFired.sqf b/addons/missile_clgp/functions/fnc_submunition_ammoFired.sqf new file mode 100644 index 00000000000..39aa6b97182 --- /dev/null +++ b/addons/missile_clgp/functions/fnc_submunition_ammoFired.sqf @@ -0,0 +1,49 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Generic handler for firing a clgp submuntion ammo. Called from the ammo's fired EH. + * + * Arguments: + * FiredEH + * + * Return Value: + * Nothing + * + * Example: + * [] call ace_missile_clgp_fnc_submunition_ammoFired + * + * Public: No + */ + +params ["_unit", "", "", "", "_ammo", "", "_projectile", "_gunner"]; +if (!local _gunner) exitWith {}; +if (isNull _projectile) exitWith {}; +TRACE_4("ammoFired local",typeOf _unit,_ammo,_projectile,_gunner); +private _ammoCfg = configOf _projectile; + +// Get MissileGuidance args now +private _firedEH = +_this; +// Inject the submunition ammo into guidance args +_firedEH set [4, getText (_ammoCfg >> "submunitionAmmo")]; +private _guidanceArgs = _firedEH call EFUNC(missileguidance,onFiredGetArgs); +if (_guidanceArgs isEqualTo []) then { WARNING_1("no args %1",_projectile); }; +_projectile setVariable [QGVAR(guidanceArgs), _guidanceArgs]; + +// On missile deploy start guidance +_projectile addEventHandler ["SubmunitionCreated", LINKFUNC(submunition_submunitionCreated)]; + +// Trigger ammo when conditions are met +private _deployCondition = getText (_ammoCfg >> QGVAR(deployCondition)); +if (_deployCondition != "") then { + _deployCondition = missionNamespace getVariable [_deployCondition, { ERROR("bad func"); true} ]; + [{ + params ["_projectile", "", "_deployCondition"]; + if (isNull _projectile) exitWith { true }; + _this call _deployCondition + }, { + params ["_projectile"]; + if (isNull _projectile) exitWith { TRACE_1("null at trigger condition %1",_projectile); }; + TRACE_1("triggerAmmo",_projectile); + triggerAmmo _projectile; + }, [_projectile, _guidanceArgs, _deployCondition]] call CBA_fnc_waitUntilAndExecute; +}; diff --git a/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf b/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf new file mode 100644 index 00000000000..b0f6b3303cd --- /dev/null +++ b/addons/missile_clgp/functions/fnc_submunition_applyDrag.sqf @@ -0,0 +1,39 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Applies drag to a missile (based on ace_artillerytables_fnc_firedEH) + * + * Arguments: + * 0: Projectile + * 1: Drag + * 2: Last time ran (modified via _this array) + * + * Return Value: + * None + * + * Example: + * [x, 2, 2] call ace_missile_clgp_fnc_submunition_applyDrag + * + * Public: No + */ + +params ["_projectile", "_kFactor", "_time"]; + +private _bulletVelocity = velocity _projectile; +private _deltaT = CBA_missionTime - _time; +_this set [2, CBA_missionTime]; + +if (_kFactor != 0) then { + private _trueVelocity = _bulletVelocity vectorDiff wind; + private _trueSpeed = vectorMagnitude _trueVelocity; + + private _drag = _deltaT * _kFactor * _trueSpeed; + private _accel = _trueVelocity vectorMultiply _drag; + _bulletVelocity = _bulletVelocity vectorAdd _accel; + + _projectile setVelocity _bulletVelocity; +}; + +private _dir = vectorNormalized _bulletVelocity; +_projectile setVectorDirAndUp [_dir, _dir vectorCrossProduct vectorSide _projectile]; +TRACE_2("setVectorDirAndUp",_projectile,_dir); diff --git a/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf b/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf new file mode 100644 index 00000000000..8c1be94a802 --- /dev/null +++ b/addons/missile_clgp/functions/fnc_submunition_submunitionCreated.sqf @@ -0,0 +1,42 @@ +#include "..\script_component.hpp" +/* + * Author: PabstMirror + * Generic handler for submunitionCreated + * + * Arguments: + * 0: Old Projectile + * 1: New Projectile + * + * Return Value: + * Nothing + * + * Example: + * [a,b] call ace_missile_clgp_fnc_submunition_submunitionCreated + * + * Public: No + */ + +params ["_projectile", "_submunitionProjectile"]; + +private _guidanceArgs = _projectile getVariable [QGVAR(guidanceArgs), []]; +TRACE_2("submunitionCreated",typeOf _projectile,typeOf _submunitionProjectile); +if (isNull _submunitionProjectile) exitWith { WARNING_1("null %1",_this); }; + +if (_guidanceArgs isNotEqualTo []) then { // Inject the submunition projectile and time into guidance args + _guidanceArgs params ["_firedEH", "", "", "", "_stateParams"]; + _firedEH set [6, _submunitionProjectile]; // _firedEH params ["","","","","","","_projectile"]; + _stateParams set [0, diag_tickTime]; // _stateParams params ["_lastRunTime"] + TRACE_2("-Starting missileGuidance",_submunitionProjectile,count _guidanceArgs); + [EFUNC(missileguidance,guidancePFH), 0, _guidanceArgs] call CBA_fnc_addPerFrameHandler; +}; + +private _deployArtilleryDragConfig = (configOf _projectile) >> QGVAR(artilleryDrag); +if (isNumber _deployArtilleryDragConfig) then { + private _deployArtilleryDrag = getNumber _deployArtilleryDragConfig; + if (_deployArtilleryDrag < 0) exitWith { TRACE_1("-Ignoring Drag",_deployArtilleryDrag); }; + private _kFactor = _projectile getVariable [QEGVAR(artillerytables,kFactor), 0]; + TRACE_2("-Drag",_deployArtilleryDrag,_kFactor); + _kFactor = _kFactor * _deployArtilleryDrag; // Can be 0 from either source (0 is valid and will keep nose pointed) + private _dragArray = [_submunitionProjectile, _kFactor, CBA_missionTime]; + _submunitionProjectile setVariable [QGVAR(dragArray), _dragArray]; +}; diff --git a/addons/missile_clgp/script_component.hpp b/addons/missile_clgp/script_component.hpp new file mode 100644 index 00000000000..2d2043b2a12 --- /dev/null +++ b/addons/missile_clgp/script_component.hpp @@ -0,0 +1,12 @@ +#define COMPONENT missile_clgp +#define COMPONENT_BEAUTIFIED Cannon Launched Guided Projectiles +#include "\z\ace\addons\main\script_mod.hpp" + +// #define DEBUG_MODE_FULL +// #define DISABLE_COMPILE_CACHE +// #define ENABLE_QUICK_TESTING +// #define ENABLE_PERFORMANCE_COUNTERS + +#include "\z\ace\addons\main\script_macros.hpp" + +#define COPPERHEAD_DEFUALT_SETTINGS [ARR_5(1,1,1,1,1)] diff --git a/addons/missile_clgp/stringtable.xml b/addons/missile_clgp/stringtable.xml new file mode 100644 index 00000000000..3c6d47beb55 --- /dev/null +++ b/addons/missile_clgp/stringtable.xml @@ -0,0 +1,14 @@ + + + + + Semi-Active Laser Guided 40mm Grenade + + + 40mm Pike + + + Pike SALH + + + diff --git a/addons/missile_clgp/ui/gear_pike_ca.paa b/addons/missile_clgp/ui/gear_pike_ca.paa new file mode 100644 index 0000000000000000000000000000000000000000..1b0ecb3807810796e38ebe0a352bfca928621615 GIT binary patch literal 25111 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 + * 1: Weapon + * 3: Mode * 4: Ammo * 6: Projectile * @@ -30,212 +32,11 @@ if ( !isPlayer _shooter && { GVAR(enabled) < 2 } ) exitWith {}; // Verify ammo has explicity added guidance config (ignore inheritances) private _configs = configProperties [(configFile >> "CfgAmmo" >> _ammo), QUOTE(configName _x == QUOTE(QUOTE(ADDON))), false]; -if ((count _configs) < 1) exitWith {}; +if (_configs isEqualTo []) exitWith {}; -// MissileGuidance is enabled for this shot -TRACE_4("enabled",_shooter,_ammo,_projectile,typeOf _shooter); - -private _config = configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON); - -private _target = _shooter getVariable [QGVAR(target), nil]; -private _targetPos = _shooter getVariable [QGVAR(targetPosition), nil]; -private _seekerType = _shooter getVariable [QGVAR(seekerType), nil]; -private _attackProfile = _shooter getVariable [QGVAR(attackProfile), nil]; -private _navigationType = _shooter getVariable [QGVAR(navigationType), nil]; -if ((getNumber (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON) >> "useModeForAttackProfile")) == 1) then { - _attackProfile = getText (configFile >> "CfgWeapons" >> _weapon >> _mode >> QGVAR(attackProfile)) -}; -private _lockMode = _shooter getVariable [QGVAR(lockMode), nil]; - -private _laserCode = _shooter getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE]; -private _laserInfo = [_laserCode, ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_WAVELENGTH]; - -TRACE_7("getVars",_target,_targetPos,_seekerType,_attackProfile,_lockMode,_laserCode,_navigationType); - -private _launchPos = getPosASL (vehicle _shooter); - -if (isNil "_seekerType" || {!(_seekerType in (getArray (_config >> "seekerTypes")))}) then { - _seekerType = getText (_config >> "defaultSeekerType"); -}; -if (isNil "_attackProfile" || {!(_attackProfile in (getArray (_config >> "attackProfiles")))}) then { - _attackProfile = getText (_config >> "defaultAttackProfile"); -}; -if (isNil "_lockMode" || {!(_lockMode in (getArray (_config >> "seekerLockModes")))}) then { - _lockMode = getText (_config >> "defaultSeekerLockMode"); -}; -if (isNil "_navigationType" || {!(_navigationType in (getArray (_config >> "navigationTypes")))}) then { - _navigationType = getText (_config >> "defaultNavigationType"); -}; - -if (isNil "_navigationType" || _navigationType isEqualTo "") then { - // most missiles use ProNav by default - _navigationType = "ProportionalNavigation"; -}; - -// If we didn't get a target, try to fall back on tab locking -if (isNil "_target") then { - if (!isPlayer _shooter) then { - // This was an AI shot, lets still guide it on the AI target - _target = _shooter getVariable [QGVAR(vanilla_target), nil]; - TRACE_1("Detected AI Shooter!",_target); - } else { - private _canUseLock = getNumber (_config >> "canVanillaLock"); - // @TODO: Get vanilla target - if (_canUseLock > 0 || difficulty < 1) then { - private _vanillaTarget = missileTarget _projectile; - - TRACE_1("Using Vanilla Locking",_vanillaTarget); - if (!isNil "_vanillaTarget") then { - _target = _vanillaTarget; - }; - }; - }; -}; -_targetPos = getPosASLVisual _target; - -// Array for seek last target position -private _seekLastTargetPos = (getNumber ( _config >> "seekLastTargetPos")) == 1; -private _lastKnownPosState = [_seekLastTargetPos]; -if (_seekLastTargetPos && {!isNil "_target"}) then { - _lastKnownPosState set [1, (getPosASL _target)]; -} else { - _lastKnownPosState set [1, [0,0,0]]; -}; - -private _navigationParameters = [ - // set up in navigation type onFired function -]; - -// default config values to make sure there is backwards compat -private _pitchRate = 30; -private _yawRate = 30; -private _bangBang = false; -if (isNumber (_config >> "pitchRate")) then { - _pitchRate = getNumber ( _config >> "pitchRate" ); - _yawRate = getNumber ( _config >> "yawRate" ); - _bangBang = (1 == getNumber (_config >> "bangBangGuidance")); -}; - -// How much this projectile likes to stay toward current velocity -private _stabilityCoefficient = getNumber (_config >> "stabilityCoefficient"); - -// show a light trail in flight -private _showTrail = (1 == getNumber (_config >> "showTrail")); - -private _navigationStateSubclass = _config >> "navigationStates"; -private _states = getArray (_navigationStateSubclass >> "states"); - -private _navigationStateData = []; - -if (_states isNotEqualTo []) then { - { - private _stateClass = _navigationStateSubclass >> _x; - _navigationStateData pushBack [ - getText (_stateClass >> "transitionCondition"), - getText (_stateClass >> "navigationType"), - [] - ]; - } forEach _states; -}; - -private _initialRoll = getNumber (_config >> "initialRoll"); -private _initialYaw = getNumber (_config >> "initialYaw"); -private _initialPitch = getNumber (_config >> "initialPitch"); - -private _yawRollPitch = (vectorDir _projectile) call CBA_fnc_vect2Polar; - -TRACE_5("Beginning ACE guidance system",_target,_ammo,_seekerType,_attackProfile,_navigationType); -private _args = [_this, - [ _shooter, - [_target, _targetPos, _launchPos, vectorDirVisual vehicle _shooter, CBA_missionTime], - _seekerType, - _attackProfile, - _lockMode, - _laserInfo, - _navigationType - ], - [ - _pitchRate, - _yawRate, - _bangBang, - _stabilityCoefficient, - _showTrail - ], - [ - getNumber ( _config >> "seekerAngle" ), - getNumber ( _config >> "seekerAccuracy" ), - getNumber ( _config >> "seekerMaxRange" ), - getNumber ( _config >> "seekerMinRange" ) - ], - [ diag_tickTime, [], [], _lastKnownPosState, _navigationParameters, [_initialYaw + (_yawRollPitch select 1), _initialRoll, _initialPitch + (_yawRollPitch select 2)]], - [ - // target data from missile. Must be filled by seeker for navigation to work - [0, 0, 0], // direction to target - [0, 0, 0], // direction to attack profile - 0, // range to target - [0, 0, 0], // target velocity - [0, 0, 0] // target acceleration - ], - [0, _navigationStateData] - ]; - -private _onFiredFunc = getText (configFile >> QGVAR(SeekerTypes) >> _seekerType >> "onFired"); -TRACE_1("seeker on fired",_onFiredFunc); -if (_onFiredFunc != "") then { - _args call (missionNamespace getVariable _onFiredFunc); -}; - -_onFiredFunc = getText (configFile >> QGVAR(AttackProfiles) >> _attackProfile >> "onFired"); -TRACE_1("attack on fired",_onFiredFunc); -if (_onFiredFunc != "") then { - _args call (missionNamespace getVariable _onFiredFunc); -}; - -if (_states isEqualTo []) then { - _onFiredFunc = getText (configFile >> QGVAR(NavigationTypes) >> _navigationType >> "onFired"); - TRACE_1("navigation on fired",_onFiredFunc); - if (_onFiredFunc != "") then { - private _navState = (_args call (missionNamespace getVariable _onFiredFunc)); - (_args select 4) set [4, _navState]; - }; -} else { - { - _onFiredFunc = getText (configFile >> QGVAR(NavigationTypes) >> _x >> "onFired"); - TRACE_1("navigation on fired",_onFiredFunc); - if (_onFiredFunc != "") then { - private _navState = (_args call (missionNamespace getVariable _onFiredFunc)); - (_navigationStateData select _forEachIndex) set [2, _navState]; - }; - } forEach getArray (_config >> "navigationTypes"); -}; - -// Run the "onFired" function passing the full guidance args array -_onFiredFunc = getText (_config >> "onFired"); -TRACE_1("general on fired",_onFiredFunc); -if (_onFiredFunc != "") then { - _args call (missionNamespace getVariable _onFiredFunc); -}; - -// Reverse: -// _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"]; -// _firedEH params ["_shooter","","","","_ammo","","_projectile"]; -// _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; -// _targetLaunchParams params ["_target", "_targetPos", "_launchPos", "_launchDir", "_launchTime"]; -// _flightParams params ["_pitchRate", "_yawRate", "_isBangBangGuidance"]; -// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState", "_navigationParams", "_guidanceParameters"]; -// _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; -// _targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; - -[LINKFUNC(guidancePFH),0, _args ] call CBA_fnc_addPerFrameHandler; +private _args = call FUNC(onFiredGetArgs); +[LINKFUNC(guidancePFH),0, _args] call CBA_fnc_addPerFrameHandler; if (GVAR(debug_enableMissileCamera)) then { [_projectile] call FUNC(dev_ProjectileCamera); }; - - -/* Clears locking settings -(vehicle _shooter) setVariable [QGVAR(target), nil]; -(vehicle _shooter) setVariable [QGVAR(seekerType), nil]; -(vehicle _shooter) setVariable [QGVAR(attackProfile), nil]; -(vehicle _shooter) setVariable [QGVAR(lockMode), nil]; - */ diff --git a/addons/missileguidance/functions/fnc_onFiredGetArgs.sqf b/addons/missileguidance/functions/fnc_onFiredGetArgs.sqf new file mode 100644 index 00000000000..93bd58e4c31 --- /dev/null +++ b/addons/missileguidance/functions/fnc_onFiredGetArgs.sqf @@ -0,0 +1,218 @@ +#include "..\script_component.hpp" +/* + * Author: jaynus, nou, TCVM, PabstMirror + * Gets guidance args for a fired missile, running fired EHs and returning the full guidance arg array + * + * Arguments: + * 0: Shooter (Man/Vehicle) + * 1: Weapon + * 3: Mode + * 4: Ammo (in the future) + * 6: Projectile + * + * Return Value: + * + * + * Example: + * [player, "", "", "", "ACE_Javelin_FGM148", "", theMissile] call ace_missileguidance_fnc_onFiredGetArgs + * + * Public: No + */ + +params ["_shooter","_weapon","","_mode","_ammo","","_projectile"]; + +// MissileGuidance is enabled for this shot +TRACE_4("enabled",_shooter,_ammo,_projectile,typeOf _shooter); + +private _config = configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON); + +private _target = _shooter getVariable [QGVAR(target), nil]; +private _targetPos = _shooter getVariable [QGVAR(targetPosition), nil]; +private _seekerType = _shooter getVariable [QGVAR(seekerType), nil]; +private _attackProfile = _shooter getVariable [QGVAR(attackProfile), nil]; +private _navigationType = _shooter getVariable [QGVAR(navigationType), nil]; +if ((getNumber (configFile >> "CfgAmmo" >> _ammo >> QUOTE(ADDON) >> "useModeForAttackProfile")) == 1) then { + _attackProfile = getText (configFile >> "CfgWeapons" >> _weapon >> _mode >> QGVAR(attackProfile)) +}; +private _lockMode = _shooter getVariable [QGVAR(lockMode), nil]; + +private _laserCode = _shooter getVariable [QEGVAR(laser,code), ACE_DEFAULT_LASER_CODE]; +private _laserInfo = [_laserCode, ACE_DEFAULT_LASER_WAVELENGTH, ACE_DEFAULT_LASER_WAVELENGTH]; + +TRACE_7("onFiredGetArgs",_target,_targetPos,_seekerType,_attackProfile,_lockMode,_laserCode,_navigationType); + +private _launchPos = getPosASL (vehicle _shooter); + +if (isNil "_seekerType" || {!(_seekerType in (getArray (_config >> "seekerTypes")))}) then { + _seekerType = getText (_config >> "defaultSeekerType"); +}; +if (isNil "_attackProfile" || {!(_attackProfile in (getArray (_config >> "attackProfiles")))}) then { + _attackProfile = getText (_config >> "defaultAttackProfile"); +}; +if (isNil "_lockMode" || {!(_lockMode in (getArray (_config >> "seekerLockModes")))}) then { + _lockMode = getText (_config >> "defaultSeekerLockMode"); +}; +if (isNil "_navigationType" || {!(_navigationType in (getArray (_config >> "navigationTypes")))}) then { + _navigationType = getText (_config >> "defaultNavigationType"); +}; + +if (isNil "_navigationType" || _navigationType isEqualTo "") then { + // most missiles use ProNav by default + _navigationType = "ProportionalNavigation"; +}; + +// If we didn't get a target, try to fall back on tab locking +if (isNil "_target") then { + if (!isPlayer _shooter) then { + // This was an AI shot, lets still guide it on the AI target + _target = _shooter getVariable [QGVAR(vanilla_target), nil]; + TRACE_1("Detected AI Shooter!",_target); + } else { + private _canUseLock = getNumber (_config >> "canVanillaLock"); + // @TODO: Get vanilla target + if (_canUseLock > 0 || difficulty < 1) then { + private _vanillaTarget = missileTarget _projectile; + + TRACE_1("Using Vanilla Locking",_vanillaTarget); + if (!isNil "_vanillaTarget") then { + _target = _vanillaTarget; + }; + }; + }; +}; +_targetPos = getPosASLVisual _target; + +// Array for seek last target position +private _seekLastTargetPos = (getNumber ( _config >> "seekLastTargetPos")) == 1; +private _lastKnownPosState = [_seekLastTargetPos]; +if (_seekLastTargetPos && {!isNil "_target"}) then { + _lastKnownPosState set [1, (getPosASL _target)]; +} else { + _lastKnownPosState set [1, [0,0,0]]; +}; + +private _navigationParameters = [ + // set up in navigation type onFired function +]; + +// default config values to make sure there is backwards compat +private _pitchRate = 30; +private _yawRate = 30; +private _bangBang = false; +if (isNumber (_config >> "pitchRate")) then { + _pitchRate = getNumber ( _config >> "pitchRate" ); + _yawRate = getNumber ( _config >> "yawRate" ); + _bangBang = (1 == getNumber (_config >> "bangBangGuidance")); +}; + +// How much this projectile likes to stay toward current velocity +private _stabilityCoefficient = getNumber (_config >> "stabilityCoefficient"); + +// show a light trail in flight +private _showTrail = (1 == getNumber (_config >> "showTrail")); + +private _navigationStateSubclass = _config >> "navigationStates"; +private _states = getArray (_navigationStateSubclass >> "states"); + +private _navigationStateData = []; + +if (_states isNotEqualTo []) then { + { + private _stateClass = _navigationStateSubclass >> _x; + _navigationStateData pushBack [ + getText (_stateClass >> "transitionCondition"), + getText (_stateClass >> "navigationType"), + [] + ]; + } forEach _states; +}; + +private _initialRoll = getNumber (_config >> "initialRoll"); +private _initialYaw = getNumber (_config >> "initialYaw"); +private _initialPitch = getNumber (_config >> "initialPitch"); + +private _yawRollPitch = (vectorDir _projectile) call CBA_fnc_vect2Polar; + +TRACE_5("Beginning ACE guidance system",_target,_ammo,_seekerType,_attackProfile,_navigationType); +private _args = [_this, + [ _shooter, + [_target, _targetPos, _launchPos, vectorDirVisual vehicle _shooter, CBA_missionTime], + _seekerType, + _attackProfile, + _lockMode, + _laserInfo, + _navigationType + ], + [ + _pitchRate, + _yawRate, + _bangBang, + _stabilityCoefficient, + _showTrail + ], + [ + getNumber ( _config >> "seekerAngle" ), + getNumber ( _config >> "seekerAccuracy" ), + getNumber ( _config >> "seekerMaxRange" ), + getNumber ( _config >> "seekerMinRange" ) + ], + [ diag_tickTime, [], [], _lastKnownPosState, _navigationParameters, [_initialYaw + (_yawRollPitch select 1), _initialRoll, _initialPitch + (_yawRollPitch select 2)]], + [ + // target data from missile. Must be filled by seeker for navigation to work + [0, 0, 0], // direction to target + [0, 0, 0], // direction to attack profile + 0, // range to target + [0, 0, 0], // target velocity + [0, 0, 0] // target acceleration + ], + [0, _navigationStateData] + ]; + +private _onFiredFunc = getText (configFile >> QGVAR(SeekerTypes) >> _seekerType >> "onFired"); +TRACE_1("seeker on fired",_onFiredFunc); +if (_onFiredFunc != "") then { + _args call (missionNamespace getVariable _onFiredFunc); +}; + +_onFiredFunc = getText (configFile >> QGVAR(AttackProfiles) >> _attackProfile >> "onFired"); +TRACE_1("attack on fired",_onFiredFunc); +if (_onFiredFunc != "") then { + _args call (missionNamespace getVariable _onFiredFunc); +}; + +if (_states isEqualTo []) then { + _onFiredFunc = getText (configFile >> QGVAR(NavigationTypes) >> _navigationType >> "onFired"); + TRACE_1("navigation on fired",_onFiredFunc); + if (_onFiredFunc != "") then { + private _navState = (_args call (missionNamespace getVariable _onFiredFunc)); + (_args select 4) set [4, _navState]; + }; +} else { + { + _onFiredFunc = getText (configFile >> QGVAR(NavigationTypes) >> _x >> "onFired"); + TRACE_1("navigation on fired",_onFiredFunc); + if (_onFiredFunc != "") then { + private _navState = (_args call (missionNamespace getVariable _onFiredFunc)); + (_navigationStateData select _forEachIndex) set [2, _navState]; + }; + } forEach getArray (_config >> "navigationTypes"); +}; + +// Run the "onFired" function passing the full guidance args array +_onFiredFunc = getText (_config >> "onFired"); +TRACE_1("general on fired",_onFiredFunc); +if (_onFiredFunc != "") then { + _args call (missionNamespace getVariable _onFiredFunc); +}; + +// Reverse: +// _args params ["_firedEH", "_launchParams", "_flightParams", "_seekerParams", "_stateParams", "_targetData", "_navigationStateData"]; +// _firedEH params ["_shooter","","","","_ammo","","_projectile"]; +// _launchParams params ["_shooter","_targetLaunchParams","_seekerType","_attackProfile","_lockMode","_laserInfo","_navigationType"]; +// _targetLaunchParams params ["_target", "_targetPos", "_launchPos", "_launchDir", "_launchTime"]; +// _flightParams params ["_pitchRate", "_yawRate", "_isBangBangGuidance"]; +// _stateParams params ["_lastRunTime", "_seekerStateParams", "_attackProfileStateParams", "_lastKnownPosState", "_navigationParams", "_guidanceParameters"]; +// _seekerParams params ["_seekerAngle", "_seekerAccuracy", "_seekerMaxRange", "_seekerMinRange"]; +// _targetData params ["_targetDirection", "_attackProfileDirection", "_targetRange", "_targetVelocity", "_targetAcceleration"]; + +_args diff --git a/docs/wiki/framework/clgp-framework.md b/docs/wiki/framework/clgp-framework.md new file mode 100644 index 00000000000..8d8dc6dda43 --- /dev/null +++ b/docs/wiki/framework/clgp-framework.md @@ -0,0 +1,56 @@ +--- +layout: wiki +title: Missile CLGP Framework +description: Explains how to set-up ammo for the cannon-launched-guided-projectile system. +group: framework +parent: wiki +order: 7 +mod: ace +version: + major: 3 + minor: 0 + patch: 0 +--- + +## 1. Overview + +CLGP allows firing submunition shells that will deploy into missiles that can use the Missile Guidance framework. + +## 2. Config Values + +### 2.1 Example Config +```cpp +class CfgAmmo { + class x_submunition: SubmunitionBase { // this ammo can be fired normally + ace_missile_clgp_deployCondition = "your_fnc"; // function that returns true when it should be triggered + ace_missile_clgp_artilleryDrag = 1; + submunitionAmmo = "x_missle"; + class Eventhandlers { + fired = "call ace_missile_clgp_fnc_submunition_ammoFired"; // need to add the EH yourself to all ammos + }; + }; + + class x_missle: MissileBase { + class ace_missileguidance { + enabled = 2; + // rest of normal ace missile guidance config +``` + +### 2.2 Configs + +`ace_missile_clgp_deployCondition` +- A function that will trigger the ammo when returning true, passed `[_projectile, _guidanceArgs]` +- Is optional, can just use normal submuntion triggers + +`ace_missile_clgp_artilleryDrag` +- Optional (Leave undefined (or set to -1) to ignore) +- Used as a coefficient on drag from ace_artilleryTables's advancedCorrections +- Value of 0 is valid and will not apply drag but still keep nose pointed correctly (for unpowered missiles) + +## 3. Note on adding magazines via mission + +```cpp +if (local turretLocal [0]) then { + this addMagazineTurret ["ace_1rnd_155mm_m712", [0]]; +}; +```