Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Arsenal - Reuse current inventory containers when importing invalid loadouts #10364

Merged
merged 15 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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), 1] 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), 2] 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), 3] call FUNC(preventOverfilling);

GVAR(currentItems) set [IDX_CURR_BACKPACK, _item];

Expand Down
47 changes: 47 additions & 0 deletions addons/arsenal/functions/fnc_preventOverfilling.sqf
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#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 (0: all, 1: uniform, 2: vest, 3: backpack) <NUMBER>
*
* Return Value:
* None
*
* Public: No
*/

params ["_unit", ["_container", 0]];
mrschick marked this conversation as resolved.
Show resolved Hide resolved

// Remove excess items from uniform
if (_container in [0, 1]) then {
private _uniformItems = uniformItems _unit;
private _index = count _uniformItems - 1;
while {loadUniform _unit > 1 && {_index >= 0}} do {
_unit removeItemFromUniform (_uniformItems select _index);
DEC(_index);
};
};

// Remove excess items from vest
if (_container in [0, 2]) then {
private _vestItems = vestItems _unit;
private _index = count _vestItems - 1;
while {loadVest _unit > 1 && {_index >= 0}} do {
_unit removeItemFromVest (_vestItems select _index);
DEC(_index);
};
};

// Remove excess items from backpack
if (_container in [0, 3]) then {
private _backpackItems = backpackItems _unit;
private _index = count _backpackItems - 1;
while {loadBackpack _unit > 1 && {_index >= 0}} do {
_unit removeItemFromBackpack (_backpackItems select _index);
DEC(_index);
};
};
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]
mrschick marked this conversation as resolved.
Show resolved Hide resolved
*
* 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 {
mrschick marked this conversation as resolved.
Show resolved Hide resolved
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
Loading