Skip to content

Commit

Permalink
Arsenal - Reuse current inventory containers when importing invalid l…
Browse files Browse the repository at this point in the history
…oadouts (#10364)

Co-authored-by: Jouni Järvinen <[email protected]>
Co-authored-by: Grim <[email protected]>
  • Loading branch information
3 people authored Feb 5, 2025
1 parent 03d3b80 commit c82b51f
Show file tree
Hide file tree
Showing 9 changed files with 105 additions and 27 deletions.
2 changes: 2 additions & 0 deletions addons/arsenal/XEH_PREP.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ PREP(onSelChangedRightListnBox);
PREP(open3DEN);
PREP(openBox);
PREP(portVALoadouts);
PREP(preventOverfilling);
PREP(refresh);
PREP(removeAction);
PREP(removeBox);
Expand All @@ -79,6 +80,7 @@ PREP(removeStat);
PREP(removeVirtualItems);
PREP(renameDefaultLoadout);
PREP(replaceUniqueItemsLoadout);
PREP(recoverInvalidContainers);
PREP(saveLoadout);
PREP(scanConfig);
PREP(showItem);
Expand Down
5 changes: 5 additions & 0 deletions addons/arsenal/functions/fnc_buttonImport.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ if (GVAR(shiftState) && {is3DEN}) then {

// Check if CBA extended loadout array
if ((count _extendedLoadout) == 2) then {
// Verify the loadout and attempt to recover any invalid containers
_extendedLoadout = [_extendedLoadout, true] call FUNC(verifyLoadout);
// Since verification nests the extended loadout array, undo that after container recovery
_extendedLoadout = ([GVAR(center), _extendedLoadout] call FUNC(recoverInvalidContainers)) select 0;

[GVAR(center), _extendedLoadout] call CBA_fnc_setLoadout;

// Update current item list and unique items
Expand Down
3 changes: 3 additions & 0 deletions addons/arsenal/functions/fnc_buttonLoadoutsLoad.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ private _extendedLoadout = switch (GVAR(currentLoadoutsTab)) do {
// Apply loadout to unit
[GVAR(center), _extendedLoadout, true] call CBA_fnc_setLoadout;

// Prevent overloading of inventory containers
GVAR(center) call FUNC(preventOverfilling);

// Update current item list and unique items
[true] call FUNC(refresh);

Expand Down
4 changes: 3 additions & 1 deletion addons/arsenal/functions/fnc_fillLoadoutsList.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,9 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {

// If not in cache, get info and cache it
if (isNil "_loadoutCachedInfo") then {
_loadoutCachedInfo = [_loadoutData] call FUNC(verifyLoadout);
// Run verification in "recover" mode to salvage invalid containers, replacing them with those currently being worn
_loadoutCachedInfo = [_loadoutData, true] call FUNC(verifyLoadout);
_loadoutCachedInfo = [GVAR(center), _loadoutCachedInfo] call FUNC(recoverInvalidContainers);
_contentPanelCtrl setVariable [_loadoutNameAndTab, _loadoutCachedInfo];

_loadoutCachedInfo params ["", "_nullItemsList", "_unavailableItemsList", "_missingExtendedInfo"];
Expand Down
24 changes: 3 additions & 21 deletions addons/arsenal/functions/fnc_onSelChangedLeft.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -332,14 +332,8 @@ switch (GVAR(currentLeftPanel)) do {
_loadout set [IDX_LOADOUT_UNIFORM, [_item, GVAR(currentItems) select IDX_CURR_UNIFORM_ITEMS]];
GVAR(center) setUnitLoadout _loadout;

private _uniformItems = uniformItems GVAR(center);
private _index = count _uniformItems - 1;

// Remove any items that can't fit in the container (this prevents overloading)
while {loadUniform GVAR(center) > 1 && {_index >= 0}} do {
GVAR(center) removeItemFromUniform (_uniformItems select _index);
DEC(_index);
};
[GVAR(center), uniformContainer GVAR(center)] call FUNC(preventOverfilling);

GVAR(currentItems) set [IDX_CURR_UNIFORM, _item];

Expand Down Expand Up @@ -373,14 +367,8 @@ switch (GVAR(currentLeftPanel)) do {
_loadout set [IDX_LOADOUT_VEST, [_item, GVAR(currentItems) select IDX_CURR_VEST_ITEMS]];
GVAR(center) setUnitLoadout _loadout;

private _vestItems = vestItems GVAR(center);
private _index = count _vestItems - 1;

// Remove any items that can't fit in the container (this prevents overloading)
while {loadVest GVAR(center) > 1 && {_index >= 0}} do {
GVAR(center) removeItemFromVest (_vestItems select _index);
DEC(_index);
};
[GVAR(center), vestContainer GVAR(center)] call FUNC(preventOverfilling);

GVAR(currentItems) set [IDX_CURR_VEST, _item];

Expand Down Expand Up @@ -414,14 +402,8 @@ switch (GVAR(currentLeftPanel)) do {
_loadout set [IDX_LOADOUT_BACKPACK, [_item, GVAR(currentItems) select IDX_CURR_BACKPACK_ITEMS]];
GVAR(center) setUnitLoadout _loadout;

private _backpackItems = backpackItems GVAR(center);
private _index = count _backpackItems - 1;

// Remove any items that can't fit in the container (this prevents overloading)
while {loadBackpack GVAR(center) > 1 && {_index >= 0}} do {
GVAR(center) removeItemFromBackpack (_backpackItems select _index);
DEC(_index);
};
[GVAR(center), backpackContainer GVAR(center)] call FUNC(preventOverfilling);

GVAR(currentItems) set [IDX_CURR_BACKPACK, _item];

Expand Down
34 changes: 34 additions & 0 deletions addons/arsenal/functions/fnc_preventOverfilling.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include "..\script_component.hpp"
#include "..\defines.hpp"
/*
* Author: Alganthe, johnb43, mrschick
* Checks the current loadout of the given unit for inventory containers (uniform/vest/backpack) filled beyond their max load, removing excess items if present.
*
* Arguments:
* 0: Unit to check for overfill <OBJECT>
* 1: Which container to check. If unit, will go through all containers starting from uniform <OBJECT>
*
* Return Value:
* None
*
* Public: No
*/

params ["_unit", ["_container", objNull]];

if (isNull _container || _container isEqualTo _unit) then {
_container = [uniformContainer _unit, vestContainer _unit, backpackContainer _unit];
} else {
_container = [_container];
};

{
private _currentContainer = _x;
{
_currentContainer addItemCargoGlobal [_x, -1];

if (load _currentContainer <= 1) then {
break;
};
} forEachReversed (itemCargo _currentContainer);
} forEach (_container select {load _x > 1});
44 changes: 44 additions & 0 deletions addons/arsenal/functions/fnc_recoverInvalidContainers.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include "..\script_component.hpp"
#include "..\defines.hpp"
/*
* Author: mrschick
* Attempts to recover a loadout with invalid containers by substituting them for the currently worn containers.
* It is meant to be passed a loadout modified by `[loadout, true] call ace_arsenal_fnc_verifyLoadout`, nested in the format: `[[_loadout, _extendedInfo], _nullItemsList, _unavailableItemsList, _missingExtendedInfo]`
*
* Arguments:
* 0: Unit from which to get valid (worn) containers <OBJECT>
* 1: Verified loadout to insert valid containers into <ARRAY>
*
* Return Value:
* Copy of the passed loadout, with recovered containers <ARRAY>
*
* Public: No
*/

params ["_unit", "_loadout"];

// Work on a copy of the original array
private _loadoutData = +_loadout;

{
_x params ["_containerIdx", "_wornContainer"];

// Only modify the loadout if it has a filled invalid container to be recovered
if (
(_loadoutData#0#0#_containerIdx isNotEqualTo []) &&
{_loadoutData#0#0#_containerIdx#0 == ""}
) then {
// Replace loadout container with worn one, if present
if (_wornContainer == "") then {
(_loadoutData#0#0) set [_containerIdx, []];
} else {
(_loadoutData#0#0#_containerIdx) set [0, _wornContainer];
};
};
} forEach [
[3, uniform _unit],
[4, vest _unit],
[5, backpack _unit]
];

_loadoutData
14 changes: 9 additions & 5 deletions addons/arsenal/functions/fnc_verifyLoadout.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*
* Arguments:
* 0: Loadout <ARRAY> (CBA Extended Loadout or getUnitLoadout format)
* 1: Whether to attempt to recover invalid containers <BOOL>
*
* Return Value:
* Verified loadout and missing / unavailable items list and count <ARRAY>
Expand All @@ -15,7 +16,7 @@

#define NOT_IN_ARSENAL !(_name in GVAR(virtualItemsFlat))

params ["_loadout"];
params ["_loadout", ["_recoverInvalidContainers", false]];

private _extendedInfo = createHashMap;

Expand All @@ -37,7 +38,8 @@ private _missingExtendedInfo = [];

// Search for all items and check their availability
private _fnc_filterLoadout = {
_this apply {
params ["_loadout", ["_recoverInvalidContainers", false]];
_loadout apply {
if (_x isEqualType "" && {_x != ""}) then {
_name = _x call EFUNC(common,getConfigName);

Expand Down Expand Up @@ -70,11 +72,13 @@ private _fnc_filterLoadout = {
} else {
// Handle arrays
if (_x isEqualType []) then {
_itemArray = _x call _fnc_filterLoadout;
_itemArray = [_x, true] call _fnc_filterLoadout;

// If "" is given as a container, an error is thrown, therefore, filter out all unavailable/null containers
if (count _itemArray == 2 && {(_itemArray select 0) isEqualTo ""} && {(_itemArray select 1) isEqualType []}) then {
if (!_recoverInvalidContainers && {count _itemArray == 2} && {(_itemArray select 0) isEqualTo ""} && {(_itemArray select 1) isEqualType []}) then {
_itemArray = [];
};

_itemArray
} else {
// All other types and empty strings
Expand All @@ -86,7 +90,7 @@ private _fnc_filterLoadout = {

// Convert loadout to config case and replace null/unavailable items
// Loadout might come from a different modpack, which might have different config naming
_loadout = _loadout call _fnc_filterLoadout;
_loadout = [_loadout, _recoverInvalidContainers] call _fnc_filterLoadout;

{
private _class = _extendedInfo getOrDefault [_x, ""];
Expand Down
2 changes: 2 additions & 0 deletions docs/wiki/feature/arsenal.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ Saving loadouts from the default and public tabs will save them in your profile,

All loadouts can be loaded, however items not available or missing, will NOT be added. This limitation applies to all tabs as well as imported loadouts.

In the case of a stored loadout's uniform, vest or backpack not being available or missing, loading it will retain the currently equipped uniform/vest/backpack and attempt to fill it with the stored one's content that is available in the arsenal.

The color coding for loadouts is as follows:
- White: All items are available and will be loaded.
- Grey: Some items in that loadout are not available in that box.
Expand Down

0 comments on commit c82b51f

Please sign in to comment.