General - Change CBA Namespaces to HashMap (#8801)

* medical_treatment

* advanced_throwing

* common, csw

* Update fnc_replaceRegisteredItems.sqf

* Sanitised numerous components

* Update XEH_postInit.sqf

* Update XEH_postInit.sqf

* FUNC -> LINKFUNC

* Changed tagging hashmap

* Reverted some changes

* Reverted some changes

* Update XEH_clientInit.sqf

* Tweaks and fixes

* Fix number replacements

* Minor cleanup

* Update fnc_getMagazineName.sqf

* Update fnc_getMagazineName.sqf

* Minor improvement

* Made factions case-sensitive and added `toLowerANSI` to be safe

* Update fnc_getDetectedObject.sqf

* Update addons/common/functions/fnc_actionKeysNamesConverted.sqf

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>

* Throw error if item doesn't exist

---------

Co-authored-by: Salluci <69561145+Salluci@users.noreply.github.com>
Co-authored-by: johnb432 <58661205+johnb432@users.noreply.github.com>
This commit is contained in:
Grim 2024-06-11 12:34:32 -03:00 committed by GitHub
parent 898daff7f6
commit 59af3e1f6d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
50 changed files with 152 additions and 177 deletions

View File

@ -10,16 +10,6 @@ if (!hasInterface) exitWith {};
// Temporary Wind Info indication // Temporary Wind Info indication
GVAR(tempWindInfo) = false; GVAR(tempWindInfo) = false;
// Ammo/Magazines look-up hash for correctness of initSpeed
GVAR(ammoMagLookup) = call CBA_fnc_createNamespace;
{
{
private _ammo = getText (configFile >> "CfgMagazines" >> _x >> "ammo");
if (_ammo != "") then { GVAR(ammoMagLookup) setVariable [_ammo, _x]; };
} forEach (getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines"));
} forEach getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles");
// Add keybinds // Add keybinds
["ACE3 Weapons", QGVAR(prepare), localize LSTRING(Prepare), { ["ACE3 Weapons", QGVAR(prepare), localize LSTRING(Prepare), {
// Condition // Condition

View File

@ -1,3 +1,21 @@
#include "script_component.hpp" #include "script_component.hpp"
#include "XEH_PREP.hpp" #include "XEH_PREP.hpp"
// Ammo/Magazines look-up hash for correctness of initSpeed
private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgAmmo = configFile >> "CfgAmmo";
private _cfgThrow = configFile >> "CfgWeapons" >> "Throw";
private _ammoMagLookup = createHashMap;
{
{
private _ammo = getText (_cfgMagazines >> _x >> "ammo");
if (_ammo != "") then {
_ammoMagLookup set [configName (_cfgAmmo >> _ammo), _x];
};
} forEach (getArray (_cfgThrow >> _x >> "magazines"));
} forEach (getArray (_cfgThrow >> "muzzles"));
uiNamespace setVariable [QGVAR(ammoMagLookup), compileFinal _ammoMagLookup];

View File

@ -43,13 +43,10 @@ if ((!_primed) && {!((_throwableMag in (uniformItems ACE_player)) || {_throwable
// Get correct throw power for primed grenade // Get correct throw power for primed grenade
if (_primed) then { if (_primed) then {
private _ammoType = typeOf _activeThrowable; // If ammo type is not found:
_throwableMag = GVAR(ammoMagLookup) getVariable _ammoType; // What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke)
if (isNil "_throwableMag") then { // Just use HandGrenade as it has an average initSpeed value
// What we're trying to throw must not be a normal throwable because it is not in our lookup hash (e.g. 40mm smoke) _throwableMag = (uiNamespace getVariable QGVAR(ammoMagLookup)) getOrDefault [typeOf _activeThrowable, "HandGrenade"];
// Just use HandGrenade as it has an average initSpeed value
_throwableMag = "HandGrenade";
};
}; };
// Some throwables have different classname for magazine and ammo // Some throwables have different classname for magazine and ammo

View File

@ -24,7 +24,7 @@ if (isServer) then {
}]; }];
}; };
["unit", FUNC(handlePlayerChanged)] call CBA_fnc_addPlayerEventHandler; ["unit", LINKFUNC(handlePlayerChanged)] call CBA_fnc_addPlayerEventHandler;
[QGVAR(moveInCaptive), LINKFUNC(vehicleCaptiveMoveIn)] call CBA_fnc_addEventHandler; [QGVAR(moveInCaptive), LINKFUNC(vehicleCaptiveMoveIn)] call CBA_fnc_addEventHandler;
[QGVAR(moveOutCaptive), LINKFUNC(vehicleCaptiveMoveOut)] call CBA_fnc_addEventHandler; [QGVAR(moveOutCaptive), LINKFUNC(vehicleCaptiveMoveOut)] call CBA_fnc_addEventHandler;

View File

@ -145,7 +145,7 @@ if (isServer) then {
INFO_3("[%1] DC - Was Zeus [%2] while controlling unit [%3] - manually clearing `bis_fnc_moduleRemoteControl_owner`",[_x] call FUNC(getName),_dcPlayer,_x); INFO_3("[%1] DC - Was Zeus [%2] while controlling unit [%3] - manually clearing `bis_fnc_moduleRemoteControl_owner`",[_x] call FUNC(getName),_dcPlayer,_x);
_x setVariable ["bis_fnc_moduleRemoteControl_owner", nil, true]; _x setVariable ["bis_fnc_moduleRemoteControl_owner", nil, true];
}; };
} forEach (curatorEditableObjects _zeusLogic); } forEach (curatorEditableObjects _zeusLogic);
}; };
}]; }];
}; };

View File

@ -43,10 +43,10 @@ if (isNil "_keyTable") then {
}; };
}; };
private _keyCache = uiNamespace getVariable [QGVAR(keyNameCache), locationNull]; private _keyCache = uiNamespace getVariable QGVAR(keyNameCache); // @TODO: Move cache creation to preStart/somewhere else
if (isNull _keyCache) then { if (isNil "_keyCache") then {
_keyCache = call CBA_fnc_createNamespace; _keyCache = createHashMap;
uiNamespace setVariable [QGVAR(keyNameCache), _keyCache]; uiNamespace setVariable [QGVAR(keyNameCache), _keyCache];
}; };
@ -54,7 +54,7 @@ params [["_action", "", [""]]];
private _keybinds = actionKeysNamesArray _action apply { private _keybinds = actionKeysNamesArray _action apply {
private _keyName = _x; private _keyName = _x;
private _keybind = _keyCache getVariable _keyName; private _keybind = _keyCache get _keyName;
if (isNil "_keybind") then { if (isNil "_keybind") then {
private _key = -1; private _key = -1;
@ -101,7 +101,7 @@ private _keybinds = actionKeysNamesArray _action apply {
// cache // cache
_keybind = [_key, _shift, _ctrl, _alt]; _keybind = [_key, _shift, _ctrl, _alt];
_keyCache setVariable [_keyName, _keybind]; _keyCache set [_keyName, _keybind];
}; };
_keybind _keybind

View File

@ -32,7 +32,6 @@ scopeName "main";
if (_x select 0 == _name) then { if (_x select 0 == _name) then {
_x breakOut "main"; _x breakOut "main";
}; };
false } forEach GVAR(settings);
} count GVAR(settings);
[] []

View File

@ -20,15 +20,23 @@
params [["_oldItem", "", [0,""]], ["_newItems", "", ["", []]], ["_replaceInherited", false, [false]]]; params [["_oldItem", "", [0,""]], ["_newItems", "", ["", []]], ["_replaceInherited", false, [false]]];
TRACE_3("registerItemReplacement",_oldItem,_newItems,_replaceInherited); TRACE_3("registerItemReplacement",_oldItem,_newItems,_replaceInherited);
// Setup on first run // Setup on first run
if (isNil QGVAR(itemReplacements)) then { if (isNil QGVAR(itemReplacements)) then {
GVAR(itemReplacements) = [] call CBA_fnc_createNamespace; GVAR(itemReplacements) = createHashMap;
GVAR(inheritedReplacements) = []; GVAR(inheritedReplacements) = [];
GVAR(oldItems) = []; GVAR(oldItems) = [];
["loadout", LINKFUNC(replaceRegisteredItems)] call CBA_fnc_addPlayerEventHandler; ["loadout", LINKFUNC(replaceRegisteredItems)] call CBA_fnc_addPlayerEventHandler;
}; };
// Get config case - if item doesn't exist, "" is returned
if (_oldItem isEqualType "") then {
_oldItem = _oldItem call FUNC(getConfigName);
};
if (_oldItem isEqualTo "") exitWith {
ERROR("Item doesn't exist");
};
// Save item replacement // Save item replacement
// $ prefix is used for types (numbers) and replacements with inheritance // $ prefix is used for types (numbers) and replacements with inheritance
if (_replaceInherited) then { if (_replaceInherited) then {
@ -42,9 +50,8 @@ if (_newItems isEqualType "") then {
_newItems = [_newItems]; _newItems = [_newItems];
}; };
private _oldReplacements = GVAR(itemReplacements) getVariable [_oldItem, []]; private _oldReplacements = GVAR(itemReplacements) getOrDefault [_oldItem, [], true];
_oldReplacements append _newItems; _oldReplacements append _newItems;
GVAR(itemReplacements) setVariable [_oldItem, _oldReplacements];
// Force item scan when new replacement was registered in PostInit // Force item scan when new replacement was registered in PostInit
if !(isNull ACE_player) then { if !(isNull ACE_player) then {

View File

@ -42,7 +42,7 @@ for "_i" from 0 to count _newItems - 1 do {
private _replacements = []; private _replacements = [];
// Determine replacement items: direct replacements, ... // Determine replacement items: direct replacements, ...
private _directReplacements = GVAR(itemReplacements) getVariable _item; private _directReplacements = GVAR(itemReplacements) get _item;
if (!isNil "_directReplacements") then { if (!isNil "_directReplacements") then {
_doReplace = true; _doReplace = true;
_replacements append _directReplacements; _replacements append _directReplacements;
@ -50,7 +50,7 @@ for "_i" from 0 to count _newItems - 1 do {
// ... item type replacements ... // ... item type replacements ...
private _type = getNumber (_cfgWeapons >> _item >> "ItemInfo" >> "type"); private _type = getNumber (_cfgWeapons >> _item >> "ItemInfo" >> "type");
private _typeReplacements = GVAR(itemReplacements) getVariable ("$" + str _type); private _typeReplacements = GVAR(itemReplacements) get ("$" + str _type);
if (!isNil "_typeReplacements") then { if (!isNil "_typeReplacements") then {
_doReplace = true; _doReplace = true;
_replacements append _typeReplacements; _replacements append _typeReplacements;
@ -59,7 +59,7 @@ for "_i" from 0 to count _newItems - 1 do {
// ... and inherited replacements // ... and inherited replacements
{ {
if (_item isKindOf [_x, _cfgWeapons]) then { if (_item isKindOf [_x, _cfgWeapons]) then {
private _inheritedReplacements = GVAR(itemReplacements) getVariable _x; private _inheritedReplacements = GVAR(itemReplacements) get _x;
if (!isNil "_inheritedReplacements") then { if (!isNil "_inheritedReplacements") then {
_doReplace = true; _doReplace = true;
_replacements append _inheritedReplacements; _replacements append _inheritedReplacements;

View File

@ -30,4 +30,4 @@ GVAR(vectorConnected) = false;
GVAR(noVectorData) = true; GVAR(noVectorData) = true;
GVAR(vectorGrid) = "00000000"; GVAR(vectorGrid) = "00000000";
[QEGVAR(vector,rangefinderData), FUNC(handleRangeFinderData)] call CBA_fnc_addEventHandler; [QEGVAR(vector,rangefinderData), LINKFUNC(handleRangeFinderData)] call CBA_fnc_addEventHandler;

View File

@ -6,6 +6,6 @@ PREP_RECOMPILE_START;
#include "XEH_PREP.hpp" #include "XEH_PREP.hpp"
PREP_RECOMPILE_END; PREP_RECOMPILE_END;
GVAR(disabledFactions) = [] call CBA_fnc_createNamespace; GVAR(disabledFactions) = createHashMap;
ADDON = true; ADDON = true;

View File

@ -21,6 +21,6 @@ params ["_player", "_target"];
if (isNull _target) exitWith {false}; if (isNull _target) exitWith {false};
// check if disabled for faction // check if disabled for faction
if ([GVAR(disabledFactions) getVariable faction _target] param [0, false]) exitWith {false}; if ((faction _target) in GVAR(disabledFactions)) exitWith {false};
(!alive _target) || {_target getVariable ["ACE_isUnconscious", false]} (!alive _target) || {_target getVariable ["ACE_isUnconscious", false]}

View File

@ -21,6 +21,6 @@ params ["_player", "_target"];
if (isNull _target) exitWith {false}; if (isNull _target) exitWith {false};
// check if disabled for faction // check if disabled for faction
if ([GVAR(disabledFactions) getVariable faction _target] param [0, false]) exitWith {false}; if ((faction _target) in GVAR(disabledFactions)) exitWith {false};
(!alive _target) || {_target getVariable ["ACE_isUnconscious", false]} (!alive _target) || {_target getVariable ["ACE_isUnconscious", false]}

View File

@ -17,4 +17,9 @@
params [["_faction", "", [""]]]; params [["_faction", "", [""]]];
GVAR(disabledFactions) setVariable [_faction, true]; _faction = configName (configFile >> "CfgFactionClasses" >> _faction);
// Faction doesn't exist
if (_faction == "") exitWith {};
GVAR(disabledFactions) set [_faction, true];

View File

@ -31,7 +31,7 @@ private _detonators = [_unit] call FUNC(getDetonators);
if !(_x in _detonators) exitWith{ if !(_x in _detonators) exitWith{
_hasRequired = false; _hasRequired = false;
}; };
} count _requiredItems; } forEach _requiredItems;
if !(_hasRequired) exitWith {}; if !(_hasRequired) exitWith {};
private _config = ConfigFile >> "CfgMagazines" >> _magazineClass >> "ACE_Triggers" >> configName _config; private _config = ConfigFile >> "CfgMagazines" >> _magazineClass >> "ACE_Triggers" >> configName _config;

View File

@ -18,7 +18,7 @@ if (isServer) then {
}] call CBA_fnc_addEventHandler; }] call CBA_fnc_addEventHandler;
// Cache for ammo type configs // Cache for ammo type configs
GVAR(cacheRoundsTypesToTrack) = [false] call CBA_fnc_createNamespace; GVAR(cacheRoundsTypesToTrack) = createHashMap;
// Debug stuff: // Debug stuff:

View File

@ -120,7 +120,7 @@ if (_zIndex < 5) then {
// _dirvec = _pos vectorFromTo ((player modelToWorldVisualWorld (player selectionPosition "Spine3"))); // _dirvec = _pos vectorFromTo ((player modelToWorldVisualWorld (player selectionPosition "Spine3")));
// _dirvec = _dirvec vectorMultiply 100; // _dirvec = _dirvec vectorMultiply 100;
// _can setVelocity _dirvec; // _can setVelocity _dirvec;
[DFUNC(doExplosions), 0, [_explosions, 0]] call CBA_fnc_addPerFrameHandler; [LINKFUNC(doExplosions), 0, [_explosions, 0]] call CBA_fnc_addPerFrameHandler;
[_pfhID] call CBA_fnc_removePerFrameHandler; [_pfhID] call CBA_fnc_removePerFrameHandler;
}; };
END_COUNTER(fnc_findReflections); END_COUNTER(fnc_findReflections);

View File

@ -19,7 +19,7 @@
//IGNORE_PRIVATE_WARNING ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle", "_gunner", "_turret"]; //IGNORE_PRIVATE_WARNING ["_unit", "_weapon", "_muzzle", "_mode", "_ammo", "_magazine", "_projectile", "_vehicle", "_gunner", "_turret"];
TRACE_10("firedEH:",_unit,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile,_vehicle,_gunner,_turret); TRACE_10("firedEH:",_unit,_weapon,_muzzle,_mode,_ammo,_magazine,_projectile,_vehicle,_gunner,_turret);
private _shouldAdd = GVAR(cacheRoundsTypesToTrack) getVariable _ammo; private _shouldAdd = GVAR(cacheRoundsTypesToTrack) get _ammo;
if (isNil "_shouldAdd") then { if (isNil "_shouldAdd") then {
TRACE_1("no cache for round",_ammo); TRACE_1("no cache for round",_ammo);
@ -40,7 +40,7 @@ if (isNil "_shouldAdd") then {
}; };
TRACE_6("Setting Cache",_skip,_explosive,_indirectRange,_force,_fragPower,_shouldAdd); TRACE_6("Setting Cache",_skip,_explosive,_indirectRange,_force,_fragPower,_shouldAdd);
GVAR(cacheRoundsTypesToTrack) setVariable [_ammo, _shouldAdd]; GVAR(cacheRoundsTypesToTrack) set [_ammo, _shouldAdd];
}; };
if (_shouldAdd) then { if (_shouldAdd) then {

View File

@ -8,7 +8,7 @@ LOG(MSG_INIT);
// Calculate the maximum zoom allowed for this map // Calculate the maximum zoom allowed for this map
call FUNC(determineZoom); call FUNC(determineZoom);
GVAR(flashlights) = [] call CBA_fnc_createNamespace; GVAR(flashlights) = createHashMap;
["CBA_settingsInitialized", { ["CBA_settingsInitialized", {
if (isMultiplayer && {GVAR(DefaultChannel) != -1}) then { if (isMultiplayer && {GVAR(DefaultChannel) != -1}) then {

View File

@ -17,14 +17,12 @@
params [["_class", "", [""]]]; params [["_class", "", [""]]];
private _isFlashlight = GVAR(flashlights) getVariable _class; GVAR(flashlights) getOrDefaultCall [_class, {
if (isNil "_isFlashlight") then {
private _items = ([_class] + (_class call CBA_fnc_switchableAttachments)); private _items = ([_class] + (_class call CBA_fnc_switchableAttachments));
private _cfgWeapons = configFile >> "CfgWeapons"; private _cfgWeapons = configFile >> "CfgWeapons";
// if this item or any of the switchable items is a flashlight // if this item or any of the switchable items is a flashlight
_isFlashlight = _items findIf { _items findIf {
private _weaponConfig = _cfgWeapons >> _x; private _weaponConfig = _cfgWeapons >> _x;
[ [
@ -34,10 +32,5 @@ if (isNil "_isFlashlight") then {
isText (_x >> "ACE_Flashlight_Colour") isText (_x >> "ACE_Flashlight_Colour")
|| {!(getArray (_x >> "ambient") in [[], [0,0,0]]) && {getNumber (_x >> "irLight") == 0}} || {!(getArray (_x >> "ambient") in [[], [0,0,0]]) && {getNumber (_x >> "irLight") == 0}}
} != -1 // return } != -1 // return
} != -1; } != -1 // return
}, true] // return
// cache value
GVAR(flashlights) setVariable [_class, _isFlashlight];
};
_isFlashlight // return

View File

@ -8,6 +8,6 @@ PREP_RECOMPILE_END;
#include "initSettings.inc.sqf" #include "initSettings.inc.sqf"
GVAR(GroupColorCfgMappingNew) = call CBA_fnc_createNamespace; GVAR(GroupColorCfgMappingNew) = createHashMap;
ADDON = true; ADDON = true;

View File

@ -28,4 +28,4 @@ if (_group == "") exitWith {ERROR("Group ID is blank, which is not valid.")};
if (!([_leadColor] call FUNC(isValidColorArray))) exitWith {ERROR("leadColor is not a valid color array.")}; if (!([_leadColor] call FUNC(isValidColorArray))) exitWith {ERROR("leadColor is not a valid color array.")};
if (!([_unitColor] call FUNC(isValidColorArray))) exitWith {ERROR("color is not a valid color array.")}; if (!([_unitColor] call FUNC(isValidColorArray))) exitWith {ERROR("color is not a valid color array.")};
GVAR(GroupColorCfgMappingNew) setVariable [_group, [_leadColor, _unitColor]]; GVAR(GroupColorCfgMappingNew) set [toLower _group, [_leadColor, _unitColor]];

View File

@ -41,7 +41,7 @@ private _players = [_positions, FUNC(getProximityPlayers), missionNamespace, QGV
}; };
// If color settings for the group exist, then use those, otherwise fall back to the default colors // If color settings for the group exist, then use those, otherwise fall back to the default colors
private _colorMap = GVAR(GroupColorCfgMappingNew) getVariable [(groupID (group _x)), [GVAR(defaultLeadColor), GVAR(defaultColor)]]; private _colorMap = GVAR(GroupColorCfgMappingNew) getOrDefault [toLower groupID (group _x), [GVAR(defaultLeadColor), GVAR(defaultColor)]];
private _color = _colorMap select (_x != leader _x); private _color = _colorMap select (_x != leader _x);
TRACE_2("",_colorMap,_color); TRACE_2("",_colorMap,_color);

View File

@ -8,22 +8,8 @@ PREP_RECOMPILE_END;
#include "initSettings.inc.sqf" #include "initSettings.inc.sqf"
// Damage types which do not cause blood spurts
GVAR(noBloodDamageTypes) = createHashMapFromArray (call (uiNamespace getVariable QGVAR(noBloodDamageTypes)));
// blood object model namespace // blood object model namespace
GVAR(models) = [] call CBA_fnc_createNamespace; GVAR(models) = createHashMapFromArray [
{
_x params ["_name", "_model"];
// createSimpleObject expects a path without the leading slash
if ((_model select [0,1]) isEqualTo "\") then {
_model = _model select [1];
};
GVAR(models) setVariable [_name, _model];
} forEach [
// higher number means bigger model // higher number means bigger model
["blooddrop_1", QPATHTOF(data\ace_drop_1.p3d)], ["blooddrop_1", QPATHTOF(data\ace_drop_1.p3d)],
["blooddrop_2", QPATHTOF(data\ace_drop_2.p3d)], ["blooddrop_2", QPATHTOF(data\ace_drop_2.p3d)],

View File

@ -4,7 +4,4 @@
// Damage types which do not cause blood spurts // Damage types which do not cause blood spurts
private _noBloodDamageTypes = "getNumber (_x >> 'noBlood') == 1" configClasses (configFile >> "ACE_Medical_Injuries" >> "damageTypes"); private _noBloodDamageTypes = "getNumber (_x >> 'noBlood') == 1" configClasses (configFile >> "ACE_Medical_Injuries" >> "damageTypes");
uiNamespace setVariable [ uiNamespace setVariable [QGVAR(noBloodDamageTypes), compileFinal (_noBloodDamageTypes createHashMapFromArray [])];
QGVAR(noBloodDamageTypes),
compileFinal str (_noBloodDamageTypes apply {[configName _x, nil]})
];

View File

@ -21,7 +21,7 @@
params ["_type", "_position", "_source"]; params ["_type", "_position", "_source"];
TRACE_3("Creating blood",_type,_position,_source); TRACE_3("Creating blood",_type,_position,_source);
private _model = GVAR(models) getVariable _type; private _model = GVAR(models) get _type;
private _bloodDrop = createSimpleObject [_model, [0, 0, 0]]; private _bloodDrop = createSimpleObject [_model, [0, 0, 0]];
_bloodDrop setDir random 360; _bloodDrop setDir random 360;

View File

@ -22,7 +22,7 @@ params ["_unit", "_allDamages", "_shooter", "_damageType"];
(_allDamages select 0) params ["_damage"]; (_allDamages select 0) params ["_damage"];
// Don't bleed if damage type does not cause bleeding // Don't bleed if damage type does not cause bleeding
if (_damageType in GVAR(noBloodDamageTypes)) exitWith {}; if (_damageType in (uiNamespace getVariable QGVAR(noBloodDamageTypes))) exitWith {};
// Don't bleed when players only and a non-player unit is wounded // Don't bleed when players only and a non-player unit is wounded
if (GVAR(enabledFor) == BLOOD_ONLY_PLAYERS && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {}; if (GVAR(enabledFor) == BLOOD_ONLY_PLAYERS && {!isPlayer _unit && {_unit != ACE_player}}) exitWith {};

View File

@ -40,11 +40,12 @@ GVAR(armorCache) = createHashMap;
// with handle damage not returning full results. // with handle damage not returning full results.
GVAR(fixedStatics) = []; GVAR(fixedStatics) = [];
GVAR(animations) = [] call CBA_fnc_createNamespace; GVAR(animations) = createHashMapFromArray [
GVAR(animations) setVariable [QUNCON_ANIM(faceUp), [QUNCON_ANIM(2),QUNCON_ANIM(2_1),QUNCON_ANIM(7_1),QUNCON_ANIM(8_1),QUNCON_ANIM(5_1),QUNCON_ANIM(6_1)]]; [QUNCON_ANIM(faceUp), [QUNCON_ANIM(2),QUNCON_ANIM(2_1),QUNCON_ANIM(7_1),QUNCON_ANIM(8_1),QUNCON_ANIM(5_1),QUNCON_ANIM(6_1)]],
GVAR(animations) setVariable [QUNCON_ANIM(faceDown), [QUNCON_ANIM(1),QUNCON_ANIM(3),QUNCON_ANIM(4),"unconscious",QUNCON_ANIM(9),QUNCON_ANIM(3_1),QUNCON_ANIM(4_1)]]; [QUNCON_ANIM(faceDown), [QUNCON_ANIM(1),QUNCON_ANIM(3),QUNCON_ANIM(4),"unconscious",QUNCON_ANIM(9),QUNCON_ANIM(3_1),QUNCON_ANIM(4_1)]],
GVAR(animations) setVariable [QUNCON_ANIM(faceLeft), [QUNCON_ANIM(7),QUNCON_ANIM(8),QUNCON_ANIM(1_1),QUNCON_ANIM(7_1),QUNCON_ANIM(8_1)]]; [QUNCON_ANIM(faceLeft), [QUNCON_ANIM(7),QUNCON_ANIM(8),QUNCON_ANIM(1_1),QUNCON_ANIM(7_1),QUNCON_ANIM(8_1)]],
GVAR(animations) setVariable [QUNCON_ANIM(faceRight), [QUNCON_ANIM(5),QUNCON_ANIM(6),QUNCON_ANIM(10),QUNCON_ANIM(5_1),QUNCON_ANIM(6_1)]]; [QUNCON_ANIM(faceRight), [QUNCON_ANIM(5),QUNCON_ANIM(6),QUNCON_ANIM(10),QUNCON_ANIM(5_1),QUNCON_ANIM(6_1)]]
];
GVAR(customHitpoints) = ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"]; GVAR(customHitpoints) = ["hitleftarm", "hitrightarm", "hitleftleg", "hitrightleg"];

View File

@ -23,7 +23,7 @@ if !(IS_UNCONSCIOUS(_unit) && // do not run if unit is conscio
{alive _unit && // do not run if unit is dead {alive _unit && // do not run if unit is dead
{isNull objectParent _unit}}) exitWith {}; // do not run if unit in any vehicle {isNull objectParent _unit}}) exitWith {}; // do not run if unit in any vehicle
private _animsArray = GVAR(animations) getVariable [_anim, [""]]; private _animsArray = GVAR(animations) getOrDefault [_anim, [""]];
private _random = (toArray (hashValue _unit)) param [0, 0]; private _random = (toArray (hashValue _unit)) param [0, 0];
private _index = _random % (count _animsArray); private _index = _random % (count _animsArray);
private _unconsciousAnimation = _animsArray select _index; private _unconsciousAnimation = _animsArray select _index;

View File

@ -14,27 +14,23 @@ PREP_RECOMPILE_END;
// adjusting these is trail and error // adjusting these is trail and error
// if the animation is cut of ingame, increase these values // if the animation is cut of ingame, increase these values
// if the unit idles too much, decrease them // if the unit idles too much, decrease them
GVAR(animDurations) = [] call CBA_fnc_createNamespace; GVAR(animDurations) = createHashMapFromArray [
["ainvpknlmstpslaywnondnon_medic", 7.5],
{ ["ainvppnemstpslaywnondnon_medic", 7],
GVAR(animDurations) setVariable _x; ["ainvpknlmstpslaywrfldnon_medic", 7],
} forEach [ ["ainvppnemstpslaywrfldnon_medic", 9.5],
["AinvPknlMstpSlayWnonDnon_medic", 7.5], ["ainvpknlmstpslaywlnrdnon_medic", 9],
["AinvPpneMstpSlayWnonDnon_medic", 7], ["ainvpknlmstpslaywpstdnon_medic", 9.5],
["AinvPknlMstpSlayWrflDnon_medic", 7], ["ainvppnemstpslaywpstdnon_medic", 10],
["AinvPpneMstpSlayWrflDnon_medic", 9.5], ["ainvpknlmstpslaywnondnon_medicother", 8.5],
["AinvPknlMstpSlayWlnrDnon_medic", 9], ["ainvppnemstpslaywnondnon_medicother", 8.5],
["AinvPknlMstpSlayWpstDnon_medic", 9.5], ["ainvpknlmstpslaywrfldnon_medicother", 7],
["AinvPpneMstpSlayWpstDnon_medic", 10], ["ainvppnemstpslaywrfldnon_medicother", 9],
["AinvPknlMstpSlayWnonDnon_medicOther", 8.5], ["ainvpknlmstpslaywlnrdnon_medicother", 9],
["AinvPpneMstpSlayWnonDnon_medicOther", 8.5], ["ainvpknlmstpslaywpstdnon_medicother", 10],
["AinvPknlMstpSlayWrflDnon_medicOther", 7], ["ainvppnemstpslaywpstdnon_medicother", 8.5],
["AinvPpneMstpSlayWrflDnon_medicOther", 9], ["ainvpknlmstpsnonwnondnon_medic1", 10],
["AinvPknlMstpSlayWlnrDnon_medicOther", 9], ["ainvpknlmstpsnonwnondr_medic0", 12]
["AinvPknlMstpSlayWpstDnon_medicOther", 10],
["AinvPpneMstpSlayWpstDnon_medicOther", 8.5],
["AinvPknlMstpSnonWnonDnon_medic1", 10],
["AinvPknlMstpSnonWnonDr_medic0", 12]
]; ];
// class names of medical facilities (config case) // class names of medical facilities (config case)

View File

@ -76,7 +76,7 @@ if (_medic isNotEqualTo player || {!_isInZeus}) then {
}; };
// Determine the animation length // Determine the animation length
private _animDuration = GVAR(animDurations) getVariable _medicAnim; private _animDuration = GVAR(animDurations) get toLowerANSI _medicAnim;
if (isNil "_animDuration") then { if (isNil "_animDuration") then {
WARNING_2("animation [%1] for [%2] has no duration defined",_medicAnim,_classname); WARNING_2("animation [%1] for [%2] has no duration defined",_medicAnim,_classname);
_animDuration = 10; _animDuration = 10;

View File

@ -1,16 +1,7 @@
#include "script_component.hpp" #include "script_component.hpp"
// Create a dictionary to store detector configs // Create a dictionary to store detector configs
GVAR(detectorConfigs) = call CBA_fnc_createNamespace; GVAR(detectorConfigs) = createHashMap;
// Create a dictionary of detectable classnames
GVAR(detectableClasses) = call CBA_fnc_createNamespace;
private _detectableClasses = call (uiNamespace getVariable [QGVAR(detectableClasses), {[]}]); //See XEH_preStart.sqf
{
GVAR(detectableClasses) setVariable [_x, true];
} forEach _detectableClasses;
TRACE_1("built cache",count allVariables GVAR(detectableClasses));
[QGVAR(enableDetector), LINKFUNC(enableDetector)] call CBA_fnc_addEventHandler; [QGVAR(enableDetector), LINKFUNC(enableDetector)] call CBA_fnc_addEventHandler;
[QGVAR(disableDetector), LINKFUNC(disableDetector)] call CBA_fnc_addEventHandler; [QGVAR(disableDetector), LINKFUNC(disableDetector)] call CBA_fnc_addEventHandler;

View File

@ -15,5 +15,5 @@ private _detectableClasses = [];
}; };
} forEach (configProperties [configFile >> "CfgAmmo", "isClass _x", true]); } forEach (configProperties [configFile >> "CfgAmmo", "isClass _x", true]);
TRACE_1("compiled",count _detectableClasses); TRACE_1("built cache",count _detectableClasses);
uiNamespace setVariable [QGVAR(detectableClasses), compileFinal str _detectableClasses]; uiNamespace setVariable [QGVAR(detectableClasses), compileFinal (_detectableClasses createHashMapFromArray [])];

View File

@ -38,15 +38,13 @@ private _mine = objNull;
private _distance = -1; private _distance = -1;
{ {
private _objectType = typeOf _x; if ((getModelInfo _x) select 0 == "empty.p3d") then {
continue;
_isDetectable = GVAR(detectableClasses) getVariable _objectType;
if (isNil "_isDetectable" || {(getModelInfo _x) select 0 == "empty.p3d"}) then {
_isDetectable = false;
}; };
// If a nun-null object was detected exit the search // If an object was detected, exit the search
if (_isDetectable && {!isNull _x}) exitWith { if ((typeOf _x) in (uiNamespace getVariable QGVAR(detectableClasses))) exitWith {
_isDetectable = true;
_distance = _detectorPointAGL distance _x; _distance = _detectorPointAGL distance _x;
_mine = _x; _mine = _x;
TRACE_3("return",_isDetectable,_mine,_distance); TRACE_3("return",_isDetectable,_mine,_distance);

View File

@ -19,18 +19,15 @@ params ["_detectorType"];
if (_detectorType isEqualTo "") exitWith {[]}; if (_detectorType isEqualTo "") exitWith {[]};
private _detectorConfig = GVAR(detectorConfigs) getVariable _detectorType; GVAR(detectorConfigs) getOrDefaultCall [_detectorType, {
if (isNil "_detectorConfig") then {
private _cfgEntry = (configFile >> "ACE_detector" >> "detectors" >> _detectorType); private _cfgEntry = (configFile >> "ACE_detector" >> "detectors" >> _detectorType);
if (isClass _cfgEntry) then { if (isClass _cfgEntry) then {
_detectorConfig = [ [
_detectorType, _detectorType,
getNumber (_cfgEntry >> "radius"), getNumber (_cfgEntry >> "radius"),
getArray (_cfgEntry >> "sounds") getArray (_cfgEntry >> "sounds")
]; ];
} else { } else {
_detectorConfig = []; []
}; };
GVAR(detectorConfigs) setVariable [_detectorType, _detectorConfig]; }, true]
};
_detectorConfig

View File

@ -50,7 +50,7 @@ if (missionNamespace getVariable [QGVAR(useFactionIcons), true]) then {
{ {
if (isArray (_x >> QGVAR(rankIcons))) then { if (isArray (_x >> QGVAR(rankIcons))) then {
private _faction = configName _x; private _faction = configName _x;
if (!isNil {GVAR(factionRanks) getVariable _faction}) exitWith {}; // don't overwrite if already set if (_faction in GVAR(factionRanks)) exitWith {}; // don't overwrite if already set
private _icons = getArray (_x >> QGVAR(rankIcons)); private _icons = getArray (_x >> QGVAR(rankIcons));
[_faction, _icons] call FUNC(setFactionRankIcons); [_faction, _icons] call FUNC(setFactionRankIcons);
}; };

View File

@ -42,7 +42,7 @@ _fnc_parameters = {
default { default {
private _targetFaction = _target getVariable [QGVAR(faction), faction _target]; private _targetFaction = _target getVariable [QGVAR(faction), faction _target];
private _customRankIcons = GVAR(factionRanks) getVariable _targetFaction; private _customRankIcons = GVAR(factionRanks) get _targetFaction;
if (!isNil "_customRankIcons") then { if (!isNil "_customRankIcons") then {
_customRankIcons param [ALL_RANKS find rank _target, ""] // return _customRankIcons param [ALL_RANKS find rank _target, ""] // return

View File

@ -25,7 +25,7 @@
*/ */
if (isNil QGVAR(factionRanks)) then { if (isNil QGVAR(factionRanks)) then {
GVAR(factionRanks) = [] call CBA_fnc_createNamespace; GVAR(factionRanks) = createHashMap;
}; };
params [["_faction", "", [""]], ["_icons", [], [[]], [7]]]; params [["_faction", "", [""]], ["_icons", [], [[]], [7]]];
@ -33,6 +33,11 @@ TRACE_2("setFactionRankIcons",_faction,_icons);
if !(_faction != "" && {_icons isEqualTypeAll ""}) exitWith {false}; if !(_faction != "" && {_icons isEqualTypeAll ""}) exitWith {false};
GVAR(factionRanks) setVariable [_faction, _icons]; _faction = configName (configFile >> "CfgFactionClasses" >> _faction);
// Faction doesn't exist
if (_faction == "") exitWith {false};
GVAR(factionRanks) set [_faction, _icons];
true true

View File

@ -107,7 +107,7 @@ GVAR(comboBoxes) = [];
private _mirroredIndex = getNumber (_x >> "mirroredMissilePos"); private _mirroredIndex = getNumber (_x >> "mirroredMissilePos");
private _button = controlNull; private _button = controlNull;
if (count allTurrets [_aircraft, false] > 0) then { if ((allTurrets [_aircraft, false]) isNotEqualTo []) then {
_button = _display ctrlCreate ["ctrlButtonPictureKeepAspect", -1]; _button = _display ctrlCreate ["ctrlButtonPictureKeepAspect", -1];
private _turret = [_aircraft, _forEachIndex] call EFUNC(common,getPylonTurret); private _turret = [_aircraft, _forEachIndex] call EFUNC(common,getPylonTurret);
[_button, false, _turret] call FUNC(onButtonTurret); [_button, false, _turret] call FUNC(onButtonTurret);

View File

@ -1,6 +1,5 @@
#include "script_component.hpp" #include "script_component.hpp"
GVAR(hardpointGroupsCache) = [] call CBA_fnc_createNamespace;
GVAR(configTypesAdded) = []; GVAR(configTypesAdded) = [];
GVAR(magazineNameCache) = createHashMap; GVAR(magazineNameCache) = createHashMap;
GVAR(usedMagazineNames) = createHashMap; GVAR(usedMagazineNames) = createHashMap;

View File

@ -1,14 +1,6 @@
// by esteldunedain // by esteldunedain
#include "script_component.hpp" #include "script_component.hpp"
// Cache for static objects
GVAR(cacheStaticModels) = [false] call CBA_fnc_createNamespace;
private _cacheStaticModels = call (uiNamespace getVariable [QGVAR(cacheStaticModels), {[]}]);
{
GVAR(cacheStaticModels) setVariable [_x, true];
} forEach _cacheStaticModels;
if (hasInterface) then { if (hasInterface) then {
// Compile and cache config tags // Compile and cache config tags
call FUNC(compileConfigTags); call FUNC(compileConfigTags);

View File

@ -26,9 +26,9 @@ private _cfgBase = configFile >> "CfgNonAIVehicles";
private _array = _model splitString "\"; private _array = _model splitString "\";
_cacheStaticModels pushBackUnique toLowerANSI (_array select -1); _cacheStaticModels pushBackUnique toLowerANSI (_array select -1);
}; };
} forEach (_nonaivehicleClasses select {(configName _x) isKindOf ["Bridge_base_F", _cfgBase]}); } forEach (_nonAIVehicleClasses select {(configName _x) isKindOf ["Bridge_base_F", _cfgBase]});
uiNamespace setVariable [QGVAR(cacheStaticModels), compileFinal str _cacheStaticModels]; uiNamespace setVariable [QGVAR(cacheStaticModels), compileFinal (_cacheStaticModels createHashMapFromArray [])];
TRACE_1("compiled",count _cacheStaticModels); TRACE_1("compiled",count _cacheStaticModels);
// force preload of stencil texture to avoid error popup // force preload of stencil texture to avoid error popup

View File

@ -43,14 +43,14 @@
if (_object isKindOf "Static") exitWith {false}; if (_object isKindOf "Static") exitWith {false};
// Taggable vehicle, do not exit // Taggable vehicle, do not exit
if (((_object getVariable [QGVAR(canTag), getNumber (configOf _object >> QGVAR(canTag))]) in [1, true]) if (((_object getVariable [QGVAR(canTag), getNumber (configOf _object >> QGVAR(canTag))]) in [1, true])
&& {getText (configOf _object >> "selectionClan") in selectionNames _object}) exitWith { && {getText (configOf _object >> "selectionClan") in selectionNames _object}) exitWith {
false false
}; };
// If the class is not categorized correctly search the cache // If the class is not categorized correctly search the cache
private _modelName = (getModelInfo _object) select 0; private _modelName = toLowerANSI ((getModelInfo _object) select 0);
private _isStatic = GVAR(cacheStaticModels) getVariable [_modelName, false]; private _isStatic = _modelName in (uiNamespace getVariable QGVAR(cacheStaticModels));
TRACE_2("Object:",_modelName,_isStatic); TRACE_2("Object:",_modelName,_isStatic);
// If the class in not on the cache, exit // If the class in not on the cache, exit
(!_isStatic) (!_isStatic)

View File

@ -60,8 +60,8 @@ if ((!isNull _object) && {
}; };
// If the class is not categorized correctly search the cache // If the class is not categorized correctly search the cache
private _modelName = (getModelInfo _object) select 0; private _modelName = toLowerANSI ((getModelInfo _object) select 0);
private _isStatic = GVAR(cacheStaticModels) getVariable [_modelName, false]; private _isStatic = _modelName in (uiNamespace getVariable QGVAR(cacheStaticModels));
TRACE_2("Object:",_modelName,_isStatic); TRACE_2("Object:",_modelName,_isStatic);
// If the class in not on the cache, exit // If the class in not on the cache, exit
(!_isStatic) (!_isStatic)

View File

@ -4,11 +4,11 @@
if (!hasInterface) exitWith {}; if (!hasInterface) exitWith {};
// Compile and cache config UI // Compile and cache config UI
GVAR(configCache) = call CBA_fnc_createNamespace; GVAR(configCache) = createHashMap;
call FUNC(compileConfigUI); call FUNC(compileConfigUI);
// Scripted API namespace // Scripted API namespace
GVAR(elementsSet) = call CBA_fnc_createNamespace; GVAR(elementsSet) = createHashMap;
// Attach all event handlers where UI has to be updated // Attach all event handlers where UI has to be updated
["CBA_settingsInitialized", { ["CBA_settingsInitialized", {
@ -21,7 +21,7 @@ GVAR(elementsSet) = call CBA_fnc_createNamespace;
// Defaults must be set in this EH to make sure controls are activated and advanced settings can be modified // Defaults must be set in this EH to make sure controls are activated and advanced settings can be modified
{ {
[_x, missionNamespace getVariable (format [QGVAR(%1), _x]), false, !GVAR(allowSelectiveUI)] call FUNC(setAdvancedElement); [_x, missionNamespace getVariable (format [QGVAR(%1), _x]), false, !GVAR(allowSelectiveUI)] call FUNC(setAdvancedElement);
} forEach (allVariables GVAR(configCache)); } forEach (keys GVAR(configCache));
// Execute local event for when it's safe to modify UI through this API // Execute local event for when it's safe to modify UI through this API
// infoDisplayChanged can execute multiple times, make sure it only happens once // infoDisplayChanged can execute multiple times, make sure it only happens once
@ -40,8 +40,7 @@ GVAR(elementsSet) = call CBA_fnc_createNamespace;
[true] call FUNC(setElements); [true] call FUNC(setElements);
} else { } else {
private _nameNoPrefix = toLowerANSI (_name select [7]); private _nameNoPrefix = toLowerANSI (_name select [7]);
private _cachedElement = GVAR(configCache) getVariable _nameNoPrefix; if (_nameNoPrefix in GVAR(configCache)) then {
if (!isNil "_cachedElement") then {
[_nameNoPrefix, _value, true] call FUNC(setAdvancedElement); [_nameNoPrefix, _value, true] call FUNC(setAdvancedElement);
}; };
}; };

View File

@ -40,6 +40,6 @@
TRACE_1("Caching Condition",_x); TRACE_1("Caching Condition",_x);
} forEach (configProperties [_x >> "conditions"]); } forEach (configProperties [_x >> "conditions"]);
GVAR(configCache) setVariable [_class, [_idd, _elements, _location, _conditions]]; GVAR(configCache) set [_class, [_idd, _elements, _location, _conditions]];
}; };
} forEach ("true" configClasses (configFile >> "ACE_UI")); } forEach ("true" configClasses (configFile >> "ACE_UI"));

View File

@ -20,7 +20,9 @@
params ["_element", "_show", ["_showHint", false, [true]], ["_force", false, [true]]]; params ["_element", "_show", ["_showHint", false, [true]], ["_force", false, [true]]];
private _cachedElement = GVAR(configCache) getVariable _element; _element = toLowerANSI _element;
private _cachedElement = GVAR(configCache) get _element;
if (isNil "_cachedElement") exitWith {TRACE_1("nil element",_this)}; if (isNil "_cachedElement") exitWith {TRACE_1("nil element",_this)};
if (!_force && {!GVAR(allowSelectiveUI)}) exitWith { if (!_force && {!GVAR(allowSelectiveUI)}) exitWith {
@ -56,7 +58,7 @@ if (
// Get setting from scripted API // Get setting from scripted API
if (!_force) then { if (!_force) then {
private _setElement = GVAR(elementsSet) getVariable _element; private _setElement = GVAR(elementsSet) get _element;
if (!isNil "_setElement") then { if (!isNil "_setElement") then {
_setElement params ["_sourceSet", "_showSet"]; _setElement params ["_sourceSet", "_showSet"];
if (_showHint) then { if (_showHint) then {

View File

@ -32,12 +32,11 @@ if (_source == "" || {_element == ""}) exitWith {
_element = toLowerANSI _element; _element = toLowerANSI _element;
// Verify element is bound // Verify element is bound
private _cachedElement = GVAR(configCache) getVariable _element; if !(_element in GVAR(configCache)) exitWith {
if (isNil "_cachedElement") exitWith {
WARNING_2("Element '%1' does not exist - modification by '%2' failed.",_element,_source); WARNING_2("Element '%1' does not exist - modification by '%2' failed.",_element,_source);
}; };
private _setElement = GVAR(elementsSet) getVariable _element; private _setElement = GVAR(elementsSet) get _element;
private _return = false; private _return = false;
if (isNil "_setElement") then { if (isNil "_setElement") then {
@ -45,7 +44,7 @@ if (isNil "_setElement") then {
private _success = [_element, _show, false, true] call FUNC(setAdvancedElement); private _success = [_element, _show, false, true] call FUNC(setAdvancedElement);
if (_success) then { if (_success) then {
GVAR(elementsSet) setVariable [_element, [_source, _show]]; GVAR(elementsSet) set [_element, [_source, _show]];
_return = true; _return = true;
}; };
} else { } else {
@ -57,7 +56,7 @@ if (isNil "_setElement") then {
}; };
} else { } else {
TRACE_3("Unsetting element",_sourceSet,_element,_show); TRACE_3("Unsetting element",_sourceSet,_element,_show);
GVAR(elementsSet) setVariable [_element, nil]; GVAR(elementsSet) set [_element, nil];
[_element, _show, false, true] call FUNC(setAdvancedElement); [_element, _show, false, true] call FUNC(setAdvancedElement);
_return = true; _return = true;

View File

@ -11,18 +11,22 @@ GVAR(GrenadesAll) = [];
GVAR(GrenadesFrag) = []; GVAR(GrenadesFrag) = [];
GVAR(GrenadesNonFrag) = []; GVAR(GrenadesNonFrag) = [];
private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgAmmo = configFile >> "CfgAmmo";
private _cfgThrow = configFile >> "CfgWeapons" >> "Throw";
{ {
private _magazines = getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines"); private _magazines = getArray (_cfgThrow >> _x >> "magazines");
GVAR(GrenadesAll) append _magazines; GVAR(GrenadesAll) append _magazines;
{ {
private _ammo = getText (configFile >> "CfgMagazines" >> _x >> "ammo"); private _ammo = getText (_cfgMagazines >> _x >> "ammo");
private _explosive = getNumber (configFile >> "CfgAmmo" >> _ammo >> "explosive"); private _explosive = getNumber (_cfgAmmo >> _ammo >> "explosive");
([GVAR(GrenadesFrag), GVAR(GrenadesNonFrag)] select (_explosive == 0)) pushBack _x; ([GVAR(GrenadesFrag), GVAR(GrenadesNonFrag)] select (_explosive == 0)) pushBack _x;
} forEach _magazines; } forEach _magazines;
} forEach getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles"); } forEach getArray (_cfgThrow >> "muzzles");
#include "initSettings.inc.sqf" #include "initSettings.inc.sqf"

View File

@ -61,14 +61,14 @@ private _vestGrenades = vestItems _unit select {_x in GVAR(GrenadesAll)
private _backpackGrenades = backpackItems _unit select {_x in GVAR(GrenadesAll) && {_x != _nextGrenade}}; private _backpackGrenades = backpackItems _unit select {_x in GVAR(GrenadesAll) && {_x != _nextGrenade}};
// remove all grenades except those we are switching to --> this breaks the selector // remove all grenades except those we are switching to --> this breaks the selector
{_unit removeItemFromUniform _x; false} count _uniformGrenades; {_unit removeItemFromUniform _x} forEach _uniformGrenades;
{_unit removeItemFromVest _x; false} count _vestGrenades; {_unit removeItemFromVest _x} forEach _vestGrenades;
{_unit removeItemFromBackpack _x; false} count _backpackGrenades; {_unit removeItemFromBackpack _x} forEach _backpackGrenades;
// readd grenades // readd grenades
{_unit addItemToUniform _x; false} count _uniformGrenades; {_unit addItemToUniform _x} forEach _uniformGrenades;
{_unit addItemToVest _x; false} count _vestGrenades; {_unit addItemToVest _x} forEach _vestGrenades;
{_unit addItemToBackpack _x; false} count _backpackGrenades; {_unit addItemToBackpack _x} forEach _backpackGrenades;
[_nextGrenade, {_x == _nextGrenade} count _magazines] call FUNC(displayGrenadeTypeAndNumber); [_nextGrenade, {_x == _nextGrenade} count _magazines] call FUNC(displayGrenadeTypeAndNumber);