ACE3/addons/arsenal/functions/fnc_sortPanel.sqf
johnb432 fd5e56ffbc
Arsenal - Improved sorting, insignia detection, identity info verification and minor cleanup (#9795)
* Changed sorting + minor cleanup

* Update addons/arsenal/functions/fnc_fillLeftPanel.sqf

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

* check and log missing extended info

* fix extended loadout logging

* Made voice stuff config case

* use lowercase voice everywhere

* check loadout voice against configCase

* Update fnc_verifyLoadout.sqf

* Update addons/arsenal/functions/fnc_verifyLoadout.sqf

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

* Update addons/arsenal/functions/fnc_verifyLoadout.sqf

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

* Update addons/arsenal/functions/fnc_verifyLoadout.sqf

---------

Co-authored-by: LinkIsGrim <salluci.lovi@gmail.com>
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
2024-02-13 11:22:27 -08:00

280 lines
9.3 KiB
Plaintext

#include "..\script_component.hpp"
#include "..\defines.hpp"
/*
* Author: Alganthe, Dedmen, Brett Mayson, johnb43
* Sort an arsenal panel.
*
* Arguments:
* 0: Control <CONTROL>
*
* Return Value:
* None
*
* Public: No
*/
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;
};
private _display = ctrlParent _control;
private _rightSort = (ctrlIDC _control) in [IDC_sortRightTab, IDC_sortRightTabDirection];
private _right = _rightSort && {GVAR(currentLeftPanel) in [IDC_buttonUniform, IDC_buttonVest, IDC_buttonBackpack]};
private _sortCtrl = _display displayCtrl ([IDC_sortLeftTab, IDC_sortRightTab] select _rightSort);
private _sortDirectionCtrl = _display displayCtrl ([IDC_sortLeftTabDirection, IDC_sortRightTabDirection] select _rightSort);
private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgFaces = configFile >> "CfgFaces";
private _cfgUnitInsignia = configFile >> "CfgUnitInsignia";
private _cfgUnitInsigniaCampaign = campaignConfigFile >> "CfgUnitInsignia";
private _cfgUnitInsigniaMission = missionConfigFile >> "CfgUnitInsignia";
if (_rightSort) then {
[
if (_right) then {
_display displayCtrl IDC_rightTabContentListnBox
} else {
_display displayCtrl IDC_rightTabContent
},
switch (GVAR(currentRightPanel)) do {
case IDC_buttonCurrentMag;
case IDC_buttonCurrentMag2;
case IDC_buttonThrow;
case IDC_buttonPut;
case IDC_buttonMag;
case IDC_buttonMagALL: {_cfgMagazines};
default {configFile >> "CfgWeapons"};
},
GVAR(sortListRightPanel) select (
switch (GVAR(currentRightPanel)) do {
case IDC_buttonOptic: { 0 };
case IDC_buttonItemAcc: { 1 };
case IDC_buttonMuzzle: { 2 };
case IDC_buttonBipod: { 3 };
case IDC_buttonCurrentMag;
case IDC_buttonCurrentMag2;
case IDC_buttonMag;
case IDC_buttonMagALL: { 4 };
case IDC_buttonThrow: { 5 };
case IDC_buttonPut: { 6 };
case IDC_buttonMisc: { 7 };
}
)
]
} else {
[
_display displayCtrl IDC_leftTabContent,
switch (GVAR(currentLeftPanel)) do {
case IDC_buttonBackpack: {configFile >> "CfgVehicles"};
case IDC_buttonGoggles: {configFile >> "CfgGlasses"};
case IDC_buttonFace: {_cfgFaces};
case IDC_buttonVoice: {configFile >> "CfgVoice"};
case IDC_buttonInsignia: {_cfgUnitInsignia};
default {configFile >> "CfgWeapons"};
},
(GVAR(sortListLeftPanel) select ([
IDC_buttonPrimaryWeapon,
IDC_buttonHandgun,
IDC_buttonSecondaryWeapon,
IDC_buttonUniform,
IDC_buttonVest,
IDC_buttonBackpack,
IDC_buttonHeadgear,
IDC_buttonGoggles,
IDC_buttonNVG,
IDC_buttonBinoculars,
IDC_buttonMap,
IDC_buttonGPS,
IDC_buttonRadio,
IDC_buttonCompass,
IDC_buttonWatch,
IDC_buttonFace,
IDC_buttonVoice,
IDC_buttonInsignia
] find GVAR(currentLeftPanel)))
]
} params ["_panel", "_cfgClass", "_sorts"];
// Get sort & sort direction
private _sortName = _sortCtrl lbData (0 max lbCurSel _sortCtrl);
private _sortDirection = _sortDirectionCtrl lbValue (0 max lbCurSel _sortDirectionCtrl);
(_sorts select (0 max (_sorts findIf {(_x select 0) == _sortName}))) params ["", "_displayName", "_statement"];
// Update last sort & sort direction
missionNamespace setVariable [
[QGVAR(lastSortLeft), QGVAR(lastSortRight)] select _rightSort,
_displayName
];
missionNamespace setVariable [
[QGVAR(lastSortDirectionLeft), QGVAR(lastSortDirectionRight)] select _rightSort,
_sortDirection
];
// Get currently selected item
private _curSel = if (_right) then {
lnbCurSelRow _panel
} else {
lbCurSel _panel
};
private _selected = if (_right) then {
_panel lnbData [_curSel, 0]
} else {
_panel lbData _curSel
};
private _item = "";
private _quantity = "";
private _itemCfg = configNull;
private _value = "";
private _name = "";
private _fillerChar = toString [1];
private _magazineMiscItems = uiNamespace getVariable QGVAR(magazineMiscItems);
private _sortCache = uiNamespace getVariable QGVAR(sortCache);
private _faceCache = uiNamespace getVariable QGVAR(faceCache);
private _insigniaCache = uiNamespace getVariable QGVAR(insigniaCache);
private _countColumns = if (_right) then {
count lnbGetColumnsPosition _panel
} else {
0
};
private _for = if (_right) then {
for "_i" from 0 to (lnbSize _panel select 0) - 1
} else {
for "_i" from 0 to (lbSize _panel) - 1
};
_for do {
// Get item
_item = if (_right) then {
_panel lnbData [_i, 0]
} else {
_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])
} else {
0
};
// "Misc. items" magazines (e.g. spare barrels, intel, photos)
if (_item in _magazineMiscItems) then {
_cfgClass = _cfgMagazines;
};
// Check item's config
_itemCfg = if !(_cfgClass in [_cfgFaces, _cfgUnitInsignia]) then {
_cfgClass >> _item
} else {
// If insignia, check for correct config: First mission, then campaign and finally regular config
if (_cfgClass == _cfgUnitInsignia) then {
_itemCfg = _cfgUnitInsigniaMission >> _item;
if (isNull _itemCfg) then {
_itemCfg = _cfgUnitInsigniaCampaign >> _item;
};
if (isNull _itemCfg) then {
_itemCfg = _cfgUnitInsignia >> _item;
};
_itemCfg
} else {
// If face, check correct category
_cfgClass >> (_faceCache getOrDefault [_item, []]) param [2, "Man_A3"] >> _item
};
};
// Some items may not belong to the config class for the panel (e.g. misc. items panel can have unique items)
if (isNull _itemCfg) then {
_itemCfg = _item call CBA_fnc_getItemConfig;
};
// Value can be any type
_value = _sortCache getOrDefaultCall [format ["%1_%2_%3", _sortName, _item, _quantity], {
private _value = [_itemCfg, _item, _quantity] call _statement;
// If number, convert to string (keep 2 decimal after comma; Needed for correct weight sorting)
if (_value isEqualType 0) then {
_value = [_value, 8, 2] call CBA_fnc_formatNumber;
};
// If empty string, add alphabetically small char at beginning to make it sort correctly
if (_value isEqualTo "") then {
_value = "_";
};
_value
}, true];
// Set the right text temporarily, so it can be used for sorting
if (_right) then {
// Use value, display name and classname to sort, which means a fixed alphabetical order is guaranteed
// 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 {
// Use value, display name and classname to sort, which means a fixed alphabetical order is guaranteed
// 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 and select it again
if (_right) then {
[_panel, 1] lnbSortBy ["TEXT", _sortDirection == ASCENDING, false, true, false];
_for do {
// Remove sorting text, as it blocks the item name otherwise
_panel lnbSetTextRight [[_i, 1], ""];
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 {
_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 {
// Remove sorting text, as it blocks the item name otherwise
_panel lbSetTextRight [_i, ""];
};
if (_curSel != -1 && {_item == _selected}) then {
_panel lbSetCurSel _i;
// To avoid unnecessary checks after previsouly selected item was found
_curSel = -1;
};
};
};