From 5d3c28b807a20c7f8ee6e032d718a912bc924b6a Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Wed, 7 Feb 2024 13:11:58 -0800 Subject: [PATCH 1/8] ready for dedi --- framework/CfgFunctions.hpp | 10 +- .../client/functions/fn_addZenModules.sqf | 55 ---- framework/init/functions/fn_initClient.sqf | 3 + framework/zeus/functions/fn_addZenModules.sqf | 294 ++++++++++++++++++ framework/zeus/functions/fn_initClient.sqf | 14 + framework/zeus/script_component.hpp | 3 + 6 files changed, 323 insertions(+), 56 deletions(-) create mode 100644 framework/zeus/functions/fn_addZenModules.sqf create mode 100644 framework/zeus/functions/fn_initClient.sqf create mode 100644 framework/zeus/script_component.hpp diff --git a/framework/CfgFunctions.hpp b/framework/CfgFunctions.hpp index d9e5f96..5f23081 100644 --- a/framework/CfgFunctions.hpp +++ b/framework/CfgFunctions.hpp @@ -35,10 +35,10 @@ class CfgFunctions { class DOUBLES(PREFIX,client) { class functions { file = "framework\client\functions"; - class addZenModules { postInit = 1; }; class bindEmptyGroupGarbageCleanup { postInit = 1; }; class bindEventHandlers { postInit = 1; }; class bindVehicleActions { postInit = 1; }; + class addZenModules {postInit = 1;}; }; }; @@ -169,4 +169,12 @@ class CfgFunctions { class isClassExcluded {}; }; }; + + class DOUBLES(PREFIX,zeus) { + class functions { + file = "framework\zeus\functions"; + class initClient {}; + class addZenModules {}; + }; + }; }; \ No newline at end of file diff --git a/framework/client/functions/fn_addZenModules.sqf b/framework/client/functions/fn_addZenModules.sqf index 0aeb533..d59ff07 100644 --- a/framework/client/functions/fn_addZenModules.sqf +++ b/framework/client/functions/fn_addZenModules.sqf @@ -2,61 +2,6 @@ if ( !hasInterface ) exitWith {}; -[ - QUOTE(MODULE_CATEGORY_NAME), - "Create Resupply Box", - { - params [["_pos", [0,0,0], [[]], 3], ["_target", objNull, [objNull]]]; - // get parent definition - private _supplyCratesCfg = call EFUNC(resupply,getSupplyCratesCfg); - // get the subclass names - private _boxTypesAvailable = _supplyCratesCfg call BIS_fnc_getCfgSubClasses; - - _boxTypesAvailable sort true; - _comboOptions = _boxTypesAvailable apply { - [ - // display name - [_supplyCratesCfg >> _x >> "displayName", "STRING", "ERROR"] call CBA_fnc_getConfigEntry, - // tooltip - [_supplyCratesCfg >> _x >> "tooltip", "STRING", "ERROR"] call CBA_fnc_getConfigEntry, - // icon - [_supplyCratesCfg >> _x >> "icon", "STRING", "ERROR"] call CBA_fnc_getConfigEntry - ] - }; - - [ - "Resupply Box Options", - [ - // [ "COMBO", "Box Type", [[1,2,3], [["Ammo"],["Weapons"],["Medical"]],0] ] - ["COMBO", "Box Type", [_boxTypesAvailable, _comboOptions, 0]] - ], - { - - params ["_dialog", "_args"]; - - _dialog params ["_typeOptionSelected"]; - _args params ["_pos", "_target", "_keysSorted"]; - - - private _box = [_target, _typeOptionSelected, _pos] call EFUNC(resupply,createBox); - if (isNull _box) exitWith { - ["Resupply Box", "WARNING: Failed to locate or create box!"] call BIS_fnc_curatorHint; - }; - [ - "Resupply Box", - format[ - "Created %1", - getText((call EFUNC(resupply,getSupplyCratesCfg)) >> _typeOptionSelected >> "displayName") - ] - ] call BIS_fnc_curatorHint; - }, - {}, - [_pos, _target] - ] call zen_dialog_fnc_create; - } -] call zen_custom_modules_fnc_register; - - [ QUOTE(MODULE_CATEGORY_NAME), "Grounds Cleanup", diff --git a/framework/init/functions/fn_initClient.sqf b/framework/init/functions/fn_initClient.sqf index a7d106a..3f2edc7 100644 --- a/framework/init/functions/fn_initClient.sqf +++ b/framework/init/functions/fn_initClient.sqf @@ -20,6 +20,7 @@ call EFUNC(reinsert,initClient); call EFUNC(resupply,initClient); call EFUNC(triageIcons,initClient); call EFUNC(vehicleFlags,initClient); +call EFUNC(zeus,initClient); call EFUNC(fbcb2_main,initClient); call EFUNC(fbcb2_assets,initClient); @@ -31,4 +32,6 @@ call EFUNC(fbcb2_assets,initClient); [] ] call EFUNC(common,log); +localNamespace setVariable [QGVAR(complete), true]; + nil; \ No newline at end of file diff --git a/framework/zeus/functions/fn_addZenModules.sqf b/framework/zeus/functions/fn_addZenModules.sqf new file mode 100644 index 0000000..41f29e0 --- /dev/null +++ b/framework/zeus/functions/fn_addZenModules.sqf @@ -0,0 +1,294 @@ +#include "..\script_component.hpp" + +if ( !hasInterface ) exitWith {}; + +// Create Resupply Box +[ + QUOTE(MODULE_CATEGORY_NAME), + "Create Resupply Box", + { + // module placement + params [["_pos", [0,0,0], [[]], 3], ["_target", objNull, [objNull]]]; + // get parent definition + private _supplyCratesCfg = call EFUNC(resupply,getSupplyCratesCfg); + // get the subclass names + private _boxTypesAvailable = _supplyCratesCfg call BIS_fnc_getCfgSubClasses; + + _boxTypesAvailable sort true; + _comboOptions = _boxTypesAvailable apply { + [ + // display name + [_supplyCratesCfg >> _x >> "displayName", "STRING", "ERROR"] call CBA_fnc_getConfigEntry, + // tooltip + [_supplyCratesCfg >> _x >> "tooltip", "STRING", "ERROR"] call CBA_fnc_getConfigEntry, + // icon + [_supplyCratesCfg >> _x >> "icon", "STRING", "ERROR"] call CBA_fnc_getConfigEntry + ] + }; + + [ // create the dialog + "Resupply Box Options", + [ + // [ "COMBO", "Box Type", [[1,2,3], [["Ammo"],["Weapons"],["Medical"]],0] ] + ["COMBO", "Box Type", [_boxTypesAvailable, _comboOptions, 0]] + ], + { + + params ["_dialog", "_args"]; + + _dialog params ["_typeOptionSelected"]; + _args params ["_pos", "_target", "_keysSorted"]; + + + private _box = [_target, _typeOptionSelected, _pos] call EFUNC(resupply,createBox); + if (isNull _box) exitWith { + ["Resupply Box", "WARNING: Failed to locate or create box!"] call BIS_fnc_curatorHint; + }; + [ + "Resupply Box", + format[ + "Created %1", + getText((call EFUNC(resupply,getSupplyCratesCfg)) >> _typeOptionSelected >> "displayName") + ] + ] call BIS_fnc_curatorHint; + }, + {}, + [_pos, _target] + ] call zen_dialog_fnc_create; + } +] call zen_custom_modules_fnc_register; + +// Manage wheels in a vehicle's ACE cargo +[ + QUOTE(MODULE_CATEGORY_NAME), + "Manage Wheels in Vehicle", + { + // module placement + params [["_pos", [0,0,0], [[]], 3], ["_target", objNull, [objNull]]]; + + if (isNull _target) exitWith { + ["Manage Wheels in Vehicle", "WARNING: No vehicle selected!"] call BIS_fnc_curatorHint; + }; + + if (_target isKindOf "CAManBase") exitWith { + ["Manage Wheels in Vehicle", "WARNING: Cannot add wheels/tracks to a person!"] call BIS_fnc_curatorHint; + }; + + if (_target isKindOf "Static") exitWith { + ["Manage Wheels in Vehicle", "WARNING: Cannot add wheels/tracks to a static object!"] call BIS_fnc_curatorHint; + }; + + // get loaded details + private _loadedItems = _target getVariable ["ace_cargo_loaded", []]; + private _loadedItemsObjects = _loadedItems select { _x isEqualType objNull }; + private _loadedItemsVirtual = _loadedItems select { _x isEqualType "" }; + private _spaceLeft = _target getVariable ["ace_cargo_space", 0]; + + private _wheels = _loadedItemsVirtual select { _x isEqualTo "ACE_Wheel" }; + _wheels append (_loadedItemsObjects select { typeOf _x isEqualTo "ACE_Wheel" }); + + + private _maxWheels = floor ((_spaceLeft + count _loadedItems) / ("ACE_Wheel" call ace_cargo_fnc_getSizeItem)); + private _currentWheels = count _wheels; + + private _comboOptions = [[], [], _currentWheels]; + for "_i" from 0 to _maxWheels do { + _comboOptions#0 pushBack _i; + _comboOptions#1 pushBack format["%1", _i]; + }; + + + [ // create the dialog + "Manage Wheels in Vehicle", + [ + // [ "COMBO", "Box Type", [[1,2,3], [["Ammo"],["Weapons"],["Medical"]],0] ] + ["TOOLBOX", "Existing Data", [ + 0, // default value + 2, // num rows + 2, // num columns + [ + format["Loaded Items: %1", count _loadedItems], + format["Space Left: %1", _spaceLeft], + format["Loaded Wheels: %1", count _wheels] + ] + ]], + ["COMBO", "Desired ACE Wheels Count", _comboOptions, true] + ], + { + + params ["_dialogValues", "_args"]; + + _dialogValues params ["_listItem", "_desiredWheelsCount"]; + _args params ["_pos", "_target", "_currentWheelsCount"]; + + // MANAGE WHEELS + if (_desiredWheelsCount > _currentWheelsCount) then { + // add wheels + private _wheelsToAdd = _desiredWheelsCount - _currentWheelsCount; + systemChat format["Adding %1 wheels...", _wheelsToAdd]; + for "_i" from 1 to _wheelsToAdd do { + if ( + ["ACE_Wheel", _target] call ace_cargo_fnc_canLoadItemIn + ) then { + ["ACE_Wheel", _target] call ace_cargo_fnc_addCargoItem; + }; + }; + }; + if (_desiredWheelsCount < _currentWheelsCount) then { + // remove wheels + private _wheelsToRemove = _currentWheelsCount - _desiredWheelsCount; + systemChat format["Removing %1 wheels...", _wheelsToRemove]; + ["ACE_Wheel", _target, _wheelsToRemove] call ace_cargo_fnc_removeCargoItem; + }; + + + // get loaded details + private _loadedItems = _target getVariable ["ace_cargo_loaded", []]; + private _loadedItemsObjects = _loadedItems select { _x isEqualType objNull }; + private _loadedItemsVirtual = _loadedItems select { _x isEqualType "" }; + private _spaceLeft = _target getVariable ["ace_cargo_space", 0]; + + private _wheels = _loadedItemsVirtual select { _x isEqualTo "ACE_Wheel" }; + _wheels append (_loadedItemsObjects select { typeOf _x isEqualTo "ACE_Wheel" }); + + + private _maxWheels = floor ((_spaceLeft + count _loadedItems) / ("ACE_Wheel" call ace_cargo_fnc_getSizeItem)); + private _currentWheels = count _wheels; + + [ + "Manage Wheels in Vehicle", + format[ + "Updated count of wheels in vehicle: %1", + _currentWheels + ] + ] call BIS_fnc_curatorHint; + true; + }, + {}, + [_pos, _target, count _wheels, count _tracks] + ] call zen_dialog_fnc_create; + } +] call zen_custom_modules_fnc_register; + + +// Manage tracks in a vehicle's ACE cargo +[ + QUOTE(MODULE_CATEGORY_NAME), + "Manage Tracks in Vehicle", + { + // module placement + params [["_pos", [0,0,0], [[]], 3], ["_target", objNull, [objNull]]]; + + if (isNull _target) exitWith { + ["Manage Tracks in Vehicle", "WARNING: No vehicle selected!"] call BIS_fnc_curatorHint; + }; + + if (_target isKindOf "CAManBase") exitWith { + ["Manage Tracks in Vehicle", "WARNING: Cannot add wheels/tracks to a person!"] call BIS_fnc_curatorHint; + }; + + if (_target isKindOf "Static") exitWith { + ["Manage Tracks in Vehicle", "WARNING: Cannot add wheels/tracks to a static object!"] call BIS_fnc_curatorHint; + }; + + // get loaded details + private _loadedItems = _target getVariable ["ace_cargo_loaded", []]; + private _loadedItemsObjects = _loadedItems select { _x isEqualType objNull }; + private _loadedItemsVirtual = _loadedItems select { _x isEqualType "" }; + private _spaceLeft = _target getVariable ["ace_cargo_space", 0]; + + private _tracks = _loadedItemsVirtual select { _x isEqualTo "ACE_Track" }; + _tracks append (_loadedItemsObjects select { typeOf _x isEqualTo "ACE_Track" }); + + private _maxTracks = floor ((_spaceLeft + count _loadedItems) / ("ACE_Track" call ace_cargo_fnc_getSizeItem)); + private _currentTracks = count _tracks; + + private _comboOptions = [[], [], _currentTracks]; + for "_i" from 0 to _maxTracks do { + _comboOptions#0 pushBack _i; + _comboOptions#1 pushBack format["%1", _i]; + }; + + [ // create the dialog + "Manage Tracks in Vehicle", + [ + // [ "COMBO", "Box Type", [[1,2,3], [["Ammo"],["Weapons"],["Medical"]],0] ] + ["TOOLBOX", "Existing Data", [ + 0, // default value + 2, // num rows + 2, // num columns + [ + format["Loaded Items: %1", count _loadedItems], + format["Space Left: %1", _spaceLeft], + format["Loaded Tracks: %1", count _tracks] + ] + ]], + ["COMBO", "Desired ACE Tracks Count", _comboOptions, true] + ], + { + + params ["_dialogValues", "_args"]; + + _dialogValues params ["_listItem", "_desiredTracksCount"]; + _args params ["_pos", "_target", "_currentTracksCount"]; + + // MANAGE TRACKS + if (_desiredTracksCount > _currentTracksCount) then { + // add tracks + private _tracksToAdd = _desiredTracksCount - _currentTracksCount; + systemChat format["Adding %1 tracks...", _tracksToAdd]; + for "_i" from 1 to _tracksToAdd do { + if ( + ["ACE_Track", _target] call ace_cargo_fnc_canLoadItemIn + ) then { + ["ACE_Track", _target] call ace_cargo_fnc_addCargoItem; + }; + }; + }; + if (_desiredTracksCount < _currentTracksCount) then { + // remove tracks + private _tracksToRemove = _currentTracksCount - _desiredTracksCount; + systemChat format["Removing %1 tracks...", _tracksToRemove]; + ["ACE_Track", _target, _tracksToRemove] call ace_cargo_fnc_removeCargoItem; + }; + + + // get loaded details + private _loadedItems = _target getVariable ["ace_cargo_loaded", []]; + private _loadedItemsObjects = _loadedItems select { _x isEqualType objNull }; + private _loadedItemsVirtual = _loadedItems select { _x isEqualType "" }; + private _spaceLeft = _target getVariable ["ace_cargo_space", 0]; + + private _tracks = _loadedItemsVirtual select { _x isEqualTo "ACE_Track" }; + _tracks append (_loadedItemsObjects select { typeOf _x isEqualTo "ACE_Track" }); + + private _maxTracks = floor ((_spaceLeft + count _loadedItems) / ("ACE_Track" call ace_cargo_fnc_getSizeItem)); + private _currentTracks = count _tracks; + + [ + "Manage Tracks in Vehicle", + format[ + "Updated count of tracks in vehicle: %1", + _currentTracks + ] + ] call BIS_fnc_curatorHint; + true; + }, + {}, + [_pos, _target, _currentTracks] + ] call zen_dialog_fnc_create; + } +] call zen_custom_modules_fnc_register; + + + + + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "ZEUS ENHANCED MODULES ADDED", + [] +] call EFUNC(common,log); + +nil; \ No newline at end of file diff --git a/framework/zeus/functions/fn_initClient.sqf b/framework/zeus/functions/fn_initClient.sqf new file mode 100644 index 0000000..28a5108 --- /dev/null +++ b/framework/zeus/functions/fn_initClient.sqf @@ -0,0 +1,14 @@ +#include "..\script_component.hpp" + +if (!hasInterface) exitWith {}; + +call FUNC(addZenModules); + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "postInit complete", + [] +] call EFUNC(common,log); + +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/zeus/script_component.hpp b/framework/zeus/script_component.hpp new file mode 100644 index 0000000..85c6e66 --- /dev/null +++ b/framework/zeus/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT zeus +#define COMPONENT_BEAUTIFIED Zeus Utilities +#include "../script_mod.hpp" \ No newline at end of file From dfd79c0d70e46f5db840f0aa030fd985ee4b571f Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Wed, 7 Feb 2024 13:12:35 -0800 Subject: [PATCH 2/8] adds more dev info to readme --- README.md | 49 ++++++++++++++++++- .../resupply/functions/fn_initClient.sqf | 1 + 2 files changed, 48 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d48d6bd..8587393 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ Once copied, the final structure should appear similar to the following: ├── mission.sqm ``` -If you're building a mission for use in an op, please delete "aaFrameworkUtils" and "framework\x". These are for the purposes of development and add size bloat to the mission download when players connect to your mission. +If you're building a mission for use in an op, please delete "aaFrameworkUtils" and "framework\x". These are for the purposes of development and add bloat to the mission download when players connect to your mission. After the requisite configuration file edits have been made, your mission is ready to be packed into a pbo for deployment. @@ -69,4 +69,49 @@ All modules are broken apart as such in /framework. Client and server inits are Pay attention to framework/script_mod.hpp prior to deployment of releases, as the debug settings within will determine what is logged during prod missions. -CfgFunctions is sensitive to the folder/script_component.hpp of each module. \ No newline at end of file +CfgFunctions is sensitive to the folder/script_component.hpp of each module. + +### `defines` Directory + +This directory contains a number of hpp files used to define constants throughout the framework. These should ONLY be edited by or with the supervision of a developer to reflect format battalion-wide changes. + +- `ApprovedAssets.hpp`: Contains subclasses for approved aerial assets with their assigned callsigns. Used primarily in `fbcb2_assets`. +- `BattalionInfo.hpp`: Used for representing Battalion structure, element callsigns, and radio frequency assignments. Used primarily in `fbcb2_main`. +- `DisallowedEquipment.hpp`: Contains flagged item classnames by category that players may not use, or may use only in specific roles. Used to monitor and enforce equipment restrictions. +- `SignalColors.hpp`: Contains smoke/flare/chemlight colors and what they represent in the field. Used primarily in `fbcb2_main` for the Signal Colors diary record. +- `SupplyCrates.hpp`: Contains the types, contents, and metadata for all supply crate types in the `resupply` module. +- `VehicleFlags.hpp`: Defines system information, flag categories, and flag options used to populate ACE3 interaction menus for vehicles. Used by the `vehicleFlags` module. + + +### Modules List + +*Within `framework`:* + +- `ambience`: + - Adds ambient flak capabilities. +- `client`: + - Contains core client-side event handlers and actions that don't fit into other modules. +- `common`: + - Contains common functions and variables used by multiple modules. +- `fbcb2_main`: + - Contains the main FBCB2 functionality and initialization code. Populates the briefing/diary with mission information. +- `fbcb2_assets`: + - A subcomponent of `fbcb2_main`. Used to gather, display, and manage diary records as intel for assets near known bases. +- `init`: + - Contains core initialization functions. Both server and client inits across all modules are managed here. +- `map`: + - Gives players the ability to copy each other's maps. +- `performance`: + - Contains functionality for monitoring and logging performance data. +- `reinsert`: + - Provides a reinsertion queue system for players and pilots to maximize efficiency of the reinsertion process. +- `resupply`: + - Provides a Zeus module and standalone function to spawn pre-equipped supply crates onto the battlefield. + - Supply crate definitions are stored in `defines/SupplyCrates.hpp`. + - Optionally, allows players to spawn supply crates from arsenal boxes. +- `triageIcons`: + - For those with medical permissions (`ace_medical`), provides a configurable 3D icon over unconscious units indicating their current ACE Triage Card status. +- `vehicleFlags`: + - Provides an ACE3 interaction menu that allows players to attach and remove flags from vehicles. + - Flags are defined in `defines/VehicleFlags.hpp`. + diff --git a/framework/resupply/functions/fn_initClient.sqf b/framework/resupply/functions/fn_initClient.sqf index a78233f..b5601fd 100644 --- a/framework/resupply/functions/fn_initClient.sqf +++ b/framework/resupply/functions/fn_initClient.sqf @@ -10,4 +10,5 @@ call FUNC(addArsenalObjectSpawnBoxActions); "postInit complete", [] ] call EFUNC(common,log); + localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file From 7c903d10219bfb78f26747d4e7f45da367188852 Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Thu, 8 Feb 2024 11:48:41 -0800 Subject: [PATCH 3/8] add some built in flags as options --- defines/VehicleFlags.hpp | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/defines/VehicleFlags.hpp b/defines/VehicleFlags.hpp index fce9606..2e13fb2 100644 --- a/defines/VehicleFlags.hpp +++ b/defines/VehicleFlags.hpp @@ -125,5 +125,40 @@ class VehicleFlags { texture = "textures\flags_misc\flag_redcross_co.paa"; }; }; + + class BuiltIn { + actionID = "flag_builtin"; + actionTitle = "Built-In"; + class BlueFlag { + actionID = "flag_builtin_blue"; + actionTitle = "Blue Flag"; + texture = "\A3\Data_F\Flags\flag_blue_CO.paa"; + }; + class GreenFlag { + actionID = "flag_builtin_green"; + actionTitle = "Green Flag"; + texture = "\A3\Data_F\Flags\flag_green_CO.paa"; + }; + class RedFlag { + actionID = "flag_builtin_red"; + actionTitle = "Red Flag"; + texture = "\A3\Data_F\Flags\flag_red_CO.paa"; + }; + class WhiteFlag { + actionID = "flag_builtin_white"; + actionTitle = "White Flag"; + texture = "\A3\Data_F\Flags\flag_white_CO.paa"; + }; + class NATOFlag { + actionID = "flag_builtin_nato"; + actionTitle = "NATO Flag"; + texture = "\A3\Data_F\Flags\flag_NATO_CO.paa"; + }; + class UNFlag { + actionID = "flag_builtin_un"; + actionTitle = "UN Flag"; + texture = "\A3\Data_F\Flags\Flag_uno_CO.paa"; + }; + }; }; }; \ No newline at end of file From 3217ec487d54f18f0a5c3b209557473ba1914437 Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Thu, 8 Feb 2024 11:50:07 -0800 Subject: [PATCH 4/8] simplify resupply actions addition --- .../reinsert/client/fn_addAceSelfActions.sqf | 118 +++++++++--------- .../client/fn_addCheckQueueSelfAction.sqf | 48 ++++--- framework/reinsert/client/fn_initClient.sqf | 26 ++-- .../fn_addArsenalObjectSpawnBoxActions.sqf | 4 +- 4 files changed, 89 insertions(+), 107 deletions(-) diff --git a/framework/reinsert/client/fn_addAceSelfActions.sqf b/framework/reinsert/client/fn_addAceSelfActions.sqf index a6f66de..5d19ba5 100644 --- a/framework/reinsert/client/fn_addAceSelfActions.sqf +++ b/framework/reinsert/client/fn_addAceSelfActions.sqf @@ -1,69 +1,65 @@ #include "..\script_component.hpp" -params ["_type"]; // string of the object's classname -if (!(_type isKindOf "CAManBase")) exitWith {}; +params [ + ["_types", [], [[]]], // classnames to assign these action to + ["_useInheritance", false, [false]] +]; -if ( - (localNamespace getVariable [QGVAR(fileForReinsertClassesAdded), []]) - find _type != -1 -) exitWith {}; +{ // forEach _types + private _classToAddActionsTo = _x; -private _fileForReinsertAction = [ - QGVAR(fileReinsertRequestAction), - "File Re-insert Request", - "\A3\ui_f\data\igui\cfg\simpleTasks\types\takeoff_ca.paa", - { // statement - params ["_target", "_player", "_params"]; - // find nearest base or location - private _base = [_player] call EFUNC(common,getNearestBase); - private _baseName = [_base] call EFUNC(common,getNameOfBase); - // send event to server - [QGVAR(fileReinsertRequest), [_player, _base]] call CBA_fnc_serverEvent; - // notify player their request was filed - [["Re-insert Request Filed"], [format["Location: %1", _baseName]]] call CBA_fnc_notify; - }, - { // condition - params ["_target", "_player", "_params"]; - // find nearest base or location - private _base = [_player] call EFUNC(common,getNearestBase); - private _baseDistance = _player distance _base; + private _fileForReinsertAction = [ + QGVAR(fileReinsertRequestAction), + "File Re-insert Request", + "\A3\ui_f\data\igui\cfg\simpleTasks\types\takeoff_ca.paa", + { // statement + params ["_target", "_player", "_params"]; + // find nearest base or location + private _base = [_player] call EFUNC(common,getNearestBase); + private _baseName = [_base] call EFUNC(common,getNameOfBase); + // send event to server + [QGVAR(fileReinsertRequest), [_player, _base]] call CBA_fnc_serverEvent; + // notify player their request was filed + [["Re-insert Request Filed"], [format["Location: %1", _baseName]]] call CBA_fnc_notify; + }, + { // condition + params ["_target", "_player", "_params"]; + // find nearest base or location + private _base = [_player] call EFUNC(common,getNearestBase); + private _baseDistance = _player distance _base; - private _maxRangeToReady = missionNamespace getVariable [QGVAR(setting_maxRangeToReady), 400]; - private _existingQueue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; + private _maxRangeToReady = [QGVAR(setting_maxRangeToReady)] call CBA_settings_fnc_get; + private _existingQueue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; - // check if module is enabled, player is near a base, and player is not already in the queue - // (serverTime - GVAR(missionStartServerTime)) > 60*5 && // only allow after 15 minutes - missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_enabled", true] && - (_baseDistance < _maxRangeToReady) && - not (_player in (_existingQueue apply {_x#0})) - } -] call ace_interact_menu_fnc_createAction; -[_type, 1, ["ACE_SelfActions"], _fileForReinsertAction, true] call ace_interact_menu_fnc_addActionToClass; + // check if module is enabled, player is near a base, and player is not already in the queue + // (serverTime - GVAR(missionStartServerTime)) > 60*5 && // only allow after 15 minutes + [QGVAR(setting_enabled)] call CBA_settings_fnc_get && + (_baseDistance < _maxRangeToReady) && + not (_player in (_existingQueue apply {_x#0})) + } + ] call ace_interact_menu_fnc_createAction; + [_classToAddActionsTo, 1, ["ACE_SelfActions"], _fileForReinsertAction, _useInheritance] call ace_interact_menu_fnc_addActionToClass; -private _removeFileForReinsertAction = [ - QGVAR(removeReinsertRequestAction), - "Remove Re-insert Request", - "\A3\ui_f\data\igui\cfg\simpleTasks\types\land_ca.paa", - { // statement - params ["_target", "_player", "_params"]; - // send event to server - [QGVAR(removeReinsertRequest), [_player]] call CBA_fnc_serverEvent; - // notify player their request was rescinded - "Re-insert Request Rescinded" call CBA_fnc_notify; - }, - { // condition - params ["_target", "_player", "_params"]; - private _existingQueue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; - - // check if module is enabled, player is in the queue - // (serverTime - GVAR(missionStartServerTime)) > 60*5 && // only allow after 15 minutes - missionNamespace getVariable ["milsim_reinsert_setting_reinsertion_enabled", true] && - (_player in (_existingQueue apply {_x#0})) - } -] call ace_interact_menu_fnc_createAction; -[_type, 1, ["ACE_SelfActions"], _removeFileForReinsertAction, true] call ace_interact_menu_fnc_addActionToClass; - -private _classesActionsAddedTo = (localNamespace getVariable [QGVAR(fileForReinsertClassesAdded), []]); -_classesActionsAddedTo pushBackUnique _type; -localNamespace setVariable [QGVAR(fileForReinsertClassesAdded), _classesActionsAddedTo]; + private _removeFileForReinsertAction = [ + QGVAR(removeReinsertRequestAction), + "Remove Re-insert Request", + "\A3\ui_f\data\igui\cfg\simpleTasks\types\land_ca.paa", + { // statement + params ["_target", "_player", "_params"]; + // send event to server + [QGVAR(removeReinsertRequest), [_player]] call CBA_fnc_serverEvent; + // notify player their request was rescinded + "Re-insert Request Rescinded" call CBA_fnc_notify; + }, + { // condition + params ["_target", "_player", "_params"]; + private _existingQueue = missionNamespace getVariable [QGVAR(reinsertionQueue), []]; + // check if module is enabled, player is in the queue + // (serverTime - GVAR(missionStartServerTime)) > 60*5 && // only allow after 15 minutes + [QGVAR(setting_enabled)] call CBA_settings_fnc_get && + (_player in (_existingQueue apply {_x#0})) + } + ] call ace_interact_menu_fnc_createAction; + [_classToAddActionsTo, 1, ["ACE_SelfActions"], _removeFileForReinsertAction, _useInheritance] call ace_interact_menu_fnc_addActionToClass; +} forEach _types; \ No newline at end of file diff --git a/framework/reinsert/client/fn_addCheckQueueSelfAction.sqf b/framework/reinsert/client/fn_addCheckQueueSelfAction.sqf index 341e09f..819a01a 100644 --- a/framework/reinsert/client/fn_addCheckQueueSelfAction.sqf +++ b/framework/reinsert/client/fn_addCheckQueueSelfAction.sqf @@ -1,30 +1,28 @@ #include "..\script_component.hpp" -params ["_type"]; // string of the object's classname -if (!(_type isKindOf "CAManBase")) exitWith {}; +params [ + ["_types", [], [[]]], // classnames to assign these action to + ["_useInheritance", false, [false]] +]; -if ( - (localNamespace getVariable [QGVAR(checkReinsertQueueClassesAdded), []]) - find _type != -1 -) exitWith {}; +{ // forEach _types + private _classToAddActionsTo = _x; -private _checkReinsertQueueAction = [ - QGVAR(checkReinsertQueue), - "[PILOT] Check Re-insert Queue", - "\A3\ui_f\data\igui\cfg\simpleTasks\types\land_ca.paa", - { - params ["_target", "_player", "_params"]; - // request notification from the server - call FUNC(requestShowQueue); - // reset last check time - localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; - }, - { - missionNamespace getVariable [QGVAR(setting_enabled), true] - } // always allow -] call ace_interact_menu_fnc_createAction; -[_type, 1, ["ACE_SelfActions"], _checkReinsertQueueAction, true] call ace_interact_menu_fnc_addActionToClass; + private _checkReinsertQueueAction = [ + QGVAR(checkReinsertQueue), + "[PILOT] Check Re-insert Queue", + "\A3\ui_f\data\igui\cfg\simpleTasks\types\land_ca.paa", + { + params ["_target", "_player", "_params"]; + // request notification from the server + call FUNC(requestShowQueue); + // reset last check time + localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; + }, + { + GVAR(setting_enabled); + } // condition + ] call ace_interact_menu_fnc_createAction; + [_classToAddActionsTo, 1, ["ACE_SelfActions"], _checkReinsertQueueAction, _useInheritance] call ace_interact_menu_fnc_addActionToClass; -private _classesActionsAddedTo = (localNamespace getVariable [QGVAR(checkReinsertQueueClassesAdded), []]); -_classesActionsAddedTo pushBackUnique _type; -localNamespace setVariable [QGVAR(checkReinsertQueueClassesAdded), _classesActionsAddedTo]; \ No newline at end of file +} forEach _types; \ No newline at end of file diff --git a/framework/reinsert/client/fn_initClient.sqf b/framework/reinsert/client/fn_initClient.sqf index f262ffe..df78cd0 100644 --- a/framework/reinsert/client/fn_initClient.sqf +++ b/framework/reinsert/client/fn_initClient.sqf @@ -5,26 +5,16 @@ if (!hasInterface) exitWith {}; // ACE SELF-INTERACTIONS FOR FILING AND RESCINDING REINSERT REQUESTS NEAR BASE - ALL PLAYERS localNamespace setVariable [QGVAR(fileForReinsertClassesAdded), []]; // add actions to current class -[typeOf player] call FUNC(addAceSelfActions); -// add actions to future classes -["ace_interact_menu_newControllableObject", { - _this call FUNC(addAceSelfActions); -}] call CBA_fnc_addEventHandler; +[["CAManBase"], true] call FUNC(addAceSelfActions); ///////////////////////////////////////////////////// // PILOTS ONLY // ACE SELF-INTERACTIONS FOR CHECKING REINSERT QUEUE - ONLY FOR PILOTS -if ((typeOf player) in ["B_Helipilot_F", "B_helicrew_F"]) then { - localNamespace setVariable [QGVAR(checkReinsertQueueClassesAdded), []]; - localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; +localNamespace setVariable [QGVAR(checkReinsertQueueClassesAdded), []]; +localNamespace setVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; - // add actions to current class - [typeOf player] call FUNC(addCheckQueueSelfAction); - // add actions to future classes - ["ace_interact_menu_newControllableObject", { - _this call FUNC(addCheckQueueSelfAction); - }] call CBA_fnc_addEventHandler; -}; +// add actions to pilot classes, and don't apply to child classes +[["B_Helipilot_F", "B_helicrew_F"], false] call FUNC(addCheckQueueSelfAction); ///////////////////////////////////////////////////// @@ -33,13 +23,13 @@ if ((typeOf player) in ["B_Helipilot_F", "B_helicrew_F"]) then { [{ // if module not enabled and pilot forced check not enabled, exit if (not ( - missionNamespace getVariable [QGVAR(setting_enabled), true] && - missionNamespace getVariable [QGVAR(setting_pilotForcedCheckEnabled), true] + [QGVAR(setting_enabled)] call CBA_settings_fnc_get and + [QGVAR(setting_pilotForcedCheckEnabled)] call CBA_settings_fnc_get )) exitWith {}; // if last check was less than X minutes ago, skip private _lastCheck = localNamespace getVariable [QGVAR(lastReinsertQueueCheck), diag_tickTime]; - private _requiredCheckInterval = missionNamespace getVariable [QGVAR(setting_pilotForcedCheckInterval), 60*20]; + private _requiredCheckInterval = [QGVAR(setting_pilotForcedCheckInterval)] call CBA_settings_fnc_get; if ( diag_tickTime - _lastCheck < _requiredCheckInterval diff --git a/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf b/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf index 74977f9..247377c 100644 --- a/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf +++ b/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf @@ -35,9 +35,7 @@ private _supplyCrateTypesCfgs = _supplyCratesCfg call BIS_fnc_returnChildren; private _cfg = _x; private _supplyCrateDisplayName = (_cfg >> "displayName") call BIS_fnc_getCfgData; - - - + // add action to spawn supply crate private _actionID = _arsenalBox addAction [format ["Spawn %1", _supplyCrateDisplayName], { params ["_target", "_caller", "_actionId", "_arguments"]; _arguments params ["_supplyCrateCfg"]; From 7268d8fd50b916318602024fad4b3822043fe9cc Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Thu, 8 Feb 2024 12:01:51 -0800 Subject: [PATCH 5/8] change vehicle flag actions to use class inheritance instead of object --- .../vehicleFlags/functions/fn_initClient.sqf | 164 +++++++++--------- 1 file changed, 78 insertions(+), 86 deletions(-) diff --git a/framework/vehicleFlags/functions/fn_initClient.sqf b/framework/vehicleFlags/functions/fn_initClient.sqf index 7ebe0fd..bdc2ae6 100644 --- a/framework/vehicleFlags/functions/fn_initClient.sqf +++ b/framework/vehicleFlags/functions/fn_initClient.sqf @@ -16,94 +16,86 @@ private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_ private _parentClass = _x; //////////////////////////////////////////////////////////////////////// - // add CBA class event handler to add actions to vehicles after they are initialized - // all classes that inherit from the base classes will also have this applied - // an exclusion function is present for manually excluding specific classes + // create the root action //////////////////////////////////////////////////////////////////////// - [_parentClass, "InitPost", { - - - - //////////////////////////////////////////////////////////////////////// - // create the root action - //////////////////////////////////////////////////////////////////////// - private _rootActionID = "SetVehicleFlag"; - private _flagRootAction = [ - _rootActionID, // id - "Set Vehicle Flag", // displayed title - "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon - {true}, // statement - { - params ["_target", "_player", "_params"]; - // _params params ["_parentActionID", "_flagCategories"]; - - // check if vehicle is excluded - private _excluded = [typeOf _target] call FUNC(isClassExcluded); - if (_excluded || !alive _target) exitWith {false}; - - true; - }, // condition - { - //////////////////////////////////////////////////////////////////////// - // create the flag category actions (with nested flag actions) - //////////////////////////////////////////////////////////////////////// - params ["_target", "_player", "_params"]; - _params params ["_rootActionID"]; - - private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg); - if (isNull _vehicleFlagsCfg) exitWith {[]}; - private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_returnChildren; - - // return category child actions with individual flag actions nested as children - [_rootActionID, _flagCategoryCfgs] call FUNC(getActionsFlagCategories); - - }, // child code - [_rootActionID], // params - nil, // position - 4, // distance - [false, false, false, false, false], // other params - nil // modifier function code - ] call ace_interact_menu_fnc_createAction; - - //////////////////////////////////////////////////////////////////////// - // add root action to add flags - //////////////////////////////////////////////////////////////////////// - [ - (_this select 0), // object - 0, // action 0 or self-action 1 - ["ACE_MainActions"], // parent - _flagRootAction // action - ] call ace_interact_menu_fnc_addActionToObject; - - //////////////////////////////////////////////////////////////////////// - // add action to remove flag under the root action - //////////////////////////////////////////////////////////////////////// - // create action - private _removeFlagAction = [ - _rootActionID + "_removeflag", // id - "Remove Flag", // displayed title - "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon - { - params ["_target", "_player", "_params"]; - _target forceFlagTexture ""; - }, // statement - { - params ["_target", "_player", "_params"]; - alive _target && getForcedFlagTexture _target != ""; - }, // condition - nil // child code - ] call ace_interact_menu_fnc_createAction; - - // add the action to the vehicle - // in this class event handler, this#0 will be the vehicle - [ - (_this select 0), // object - 0, // action 0 or self-action 1 - ["ACE_MainActions", _rootActionID], // parent - _removeFlagAction // action - ] call ace_interact_menu_fnc_addActionToObject; + private _rootActionID = QGVAR(SetVehicleFlagAction); + private _flagRootAction = [ + _rootActionID, // id + "Set Vehicle Flag", // displayed title + "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon + {true}, // statement + { + params ["_target", "_player", "_params"]; + // _params params ["_parentActionID", "_flagCategories"]; - }, true, [], true] call CBA_fnc_addClassEventHandler; + // check if vehicle is excluded + private _excluded = [typeOf _target] call FUNC(isClassExcluded); + if (_excluded || !alive _target) exitWith {false}; + + true; + }, // condition + { + //////////////////////////////////////////////////////////////////////// + // create the flag category actions (with nested flag actions) + //////////////////////////////////////////////////////////////////////// + params ["_target", "_player", "_params"]; + _params params ["_rootActionID"]; + + private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg); + if (isNull _vehicleFlagsCfg) exitWith {[]}; + private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_returnChildren; + + // return category child actions with individual flag actions nested as children + [_rootActionID, _flagCategoryCfgs] call FUNC(getActionsFlagCategories); + + }, // child code + [_rootActionID], // params + nil, // position + 4, // distance + [false, false, false, false, false], // other params + nil // modifier function code + ] call ace_interact_menu_fnc_createAction; + + //////////////////////////////////////////////////////////////////////// + // add root action to add flags + //////////////////////////////////////////////////////////////////////// + [ + _parentClass, // parent classname + 0, // action 0 or self-action 1 + ["ACE_MainActions"], // parent + _flagRootAction, // action + true // apply to child classes + ] call ace_interact_menu_fnc_addActionToClass; + + //////////////////////////////////////////////////////////////////////// + // add action to remove flag under the root action + //////////////////////////////////////////////////////////////////////// + // create action + private _removeFlagAction = [ + _rootActionID + "_removeflag", // id + "Remove Flag", // displayed title + "\A3\ui_f\data\map\markers\flags\nato_ca.paa", // flag icon + { + params ["_target", "_player", "_params"]; + _target forceFlagTexture ""; + }, // statement + { + params ["_target", "_player", "_params"]; + alive _target && getForcedFlagTexture _target != ""; + }, // condition + nil // child code + ] call ace_interact_menu_fnc_createAction; + + // add the action to the vehicle + // in this class event handler, this#0 will be the vehicle + [ + _parentClass, // parent classname + 0, // action 0 or self-action 1 + ["ACE_MainActions", _rootActionID], // parent + _removeFlagAction, // action + true // apply to child classes + ] call ace_interact_menu_fnc_addActionToClass; + } forEach _baseClassesToApplyActionsFor; nil; \ No newline at end of file From fba423e38daaca9976d32c12dd059aec8669f718 Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Thu, 8 Feb 2024 12:47:51 -0800 Subject: [PATCH 6/8] update mapcopy module with CBA events --- README.md | 2 +- framework/CfgFunctions.hpp | 23 ++++----- framework/init/functions/fn_initClient.sqf | 1 + framework/map/fn_copyMapFromPlayer.sqf | 5 -- framework/map/fn_getPlayerMapMarkers.sqf | 16 ------- framework/map/fn_initMapCopy.sqf | 17 ------- framework/map/fn_loadMapMarkers.sqf | 10 ---- .../mapcopy/functions/fn_addCBASettings.sqf | 24 ++++++++++ .../mapcopy/functions/fn_getMapMarkers.sqf | 15 ++++++ framework/mapcopy/functions/fn_initClient.sqf | 48 +++++++++++++++++++ .../mapcopy/functions/fn_loadMapMarkers.sqf | 8 ++++ .../functions}/fn_mapMarkerToString.sqf | 0 .../functions}/fn_stringToMapMarker.sqf | 0 framework/mapcopy/script_component.hpp | 3 ++ 14 files changed, 112 insertions(+), 60 deletions(-) delete mode 100644 framework/map/fn_copyMapFromPlayer.sqf delete mode 100644 framework/map/fn_getPlayerMapMarkers.sqf delete mode 100644 framework/map/fn_initMapCopy.sqf delete mode 100644 framework/map/fn_loadMapMarkers.sqf create mode 100644 framework/mapcopy/functions/fn_addCBASettings.sqf create mode 100644 framework/mapcopy/functions/fn_getMapMarkers.sqf create mode 100644 framework/mapcopy/functions/fn_initClient.sqf create mode 100644 framework/mapcopy/functions/fn_loadMapMarkers.sqf rename framework/{map => mapcopy/functions}/fn_mapMarkerToString.sqf (100%) rename framework/{map => mapcopy/functions}/fn_stringToMapMarker.sqf (100%) create mode 100644 framework/mapcopy/script_component.hpp diff --git a/README.md b/README.md index 8587393..b3279a5 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ This directory contains a number of hpp files used to define constants throughou - A subcomponent of `fbcb2_main`. Used to gather, display, and manage diary records as intel for assets near known bases. - `init`: - Contains core initialization functions. Both server and client inits across all modules are managed here. -- `map`: +- `mapcopy`: - Gives players the ability to copy each other's maps. - `performance`: - Contains functionality for monitoring and logging performance data. diff --git a/framework/CfgFunctions.hpp b/framework/CfgFunctions.hpp index d9e5f96..997f002 100644 --- a/framework/CfgFunctions.hpp +++ b/framework/CfgFunctions.hpp @@ -20,16 +20,6 @@ class CfgFunctions { class flakInitVehicle {}; class flakEH {}; }; - - class map { - file = "framework\map"; - class initMapCopy { postInit = 1; }; - class copyMapFromPlayer {}; //needs refactor - class getPlayerMapMarkers {}; //needs refactor - class loadMapMarkers {}; //needs refactor - class mapMarkerToString {}; //needs refactor - class stringToMapMarker {}; //needs refactor - }; }; class DOUBLES(PREFIX,client) { @@ -42,7 +32,6 @@ class CfgFunctions { }; }; - class DOUBLES(PREFIX,common) { class functions { file = "framework\common\functions"; @@ -101,6 +90,18 @@ class CfgFunctions { }; }; + class DOUBLES(PREFIX,mapcopy) { + class functions { + file = "framework\mapcopy\functions"; + class addCBASettings {preInit=1;}; + class initClient {}; + class getMapMarkers {}; + class loadMapMarkers {}; + class mapMarkerToString {}; + class stringToMapMarker {}; + }; + }; + class DOUBLES(PREFIX,performance) { class functions { file = "framework\performance\functions"; diff --git a/framework/init/functions/fn_initClient.sqf b/framework/init/functions/fn_initClient.sqf index a7d106a..14259f6 100644 --- a/framework/init/functions/fn_initClient.sqf +++ b/framework/init/functions/fn_initClient.sqf @@ -16,6 +16,7 @@ waitUntil {!isNil QGVARMAIN(complete)}; // initialize other modules +call EFUNC(mapcopy,initClient); call EFUNC(reinsert,initClient); call EFUNC(resupply,initClient); call EFUNC(triageIcons,initClient); diff --git a/framework/map/fn_copyMapFromPlayer.sqf b/framework/map/fn_copyMapFromPlayer.sqf deleted file mode 100644 index 16d988e..0000000 --- a/framework/map/fn_copyMapFromPlayer.sqf +++ /dev/null @@ -1,5 +0,0 @@ -params ["_sourcePlayer","_destinationPlayer"]; - -hint format["Copying map markers from %1", name _sourcePlayer]; - -[_destinationPlayer] remoteExecCall ["milsim_fnc_getPlayerMapMarkers",_sourcePlayer]; diff --git a/framework/map/fn_getPlayerMapMarkers.sqf b/framework/map/fn_getPlayerMapMarkers.sqf deleted file mode 100644 index 299985c..0000000 --- a/framework/map/fn_getPlayerMapMarkers.sqf +++ /dev/null @@ -1,16 +0,0 @@ -params ["_destinationPlayer"]; - -_markerData = []; - -hint format["Your map is being copied by %1", name _destinationPlayer]; - -{ - _marker = toArray _x; - _marker resize 15; - if ( toString _marker == "_USER_DEFINED #" ) then { - _marker = _x call milsim_fnc_mapMarkerToString; - _markerData pushBack _marker; - }; -} forEach allMapMarkers; - -[_markerData] remoteExecCall ["milsim_fnc_loadMapMarkers",_destinationPlayer]; diff --git a/framework/map/fn_initMapCopy.sqf b/framework/map/fn_initMapCopy.sqf deleted file mode 100644 index 7e60c51..0000000 --- a/framework/map/fn_initMapCopy.sqf +++ /dev/null @@ -1,17 +0,0 @@ -_map_copy_condition = -{ - ('ItemMap' in (assignedItems _player)) && ('ItemMap' in (assignedItems _target)) && ([_player, _target, []] call ace_common_fnc_canInteractWith) -}; - -_map_copy_action = -[ - "MilSimCopyMap", - "Copy Map", - "\a3\ui_f\data\igui\cfg\actions\talk_ca.paa", - { - [_target,_player] call milsim_fnc_copyMapFromPlayer - }, - _map_copy_condition -] call ace_interact_menu_fnc_createAction; - -["Man", 0, ["ACE_MainActions"], _map_copy_action, true] call ace_interact_menu_fnc_addActionToClass; \ No newline at end of file diff --git a/framework/map/fn_loadMapMarkers.sqf b/framework/map/fn_loadMapMarkers.sqf deleted file mode 100644 index d01989b..0000000 --- a/framework/map/fn_loadMapMarkers.sqf +++ /dev/null @@ -1,10 +0,0 @@ -params ["_markerList"]; - -if ('ItemMap' in (assignedItems player)) then { - { - _x call milsim_fnc_stringToMapMarker; - } foreach _markerList; - hint format["Map copied!"]; -} else { - hint format["You need a map to copy onto!"]; -}; diff --git a/framework/mapcopy/functions/fn_addCBASettings.sqf b/framework/mapcopy/functions/fn_addCBASettings.sqf new file mode 100644 index 0000000..6e299a3 --- /dev/null +++ b/framework/mapcopy/functions/fn_addCBASettings.sqf @@ -0,0 +1,24 @@ +#include "..\script_component.hpp" + +[ + QGVAR(setting_enable), + "CHECKBOX", + "Allow Map Copying", + [QUOTE(SETTINGS_GROUP_NAME), QUOTE(COMPONENT_BEAUTIFIED)], + true, // default value + true, // is global + { + params ["_value"]; + [ + QGVAR(setting_enable), + _value + ] call EFUNC(common,logSettingChanged); + } +] call CBA_fnc_addSetting; + +[ + LEVEL_INFO, + QUOTE(COMPONENT), + "CREATED SETTINGS", + [] +] call EFUNC(common,log); \ No newline at end of file diff --git a/framework/mapcopy/functions/fn_getMapMarkers.sqf b/framework/mapcopy/functions/fn_getMapMarkers.sqf new file mode 100644 index 0000000..2764dd4 --- /dev/null +++ b/framework/mapcopy/functions/fn_getMapMarkers.sqf @@ -0,0 +1,15 @@ +#include "..\script_component.hpp" +// serializes markers on local machine and returns them as array + +_markerData = []; + +{ + _marker = toArray _x; + _marker resize 15; + if ( toString _marker == "_USER_DEFINED #" ) then { + _marker = _x call FUNC(mapMarkerToString); + _markerData pushBack _marker; + }; +} forEach allMapMarkers; + +_markerData; \ No newline at end of file diff --git a/framework/mapcopy/functions/fn_initClient.sqf b/framework/mapcopy/functions/fn_initClient.sqf new file mode 100644 index 0000000..c7eaa22 --- /dev/null +++ b/framework/mapcopy/functions/fn_initClient.sqf @@ -0,0 +1,48 @@ +#include "..\script_component.hpp" + +//////////////////////////////////////////////////////////////////// +// Create action to copy map markers on all inheritors of CAManBase +//////////////////////////////////////////////////////////////////// +private _mapCopyAction = +[ + QGVAR(actionID), + "Copy Map", + "\a3\ui_f\data\igui\cfg\actions\talk_ca.paa", + { + params ["_target", "_player", "_params"]; + format["Copying map markers from %1", name _target] call CBA_fnc_notify; + [QGVAR(mapCopyRequest), _this, _target] call CBA_fnc_targetEvent; + }, + { + params ["_target", "_player", "_params"]; + [QGVAR(setting_enable)] call CBA_settings_fnc_get && { + ('ItemMap' in (assignedItems _player)) && + ('ItemMap' in (assignedItems _target)) && + ([_player, _target, []] call ace_common_fnc_canInteractWith) + }; + } +] call ace_interact_menu_fnc_createAction; +["CAManBase", 0, ["ACE_MainActions"], _mapCopyAction, true] call ace_interact_menu_fnc_addActionToClass; + +//////////////////////////////////////////////////////////////////// +// Create CBA event to receive requests +//////////////////////////////////////////////////////////////////// +[QGVAR(mapCopyRequest), { + params ["_me", "_requester", "_params"]; + format["Your map is being copied by %1", name _requester] call CBA_fnc_notify; + private _myMarkers = _this call FUNC(getMapMarkers); + [QGVAR(mapCopyResponse), [_me, _myMarkers], _requester] call CBA_fnc_targetEvent; +}] call CBA_fnc_addEventHandler; + +//////////////////////////////////////////////////////////////////// +// Create CBA event to receive responses +//////////////////////////////////////////////////////////////////// +[QGVAR(mapCopyResponse), { + params [["_responder", objNull, [objNull]], ["_markerList", [], [[]]]]; + if ('ItemMap' in (assignedItems player)) then { + [_markerList] call FUNC(loadMapMarkers); + format["Copied %1 markers from %2", count _markerList, name _responder] call CBA_fnc_notify; + } else { + format["You need a map to copy onto!"] call CBA_fnc_notify; + }; +}] call CBA_fnc_addEventHandler; \ No newline at end of file diff --git a/framework/mapcopy/functions/fn_loadMapMarkers.sqf b/framework/mapcopy/functions/fn_loadMapMarkers.sqf new file mode 100644 index 0000000..804bc82 --- /dev/null +++ b/framework/mapcopy/functions/fn_loadMapMarkers.sqf @@ -0,0 +1,8 @@ +#include "..\script_component.hpp" +// accepts an array of serialized markers and adds them to local map + +params [["_markerList", [], [[]]]]; + +{ + _x call FUNC(stringToMapMarker); +} foreach _markerList; \ No newline at end of file diff --git a/framework/map/fn_mapMarkerToString.sqf b/framework/mapcopy/functions/fn_mapMarkerToString.sqf similarity index 100% rename from framework/map/fn_mapMarkerToString.sqf rename to framework/mapcopy/functions/fn_mapMarkerToString.sqf diff --git a/framework/map/fn_stringToMapMarker.sqf b/framework/mapcopy/functions/fn_stringToMapMarker.sqf similarity index 100% rename from framework/map/fn_stringToMapMarker.sqf rename to framework/mapcopy/functions/fn_stringToMapMarker.sqf diff --git a/framework/mapcopy/script_component.hpp b/framework/mapcopy/script_component.hpp new file mode 100644 index 0000000..1011914 --- /dev/null +++ b/framework/mapcopy/script_component.hpp @@ -0,0 +1,3 @@ +#define COMPONENT mapcopy +#define COMPONENT_BEAUTIFIED Map Copy +#include "../script_mod.hpp" \ No newline at end of file From 2db018103c0600b56e1228d9693609fc4fb7db5d Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Thu, 8 Feb 2024 15:04:22 -0800 Subject: [PATCH 7/8] move local diary mgmt to common module, clarify clientInit complete msg --- framework/CfgFunctions.hpp | 3 +-- .../functions}/fn_createOrUpdateDiaryRecord.sqf | 11 ++++++++++- framework/fbcb2_assets/functions/fn_initClient.sqf | 2 +- .../fbcb2_assets/functions/fn_updateAssetDiary.sqf | 2 +- .../fbcb2_main/functions/fn_addEnvironmentRecord.sqf | 2 +- .../fbcb2_main/functions/fn_addFrequenciesRecord.sqf | 4 ++-- .../functions/fn_addSignalColorsRecord.sqf | 2 +- framework/fbcb2_main/functions/fn_initClient.sqf | 8 +------- .../init/functions/fn_addRespawnChatHandler.sqf | 2 +- framework/init/functions/fn_initClient.sqf | 12 +++++++++++- framework/mapcopy/functions/fn_initClient.sqf | 11 ++++++++++- framework/reinsert/client/fn_initClient.sqf | 6 ++++-- framework/resupply/functions/fn_initClient.sqf | 2 +- framework/triageIcons/functions/fn_initClient.sqf | 3 ++- framework/vehicleFlags/functions/fn_initClient.sqf | 9 +++++++++ 15 files changed, 56 insertions(+), 23 deletions(-) rename framework/{fbcb2_main/util => common/functions}/fn_createOrUpdateDiaryRecord.sqf (80%) diff --git a/framework/CfgFunctions.hpp b/framework/CfgFunctions.hpp index 997f002..01d02b0 100644 --- a/framework/CfgFunctions.hpp +++ b/framework/CfgFunctions.hpp @@ -12,7 +12,6 @@ class CfgFunctions { class addRespawnChatHandler { postInit = 1; }; }; }; - class PREFIX { class ambience { @@ -38,6 +37,7 @@ class CfgFunctions { class addCBASettings { preInit = 1; }; class logMissionInfo {}; class addPlayerInfoToArray {}; + class createOrUpdateDiaryRecord {}; class getApprovedAssetsCfg {}; class getBattalionCfg {}; class getNameOfBase {}; @@ -84,7 +84,6 @@ class CfgFunctions { }; class util { file = "framework\fbcb2_main\util"; - class createOrUpdateDiaryRecord {}; class formatRadioElementForDiary {}; class generateElementFrequencyRecordText {}; }; diff --git a/framework/fbcb2_main/util/fn_createOrUpdateDiaryRecord.sqf b/framework/common/functions/fn_createOrUpdateDiaryRecord.sqf similarity index 80% rename from framework/fbcb2_main/util/fn_createOrUpdateDiaryRecord.sqf rename to framework/common/functions/fn_createOrUpdateDiaryRecord.sqf index 7f04abb..2b790d9 100644 --- a/framework/fbcb2_main/util/fn_createOrUpdateDiaryRecord.sqf +++ b/framework/common/functions/fn_createOrUpdateDiaryRecord.sqf @@ -3,12 +3,21 @@ if (!hasInterface) exitWith {}; params [ - ["_subjectID", GVAR(subjectStatusID), [""]], + ["_subjectID", "", [""]], ["_recordTitle", "", [""]], ["_recordText", "", [""]], ["_recordIcon", "", [""]] ]; +// Check if all parameters are provided +if ( + count _subjectID isEqualTo 0 || + count _recordTitle isEqualTo 0 || + count _recordText isEqualTo 0 +) exitWith { + [LEVEL_ERROR, QUOTE(COMPONENT), "Not all parameters provided"] call EFUNC(common,log); +}; + // Check if already created private _subjectRecords = GVAR(diaryRecords) getOrDefault [_subjectID, createHashMap, true]; private _existingRecord = _subjectRecords getOrDefault [_recordTitle, diaryRecordNull, true]; diff --git a/framework/fbcb2_assets/functions/fn_initClient.sqf b/framework/fbcb2_assets/functions/fn_initClient.sqf index 62dfbf3..c18b012 100644 --- a/framework/fbcb2_assets/functions/fn_initClient.sqf +++ b/framework/fbcb2_assets/functions/fn_initClient.sqf @@ -21,7 +21,7 @@ call FUNC(updateAssetDiary); [ LEVEL_DEBUG, QUOTE(COMPONENT), - "postInit complete", + "initClient complete", [] ] call EFUNC(common,log); diff --git a/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf b/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf index 72e516d..d2669d5 100644 --- a/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf +++ b/framework/fbcb2_assets/functions/fn_updateAssetDiary.sqf @@ -241,7 +241,7 @@ private _randomColors = [ ], _recordText joinString "
", _icon - ] call EFUNC(fbcb2_main,createOrUpdateDiaryRecord); + ] call EFUNC(common,createOrUpdateDiaryRecord); // "\A3\ui_f\data\igui\cfg\simpleTasks\types\car_ca.paa" } forEach _distinctVehiclesClassNames; diff --git a/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf b/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf index 3cc7dda..8aff10b 100644 --- a/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf +++ b/framework/fbcb2_main/functions/fn_addEnvironmentRecord.sqf @@ -109,4 +109,4 @@ _text = _text joinString "
"; GVAR(subjectIntelID), _recordTitle, _text -] call FUNC(createOrUpdateDiaryRecord); \ No newline at end of file +] call EFUNC(common,createOrUpdateDiaryRecord); \ No newline at end of file diff --git a/framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf b/framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf index 9f5cccb..ae10cf0 100644 --- a/framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf +++ b/framework/fbcb2_main/functions/fn_addFrequenciesRecord.sqf @@ -62,7 +62,7 @@ reverse _battalionElementCfgs; GVAR(subjectFrequenciesID), _diaryTitleText#0, _diaryTitleText#1 - ] call FUNC(createOrUpdateDiaryRecord); + ] call EFUNC(common,createOrUpdateDiaryRecord); } forEach _battalionElementCfgs; // add the battalion command to the top of the list @@ -72,6 +72,6 @@ private _diaryTitleText = [_battalionInfoCfg >> "Command", false] call FUNC(gene GVAR(subjectFrequenciesID), _diaryTitleText#0, _diaryTitleText#1 -] call FUNC(createOrUpdateDiaryRecord); +] call EFUNC(common,createOrUpdateDiaryRecord); true; \ No newline at end of file diff --git a/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf b/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf index 078c72f..ae712de 100644 --- a/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf +++ b/framework/fbcb2_main/functions/fn_addSignalColorsRecord.sqf @@ -56,4 +56,4 @@ _text = _text joinString "

"; GVAR(subjectIntelID), _recordTitle, _text -] call FUNC(createOrUpdateDiaryRecord); \ No newline at end of file +] call EFUNC(common,createOrUpdateDiaryRecord); \ No newline at end of file diff --git a/framework/fbcb2_main/functions/fn_initClient.sqf b/framework/fbcb2_main/functions/fn_initClient.sqf index b2f717b..e0cc5cb 100644 --- a/framework/fbcb2_main/functions/fn_initClient.sqf +++ b/framework/fbcb2_main/functions/fn_initClient.sqf @@ -25,12 +25,6 @@ player createDiarySubject[GVAR(subjectAssetsFixedWingID), "FBCB2 Planes"]; player createDiarySubject[GVAR(subjectAssetsRotaryID), "FBCB2 Helicopters"]; player createDiarySubject[GVAR(subjectAssetsGroundID), "FBCB2 Ground"]; -// store records in format: -// [subject, [ -// [title, diaryRecord] -// ]] -GVAR(diaryRecords) = createHashMap; - // run main inits [] call FUNC(addFrequenciesRecord); [] call FUNC(addSignalColorsRecord); @@ -47,7 +41,7 @@ GVAR(diaryRecords) = createHashMap; [ LEVEL_DEBUG, QUOTE(COMPONENT), - "postInit complete", + "initClient complete", [] ] call EFUNC(common,log); diff --git a/framework/init/functions/fn_addRespawnChatHandler.sqf b/framework/init/functions/fn_addRespawnChatHandler.sqf index b2d0007..6e4c22f 100644 --- a/framework/init/functions/fn_addRespawnChatHandler.sqf +++ b/framework/init/functions/fn_addRespawnChatHandler.sqf @@ -24,7 +24,7 @@ [ LEVEL_INFO, QUOTE(COMPONENT), - "Respawn chat handler registered", + "respawn chat handler registered", [player] call EFUNC(common,addPlayerInfoToArray) ] call EFUNC(common,log); diff --git a/framework/init/functions/fn_initClient.sqf b/framework/init/functions/fn_initClient.sqf index 14259f6..39fc06e 100644 --- a/framework/init/functions/fn_initClient.sqf +++ b/framework/init/functions/fn_initClient.sqf @@ -14,9 +14,17 @@ waitUntil {!isNil QGVARMAIN(complete)}; ["InitializePlayer", [player, true]] call BIS_fnc_dynamicGroups; +// Initialize a holder for managing local diary records +// store records in format: +// [subject, [ +// [title, diaryRecord] +// ]] +EGVAR(common,diaryRecords) = createHashMap; + // initialize other modules call EFUNC(mapcopy,initClient); +call EFUNC(rasptools,initClient); call EFUNC(reinsert,initClient); call EFUNC(resupply,initClient); call EFUNC(triageIcons,initClient); @@ -28,8 +36,10 @@ call EFUNC(fbcb2_assets,initClient); [ LEVEL_DEBUG, QUOTE(COMPONENT), - "postInit complete", + "initClient complete", [] ] call EFUNC(common,log); +localNamespace setVariable [QGVAR(complete), true]; + nil; \ No newline at end of file diff --git a/framework/mapcopy/functions/fn_initClient.sqf b/framework/mapcopy/functions/fn_initClient.sqf index c7eaa22..3287103 100644 --- a/framework/mapcopy/functions/fn_initClient.sqf +++ b/framework/mapcopy/functions/fn_initClient.sqf @@ -45,4 +45,13 @@ private _mapCopyAction = } else { format["You need a map to copy onto!"] call CBA_fnc_notify; }; -}] call CBA_fnc_addEventHandler; \ No newline at end of file +}] call CBA_fnc_addEventHandler; + +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "initClient complete", + [] +] call EFUNC(common,log); + +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/reinsert/client/fn_initClient.sqf b/framework/reinsert/client/fn_initClient.sqf index df78cd0..e770796 100644 --- a/framework/reinsert/client/fn_initClient.sqf +++ b/framework/reinsert/client/fn_initClient.sqf @@ -47,6 +47,8 @@ if ((typeOf player) in ["B_Helipilot_F", "B_helicrew_F"]) then { [ LEVEL_DEBUG, QUOTE(COMPONENT), - "postInit complete", + "initClient complete", [] -] call EFUNC(common,log); \ No newline at end of file +] call EFUNC(common,log); + +localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/resupply/functions/fn_initClient.sqf b/framework/resupply/functions/fn_initClient.sqf index b5601fd..1def6f7 100644 --- a/framework/resupply/functions/fn_initClient.sqf +++ b/framework/resupply/functions/fn_initClient.sqf @@ -7,7 +7,7 @@ call FUNC(addArsenalObjectSpawnBoxActions); [ LEVEL_DEBUG, QUOTE(COMPONENT), - "postInit complete", + "initClient complete", [] ] call EFUNC(common,log); diff --git a/framework/triageIcons/functions/fn_initClient.sqf b/framework/triageIcons/functions/fn_initClient.sqf index 79b48ec..7b22f9d 100644 --- a/framework/triageIcons/functions/fn_initClient.sqf +++ b/framework/triageIcons/functions/fn_initClient.sqf @@ -6,7 +6,8 @@ GVAR(drawTargets) = []; [ LEVEL_DEBUG, QUOTE(COMPONENT), - "postInit complete", + "initClient complete", [] ] call EFUNC(common,log); + localNamespace setVariable [QGVAR(complete), true]; \ No newline at end of file diff --git a/framework/vehicleFlags/functions/fn_initClient.sqf b/framework/vehicleFlags/functions/fn_initClient.sqf index bdc2ae6..dd2dbcc 100644 --- a/framework/vehicleFlags/functions/fn_initClient.sqf +++ b/framework/vehicleFlags/functions/fn_initClient.sqf @@ -98,4 +98,13 @@ private _flagCategoryCfgs = (_vehicleFlagsCfg >> "FlagCategories") call BIS_fnc_ } forEach _baseClassesToApplyActionsFor; +[ + LEVEL_DEBUG, + QUOTE(COMPONENT), + "initClient complete", + [] +] call EFUNC(common,log); + +localNamespace setVariable [QGVAR(complete), true]; + nil; \ No newline at end of file From 442cb0b0b2885cb896aa94d5edecfa873151e8fd Mon Sep 17 00:00:00 2001 From: IndigoFox Date: Thu, 8 Feb 2024 15:16:46 -0800 Subject: [PATCH 8/8] bugfixing --- framework/init/functions/fn_initClient.sqf | 1 - .../fn_addArsenalObjectSpawnBoxActions.sqf | 5 ++++- .../vehicleFlags/functions/fn_initClient.sqf | 4 ++-- .../functions/fn_isClassExcluded.sqf | 19 ++++++++++++++----- 4 files changed, 20 insertions(+), 9 deletions(-) diff --git a/framework/init/functions/fn_initClient.sqf b/framework/init/functions/fn_initClient.sqf index 39fc06e..e45f73e 100644 --- a/framework/init/functions/fn_initClient.sqf +++ b/framework/init/functions/fn_initClient.sqf @@ -24,7 +24,6 @@ EGVAR(common,diaryRecords) = createHashMap; // initialize other modules call EFUNC(mapcopy,initClient); -call EFUNC(rasptools,initClient); call EFUNC(reinsert,initClient); call EFUNC(resupply,initClient); call EFUNC(triageIcons,initClient); diff --git a/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf b/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf index 247377c..b1f8f65 100644 --- a/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf +++ b/framework/resupply/functions/fn_addArsenalObjectSpawnBoxActions.sqf @@ -44,13 +44,16 @@ private _supplyCrateTypesCfgs = _supplyCratesCfg call BIS_fnc_returnChildren; configName _supplyCrateCfg, getPos _target ] call FUNC(createBox); + // log action use in server RPT + private _supplyCrateDisplayName = (_supplyCrateCfg >> "displayName") call BIS_fnc_getCfgData; [ LEVEL_INFO, QUOTE(COMPONENT), "Supply crate spawned", [player, [ - ["supplyCrateType", _supplyCrateDisplayName], + ["supplyCrateDisplayName", _supplyCrateDisplayName], + ["supplyCrateCfgName", configName _supplyCrateCfg], ["position", getPos _target] ]] call EFUNC(common,addPlayerInfoToArray) ] remoteExec [QEFUNC(common,log), 2]; diff --git a/framework/vehicleFlags/functions/fn_initClient.sqf b/framework/vehicleFlags/functions/fn_initClient.sqf index dd2dbcc..b0d9537 100644 --- a/framework/vehicleFlags/functions/fn_initClient.sqf +++ b/framework/vehicleFlags/functions/fn_initClient.sqf @@ -1,7 +1,7 @@ -if (!hasInterface) exitWith {}; - #include "..\script_component.hpp" +if (!hasInterface) exitWith {}; + private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg); if (!isClass _vehicleFlagsCfg) exitWith { diff --git a/framework/vehicleFlags/functions/fn_isClassExcluded.sqf b/framework/vehicleFlags/functions/fn_isClassExcluded.sqf index 223d6ae..8c3977e 100644 --- a/framework/vehicleFlags/functions/fn_isClassExcluded.sqf +++ b/framework/vehicleFlags/functions/fn_isClassExcluded.sqf @@ -6,21 +6,30 @@ Parameter(s): 0: STRING - Classname of the vehicle to check */ - +#include "..\script_component.hpp" if (!hasInterface) exitWith {}; params [["_className", "", [""]]]; if (_className == "") exitWith {false}; -private _vehicleFlagsCfg = call milsim_vehicleFlags_fnc_getVehicleFlagsCfg; +private _vehicleFlagsCfg = call FUNC(getVehicleFlagsCfg); private _excludedVehiclesClass = (_vehicleFlagsCfg >> "ExcludedVehicles"); private _exclusionGroups = configProperties [_vehicleFlagsCfg >> "ExcludedVehicles"]; +private _isExcluded = false; { - // Check if the class doesn't have a flag proxy + // Check if the class is directly excluded private _excludedClasses = _x call BIS_fnc_getCfgDataArray; - if (_className in _excludedClasses) exitWith {true}; + if (_className in _excludedClasses) exitWith { + _isExcluded = true; + }; + { + if (_className isKindOf _x) exitWith { + _isExcluded = true; + }; + } forEach _excludedClasses; + if (_isExcluded) exitWith {}; } forEach _exclusionGroups; -false; +_isExcluded;