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 - Improved sorting, insignia detection, identity info verification and minor cleanup #9795

Merged
merged 12 commits into from
Feb 13, 2024
Merged
18 changes: 5 additions & 13 deletions addons/arsenal/XEH_postInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -108,24 +108,16 @@ GVAR(lastSortDirectionRight) = DESCENDING;
private _face = _extendedInfo getOrDefault [QGVAR(face), ""];

if (_face != "") then {
if (isMultiplayer) then {
private _id = [QGVAR(broadcastFace), [_unit, _face], QGVAR(centerFace_) + netId _unit] call CBA_fnc_globalEventJIP;
[_id, _unit] call CBA_fnc_removeGlobalEventJIP;
} else {
_unit setFace _face;
};
private _id = [QGVAR(broadcastFace), [_unit, _face], QGVAR(centerFace_) + hashValue _unit] call CBA_fnc_globalEventJIP;
[_id, _unit] call CBA_fnc_removeGlobalEventJIP;
};

// Set voice
private _voice = _extendedInfo getOrDefault [QGVAR(voice), ""];

if (_voice != "") then {
if (isMultiplayer) then {
private _id = [QGVAR(broadcastVoice), [_unit, _voice], QGVAR(centerVoice_) + netId _unit] call CBA_fnc_globalEventJIP;
[_id, _unit] call CBA_fnc_removeGlobalEventJIP;
} else {
_unit setSpeaker _voice;
};
private _id = [QGVAR(broadcastVoice), [_unit, _voice], QGVAR(centerVoice_) + hashValue _unit] call CBA_fnc_globalEventJIP;
[_id, _unit] call CBA_fnc_removeGlobalEventJIP;
};

// Set insignia
Expand All @@ -147,7 +139,7 @@ GVAR(lastSortDirectionRight) = DESCENDING;

// Set voice if enabled
if (GVAR(loadoutsSaveVoice)) then {
_extendedInfo set [QGVAR(voice), speaker _unit];
_extendedInfo set [QGVAR(voice), (speaker _unit) call EFUNC(common,getConfigName)];
};

// Set insignia if enabled
Expand Down
1 change: 0 additions & 1 deletion addons/arsenal/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -91,5 +91,4 @@ private _insigniaCondition = toString {
GVAR(insigniaCache) set [_x, 2];
} forEach (_insigniaCondition configClasses (missionConfigFile >> "CfgUnitInsignia"));


ADDON = true;
4 changes: 2 additions & 2 deletions addons/arsenal/functions/fnc_addListBoxItem.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*
* Arguments:
* 0: Config category, must be "CfgWeapons", "CfgVehicles", "CfgMagazines", "CfgVoice" or "CfgUnitInsignia" <STRING>
* 1: Classname <STRING>
* 1: Classname (must be in config case) <STRING>
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
* 2: Panel control <CONTROL>
* 3: Name of the picture entry in that Cfg class <STRING> (default: "picture")
* 4: Config root <NUMBER> (default: 0 -> configFile)
Expand Down Expand Up @@ -42,7 +42,7 @@ if (_skip) then {

if (_skip) exitWith {};

// Sanitise key, as it's public; If not in cache, find info and cache it for later use
// If not in cache, find info and cache it for later use
((uiNamespace getVariable QGVAR(addListBoxItemCache)) getOrDefaultCall [_configCategory + _className + str _configRoot, {
// Get classname (config case), display name, picture and DLC
private _configPath = ([configFile, campaignConfigFile, missionConfigFile] select _configRoot) >> _configCategory >> _className;
Expand Down
7 changes: 4 additions & 3 deletions addons/arsenal/functions/fnc_fillLoadoutsList.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -71,15 +71,16 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
_loadoutCachedInfo = [_loadoutData] call FUNC(verifyLoadout);
_contentPanelCtrl setVariable [_loadoutNameAndTab, _loadoutCachedInfo];

_loadoutCachedInfo params ["", "_nullItemsList", "_unavailableItemsList"];
_loadoutCachedInfo params ["", "_nullItemsList", "_unavailableItemsList", "_missingExtendedInfo"];

// Log missing / nil items to RPT (only once per arsenal session)
if (GVAR(EnableRPTLog) && {(_nullItemsList isNotEqualTo []) || {_unavailableItemsList isNotEqualTo []}}) then {
if (GVAR(EnableRPTLog) && {(_nullItemsList isNotEqualTo []) || {_unavailableItemsList isNotEqualTo [] || {_missingExtendedInfo isNotEqualTo []}}}) then {
private _printComponent = "ACE_Arsenal - Loadout:";
private _printNullItemsList = ["Missing items:", str _nullItemsList] joinString " ";
private _printUnavailableItemsList = ["Unavailable items:", str _unavailableItemsList] joinString " ";
private _printMissingExtendedInfo = ["Missing extended loadout:", str _missingExtendedInfo] joinString " ";

diag_log text (format ["%1%5 %2%5 %3%5 %4", _printComponent, "Name: " + _loadoutName, _printNullItemsList, _printUnavailableItemsList, endl]);
diag_log text (format ["%1%6 %2%6 %3%6 %4%6 %5", _printComponent, "Name: " + _loadoutName, _printNullItemsList, _printUnavailableItemsList, _printMissingExtendedInfo, endl]);
};
};

Expand Down
2 changes: 1 addition & 1 deletion addons/arsenal/functions/fnc_onArsenalOpen.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ if (isNil QGVAR(virtualItems)) then {
GVAR(virtualItemsFlatAll) = +GVAR(virtualItemsFlat);

GVAR(currentFace) = face GVAR(center);
GVAR(currentVoice) = speaker GVAR(center);
GVAR(currentVoice) = (speaker GVAR(center)) call EFUNC(common,getConfigName);
GVAR(currentInsignia) = GVAR(center) call BIS_fnc_getUnitInsignia;

GVAR(currentAction) = "Stand";
Expand Down
17 changes: 11 additions & 6 deletions addons/arsenal/functions/fnc_onSelChangedLeft.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -683,14 +683,19 @@ switch (GVAR(currentLeftPanel)) do {

TOGGLE_RIGHT_PANEL_HIDE

private _unitInsigniaConfig = configFile >> "CfgUnitInsignia" >> _item;
// Check for correct config: First mission, then campaign and finally regular config
private _itemCfg = missionConfigFile >> "CfgUnitInsignia" >> _item;

// Display new items's info on the bottom right
if (isNull _unitInsigniaConfig) then {
[_display, _control, _curSel, missionConfigFile >> "CfgUnitInsignia" >> _item] call FUNC(itemInfo);
} else {
[_display, _control, _curSel, _unitInsigniaConfig] call FUNC(itemInfo);
if (isNull _itemCfg) then {
_itemCfg = campaignConfigFile >> "CfgUnitInsignia" >> _item;
};

if (isNull _itemCfg) then {
_itemCfg = configFile >> "CfgUnitInsignia" >> _item;
};

// Display new items's info on the bottom right
[_display, _control, _curSel, _itemCfg] call FUNC(itemInfo);
};
};

Expand Down
72 changes: 38 additions & 34 deletions addons/arsenal/functions/fnc_sortPanel.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@

params ["_control"];

// https://community.bistudio.com/wiki/toString, see comment
// However, using 55295 did not work as expected, 55291 was found by trial and error
#define HIGHEST_VALUE_CHAR 55291

// When filling the sorting panel, FUNC(sortPanel) is called twice, so ignore first call
if (GVAR(ignoreFirstSortPanelCall)) exitWith {
GVAR(ignoreFirstSortPanelCall) = false;
Expand All @@ -29,6 +33,7 @@ private _sortDirectionCtrl = _display displayCtrl ([IDC_sortLeftTabDirection, ID
private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgFaces = configFile >> "CfgFaces";
private _cfgUnitInsignia = configFile >> "CfgUnitInsignia";
private _cfgUnitInsigniaCampaign = campaignConfigFile >> "CfgUnitInsignia";
private _cfgUnitInsigniaMission = missionConfigFile >> "CfgUnitInsignia";

if (_rightSort) then {
Expand Down Expand Up @@ -126,7 +131,6 @@ private _selected = if (_right) then {
_panel lbData _curSel
};

private _originalNames = createHashMap;
private _item = "";
private _quantity = "";
private _itemCfg = configNull;
Expand All @@ -136,12 +140,8 @@ private _fillerChar = toString [1];

private _magazineMiscItems = uiNamespace getVariable QGVAR(magazineMiscItems);
private _sortCache = uiNamespace getVariable QGVAR(sortCache);

private _faceCache = if (_cfgClass == _cfgFaces) then {
uiNamespace getVariable [QGVAR(faceCache), createHashMap]
} else {
createHashMap
};
private _faceCache = uiNamespace getVariable QGVAR(faceCache);
private _insigniaCache = uiNamespace getVariable QGVAR(insigniaCache);

private _countColumns = if (_right) then {
count lnbGetColumnsPosition _panel
Expand All @@ -150,9 +150,9 @@ private _countColumns = if (_right) then {
};

private _for = if (_right) then {
for '_i' from 0 to (lnbSize _panel select 0) - 1
for "_i" from 0 to (lnbSize _panel select 0) - 1
} else {
for '_i' from 0 to (lbSize _panel) - 1
for "_i" from 0 to (lbSize _panel) - 1
};

_for do {
Expand All @@ -163,6 +163,14 @@ _for do {
_panel lbData _i
};

// Check if entry is "Empty"
if (!_right && {(_panel lbValue _i) == -1}) then {
// Set to lowest/highest lexicographical value, so that "Empty" is always at the top
_panel lbSetTextRight [_i, ["", toString [HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR, HIGHEST_VALUE_CHAR]] select (_sortDirection == ASCENDING)];

continue;
};

// Get item's count
_quantity = if (_right) then {
parseNumber (_panel lnbText [_i, 2])
Expand All @@ -179,18 +187,22 @@ _for do {
_itemCfg = if !(_cfgClass in [_cfgFaces, _cfgUnitInsignia]) then {
_cfgClass >> _item
} else {
// If insignia, check both config and mission file
// If insignia, check for correct config: First mission, then campaign and finally regular config
if (_cfgClass == _cfgUnitInsignia) then {
_itemCfg = _cfgClass >> _item;
_itemCfg = _cfgUnitInsigniaMission >> _item;

if (isNull _itemCfg) then {
_itemCfg = _cfgUnitInsigniaMission >> _item;
_itemCfg = _cfgUnitInsigniaCampaign >> _item;
};

if (isNull _itemCfg) then {
_itemCfg = _cfgUnitInsignia >> _item;
};

_itemCfg
} else {
// If face, check correct category
_cfgClass >> (_faceCache get _item) param [2, "Man_A3"] >> _item
_cfgClass >> (_faceCache getOrDefault [_item, []]) param [2, "Man_A3"] >> _item
};
};

Expand All @@ -216,55 +228,47 @@ _for do {
_value
}, true];

// Save the current row's item's name in a cache and set text to it's sorting value
// Set the right text temporarily, so it can be used for sorting
if (_right) then {
_name = _panel lnbText [_i, 1];
_originalNames set [_item, _name];

// Use value, display name and classname to sort, which means a fixed alphabetical order is guaranteed
// Filler char has lowest lexicographical order possible
_panel lnbSetText [[_i, 1], format ["%1%2%4%3", _value, _name, _item, _fillerChar]];
// Filler char has lowest lexicographical value possible
_panel lnbSetTextRight [[_i, 1], format ["%1%2%4%3", _value, _panel lnbText [_i, 1], _item, _fillerChar]];
} else {
if (_item != "") then {
_name = _panel lbText _i;
_originalNames set [_item, _name];

// Use value, display name and classname to sort, which means a fixed alphabetical order is guaranteed
// Filler char has lowest lexicographical order possible
_panel lbSetText [_i, format ["%1%2%4%3", _value, _name, _item, _fillerChar]];
// Filler char has lowest lexicographical value possible
_panel lbSetTextRight [_i, format ["%1%2%4%3", _value, _panel lbText _i, _item, _fillerChar]];
};
};
};

// Sort alphabetically, find the previously selected item, select it again and reset text to original text
// Sort alphabetically, find the previously selected item and select it again
if (_right) then {
_panel lnbSort [1, _sortDirection == ASCENDING];
[_panel, 1] lnbSortBy ["TEXT", _sortDirection == ASCENDING, false, true, false];

_for do {
_item = _panel lnbData [_i, 0];

_panel lnbSetText [[_i, 1], _originalNames get _item];
// Remove sorting text, as it blocks the item name otherwise
_panel lnbSetTextRight [[_i, 1], ""];

// Set selection after text, otherwise item info box on the right side shows invalid name
if (_curSel != -1 && {_item == _selected}) then {
if (_curSel != -1 && {(_panel lnbData [_i, 0]) == _selected}) then {
_panel lnbSetCurSelRow _i;

// To avoid unnecessary checks after previsouly selected item was found
_curSel = -1;
};
};
} else {
lbSort [_panel, ["DESC", "ASC"] select _sortDirection];
_panel lbSortBy ["TEXT", _sortDirection == ASCENDING, false, true, false];

_for do {
_item = _panel lbData _i;

// Check if valid item (problems can be caused when searching)
if (_item != "") then {
_panel lbSetText [_i, _originalNames get _item];
// Remove sorting text, as it blocks the item name otherwise
_panel lbSetTextRight [_i, ""];
};

// Set selection after text, otherwise item info box on the right side shows invalid name
if (_curSel != -1 && {_item == _selected}) then {
_panel lbSetCurSel _i;

Expand Down
20 changes: 18 additions & 2 deletions addons/arsenal/functions/fnc_verifyLoadout.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ private _name = "";
private _itemArray = [];
private _nullItemsList = [];
private _unavailableItemsList = [];
private _missingExtendedInfo = [];

// Search for all items and check their availability
private _fnc_filterLoadout = {
Expand Down Expand Up @@ -70,7 +71,22 @@ private _fnc_filterLoadout = {
// Loadout might come from a different modpack, which might have different config naming
_loadout = _loadout call _fnc_filterLoadout;

{
private _class = _extendedInfo getOrDefault [_x, ""];
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
private _cache = missionNamespace getVariable (_x + "Cache");

// Previously voices were stored in lower case (speaker command returns lower case), so this is to make old loadouts compatible
if (_class != "" && {_x == QGVAR(voice)}) then {
_class = _class call EFUNC(common,getConfigName);
};
if (_class != "" && {!(_class in _cache)}) then {
_missingExtendedInfo pushBack [_x, _class];
_extendedInfo deleteAt _x;
};
} forEach [QGVAR(insignia), QGVAR(face), QGVAR(voice)];

// Raise event for 3rd party: mostly for handling extended info
johnb432 marked this conversation as resolved.
Show resolved Hide resolved
[QGVAR(loadoutVerified), [_loadout, _extendedInfo]] call CBA_fnc_localEvent;
// Pass all items, including duplicates
[QGVAR(loadoutVerified), [_loadout, _extendedInfo, _nullItemsList, _unavailableItemsList, _missingExtendedInfo]] call CBA_fnc_localEvent;

[[_loadout, _extendedInfo], _nullItemsList arrayIntersect _nullItemsList, _unavailableItemsList arrayIntersect _unavailableItemsList]
[[_loadout, _extendedInfo], _nullItemsList arrayIntersect _nullItemsList, _unavailableItemsList arrayIntersect _unavailableItemsList, _missingExtendedInfo]
2 changes: 2 additions & 0 deletions addons/arsenal/ui/RscAttributes.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,7 @@ class GVAR(display) {
colorSelect[] = {1,1,1,1};
colorSelect2[] = {1,1,1,1};
colorPictureRightSelected[] = {1,1,1,1};
colorTextRight[] = {0.5, 0.5, 0.5, 0};
onLBSelChanged = QUOTE(_this call FUNC(onSelChangedLeft));
onLBDblClick = QUOTE(_this call FUNC(onPanelDblClick));
onSetFocus = QUOTE(GVAR(leftTabFocus) = true);
Expand Down Expand Up @@ -594,6 +595,7 @@ class GVAR(display) {
colorSelect[] = {1,1,1,1};
colorSelect2[] = {1,1,1,1};
colorPictureRightSelected[] = {1,1,1,1};
colorTextRight[] = {0.5, 0.5, 0.5, 0};
columns[] = {0.07, 0.15, 0.75};
idcLeft = IDC_arrowMinus;
idcRIght = IDC_arrowPlus;
Expand Down
1 change: 0 additions & 1 deletion addons/arsenal/ui/script_component.hpp

This file was deleted.

2 changes: 1 addition & 1 deletion addons/common/functions/fnc_getConfigName.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@

params ["_className"];

(uiNamespace getVariable QGVAR(configNames)) getOrDefaultCall [toLower _className, {
(uiNamespace getVariable QGVAR(configNames)) getOrDefaultCall [toLowerANSI _className, {
private _config = configNull;

{
Expand Down
25 changes: 18 additions & 7 deletions addons/gunbag/XEH_preInit.sqf
Original file line number Diff line number Diff line change
Expand Up @@ -27,23 +27,34 @@ PREP_RECOMPILE_END;
}] call CBA_fnc_addClassEventHandler;

[QEGVAR(arsenal,loadoutVerified), {
params ["_loadout", "_extendedInfo"];
params ["_loadout", "_extendedInfo", "", "", "_missingExtendedInfo"];
private _gunbagInfo = _extendedInfo getOrDefault [QGVAR(gunbagWeapon), []];
if (_gunbagInfo isEqualTo []) exitWith {};

private _weapon = (_gunbagInfo select 0) call EFUNC(arsenal,baseWeapon);
if !(_weapon in EGVAR(arsenal,virtualItemsFlat)) exitWith {
INFO_1("removing [%1] from loadout",_gunbagInfo);
_missingExtendedInfo pushBack [QGVAR(gunbagWeapon), _weapon];
_extendedInfo deleteAt QGVAR(gunbagWeapon);
};
private _missingItems = [];
private _attachments = _gunbagInfo select 1;
{
if (_x != "" && {!(_x call EFUNC(arsenal,baseWeapon) in EGVAR(arsenal,virtualItemsFlat))}) then {
_missingItems pushBack _x;
_attachments set [_forEachIndex, ""];
};
} forEach _attachments;
private _magazines = _gunbagInfo select 2;
{
private _class = _x param [0, ""];
private _defaultValue = ["", []] select {_x isEqualType []};
if (_class != "" && {!(_class in EGVAR(arsenal,virtualItemsFlat))}) then {
INFO_1("removing [%1] from loadout",_x);
_gunbagInfo set [_forEachIndex + 1, _defaultValue];
if !(_class != "" && {_class in EGVAR(arsenal,virtualItemsFlat)}) then {
_missingItems pushBack _class;
_magazines set [_forEachIndex, ["", 0]];
};
} forEach (_gunbagInfo select [1]); // weapon was verified above
} forEach _magazines;
if (_missingItems isNotEqualTo []) then {
_missingExtendedInfo pushBack [QGVAR(gunbagWeapon), _missingItems];
};
}] call CBA_fnc_addEventHandler;

["CBA_loadoutSet", {
Expand Down
2 changes: 1 addition & 1 deletion docs/wiki/framework/arsenal-framework.md
Original file line number Diff line number Diff line change
Expand Up @@ -511,7 +511,7 @@ All are local.
| ace_arsenal_loadoutsDisplayClosed | None | 3.12.3 |
| ace_arsenal_loadoutsTabChanged | loadouts screen display (DISPLAY), tab control (CONTROL) | 3.12.3 |
| ace_arsenal_loadoutsListFilled | loadouts screen display (DISPLAY), tab control (CONTROL) | 3.12.3 |
| ace_arsenal_loadoutVerified | loadout data (ARRAY), loadout CBA extended data (HASHMAP) | 3.17.0 |
| ace_arsenal_loadoutVerified | loadout data (ARRAY), loadout CBA extended data (HASHMAP), null items (ARRAY), unavailable items (ARRAY), unavailable extended data (ARRAY) | 3.17.0 |
| ace_arsenal_weaponItemChanged | weapon classname (STRING), item classname (STRING), item index (NUMBER, 0-5: muzzle, side, optic, bipod, magazine, underbarrel) | 3.16.0 |

## 9. Custom sub item categories
Expand Down
Loading