diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml
index f78465887e..2ba4cbfcaf 100644
--- a/.github/release-drafter.yml
+++ b/.github/release-drafter.yml
@@ -5,6 +5,9 @@ branches:
name-template: 'Version $NEXT_PATCH_VERSION'
tag-template: 'v$NEXT_PATCH_VERSION'
+sort-by: title # sort alphabetically
+sort-direction: ascending
+
categories:
- title: '**ADDED:**'
labels:
diff --git a/.hemtt/project.toml b/.hemtt/project.toml
index 60cff33c2d..206bf9573c 100644
--- a/.hemtt/project.toml
+++ b/.hemtt/project.toml
@@ -28,9 +28,6 @@ exclude = [
"zeus/functions/fnc_zeusAttributes.sqf",
]
-[hemtt.config]
-preset = "Hemtt"
-
[hemtt.launch]
workshop = [
"450814997", # CBA_A3
diff --git a/addons/advanced_fatigue/XEH_postInit.sqf b/addons/advanced_fatigue/XEH_postInit.sqf
index d447c3f651..57b57dcf22 100644
--- a/addons/advanced_fatigue/XEH_postInit.sqf
+++ b/addons/advanced_fatigue/XEH_postInit.sqf
@@ -60,7 +60,7 @@ if (!hasInterface) exitWith {};
}, true] call CBA_fnc_addPlayerEventHandler;
// - Duty factors -------------------------------------------------------------
- if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then {
+ if (["ace_medical"] call EFUNC(common,isModLoaded)) then {
[QEGVAR(medical,pain), { // 0->1.0, 0.5->1.05, 1->1.1
linearConversion [0, 1, (_this getVariable [QEGVAR(medical,pain), 0]), 1, 1.1, true];
}] call FUNC(addDutyFactor);
@@ -68,7 +68,7 @@ if (!hasInterface) exitWith {};
linearConversion [6, 0, (_this getVariable [QEGVAR(medical,bloodVolume), 6]), 1, 2, true];
}] call FUNC(addDutyFactor);
};
- if (["ACE_Dragging"] call EFUNC(common,isModLoaded)) then {
+ if (["ace_dragging"] call EFUNC(common,isModLoaded)) then {
[QEGVAR(dragging,isCarrying), {
[1, 3] select (_this getVariable [QEGVAR(dragging,isCarrying), false]);
}] call FUNC(addDutyFactor);
diff --git a/addons/arsenal/functions/fnc_addDefaultLoadout.sqf b/addons/arsenal/functions/fnc_addDefaultLoadout.sqf
index b9b8853f15..f54ff03eeb 100644
--- a/addons/arsenal/functions/fnc_addDefaultLoadout.sqf
+++ b/addons/arsenal/functions/fnc_addDefaultLoadout.sqf
@@ -20,8 +20,9 @@
params [["_name", "", [""]], ["_loadout", [], [[]]], ["_global", false, [false]]];
-if (_global) then {
- [QGVAR(addDefaultLoadout), [_name, _loadout]] call CBA_fnc_remoteEvent;
+if (_global) exitWith {
+ private _eventID = format [QGVAR(loadouts_%1), _name];
+ [QGVAR(addDefaultLoadout), [_name, _loadout], _eventID] call CBA_fnc_globalEventJIP;
};
private _extendedInfo = createHashMap;
diff --git a/addons/arsenal/functions/fnc_buttonCargo.sqf b/addons/arsenal/functions/fnc_buttonCargo.sqf
index 48c5ee477e..d7713a2518 100644
--- a/addons/arsenal/functions/fnc_buttonCargo.sqf
+++ b/addons/arsenal/functions/fnc_buttonCargo.sqf
@@ -47,8 +47,8 @@ private _container = switch (GVAR(currentLeftPanel)) do {
};
};
- /// Get all items from container (excluding container itself)
- _containerItems = [GVAR(center), 0, 3, 0, 0, false] call EFUNC(common,uniqueUnitItems);
+ // Get all items from container
+ _containerItems = uniformItems GVAR(center);
// Update currentItems
GVAR(currentItems) set [IDX_CURR_UNIFORM_ITEMS, ((getUnitLoadout GVAR(center)) select IDX_LOADOUT_UNIFORM) param [1, []]];
@@ -75,8 +75,8 @@ private _container = switch (GVAR(currentLeftPanel)) do {
};
};
- // Get all items from container (excluding container itself)
- _containerItems = [GVAR(center), 0, 0, 3, 0, false] call EFUNC(common,uniqueUnitItems);
+ // Get all items from container
+ _containerItems = vestItems GVAR(center);
// Update currentItems
GVAR(currentItems) set [IDX_CURR_VEST_ITEMS, ((getUnitLoadout GVAR(center)) select IDX_LOADOUT_VEST) param [1, []]];
@@ -103,8 +103,8 @@ private _container = switch (GVAR(currentLeftPanel)) do {
};
};
- // Get all items from container (excluding container itself)
- _containerItems = [GVAR(center), 0, 0, 0, 3, false] call EFUNC(common,uniqueUnitItems);
+ // Get all items from container
+ _containerItems = backpackItems GVAR(center);
// Update currentItems
GVAR(currentItems) set [IDX_CURR_BACKPACK_ITEMS, ((getUnitLoadout GVAR(center)) select IDX_LOADOUT_BACKPACK) param [1, []]];
@@ -117,7 +117,7 @@ private _container = switch (GVAR(currentLeftPanel)) do {
};
// Find out how many items of that type there are and update the number displayed
-_ctrlList lnbSetText [[_lnbCurSel, 2], str (_containerItems getOrDefault [_item, 0])];
+_ctrlList lnbSetText [[_lnbCurSel, 2], str ({_item == _x} count _containerItems)];
[QGVAR(cargoChanged), [_display, _item, _addOrRemove, GVAR(shiftState)]] call CBA_fnc_localEvent;
diff --git a/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf b/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf
index 87191a99c2..d25fa485cf 100644
--- a/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf
+++ b/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf
@@ -43,11 +43,7 @@ private _loadoutIndex = _data findIf {(_x select 0) == _loadoutName};
(_data select _loadoutIndex) set [0, _editBoxContent];
if (GVAR(currentLoadoutsTab) == IDC_buttonDefaultLoadouts) then {
- if (is3DEN) then {
- set3DENMissionAttributes [[QGVAR(DummyCategory), QGVAR(DefaultLoadoutsListAttribute), GVAR(defaultLoadoutsList)]];
- } else {
- [QGVAR(renameDefaultLoadout), [_loadoutName, _editBoxContent]] call CBA_fnc_remoteEvent;
- };
+ set3DENMissionAttributes [[QGVAR(DummyCategory), QGVAR(DefaultLoadoutsListAttribute), GVAR(defaultLoadoutsList)]];
};
private _currentLoadoutsTab = str GVAR(currentLoadoutsTab);
diff --git a/addons/arsenal/functions/fnc_fillRightPanel.sqf b/addons/arsenal/functions/fnc_fillRightPanel.sqf
index c562e8727d..346e07fa59 100644
--- a/addons/arsenal/functions/fnc_fillRightPanel.sqf
+++ b/addons/arsenal/functions/fnc_fillRightPanel.sqf
@@ -44,10 +44,14 @@ private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgWeapons = configFile >> "CfgWeapons";
private _rightPanelCache = uiNamespace getVariable QGVAR(rightPanelCache);
-private _currentCargo = itemsWithMagazines GVAR(center);
+private _currentCargo = []; // we only need this if we're filtering for favorites
+if (GVAR(favoritesOnly)) then {
+ _currentCargo = itemsWithMagazines GVAR(center) + backpacks GVAR(center);
+ _currentCargo = _currentCargo arrayIntersect _currentCargo;
+};
private _fnc_fillRightContainer = {
- params ["_configCategory", "_className", "_hasItemInfo", ["_isUnique", false, [false]], ["_unknownOrigin", false, [false]]];
+ params ["_configCategory", "_className", ["_isUnique", false, [false]], ["_unknownOrigin", false, [false]]];
if (GVAR(favoritesOnly) && {!(_className in _currentCargo)} && {!((toLower _className) in GVAR(favorites))}) exitWith {};
@@ -64,7 +68,6 @@ private _fnc_fillRightContainer = {
// "Misc. items" magazines (e.g. spare barrels, intel, photos)
if (_className in (uiNamespace getVariable QGVAR(magazineMiscItems))) then {
_configPath = _cfgMagazines >> _className;
- _hasItemInfo = false;
};
// If an item with unknown origin is in the arsenal list, try to find it
@@ -75,34 +78,15 @@ private _fnc_fillRightContainer = {
if (isNull _configPath) then {
_configPath = _className call CBA_fnc_getObjectConfig;
};
-
- // Check if item is has item info
- _itemInfo = isClass (_cfgWeapons >> configName _configPath);
};
- // Get mass
- private _mass = if (!_hasItemInfo) then {
- getNumber (_configPath >> "mass")
- } else {
- private _mass = getNumber (_configPath >> "itemInfo" >> "mass");
-
- if (_mass == 0) then {
- _mass = getNumber (_configPath >> "WeaponSlotsInfo" >> "mass");
- };
-
- _mass
- };
-
- _rightPanelCache set [_className, _mass]; // Needed because this provides more accurate weight for FUNC(updateRightPanel)
-
- [getText (_configPath >> "displayName"), getText (_configPath >> "picture"), _mass]
- }, true]) params ["_displayName", "_picture", "_mass"];
+ [getText (_configPath >> "displayName"), getText (_configPath >> "picture")]
+ }, true]) params ["_displayName", "_picture"];
private _lbAdd = _ctrlPanel lnbAddRow ["", _displayName, "0"];
_ctrlPanel lnbSetText [[_lbAdd, 1], _displayName];
_ctrlPanel lnbSetData [[_lbAdd, 0], _className];
_ctrlPanel lnbSetPicture [[_lbAdd, 0], _picture];
- _ctrlPanel lnbSetValue [[_lbAdd, 0], _mass];
_ctrlPanel lnbSetValue [[_lbAdd, 2], [0, 1] select _isUnique];
_ctrlPanel lnbSetTooltip [[_lbAdd, 0], format ["%1\n%2", _displayName, _className]];
if ((toLower _className) in GVAR(favorites)) then {
@@ -230,11 +214,11 @@ switch (_ctrlIDC) do {
} forEach _compatibleItems;
} else {
{
- ["CfgWeapons", _x, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x] call _fnc_fillRightContainer;
} forEach (keys ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get _index));
{
- ["CfgWeapons", _x, true, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x, true] call _fnc_fillRightContainer;
} forEach (keys ((GVAR(virtualItems) get IDX_VIRT_UNIQUE_ATTACHMENTS) get _index));
};
};
@@ -253,44 +237,44 @@ switch (_ctrlIDC) do {
case IDC_buttonMag: {
{
if (_x in (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL)) then {
- ["CfgMagazines", _x, false] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x] call _fnc_fillRightContainer;
continue;
};
if (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_VIRT_ITEMS_ALL)) then {
- ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x, true] call _fnc_fillRightContainer;
};
} forEach (keys _compatibleMagsAll);
};
// All magazines
case IDC_buttonMagALL: {
{
- ["CfgMagazines", _x, false] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x] call _fnc_fillRightContainer;
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL));
{
- ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x, true] call _fnc_fillRightContainer;
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_VIRT_ITEMS_ALL));
};
// Grenades
case IDC_buttonThrow: {
{
- ["CfgMagazines", _x, false] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x] call _fnc_fillRightContainer;
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_GRENADES));
{
- ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x, true] call _fnc_fillRightContainer;
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GRENADES));
};
// Explosives
case IDC_buttonPut: {
{
- ["CfgMagazines", _x, false] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x] call _fnc_fillRightContainer;
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_EXPLOSIVES));
{
- ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgMagazines", _x, true] call _fnc_fillRightContainer;
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_EXPLOSIVES));
};
// Misc. items
@@ -309,33 +293,35 @@ switch (_ctrlIDC) do {
// "Regular" misc. items
{
if !(_x in _items) then {
- ["CfgWeapons", _x, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x] call _fnc_fillRightContainer;
};
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS));
// Unique items
{
if !(_x in _items) then {
- ["CfgWeapons", _x, true, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x, true] call _fnc_fillRightContainer;
};
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_MISC_ITEMS));
// Unique backpacks
{
if !(_x in _items) then {
- ["CfgVehicles", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgVehicles", _x, true] call _fnc_fillRightContainer;
};
} forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_BACKPACKS));
// Unique goggles
{
if !(_x in _items) then {
- ["CfgGlasses", _x, false, true] call _fnc_fillRightContainer;
+ // _y indicates if an item is truly unique or if it's a non-inventory item in a container (e.g. goggles in backpack)
+ ["CfgGlasses", _x, _y] call _fnc_fillRightContainer;
};
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES));
+ } forEach (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES);
// Unknown items
{
if !(_x in _items) then {
- ["CfgWeapons", _x, true, true, true] call _fnc_fillRightContainer;
+ // _y indicates if an item is truly unique or if it's a non-inventory item in a container (e.g. helmet in backpack)
+ ["CfgWeapons", _x, _y, true] call _fnc_fillRightContainer;
};
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS));
+ } forEach (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS); // if an item is here but in virtual items, it's just in the wrong place
};
// Custom buttons
default {
@@ -347,23 +333,23 @@ switch (_ctrlIDC) do {
switch (true) do {
// "Regular" misc. items
case (_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)): {
- ["CfgWeapons", _x, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x] call _fnc_fillRightContainer;
};
// Unique items
case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_MISC_ITEMS)): {
- ["CfgWeapons", _x, true, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x, true] call _fnc_fillRightContainer;
};
// Unique backpacks
case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_BACKPACKS)): {
- ["CfgVehicles", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgVehicles", _x, true] call _fnc_fillRightContainer;
};
// Unique goggles
case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES)): {
- ["CfgGlasses", _x, false, true] call _fnc_fillRightContainer;
+ ["CfgGlasses", _x, GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES get _x] call _fnc_fillRightContainer;
};
// Unknown items
case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS)): {
- ["CfgWeapons", _x, true, true, true] call _fnc_fillRightContainer;
+ ["CfgWeapons", _x, GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS get _x, true] call _fnc_fillRightContainer;
};
};
} forEach _items;
@@ -389,8 +375,8 @@ if (_isContainer) then {
// Update load bar
(_display displayCtrl IDC_loadIndicatorBar) progressSetPosition (loadUniform GVAR(center));
- // Get all items from container (excluding container itself)
- _containerItems = [GVAR(center), 0, 3, 0, 0, false] call EFUNC(common,uniqueUnitItems);
+ // Get all items from container
+ _containerItems = uniformItems GVAR(center);
uniformContainer GVAR(center)
};
@@ -399,8 +385,8 @@ if (_isContainer) then {
// Update load bar
(_display displayCtrl IDC_loadIndicatorBar) progressSetPosition (loadVest GVAR(center));
- // Get all items from container (excluding container itself)
- _containerItems = [GVAR(center), 0, 0, 3, 0, false] call EFUNC(common,uniqueUnitItems);
+ // Get all items from container
+ _containerItems = vestItems GVAR(center);
vestContainer GVAR(center)
};
@@ -409,8 +395,8 @@ if (_isContainer) then {
// Update load bar
(_display displayCtrl IDC_loadIndicatorBar) progressSetPosition (loadBackpack GVAR(center));
- // Get all items from container (excluding container itself)
- _containerItems = [GVAR(center), 0, 0, 0, 3, false] call EFUNC(common,uniqueUnitItems);
+ // Get all items from container
+ _containerItems = backpackItems GVAR(center);
backpackContainer GVAR(center)
};
@@ -418,7 +404,8 @@ if (_isContainer) then {
// Find out how many items of a type there are and update the number displayed
for "_lbIndex" from 0 to (lnbSize _ctrlPanel select 0) - 1 do {
- _ctrlPanel lnbSetText [[_lbIndex, 2], str (_containerItems getOrDefault [_ctrlPanel lnbData [_lbIndex, 0], 0])];
+ private _xItem = _ctrlPanel lnbData [_lbIndex, 0];
+ _ctrlPanel lnbSetText [[_lbIndex, 2], str ({_xItem == _x} count _containerItems)];
};
// Refresh availibility of items based on space remaining in container
diff --git a/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf b/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf
index a0203ff5b9..a8938e8c48 100644
--- a/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf
+++ b/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf
@@ -63,6 +63,7 @@ switch (ctrlIDC _control) do {
_saveButtonCtrl ctrlSetTooltip LLSTRING(buttonSaveTooltip);
};
+ _renameButtonCtrl ctrlEnable is3DEN; // no renaming mid-mission
_saveButtonCtrl ctrlEnable call FUNC(canEditDefaultLoadout);
_saveButtonCtrl ctrlCommit 0;
};
diff --git a/addons/arsenal/functions/fnc_onArsenalClose.sqf b/addons/arsenal/functions/fnc_onArsenalClose.sqf
index c6a1da0215..bc862f2de0 100644
--- a/addons/arsenal/functions/fnc_onArsenalClose.sqf
+++ b/addons/arsenal/functions/fnc_onArsenalClose.sqf
@@ -51,13 +51,6 @@ if (is3DEN) then {
["ShowInterface", true] call BIS_fnc_3DENInterface;
GVAR(visionMode) call BIS_fnc_3DENVisionMode;
} else {
- // Select correct weapon
- switch (GVAR(selectedWeaponType)) do {
- case 0: {GVAR(center) selectWeapon (primaryWeapon GVAR(center))};
- case 1: {GVAR(center) selectWeapon (secondaryWeapon GVAR(center))};
- case 2: {GVAR(center) selectWeapon (handgunWeapon GVAR(center))};
- };
-
if (!isNull curatorCamera && {ACE_player == player}) then {
curatorCamera cameraEffect ["Internal", "BACK"];
} else {
diff --git a/addons/arsenal/functions/fnc_onArsenalOpen.sqf b/addons/arsenal/functions/fnc_onArsenalOpen.sqf
index 5e35500248..bcc91c133a 100644
--- a/addons/arsenal/functions/fnc_onArsenalOpen.sqf
+++ b/addons/arsenal/functions/fnc_onArsenalOpen.sqf
@@ -243,7 +243,15 @@ GVAR(refreshing) = false;
_panel ctrlCommit 0;
} forEach [IDC_leftTabContent, IDC_rightTabContent, IDC_rightTabContentListnBox];
-[_display, _display displayCtrl IDC_buttonPrimaryWeapon] call FUNC(fillLeftPanel);
+// Open left panel for current weapon, do some math
+GVAR(selectedWeaponType) = [primaryWeapon GVAR(center), secondaryWeapon GVAR(center), handgunWeapon GVAR(center), binocular GVAR(center)] find (currentWeapon GVAR(center));
+if (GVAR(selectedWeaponType) == -1) then {
+ GVAR(selectedWeaponType) = 0; // default to primary
+};
+
+private _leftPanelIDC = [IDC_buttonPrimaryWeapon, IDC_buttonSecondaryWeapon, IDC_buttonHandgun, IDC_buttonBinoculars] select GVAR(selectedWeaponType);
+
+[_display, _display displayCtrl _leftPanelIDC] call FUNC(fillLeftPanel);
//--------------- Init camera
if (isNil QGVAR(cameraPosition)) then {
diff --git a/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf b/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf
index e84aad5c04..3ca877f7fd 100644
--- a/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf
+++ b/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf
@@ -17,8 +17,10 @@
*/
params [["_name", "", [""]], ["_global", false, [false]]];
-if (_global) then {
- [QGVAR(removeDefaultLoadout), [_name]] call CBA_fnc_remoteEvent;
+if (_global) exitWith {
+ private _eventID = format [QGVAR(loadouts_%1), _name];
+ [_eventID] call CBA_fnc_removeGlobalEventJIP;
+ [QGVAR(removeDefaultLoadout), [_name]] call CBA_fnc_globalEvent;
};
GVAR(defaultLoadoutsList) deleteAt (GVAR(defaultLoadoutsList) findIf {(_x select 0) == _name});
diff --git a/addons/arsenal/functions/fnc_showItem.sqf b/addons/arsenal/functions/fnc_showItem.sqf
index 76a95e6981..7ceda5f0d5 100644
--- a/addons/arsenal/functions/fnc_showItem.sqf
+++ b/addons/arsenal/functions/fnc_showItem.sqf
@@ -15,6 +15,10 @@
if (GVAR(centerNotPlayer)) exitWith {};
+if (EGVAR(common,isReloading)) exitWith { // if player is reloading then wait until it's done so we don't send magazines to the shadow realm
+ [{!EGVAR(common,isReloading)}, FUNC(showItem)] call CBA_fnc_waitUntilAndExecute;
+};
+
// Determine action to play based on current category selection
private _nextAction = switch (GVAR(currentLeftPanel)) do {
// Primary weapon
@@ -54,10 +58,12 @@ if (_nextAction != GVAR(currentAction)) then {
case "PrimaryWeapon": {0};
case "SecondaryWeapon": {1};
case "HandGunOn": {2};
+ case "Binoculars": {3};
default {GVAR(selectedWeaponType)};
};
if (simulationEnabled GVAR(center)) then {
+ GVAR(center) call EFUNC(common,stopGesture); // reset gesture state (if arsenal is opened on animation transition, animations played whilst in the arsenal break)
GVAR(center) playActionNow _nextAction;
} else {
GVAR(center) switchAction _nextAction;
@@ -65,3 +71,7 @@ if (_nextAction != GVAR(currentAction)) then {
GVAR(currentAction) = _nextAction;
};
+
+if (!(GVAR(currentAction) in ["Civil", "Salute"])) then {
+ GVAR(center) selectWeapon ([primaryWeapon GVAR(center), secondaryWeapon GVAR(center), handgunWeapon GVAR(center), binocular GVAR(center)] select GVAR(selectedWeaponType)); // select correct weapon, prevents floating weapons
+};
diff --git a/addons/arsenal/functions/fnc_updateRightPanel.sqf b/addons/arsenal/functions/fnc_updateRightPanel.sqf
index e51f923655..e43f06c74f 100644
--- a/addons/arsenal/functions/fnc_updateRightPanel.sqf
+++ b/addons/arsenal/functions/fnc_updateRightPanel.sqf
@@ -18,19 +18,18 @@
params ["_control", "_container", "_hasItems"];
private _loadRemaining = maxLoad _container - loadAbs _container;
-private _rightPanelCache = uiNamespace getVariable [QGVAR(rightPanelCache), createHashMap];
-private _mass = -1;
+private _item = "";
private _color = [];
private _alpha = 1;
// Grey out items that are too big to fit in remaining space of the container
for "_row" from 0 to (lnbSize _control select 0) - 1 do {
- _mass = _rightPanelCache getOrDefault [_control lnbData [_row, 0], 0];
+ _item = _control lnbData [_row, 0];
_color = _control lnbColor [_row, 1];
// Lower alpha on color for items that can't fit
- _alpha = [0.25, 1] select (_mass <= _loadRemaining);
+ _alpha = [0.25, 1] select (_container canAdd _item);
_color set [3, _alpha];
_control lnbSetColor [[_row, 1], _color];
_control lnbSetColor [[_row, 2], [1, 1, 1, _alpha]];
@@ -55,6 +54,6 @@ private _curSel = lnbCurSelRow _control;
// Disable '+' button if item is unique or too big to fit in remaining space
if (_curSel != -1) then {
private _plusButtonCtrl = _display displayCtrl IDC_arrowPlus;
- _plusButtonCtrl ctrlEnable !((_control lnbValue [_curSel, 2]) == 1 || {(_rightPanelCache getOrDefault [_control lnbData [_curSel, 0], 0]) > _loadRemaining});
+ _plusButtonCtrl ctrlEnable ((_control lnbValue [_curSel, 2]) != 1 && {_container canAdd (_control lnbData [_curSel, 0])});
_plusButtonCtrl ctrlCommit FADE_DELAY;
};
diff --git a/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf b/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf
index ccbf7b7abb..fddc9b3b9c 100644
--- a/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf
+++ b/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf
@@ -125,7 +125,8 @@ private _fnc_uniqueEquipment = {
};
} forEach (getUnitLoadout GVAR(center)); // Only need items, not extended loadout
-
+// Get all items from unit
+_items = itemsWithMagazines GVAR(center) + backpacks GVAR(center);
private _isMagazine = false;
private _isWeapon = false;
private _isGrenade = false;
@@ -136,6 +137,9 @@ private _simulationType = "";
private _configItemInfo = "";
private _hasItemInfo = false;
private _itemInfoType = 0;
+private _baseWeapon = "";
+private _weapons = GVAR(virtualItems) get IDX_VIRT_WEAPONS;
+private _attachments = GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS;
{
_isMagazine = isClass (_cfgMagazines >> _x);
@@ -184,8 +188,13 @@ private _itemInfoType = 0;
// Unknown
default {
// Don't add items that are part of the arsenal
- if !(_x in GVAR(virtualItemsFlatAll)) then {
- (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, nil];
+ if (
+ !(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)) &&
+ {!(_x in (GVAR(virtualItems) get IDX_VIRT_GRENADES))} &&
+ {!(_x in (GVAR(virtualItems) get IDX_VIRT_EXPLOSIVES))} &&
+ {!(_x in (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL))}
+ ) then {
+ (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, true];
};
};
};
@@ -199,11 +208,17 @@ private _itemInfoType = 0;
_itemInfoType = if (_hasItemInfo) then {getNumber (_configItemInfo >> "type")} else {0};
_isMiscItem = _x isKindOf ["CBA_MiscItem", _cfgWeapons];
+ _baseWeapon = if (!_isMiscItem) then {
+ _x call FUNC(baseWeapon)
+ } else {
+ _x
+ };
+
switch (true) do {
// Optics
case (
- !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_OPTICS_ATTACHMENTS)) &&
- {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_OPTICS_ATTACHMENTS) ||
+ !(_baseWeapon in (_attachments get IDX_VIRT_OPTICS_ATTACHMENTS)) &&
+ {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_OPTICS_ATTACHMENTS) ||
{_hasItemInfo &&
{!_isMiscItem} &&
{_itemInfoType == TYPE_OPTICS}}}
@@ -212,8 +227,8 @@ private _itemInfoType = 0;
};
// Flashlights
case (
- !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_FLASHLIGHT_ATTACHMENTS)) &&
- {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_FLASHLIGHT_ATTACHMENTS) ||
+ !(_baseWeapon in (_attachments get IDX_VIRT_FLASHLIGHT_ATTACHMENTS)) &&
+ {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_FLASHLIGHT_ATTACHMENTS) ||
{_hasItemInfo &&
{!_isMiscItem} &&
{_itemInfoType == TYPE_FLASHLIGHT}}}
@@ -222,8 +237,8 @@ private _itemInfoType = 0;
};
// Muzzle attachments
case (
- !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_MUZZLE_ATTACHMENTS)) &&
- {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_MUZZLE_ATTACHMENTS) ||
+ !(_baseWeapon in (_attachments get IDX_VIRT_MUZZLE_ATTACHMENTS)) &&
+ {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_MUZZLE_ATTACHMENTS) ||
{_hasItemInfo &&
{!_isMiscItem} &&
{_itemInfoType == TYPE_MUZZLE}}}
@@ -232,8 +247,8 @@ private _itemInfoType = 0;
};
// Bipods
case (
- !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_BIPOD_ATTACHMENTS)) &&
- {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_BIPOD_ATTACHMENTS) ||
+ !(_baseWeapon in (_attachments get IDX_VIRT_BIPOD_ATTACHMENTS)) &&
+ {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_BIPOD_ATTACHMENTS) ||
{_hasItemInfo &&
{!_isMiscItem} &&
{_itemInfoType == TYPE_BIPOD}}}
@@ -242,7 +257,7 @@ private _itemInfoType = 0;
};
// Misc. items
case (
- !(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)) &&
+ !(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)) && // misc. items don't use 'baseWeapon'
{_x in (_configItems get IDX_VIRT_MISC_ITEMS) ||
{_hasItemInfo &&
{_isMiscItem &&
@@ -254,9 +269,21 @@ private _itemInfoType = 0;
};
// Unknown
default {
- // Don't add items that are part of the arsenal
- if !(_x in GVAR(virtualItemsFlatAll)) then {
- (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, nil];
+ // Don't add attachments or misc. items
+ if (
+ !(_baseWeapon in (_attachments get IDX_VIRT_OPTICS_ATTACHMENTS)) &&
+ {!(_baseWeapon in (_attachments get IDX_VIRT_FLASHLIGHT_ATTACHMENTS))} &&
+ {!(_baseWeapon in (_attachments get IDX_VIRT_MUZZLE_ATTACHMENTS))} &&
+ {!(_baseWeapon in (_attachments get IDX_VIRT_BIPOD_ATTACHMENTS))} &&
+ {!(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS))}
+ ) then {
+ // If item is a weapon (including binos), make it unique
+ (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x,
+ _baseWeapon in (_weapons get IDX_VIRT_PRIMARY_WEAPONS) ||
+ {_baseWeapon in (_weapons get IDX_VIRT_HANDGUN_WEAPONS)} ||
+ {_baseWeapon in (_weapons get IDX_VIRT_SECONDARY_WEAPONS)} ||
+ {_baseWeapon in (GVAR(virtualItems) get IDX_VIRT_BINO)}
+ ];
};
};
};
@@ -267,14 +294,14 @@ private _itemInfoType = 0;
};
// Facewear
case (isClass (_cfgGlasses >> _x)): {
- (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES) set [_x, nil];
+ (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES) set [_x, !(_x in (GVAR(virtualItems) get IDX_VIRT_GOGGLES))];
};
// Unknown
default {
// Don't add items that are part of the arsenal
if !(_x in GVAR(virtualItemsFlatAll)) then {
- (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, nil];
+ (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, true];
};
};
};
-} forEach (keys ([GVAR(center), 0, 3, 3, 3, false] call EFUNC(common,uniqueUnitItems))); // Get all items from unit
+} forEach (_items arrayIntersect _items);
diff --git a/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf b/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf
index 207039f8ae..3ce0dd54d0 100644
--- a/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf
+++ b/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf
@@ -10,16 +10,18 @@ cba_diagnostic_projectileMaxLines = 10;
// Player pose
[{
- switch (true) do {
- case (primaryWeapon _this != ""): {
- _this switchMove "amovpercmstpslowwrfldnon";
- };
- case (handgunWeapon _this != ""): {
- _this switchMove "amovpercmstpslowwpstdnon";
- };
- default {
+ switch (currentWeapon _this) do {
+ case (""): {
_this switchMove "amovpercmstpsnonwnondnon";
};
+ case (primaryWeapon _this): {
+ _this switchMove "amovpercmstpslowwrfldnon";
+ };
+ case (handgunWeapon _this): {
+ _this switchMove "amovpercmstpslowwpstdnon";
+ };
+ case (binocular _this);
+ case (secondaryWeapon _this): {}; // deliberately nothing
};
}, _player] call CBA_fnc_execNextFrame;
@@ -88,6 +90,7 @@ cba_diagnostic_projectileMaxLines = 10;
{
_unit = _x;
+ removeVest _unit;
if (vest _player != "") then { _unit addVest vest _player; };
removeBackpack _unit;
diff --git a/addons/arsenal/stringtable.xml b/addons/arsenal/stringtable.xml
index ce78b8df46..7f6947d913 100644
--- a/addons/arsenal/stringtable.xml
+++ b/addons/arsenal/stringtable.xml
@@ -1693,6 +1693,7 @@
Suche\nSTRG + Click für Live-Aktualisierung während des Schreibens
Cerca\nCTRL + Click per modificare i risultati mentre scrivi
検索\nCTRL + クリックで検索結果の即時表示を有効化
+ 검색\nCtrl + 클릭으로 실시간 검색 결과를 활성화
diff --git a/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf b/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf
index 701ce544f7..a57a52bba7 100644
--- a/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf
+++ b/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf
@@ -41,7 +41,11 @@ if (_initSpeedCoef > 0) then {
};
private _abAdjustText = "";
-if (_magIsForCurrentWeapon && {["ace_advanced_ballistics"] call EFUNC(common,isModLoaded)}) then {
+if (
+ _magIsForCurrentWeapon &&
+ {missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]} &&
+ {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} // this can be on while AB is off or vice-versa
+) then {
private _configAmmo = (configFile >> "CfgAmmo" >> (getText (_configMagazine >> "ammo")));
private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength");
private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities");
diff --git a/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf b/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf
index 16ab9e2a47..e11c7cf5fb 100644
--- a/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf
+++ b/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf
@@ -37,7 +37,10 @@ if (_magazine isEqualTo "") then {
};
private _abAdjustText = "";
- if (["ace_advanced_ballistics"] call EFUNC(common,isModLoaded)) then {
+ if (
+ missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] &&
+ {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} // this can be on while AB is off or vice-versa
+ ) then {
private _configAmmo = (configFile >> "CfgAmmo" >> (getText (_configMagazine >> "ammo")));
private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength");
private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities");
diff --git a/addons/captives/functions/fnc_doEscortCaptive.sqf b/addons/captives/functions/fnc_doEscortCaptive.sqf
index 1d94b30b87..817745ece3 100644
--- a/addons/captives/functions/fnc_doEscortCaptive.sqf
+++ b/addons/captives/functions/fnc_doEscortCaptive.sqf
@@ -50,9 +50,14 @@ if (_state) then {
detach _target;
_unit removeAction _actionID;
_unit setVariable [QGVAR(escortedUnit), objNull, true];
+
+ // Public event
+ [QGVAR(escortingCaptive), [_target, false, _unit]] call CBA_fnc_localEvent;
};
}, 0, [_unit, _target, _actionID]] call CBA_fnc_addPerFrameHandler;
+ // Public event
+ [QGVAR(escortingCaptive), [_target, true, _unit]] call CBA_fnc_localEvent;
} else {
_unit setVariable [QGVAR(isEscorting), false, true];
_unit setVariable [QGVAR(escortedUnit), objNull, true];
diff --git a/addons/cargo/stringtable.xml b/addons/cargo/stringtable.xml
index c77be79035..5e42af6c13 100644
--- a/addons/cargo/stringtable.xml
+++ b/addons/cargo/stringtable.xml
@@ -310,6 +310,7 @@
Impossibile da scaricare
Ne peut pas être déchargé
降ろせません
+ 하역할 수가 없습니다
Custom Name
diff --git a/addons/common/CfgGesturesMale.hpp b/addons/common/CfgGesturesMale.hpp
new file mode 100644
index 0000000000..0d3737cb62
--- /dev/null
+++ b/addons/common/CfgGesturesMale.hpp
@@ -0,0 +1,14 @@
+// From ACRE
+class CfgGesturesMale {
+ skeletonName = "OFP2_ManSkeleton";
+ class States {
+ class GestureNod;
+ class GVAR(stop): GestureNod {
+ file = "a3\anims_f\data\anim\sdr\gst\gestureEmpty.rtm";
+ disableWeapons = 0;
+ disableWeaponsLong = 0;
+ enableOptics = 1;
+ mask = "empty";
+ };
+ };
+};
diff --git a/addons/common/CfgMoves.hpp b/addons/common/CfgMoves.hpp
index b0df9a4466..14686526e9 100644
--- a/addons/common/CfgMoves.hpp
+++ b/addons/common/CfgMoves.hpp
@@ -1,9 +1,15 @@
-
class CfgMovesBasic {
class Default;
+ // From ACRE
+ class ManActions {
+ GVAR(stop) = QGVAR(stop);
+ };
class Actions {
+ class NoActions: ManActions {
+ GVAR(stop)[] = {QGVAR(stop), "Gesture"};
+ };
+
// fixes grab animation with equipped pistol
- class NoActions;
class PistolStandActions: NoActions {
grabDrag = "AmovPercMstpSlowWrflDnon_AcinPknlMwlkSlowWrflDb_2";
};
@@ -62,8 +68,12 @@ class CfgMovesMaleSdr: CfgMovesBasic {
// fix falling back to unconsciousness animation and disable rotating in that state
class Unconscious: Default {
- ConnectTo[] = {};
+ // Prevents AI from moving torso and head when unconscious
+ aiming = "aimingNo";
+ aimingBody = "aimingUpNo";
head = "headNo";
+
+ ConnectTo[] = {};
forceAim = 1;
static = 1;
};
diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp
index 25899db1ae..ce6ac334ee 100644
--- a/addons/common/XEH_PREP.hpp
+++ b/addons/common/XEH_PREP.hpp
@@ -181,6 +181,7 @@ PREP(statusEffect_resetVariables);
PREP(statusEffect_respawnEH);
PREP(statusEffect_sendEffects);
PREP(statusEffect_set);
+PREP(stopGesture);
PREP(stringCompare);
PREP(stringToColoredText);
PREP(swayLoop);
diff --git a/addons/common/config.cpp b/addons/common/config.cpp
index 758957987e..144e7d96c6 100644
--- a/addons/common/config.cpp
+++ b/addons/common/config.cpp
@@ -4,7 +4,7 @@ class CfgPatches {
class ADDON {
name = COMPONENT_NAME;
units[] = {"ACE_Box_Misc", "ACE_bananaItem", "ACE_Flag_Black", "ACE_Flag_White"};
- weapons[] = {"ACE_ItemCore","ACE_FakePrimaryWeapon", "ACE_Banana"};
+ weapons[] = {"ACE_ItemCore", "ACE_FakePrimaryWeapon", "ACE_Banana"};
requiredVersion = REQUIRED_VERSION;
requiredAddons[] = {"ace_main","ace_modules"};
author = CSTRING(ACETeam);
@@ -17,6 +17,7 @@ class CfgPatches {
#include "CfgEden.hpp"
#include "CfgEventHandlers.hpp"
#include "CfgLocationTypes.hpp"
+#include "CfgGesturesMale.hpp"
#include "CfgMagazines.hpp"
#include "CfgMoves.hpp"
#include "CfgSounds.hpp"
diff --git a/addons/common/functions/fnc_disableUserInput.sqf b/addons/common/functions/fnc_disableUserInput.sqf
index 4037a168b7..6c58954b13 100644
--- a/addons/common/functions/fnc_disableUserInput.sqf
+++ b/addons/common/functions/fnc_disableUserInput.sqf
@@ -1,7 +1,8 @@
#include "..\script_component.hpp"
#include "\a3\ui_f_curator\ui\defineResinclDesign.inc"
+#include "\a3\ui_f\hpp\defineDIKCodes.inc"
/*
- * Author: commy2
+ * Author: commy2, johnb43
* Disables key input. ESC can still be pressed to open the menu.
*
* Arguments:
@@ -27,7 +28,7 @@ if (_state) then {
if (!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])) exitWith {};
if (!isNil QGVAR(disableInputPFH)) exitWith {};
- // end TFAR and ACRE2 radio transmissions
+ // End TFAR and ACRE2 radio transmissions
call FUNC(endRadioTransmission);
// Close map
@@ -45,38 +46,120 @@ if (_state) then {
private _map = _display displayCtrl 101;
_map ctrlMapCursor ["", QGVAR(blank)];
+ GVAR(keyboardInputMain) = createHashMap;
+ GVAR(keyboardInputCombo) = createHashMap;
+
_display displayAddEventHandler ["KeyDown", {
+ // If input is enabled again, ignore
+ if (isNil QGVAR(keyboardInputMain)) exitWith {};
+
params ["", "_key"];
- if (_key == 1 && {alive player}) then {
- createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select isMultiplayer);
+ // Get key info; Stored as [isPressed, pressedCount]
+ private _keyPressedInfo = GVAR(keyboardInputMain) getOrDefault [_key, [false, 0], true];
+ _keyPressedInfo params ["_keyPressed", "_keyPressedCount"];
+ // For regular keys: If pressed, set to release and remove one key press
+ if (!_keyPressed) then {
+ _keyPressedInfo set [0, true];
+ _keyPressedInfo set [1, _keyPressedCount + 1];
+ };
+
+ // For combo keys, register only if pushed or released (no keypress count)
+ if !(GVAR(keyboardInputCombo) getOrDefault [_key, false]) then {
+ GVAR(keyboardInputCombo) set [_key, true];
+ };
+
+ // Look if keybinds of various actions have been pressed
+ private _action = "";
+ private _comboDikPressed = false;
+ private _return = false;
+
+ // This technique has a limitation: It can't process the Escape key properly (KeyUp EH does not fire)
+ (["TeamSwitch", "CuratorInterface", "ShowMap", "DefaultAction", "Throw", "Chat", "PrevChannel", "NextChannel"] apply {
+ _action = _x;
+
+ {
+ _x params ["_mainKeyArray", "_comboKeyArray", "_isDoubleTap"];
+ _mainKeyArray params ["_mainDik", "_mainDevice"];
+
+ // If keybind doesn't contain key combo, it returns empty array; Therefore, return true
+ _comboDikPressed = if (_comboKeyArray isEqualTo []) then {
+ true
+ } else {
+ _comboKeyArray params ["_comboDik", "_comboDevice"];
+
+ _comboDevice == "KEYBOARD" && {GVAR(keyboardInputCombo) getOrDefault [_comboDik, false]}
+ };
+
+ // Check if the necessary keys were pressed for a keybind
+ _return = _comboDikPressed &&
+ {_mainDevice == "KEYBOARD"} &&
+ {((GVAR(keyboardInputMain) getOrDefault [_mainDik, [false, 0]]) select 1) > ([0, 1] select _isDoubleTap)}; // check how many times the main key was pressed
+
+ // Keybind was detected
+ if (_return) exitWith {
+ TRACE_1("Action triggered: ",_action);
+ };
+ } forEach (actionKeysEx _action);
+
+ _return
+ }) params ["_teamSwitch", "_curatorInterface", "_showMap", "_defaultAction", "_throw", "_chat", "_prevChannel", "_nextChannel"];
+
+ // Handle Escape separately because of limitation mentioned above
+ if (_key == DIK_ESCAPE && {alive player}) then {
disableSerialization;
+ private _isMultiplayer = isMultiplayer;
+ private _is3DENPreview = is3DENPreview;
+
+ createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select _isMultiplayer);
+
private _dlg = findDisplay 49;
for "_index" from 100 to 2000 do {
(_dlg displayCtrl _index) ctrlEnable false;
};
- private _ctrl = _dlg displayctrl 103;
- _ctrl ctrlSetEventHandler ["buttonClick", QUOTE(while {!isNull (uiNamespace getVariable [ARR_2(QUOTE(QGVAR(dlgDisableMouse)),displayNull)])} do {closeDialog 0}; failMission 'LOSER'; [false] call DFUNC(disableUserInput))];
- _ctrl ctrlEnable true;
- _ctrl ctrlSetText "ABORT";
- _ctrl ctrlSetTooltip "Abort.";
+ private _ctrl = _dlg displayCtrl 103;
+ _ctrl ctrlSetEventHandler ["ButtonClick", toString {
+ while {!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])} do {
+ closeDialog 0
+ };
- _ctrl = _dlg displayctrl ([104, 1010] select isMultiplayer);
- if (["ace_medical"] call FUNC(isModLoaded)) then {
- _ctrl ctrlSetEventHandler ["buttonClick", 'closeDialog 0; [player, "respawn_button"] call EFUNC(medical_status,setDead); [false] call DFUNC(disableUserInput);'];
- } else {
- _ctrl ctrlSetEventHandler ["buttonClick", QUOTE(closeDialog 0; player setDamage 1; [false] call DFUNC(disableUserInput))];
- };
- _ctrl ctrlEnable ((getMissionConfigValue ["respawnButton", -1]) != 0); // handles 3den attribute or description.ext
- _ctrl ctrlSetText localize "$str_3den_multiplayer_attributecategory_respawn_displayname";
- _ctrl ctrlSetTooltip "Respawn.";
+ failMission "LOSER";
+
+ [false] call FUNC(disableUserInput);
+ }];
+ _ctrl ctrlEnable true;
+ _ctrl ctrlSetText localize (["str_disp_int_abort", "STR_3DEN_RscDisplayInterrupt_ButtonAbort_3DEN_text"] select (_is3DENPreview && !_isMultiplayer));
+ _ctrl ctrlSetTooltip localize ([
+ "STR_TOOLTIP_MAIN_ABORT_CAMPAIGN",
+ "STR_3DEN_RscDisplayInterrupt_ButtonAbort_3DEN_tooltip",
+ "STR_TOOLTIP_MAIN_ABORT"
+ ] select (([_is3DENPreview, _isMultiplayer] call FUNC(toBitmask)) min 2));
+
+ _ctrl = _dlg displayCtrl ([104, 1010] select _isMultiplayer);
+ _ctrl ctrlSetEventHandler ["ButtonClick", toString {
+ closeDialog 0;
+
+ if (["ace_medical"] call FUNC(isModLoaded)) then {
+ [player, "respawn_button"] call EFUNC(medical_status,setDead);
+ } else {
+ player setDamage 1;
+ };
+
+ [false] call FUNC(disableUserInput);
+ }];
+
+ private _respawnEnabled = (getMissionConfigValue ["respawnButton", -1]) != 0;
+
+ _ctrl ctrlEnable _respawnEnabled; // handles 3den attribute or description.ext
+ _ctrl ctrlSetText localize "str_disp_int_respawn";
+ _ctrl ctrlSetTooltip localize (["str_3den_attributes_respawn_none_tooltip", "str_disp_int_respawn"] select _respawnEnabled);
};
- if (_key in actionKeys "TeamSwitch" && {teamSwitchEnabled}) then {
+ if (_teamSwitch && teamSwitchEnabled) then {
(uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
private _acc = accTime;
@@ -84,18 +167,20 @@ if (_state) then {
setAccTime _acc;
};
- if (_key in actionKeys "CuratorInterface" && {getAssignedCuratorLogic player in allCurators}) then {
+ if (_curatorInterface && {!isNull getAssignedCuratorLogic player}) then {
(uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
+
openCuratorInterface;
};
- if (_key in actionKeys "ShowMap" && {player getVariable ["ACE_canSwitchUnits", false]}) then {
+ if (_showMap && {player getVariable ["ACE_canSwitchUnits", false]}) then {
(uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
+
openMap true;
};
- if (isServer || {serverCommandAvailable "#kick"}) then {
- if (!(_key in (actionKeys "DefaultAction" + actionKeys "Throw")) && {_key in (actionKeys "Chat" + actionKeys "PrevChannel" + actionKeys "NextChannel")}) then {
+ if (isMultiplayer && {isServer || {serverCommandAvailable "#kick"}}) then {
+ if (!(_defaultAction || _throw) && {_chat || _prevChannel || _nextChannel}) then {
_key = 0;
};
};
@@ -103,7 +188,41 @@ if (_state) then {
_key > 0
}];
- _display displayAddEventHandler ["KeyUp", {true}];
+ _display displayAddEventHandler ["KeyUp", {
+ // If input is enabled again, ignore
+ if (isNil QGVAR(keyboardInputMain)) exitWith {};
+
+ params ["", "_key"];
+
+ // For combo keys: If pressed, release
+ if (GVAR(keyboardInputCombo) getOrDefault [_key, false]) then {
+ GVAR(keyboardInputCombo) deleteAt _key;
+ };
+
+ private _keyPressedInfo = GVAR(keyboardInputMain) getOrDefault [_key, [false, 0]];
+
+ // If pressed, release it
+ if (_keyPressedInfo select 0) then {
+ _keyPressedInfo set [0, false];
+ };
+
+ // Cache keystrokes of regular keys for a small amount of time
+ [{
+ // If input is enabled again, ignore
+ if (isNil QGVAR(keyboardInputMain)) exitWith {};
+
+ params ["_key"];
+
+ private _keyPressedInfo = GVAR(keyboardInputMain) getOrDefault [_key, [false, 0]];
+
+ // Release it
+ _keyPressedInfo set [1, ((_keyPressedInfo select 1) - 1) max 0];
+
+ if (_keyPressedInfo isEqualTo [false, 0]) then {
+ GVAR(keyboardInputMain) deleteAt _key,
+ };
+ }, _key, 0.5] call CBA_fnc_waitAndExecute;
+ }];
};
GVAR(disableInputPFH) = [{
@@ -133,4 +252,7 @@ if (_state) then {
};
(uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
+
+ GVAR(keyboardInputMain) = nil;
+ GVAR(keyboardInputCombo) = nil;
};
diff --git a/addons/common/functions/fnc_isModLoaded.sqf b/addons/common/functions/fnc_isModLoaded.sqf
index fb7b1807b6..b070b39b38 100644
--- a/addons/common/functions/fnc_isModLoaded.sqf
+++ b/addons/common/functions/fnc_isModLoaded.sqf
@@ -4,24 +4,17 @@
* Check in CfgPatches if modification is loaded
*
* Arguments:
- * 0: Mod Name or Classname of the mod in CfgPatches
+ * 0: Classname of the mod in CfgPatches
*
* Return Value:
- * if modification is loaded
+ * If modification is loaded
*
* Example:
- * ["class"] call ace_common_fnc_isModLoaded
+ * "class" call ace_common_fnc_isModLoaded
*
* Public: Yes
*/
params [["_modName", "", [""]]];
-private _return = GVAR(isModLoadedCache) get _modName;
-
-if (isNil "_return") then {
- _return = isClass (configFile >> "CfgPatches" >> _modName);
- GVAR(isModLoadedCache) set [_modName, _return];
-};
-
-_return
+GVAR(isModLoadedCache) getOrDefaultCall [toLowerANSI _modName, {isClass (configFile >> "CfgPatches" >> _modName)}, true]
diff --git a/addons/common/functions/fnc_stopGesture.sqf b/addons/common/functions/fnc_stopGesture.sqf
new file mode 100644
index 0000000000..53e319b04b
--- /dev/null
+++ b/addons/common/functions/fnc_stopGesture.sqf
@@ -0,0 +1,20 @@
+#include "..\script_component.hpp"
+/*
+ * Author: ACRE2Team
+ * Stops a unit's gesture.
+ *
+ * Arguments:
+ * 0: Target