Skip to content

Commit 5178994

Browse files
Wardrobe - Add support for converting items (Face, Head, NVG) (#11364)
* new fnc: getTypeNumber * add automatic target slot desc * fixes * little cleanup * upt to hashmap * upt handling + hashmap * rework, replaceData, cleanup * better notification * Update wardrobe-framework.md * re-add _extendedInfo * improve compats to test stuff * extend bg of notification * Update addons/wardrobe/functions/fnc_replaceOther.sqf Co-authored-by: PabstMirror <pabstmirror@gmail.com> * Update addons/wardrobe/functions/fnc_replaceContainer.sqf Co-authored-by: PabstMirror <pabstmirror@gmail.com> * clean up headers * Update docs/wiki/framework/wardrobe-framework.md * Update docs/wiki/framework/wardrobe-framework.md * Update docs/wiki/framework/wardrobe-framework.md --------- Co-authored-by: PabstMirror <pabstmirror@gmail.com>
1 parent 948f4d5 commit 5178994

11 files changed

Lines changed: 189 additions & 76 deletions

File tree

addons/compat_rhs_afrf3/compat_rhs_afrf3_wardrobe/ACE_Wardrobe_Headgear.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
BASE_PAIR(rhs_facewear_6m2,rhs_6m2_nvg);
2-
BASE_PAIR(rhs_facewear_6m2_1,rhs_6m2_1_nvg);
1+
BASE_TRIPLET(rhs_6m2,rhs_facewear_6m2,rhs_6m2_nvg);
2+
BASE_TRIPLET(rhs_6m2_1,rhs_facewear_6m2_1,rhs_6m2_1_nvg);
33

44
#define HEADSET rhs_facewear_6m2
55
#define HEADSET_MIC rhs_facewear_6m2_1

addons/wardrobe/XEH_PREP.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ PREP(getDuration);
1111
PREP(getGesture);
1212
PREP(getIcon);
1313
PREP(getItemVariants);
14+
PREP(getSlotName);
1415
PREP(getSound);
1516
PREP(getSoundTiming);
17+
PREP(getTypeNumber);
1618
PREP(isModifiable);
1719
PREP(replace);
1820
PREP(replaceContainer);

addons/wardrobe/XEH_preInit.sqf

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ GVAR(replaceHashmap) = createHashMapFromArray [
1919
[TYPE_GOGGLE, LINKFUNC(replaceOther) ]
2020
];
2121

22-
// Cache Wardrobe Replace Exceptions
22+
// Handle Variables on containers (key is varName, values is global-broadcast)
23+
GVAR(containerVarsToTransfer) = createHashMapFromArray [
24+
[toLower QEGVAR(gunbag,gunbagWeapon), true],
25+
[toLower QEGVAR(movement,vload), true],
26+
[toLower "radio_settings", true] // From TFAR
27+
];
28+
29+
// Exception Handling
2330
private _map = createHashMap;
2431
{
25-
_map set [
26-
configName _x,
27-
[
28-
toLower getText (_x >> "mode"),
29-
getText (_x >> "code") call CBA_fnc_convertStringCode
30-
]
31-
];
32+
_map set [ configName _x, [ toLower getText (_x >> "mode"), getText (_x >> "code") call CBA_fnc_convertStringCode ] ];
3233
} forEach ("true" configClasses (configFile >> QGVAR(exceptions)));
3334
GVAR(exceptions) = _map;
3435

@@ -37,11 +38,5 @@ GVAR(exceptions) = _map;
3738
{ _this call (GVAR(exceptions) get (_this#0) select 1) }
3839
] call CBA_fnc_addEventHandler;
3940

40-
// Variables to transfer when changing containers (key is varName, values is global-broadcast)
41-
GVAR(containerVarsToTransfer) = createHashMapFromArray [
42-
[toLower QEGVAR(gunbag,gunbagWeapon), true],
43-
[toLower QEGVAR(movement,vload), true],
44-
[toLower "radio_settings", true] // From TFAR
45-
];
4641

4742
ADDON = true;

addons/wardrobe/functions/fnc_getDisplayName.sqf

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ private _classOrigin = configName _cfgOrigin;
2323
private _classTarget = configName _cfgTarget;
2424

2525
switch (true) do {
26-
26+
2727
// check legacy directional
2828
case (
2929
isText (configFile >> QUOTE(ADDON) >> _classOrigin >> "modifiableTo" >> _classTarget >> "directionalActionName")
@@ -55,6 +55,18 @@ switch (true) do {
5555

5656
// Fallback displayName of Item
5757
default {
58-
getText (_cfgTarget >> "displayName")
58+
59+
private _return = getText (_cfgTarget >> "displayName");
60+
61+
// Adds type-descriptor when its converting to a different slot
62+
private _typeOrigin = _cfgOrigin call LINKFUNC(getTypeNumber);
63+
private _typeTarget = _cfgTarget call LINKFUNC(getTypeNumber);
64+
65+
if (_typeOrigin isNotEqualTo _typeTarget) then {
66+
_return = _return + " (" + ( _typeTarget call LINKFUNC(getSlotName) ) + ")";
67+
};
68+
69+
_return
70+
5971
};
60-
};
72+
} // return
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#include "../script_component.hpp"
2+
/*
3+
* Author: OverlordZorn
4+
* Getter Function
5+
*
6+
* Arguments:
7+
* 0: TYPENUMBER <NUMBER>
8+
*
9+
* Return Value:
10+
* Localised Displayname <STRING>
11+
*
12+
* Example:
13+
* TYPE_HMD call ace_wardrobe_fnc_getSlotName;
14+
*
15+
* Public: No
16+
*/
17+
18+
params ["_typeNumber"];
19+
20+
switch (_typeNumber) do {
21+
case TYPE_UNIFORM: { localize "str_a3_rscdisplayarsenal_tab_uniform" };
22+
case TYPE_VEST: { localize "str_a3_rscdisplayarsenal_tab_vest" };
23+
case TYPE_BACKPACK: { localize "str_a3_rscdisplayarsenal_tab_backpack" };
24+
case TYPE_HEADGEAR: { localize "str_a3_rscdisplayarsenal_tab_headgear" };
25+
case TYPE_GOGGLE: { localize "str_a3_rscdisplayarsenal_tab_goggles" };
26+
case TYPE_HMD: { localize "str_a3_rscdisplayarsenal_tab_nvgs" };
27+
default { "" };
28+
} // return
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
#include "../script_component.hpp"
2+
/*
3+
* Author: OverlordZorn
4+
* Returns typenumber of item based on config. Simplified for Wardrobe.
5+
*
6+
* Arguments:
7+
* 0: Item Config <CONFIG>
8+
*
9+
* Return Value:
10+
* TypeNumber <NUMBER>
11+
*
12+
* Example:
13+
* [configFile >> "CfgWeapons" >> "U_B_CTRG_1", configFile >> "CfgWeapons" >> "U_B_CTRG_3"] call ace_wardrobe_fnc_getTypeNumber;
14+
*
15+
* Public: No
16+
*/
17+
18+
params ["_itemConfig"];
19+
20+
private _typeNumber = getNumber (_itemConfig >> "ItemInfo" >> "type");
21+
22+
23+
// Handle Edgecases
24+
if (_typeNumber isEqualTo 0) then {
25+
private _className = configName _itemConfig;
26+
27+
_typeNumber = switch (true) do {
28+
case (isClass (configFile >> "CfgGlasses" >> _className)): { TYPE_GOGGLE }; // CfgGlasses items do not have ItemInfo subclass
29+
case (getNumber (configFile >> "CfgVehicles" >> _className >> "isBackpack") isEqualTo 1): { TYPE_BACKPACK }; // Backpacks
30+
default { 0 };
31+
};
32+
};
33+
34+
//return
35+
_typeNumber

addons/wardrobe/functions/fnc_replace.sqf

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -22,49 +22,64 @@
2222
params ["", "_player", "_actionParams"];
2323
_actionParams params ["_cfgOrigin", "_cfgTarget"];
2424

25-
private _classTarget = configName _cfgTarget;
25+
26+
// PREP
2627
private _classOrigin = configName _cfgOrigin;
27-
private _cfgWardobeTarget = configFile >> QUOTE(ADDON) >> _classTarget;
28+
private _classTarget = configName _cfgTarget;
29+
30+
private _typeOrigin = _cfgOrigin call LINKFUNC(getTypeNumber);
31+
private _typeTarget = _cfgTarget call LINKFUNC(getTypeNumber);
2832

29-
// duration of the "animation"
33+
// Duration of Animationphase
3034
private _duration = _actionParams call LINKFUNC(getDuration);
3135

32-
// replace the main Item
33-
private _typeNumber = getNumber (_cfgOrigin >> "ItemInfo" >> "type");
34-
35-
if (_typeNumber isEqualTo 0) then {
36-
37-
// Switch-statement incase there will be more edge cases like CfgGlassess
38-
_typeNumber = switch (true) do {
39-
// CfgGlasses items do not have a ItemInfo subclass and therefore, will return 0
40-
case (isClass (configFile >> "CfgGlasses" >> _classOrigin)): { TYPE_GOGGLE };
41-
case (getNumber (configFile >> "CfgVehicles" >> _classOrigin >> "isBackpack") isEqualTo 1): { TYPE_BACKPACK };
42-
default { 0 };
43-
};
44-
};
4536

46-
private _replaceCode = GVAR(replaceHashmap) get _typeNumber;
37+
private _replaceCode = GVAR(replaceHashmap) get _typeOrigin;
4738

48-
if (isNil "_replaceCode") exitWith { ERROR_2("typeNumber undefined: %1 - %2",_typeNumber,_classOrigin); };
4939

50-
private _extendedInfo = createHashMap;
51-
[QGVAR(itemChangedStart), [_player, _classOrigin, _classTarget, _typeNumber, _extendedInfo]] call CBA_fnc_localEvent;
40+
// FAIL CONDITIONS
41+
private _isNotEqualTypeNumber = _typeOrigin isNotEqualTo _typeTarget;
5242

53-
// temp action disabled
43+
if (isNil "_replaceCode") exitWith { ERROR_2("typeNumber undefined: %1 - %2",_typeOrigin,_classOrigin); };
44+
if (_isNotEqualTypeNumber && { _typeTarget in [TYPE_UNIFORM, TYPE_VEST, TYPE_BACKPACK] }) exitWith {
45+
ERROR_4("Convertion of containers not supported: %1: %2 -> %3: %4",_classOrigin,_typeOrigin,_classTarget,_typeTarget)
46+
};
47+
if (_isNotEqualTypeNumber && {
48+
switch (_typeTarget) do {
49+
case TYPE_HEADGEAR: { "" isNotEqualTo headgear _player };
50+
case TYPE_GOGGLE: { "" isNotEqualTo goggles _player };
51+
case TYPE_HMD: { "" isNotEqualTo hmd _player };
52+
}
53+
}
54+
) exitWith { [ [LLSTRING(slotOccupied), _typeTarget call LINKFUNC(getSlotName)], 2 ] call EFUNC(common,displayTextStructured); };
55+
56+
// REPLACE MECHANIC
57+
// Disables Wardrobe Action temporarily
5458
GVAR(inProgress) = true;
5559

56-
[{
57-
params ["_player", "_classOrigin", "_classTarget", "_typeNumber", "_replaceCode", "_extendedInfo"];
60+
// use hashmap instead of array to futureproofing - espl. regarding API Events - extended data can simply be added
61+
private _replaceData = createHashMapFromArray [
62+
["player", _player],
63+
["classOrigin", _classOrigin],
64+
["classTarget", _classTarget],
65+
["typeOrigin", _typeOrigin],
66+
["typeTarget", _typeTarget]
67+
];
68+
69+
private _extendedInfo = createHashMap;
70+
[QGVAR(itemChangedStart), [_replaceData, _extendedInfo]] call CBA_fnc_localEvent; // API
5871

59-
[QGVAR(itemChangedBegin), [_player, _classOrigin, _classTarget, _typeNumber, _extendedInfo]] call CBA_fnc_localEvent;
72+
[{
73+
params ["_replaceData", "_replaceCode", "_extendedInfo"];
6074

61-
[_player, _classTarget, _typeNumber] call _replaceCode;
75+
[QGVAR(itemChangedBegin), [_replaceData, _extendedInfo]] call CBA_fnc_localEvent; // API
76+
_replaceData call _replaceCode;
77+
[QGVAR(itemChangedEnd), [_replaceData, _extendedInfo]] call CBA_fnc_localEvent; // API
6278

63-
[QGVAR(itemChangedEnd), [_player, _classOrigin, _classTarget, _typeNumber, _extendedInfo]] call CBA_fnc_localEvent;
79+
}, [_replaceData, _replaceCode, _extendedInfo], _duration] call CBA_fnc_waitAndExecute;
6480

65-
}, [_player, _classOrigin, _classTarget, _typeNumber, _replaceCode, _extendedInfo], _duration] call CBA_fnc_waitAndExecute;
6681

67-
// handle components
82+
// HANDLE COMPONENTS
6883
[_classOrigin, _classTarget] call FUNC(compareComponents) params ["_missing", "_surplus"];
6984

7085
// add surplus
@@ -89,11 +104,12 @@ GVAR(inProgress) = true;
89104
};
90105
} forEach _missing;
91106

92-
// handle effects
107+
108+
// EFFECTS
93109
// animation/gestures
94110
[_player, _actionParams call LINKFUNC(getGesture)] call EFUNC(common,doGesture);
95111

96-
// plays random sound at the beginning
112+
// Soundseffects
97113
private _sound = _actionParams call LINKFUNC(getSound);
98114
if (_sound isNotEqualTo "") then {
99115
[
@@ -103,7 +119,7 @@ if (_sound isNotEqualTo "") then {
103119
] call CBA_fnc_waitAndExecute;
104120
};
105121

106-
// notification
122+
// Notification
107123
private _imgNotify = getText (_cfgTarget >> "picture");
108124
if !(".paa" in _imgNotify) then {
109125
// some vanilla items dont have the .paa and cba notify will display the path as a string without the .paa

addons/wardrobe/functions/fnc_replaceContainer.sqf

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,22 @@
44
* Function to replace a units wearable container while maintaining the content of the container.
55
*
66
* Arguments:
7-
* 0: Unit <OBJECT>
8-
* 1: Desired variant as classname <STRING>
9-
* 2: Type of wearable container <STRING>
7+
* 0: Params Hash <HASHMAP>
108
*
119
* Return Value:
1210
* None
1311
*
1412
* Example:
15-
* [player, "U_B_CTRG_3", "UNIFORM"] call ace_wardrobe_fnc_replaceContainer
16-
* [player, "U_B_CTRG_1", "UNIFORM"] call ace_wardrobe_fnc_replaceContainer
13+
* [_replaceData] call ace_wardrobe_fnc_replaceContainer
1714
*
1815
* Public: No
1916
*/
2017

21-
params ["_player", "_classTarget", "_typeNumber"];
18+
params ["_replaceData"];
19+
private _player = _replaceData get "player";
20+
private _classTarget = _replaceData get "classTarget";
21+
private _typeTarget = _replaceData get "typeTarget";
22+
2223

2324
private _allMags = (magazinesAmmoFull _player) apply { _x#0 };
2425

@@ -51,7 +52,7 @@ private _containerVars = [];
5152
} forEach [uniformContainer _player, vestContainer _player, backpackContainer _player];
5253

5354
// Replace Wearable Container
54-
switch (_typeNumber) do {
55+
switch (_typeTarget) do {
5556
case TYPE_UNIFORM: { _loadout # 3 set [0, _classTarget]; };
5657
case TYPE_VEST: { _loadout # 4 set [0, _classTarget]; };
5758
case TYPE_BACKPACK: { _loadout # 5 set [0, _classTarget]; };

addons/wardrobe/functions/fnc_replaceOther.sqf

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,47 @@
11
#include "../script_component.hpp"
22
/*
33
* Author: OverlordZorn
4-
* Function to replace a unit's goggles/facewear.
4+
* Function to replace a unit's Facewear, NVG/HMD or Headgear.
55
*
66
* Arguments:
7-
* 0: Unit <OBJECT>
8-
* 1: Desired variant as classname <STRING>
9-
* 2: Type of wearable container <STRING>
7+
* 0: Params Hash <HASHMAP>
108
*
119
* Return Value:
1210
* None
1311
*
1412
* Example:
15-
* [player, "G_Bandanna_blk", "FACEWEAR"] call ace_wardrobe_fnc_replaceOther
16-
* [player, "G_Bandanna_aviator", "FACEWEAR"] call ace_wardrobe_fnc_replaceOther
13+
* [_replaceData] call ace_wardrobe_fnc_replaceOther
1714
*
1815
* Public: No
1916
*/
2017

21-
params ["_player", "_classTarget", "_typeNumber"];
18+
params ["_replaceData"];
2219

23-
switch (_typeNumber) do {
20+
private _player = _replaceData get "player";
21+
22+
// Remove
23+
switch (_replaceData get "typeOrigin") do {
2424
case TYPE_HEADGEAR: {
2525
removeHeadgear _player;
26-
_player addHeadgear _classTarget;
2726
};
2827
case TYPE_GOGGLE: {
2928
removeGoggles _player;
30-
_player addGoggles _classTarget;
3129
};
3230
case TYPE_HMD: {
33-
_player linkItem _classTarget;
31+
_player unlinkItem (_replaceData get "classOrigin")
32+
};
33+
};
34+
35+
// ADD
36+
switch (_replaceData get "typeTarget") do {
37+
case TYPE_HEADGEAR: {
38+
_player addHeadgear (_replaceData get "classTarget");
39+
};
40+
case TYPE_GOGGLE: {
41+
_player addGoggles (_replaceData get "classTarget");
42+
};
43+
case TYPE_HMD: {
44+
_player linkItem (_replaceData get "classTarget");
3445
};
3546
};
3647

addons/wardrobe/stringtable.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,9 @@
152152
<Russian>Надеть маску</Russian>
153153
<Japanese>マスクを着ける</Japanese>
154154
</Key>
155+
<Key ID="STR_ACE_Wardrobe_slotOccupied">
156+
<English>Your %1 slot is already occupied</English>
157+
</Key>
155158
<Key ID="STR_ACE_Wardrobe_missingComponents">
156159
<English>Cannot switch to&lt;br/&gt;%1&lt;br/&gt;due to missing components</English>
157160
<French>Impossible de passer à&lt;br/&gt;%1&lt;br/&gt;en raison de composants manquants</French>

0 commit comments

Comments
 (0)