Arsenal - Add arsenal actions addition and removal via functions (#9318)

* Add and remove arsenal actions via functions

* Fixed header

* Update addons/arsenal/functions/fnc_addAction.sqf

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

* Update fnc_addSort.sqf

* Update addons/arsenal/functions/fnc_removeAction.sqf

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

* Update addons/arsenal/functions/fnc_removeAction.sqf

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

---------

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
This commit is contained in:
johnb432 2023-08-18 18:33:56 +02:00 committed by GitHub
parent d290ca3d63
commit a168330550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 254 additions and 26 deletions

View File

@ -1,3 +1,4 @@
PREP(addAction);
PREP(addDefaultLoadout);
PREP(addListBoxItem);
PREP(addRightPanelButton);
@ -62,6 +63,7 @@ PREP(open3DEN);
PREP(openBox);
PREP(portVALoadouts);
PREP(refresh);
PREP(removeAction);
PREP(removeBox);
PREP(removeDefaultLoadout);
PREP(removeSort);

View File

@ -0,0 +1,122 @@
#include "script_component.hpp"
/*
* Author: johnb43
* Adds custom action buttons.
*
* Arguments:
* 0: Tabs to add action to <ARRAY>
* 1: Action class (unique string for each action) <STRING>
* 2: Title <STRING>
* 3: Actions <ARRAY of ARRAYS>
* 4: Condition <CODE> (default: {true})
* 5: Scope editor <NUMBER> (default: 2)
*
* Return Value:
* 0: Array of IDs <ARRAY of STRINGS>
*
* Example:
* [[0, 5], "TAG_myActions", "My Actions", [
* ["text", "Text", {true}, "Text"],
* ["statement", "Statement", {true}, "", {[_this select 0] call tag_fnc_myTextStatement}],
* ["button", "Button", {true}, "", {}, {_this call tag_fnc_myAction}]
* ]] call ace_arsenal_fnc_addAction
*
* Public: Yes
*/
params [
["_tabs", [], [[]]],
["_rootClass", "", [""]],
["_title", "", [""]],
["_actions", [], [[]]],
["_rootCondition", {true}, [{}]],
["_scopeEditor", 2, [0]]
];
// Compile actions from config (in case this is called before preInit)
call FUNC(compileActions);
// Skip if not allowed in editor and in editor
if (is3DEN && {_scopeEditor != 2}) exitWith {
TRACE_1("Skipping action because in editor", _rootClass);
[]
};
// Class can't contain ~, because it's used for formatting result
if ("~" in _rootClass) exitWith {
TRACE_1("Classname can't contain '~'", _rootClass);
[]
};
private _return = [];
private _fnc_addToGroup = {
params ["_group", "_tab"];
private _type = -1;
{
_x params [["_class", "", [""]], ["_label", "", [""]], ["_condition", {true}, [{}]], ["_text", "", [""]], ["_textStatement", {}, [{}]], ["_statement", {}, [{}]]];
// Class can't contain ~, because it's used for formatting result
if (_class == "" || {"~" in _class}) then {
continue;
};
// Don't allow two of the same class
if (_group findIf {(_x select 0) == _class} != -1) then {
TRACE_1("An action with this ID already exists", _class);
continue;
};
_type = switch (false) do {
case (_text == ""): {
_statement = format ["{""%1""}", _text];
ACTION_TYPE_TEXT
};
case (_textStatement isEqualTo {}): {
_statement = _textStatement;
ACTION_TYPE_TEXT
};
case (_statement isEqualTo {}): {
_statement = _statement;
ACTION_TYPE_BUTTON
};
default {
-1
};
};
if (_type == -1) then {
continue;
};
_statement = compile format [QUOTE([GVAR(center)] call %1), _statement];
_group pushBack [_class, _type, _label, _statement, _condition];
_return pushBack ([_rootClass, _class, _tab] joinString "~");
} forEach _actions;
};
private _tab = [];
private _index = -1;
private _group = [];
{
_tab = GVAR(actionList) select _x;
_index = _tab findIf {(_x select 0) == _rootClass};
// Add to existing group
if (_index != -1) then {
[_tab select _index select 3, _x] call _fnc_addToGroup;
} else {
// Add to new group
_group = [];
[_group, _x] call _fnc_addToGroup;
_tab pushBack [_rootClass, _title, _rootCondition, _group];
};
} forEach _tabs;
_return

View File

@ -7,10 +7,10 @@
* 0: Tabs to add sort to <ARRAY>
* - 0: Left Tab Indexes <ARRAY of NUMBERS>
* - 1: Right Tab Indexes <ARRAY of NUMBERS>
* 1: Sort Class (a unique string for each algorithm) <STRING>
* 1: Sort class (a unique string for each algorithm) <STRING>
* 2: Title <STRING>
* 3: Algorithm <CODE>
* 4: Condition <CODE> (default: true)
* 4: Condition <CODE> (default: {true})
*
* Return Value:
* 0: Array of IDs <ARRAY of STRINGS>
@ -27,7 +27,7 @@
*
* _fireRate sort true;
* _fireRate param [0, 0]
* }] call ace_arsenal_fnc_addSort;
* }] call ace_arsenal_fnc_addSort
*
* Public: Yes
*/
@ -37,8 +37,7 @@ params [
["_class", "", [""]],
["_title", "", [""]],
["_statement", {}, [{}]],
["_condition", {true}, [{}]],
["_overwrite", false, [false]]
["_condition", {true}, [{}]]
];
_tabs params [

View File

@ -6,7 +6,7 @@
*
* Arguments:
* 0: Arsenal display <DISPLAY>
* 1. Actions control <CONTROL>
* 1: Actions control <CONTROL>
* 2: Previous or next <BOOL> (false = previous, true = next)
*
* Return Value:

View File

@ -1,7 +1,7 @@
#include "script_component.hpp"
/*
* Author: Brett Mayson
* Create the internal actions arrays when needed for the first time
* Create the internal actions arrays when needed for the first time.
*
* Arguments:
* None
@ -39,10 +39,12 @@ private _configGroupEntries = "true" configClasses (configFile >> QGVAR(actions)
{
private _scopeEditor = getNumber (_x >> "scopeEditor");
if (is3DEN && {_scopeEditor != 2}) then {continue};
private _configActions = "true" configClasses _x;
private _rootClass = configName _x;
private _rootDisplayName = getText (_x >> "displayName");
private _rootCondition = getText (_x >> "condition");
private _rootTabs = getArray (_x >> "tabs");
@ -56,6 +58,7 @@ private _configGroupEntries = "true" configClasses (configFile >> QGVAR(actions)
private _group = [];
{
private _class = configName _x;
private _label = getText (_x >> "label");
private _condition = getText (_x >> "condition");
private _statement = getText (_x >> "statement");
@ -79,9 +82,11 @@ private _configGroupEntries = "true" configClasses (configFile >> QGVAR(actions)
-1
};
};
if (_type == -1) then {
continue;
};
_statement = compile format [QUOTE([GVAR(center)] call {%1}), _statement];
if (_condition != "") then {
@ -90,12 +95,13 @@ private _configGroupEntries = "true" configClasses (configFile >> QGVAR(actions)
_condition = {true};
};
_group pushBack [_type, _label, _statement, _condition];
// No duplicates are possible here
_group pushBack [_class, _type, _label, _statement, _condition];
} forEach _configActions;
{
(_actionList select _x) pushBack [_rootDisplayName, _rootCondition, _group];
(_actionList select _x) pushBack [_rootClass, _rootDisplayName, _rootCondition, _group];
} forEach _rootTabs;
} forEach _configGroupEntries;
missionNamespace setVariable [QGVAR(actionList), _actionList];
GVAR(actionList) = _actionList;

View File

@ -63,7 +63,6 @@ private _sortListRightPanel = [
[] // Misc 7
];
//------------------------- Config handling
private _class = "";
private _displayName = "";
private _statement = "";

View File

@ -78,7 +78,6 @@ private _statsListRightPanel = [
[] // Misc 7
];
//------------------------- Config handling
private _finalArray = [];
private _class = "";
private _stats = [];
@ -127,6 +126,5 @@ private _priority = 0;
[_statsListLeftPanel] call _fnc_sortLists;
[_statsListRightPanel] call _fnc_sortLists;
//------------------------- Config Handling
GVAR(statsListLeftPanel) = _statsListLeftPanel;
GVAR(statsListRightPanel) = _statsListRightPanel;

View File

@ -42,7 +42,7 @@ private _panel = [
] find GVAR(currentLeftPanel);
private _groups = (GVAR(actionList) select _panel) select {
[GVAR(center)] call (_x select 1)
[GVAR(center)] call (_x select 2)
};
private _show = _groups isNotEqualTo [];
@ -57,9 +57,11 @@ private _actionsCurrentPageCtrl = _display displayCtrl IDC_actionsCurrentPage;
private _currentPage = GVAR(currentActionPage);
private _pages = count _groups;
if (_currentPage < 0) then {
_currentPage = _pages - 1;
};
if (_currentPage >= _pages) then {
_currentPage = 0;
GVAR(currentActionPage) = _currentPage;
@ -72,25 +74,28 @@ if (_currentPage >= _pages) then {
} forEach [IDC_actionsPreviousPage, IDC_actionsNextPage];
private _group = _groups select _currentPage;
private _items = _group select 2 select {
[GVAR(center)] call (_x select 3)
private _items = _group select 3 select {
[GVAR(center)] call (_x select 4)
};
_actionsCurrentPageCtrl ctrlSetText (_group select 0);
_actionsCurrentPageCtrl ctrlSetText (_group select 1);
_actionsCurrentPageCtrl ctrlSetFade 0;
_actionsCurrentPageCtrl ctrlShow true;
_actionsCurrentPageCtrl ctrlCommit 0;
{
_x params ["_type", "_label", "_statement"];
_x params ["", "_type", "_label", "_statement"];
private _idc = 9001 + _forEachIndex * 2;
private _actionTextCtrl = _display displayCtrl _idc;
private _actionButtonCtrl = _display displayCtrl (_idc + 1);
switch (_type) do {
case ACTION_TYPE_BUTTON: {
_actionButtonCtrl ctrlRemoveAllEventHandlers "ButtonClick";
_actionButtonCtrl ctrlAddEventHandler ["ButtonClick", {
if (is3DEN) exitWith {call FUNC(refresh)};
[{
call FUNC(refresh);
}] call CBA_fnc_execNextFrame;
@ -104,10 +109,12 @@ _actionsCurrentPageCtrl ctrlCommit 0;
_actionTextCtrl ctrlCommit 0;
};
case ACTION_TYPE_TEXT: {
private _text = (call _statement);
private _text = call _statement;
if (isNil "_text") then {
_text = "";
};
_actionTextCtrl ctrlSetText _text;
_actionTextCtrl ctrlSetFade 0;
_actionTextCtrl ctrlCommit 0;
@ -129,6 +136,7 @@ private _actionCount = count _items;
private _idc = 9001 + _x * 2;
private _actionTextCtrl = _display displayCtrl _idc;
private _actionButtonCtrl = _display displayCtrl (_idc + 1);
_actionTextCtrl ctrlSetFade 1;
_actionTextCtrl ctrlCommit 0;
_actionButtonCtrl ctrlSetFade 1;

View File

@ -0,0 +1,41 @@
#include "script_component.hpp"
/*
* Author: johnb43
* Remove a custom action button from ACE Arsenal.
*
* Arguments:
* 0: Array of IDs <ARRAY of STRINGS>
*
* Return Value:
* None
*
* Example:
* [["TAG_myActions~text~0", "TAG_myActions~statement~0", "TAG_myActions~button~0"]] call ace_arsenal_fnc_removeAction
*
* Public: Yes
*/
params ["_IDList"];
// Compile sorts from config (in case this is called before preInit)
call FUNC(compileActions);
// Remove entries (all names are unique, there are no duplicates)
{
(_x splitString "~") params ["_rootClass", "_class", "_tab"];
_tab = parseNumber _tab;
{
if ((_x select 0) == _rootClass) exitWith {
(_x select 3) deleteAt ((_x select 3) findIf {(_x select 0) == _class});
// If no entries left in group, remove group
if ((_x select 3) isEqualTo []) then {
(GVAR(actionList) select _tab) deleteAt _forEachIndex;
};
};
} forEach (GVAR(actionList) select _tab);
} forEach _IDList;
nil // return

View File

@ -4,20 +4,20 @@ class EGVAR(arsenal,actions) {
condition = QUOTE(_this call FUNC(hasGunbag));
scopeEditor = 0; // variables are reset between 3DEN and mission start
tabs[] = {0,5};
class status {
class GVAR(status) {
textStatement = QUOTE([_this select 0] call FUNC(weaponName));
};
class store {
class GVAR(store) {
label = CSTRING(ToGunbag);
condition = QUOTE([ARR_2(_this select 0,_this select 0)] call FUNC(canInteract) == 0);
statement = QUOTE([ARR_2(_this select 0,_this select 0)] call FUNC(toGunbagCallback));
};
class retrieve {
class GVAR(retrieve) {
label = CSTRING(OffGunbag);
condition = QUOTE([ARR_2(_this select 0,_this select 0)] call FUNC(canInteract) == 1);
statement = QUOTE([ARR_2(_this select 0,_this select 0)] call FUNC(offGunbagCallback));
};
class swap {
class GVAR(swap) {
label = CSTRING(SwapGunbag);
condition = QUOTE([ARR_2(_this select 0,_this select 0)] call FUNC(canInteract) == 2);
statement = QUOTE([ARR_2(_this select 0,_this select 0)] call FUNC(swapGunbagCallback));

View File

@ -256,6 +256,8 @@ Example:
}, {true}]] call ace_arsenal_fnc_addStat;
```
If a stat already exists (so same class ID and tab), it will ignore the new addition.
### 5.3 Removing stats via a function
`ace_arsenal_fnc_removeStat`
@ -350,7 +352,7 @@ The argument passed to the condition is:
1 | Stat class ID | String | Required
2 | Title | String | Required
3 | Algorithm | Code | Required
4 | Condition | Code | Optional (default: `true`)
4 | Condition | Code | Optional (default: `{true}`)
Return Value:
- Array of sort IDs
@ -373,6 +375,8 @@ Example:
Sorting method IDs are unique and are generated in the same fashion as the stat IDs (see `5.3 Removing stats via a function`).
If a sorting method already exists (so same class ID and tab), it will ignore the new addition.
### 6.3 Removing sorting methods via a function
`ace_arsenal_fnc_removeSort`
@ -395,8 +399,6 @@ ACE Arsenal actions are customizable, this will show you how.
### 7.1 Adding actions via config
Actions use the same tab definitions as stats, found above.
```cpp
class ace_arsenal_actions {
class TAG_myActions {
@ -422,6 +424,57 @@ class ace_arsenal_actions {
```
The focused unit object is passed to the condition and statement functions.
### 7.2 Adding sorting methods via a function
`ace_arsenal_fnc_addAction`
| | Argument | Type | Optional (default value)
--- | -------- | ---- | ------------------------
0 | Tabs to add the sort to | Array of numbers | Required
1 | Action class ID | String | Required
2 | Title | String | Required
3 | Actions | Array of arrays | Required
4 | Condition | Code | Optional (default: `{true}`)
5 | Scope editor | Number | Optional (default: `2`)
Return Value:
- Array of action IDs
Example:
```sqf
[[0, 5], "TAG_myActions", "My Actions", [
["text", "Text", {true}, "Text"],
["statement", "Statement", {true}, "", {[_this select 0] call tag_fnc_myTextStatement}],
["button", "Button", {true}, "", {}, {_this call tag_fnc_myAction}]
]] call ace_arsenal_fnc_addAction;
```
The example above results in the same actions as in `7.1 Adding actions via config`.
Action IDs are unique and are generated as a string in the following fashion:
`_rootClassName + "~" + _class + "~" + _tab`
The example above returns:
`["TAG_myActions~text~0","TAG_myActions~statement~0","TAG_myActions~button~0","TAG_myActions~text~5","TAG_myActions~statement~5","TAG_myActions~button~5"]`
If an action already exists (so same class ID and tab within an action), it will ignore the new addition.
### 7.3 Removing actions via a function
`ace_arsenal_fnc_removeAction`
| | Argument | Type | Optional (default value)
---| -------- | ---- | ------------------------
0 | Array of IDs | Array | Required
Action IDs are unique and their generation is explained in `7.2 Adding sorting methods via a function`.
For config added actions the classname is used, for function added ones the string provided is used.
### 7.4 Action tab numbers
The same numbers are used for actions as for stats (see `5.4 Stat tab numbers`).
## 8. Eventhandlers
All are local.