diff --git a/addons/advanced_fatigue/stringtable.xml b/addons/advanced_fatigue/stringtable.xml
index dc68259db8..af25a7c181 100644
--- a/addons/advanced_fatigue/stringtable.xml
+++ b/addons/advanced_fatigue/stringtable.xml
@@ -192,6 +192,7 @@
Verwacklungsfaktor, wenn aufgelegt
Fattore di Oscillazione Appoggiato
静止時の手ぶれ係数
+ Коэффициент колебания в состоянии покоя
Influences the amount of weapon sway while weapon is rested.
@@ -201,6 +202,7 @@
Beeinflusst, wie ruhig man die Waffe hält, während sie aufgelegt ist.
Determina la quantità di oscillazione dell'arma quando questa è appoggiata.
静止している時の武器の手ぶれの量に影響します。
+ Влияет на величину колебания оружия в состоянии покоя.
Deployed sway factor
@@ -210,6 +212,7 @@
Verwacklungsfaktor, wenn Zweibein aufgestellt ist.
Fattore di Oscillazione su Bipode
展開時の手ぶれ係数
+ Коэффициент колебания при развертывании
Influences the amount of weapon sway while weapon is deployed.
@@ -219,6 +222,7 @@
Beeinflusst, wie ruhig man die Waffen hält, während das Zweibein aufgestellt ist.
Determina la quantità di oscillazione dell'arma quando questa è stabilizzata usando il bipode.
武器の展開(Cキー)時の武器の手ぶれの量に影響します。
+ Влияет на величину колебания оружия при его развертывании.
Enabled
diff --git a/addons/ai/stringtable.xml b/addons/ai/stringtable.xml
index 12c9c8d73f..821d42fd27 100644
--- a/addons/ai/stringtable.xml
+++ b/addons/ai/stringtable.xml
@@ -90,6 +90,7 @@
Equipement JVN automatique
Equipar NVGs automaticamente
暗視装置の自動装備
+ Автоматическое оснащение ПНВ
Equips NVG in inventory during night time and unequips it during day time.\nDoes not add NVGs to inventory!
@@ -100,6 +101,7 @@
Equipe des JVN pendant la nuit et les déséquipe le jour.\nN'ajoute pas les JVN dans l'intenvaire !
Equipa o NVG do inventário durante a noite e desequipa durante o dia.\nNão adiciona NVGs ao inventário!
インベントリ内の暗視装置を夜間に装備し、日中は解除し収納します。\nこれはNVGをインベントリに追加しません。
+ Оснащает ПНВ в инвентаре в ночное время и отключает его в дневное время.\nНе добавляет ПНВ в инвентарь!
diff --git a/addons/arsenal/Cfg3DEN.hpp b/addons/arsenal/Cfg3DEN.hpp
index f119af364b..1cec4a9c75 100644
--- a/addons/arsenal/Cfg3DEN.hpp
+++ b/addons/arsenal/Cfg3DEN.hpp
@@ -110,7 +110,7 @@ class Cfg3DEN {
h = QUOTE(65 * ATTRIBUTE_H);
drawSideArrows = 1;
disableOverflow = 1;
- columns[] = {0.05, 0.15, 0.85};
+ columns[] = {0.05, 0.15, 0.83, 0.87};
};
class ArrowLeft: ctrlButton {
idc = IDC_ATTRIBUTE_LIST_LEFT;
diff --git a/addons/arsenal/XEH_postInit.sqf b/addons/arsenal/XEH_postInit.sqf
index 33646a25d7..7c7c677819 100644
--- a/addons/arsenal/XEH_postInit.sqf
+++ b/addons/arsenal/XEH_postInit.sqf
@@ -70,7 +70,7 @@ GVAR(lastSortDirectionRight) = DESCENDING;
if (!isNil QGVAR(currentLoadoutsTab) && {GVAR(currentLoadoutsTab) == IDC_buttonSharedLoadouts}) then {
private _curSelData = _contentPanelCtrl lnbData [lnbCurSelRow _contentPanelCtrl, 1];
- ([_loadoutData] call FUNC(verifyLoadout)) params ["_extendedLoadout", "_nullItemsAmount", "_unavailableItemsAmount"];
+ ([_loadoutData] call FUNC(verifyLoadout)) params ["_extendedLoadout", "_nullItemsList", "_unavailableItemsList"];
_extendedLoadout params ["_loadout"];
private _newRow = _contentPanelCtrl lnbAddRow [_playerName, _loadoutName];
@@ -81,10 +81,10 @@ GVAR(lastSortDirectionRight) = DESCENDING;
_contentPanelCtrl lnbSetData [[_newRow, 1], _playerName + _loadoutName];
// Set color of row, depending if items are unavailable/missing
- if (_nullItemsAmount > 0) then {
+ if (_nullItemsList isNotEqualTo []) then {
_contentPanelCtrl lnbSetColor [[_newRow, 1], [1, 0, 0, 0.8]];
} else {
- if (_unavailableItemsAmount > 0) then {
+ if (_unavailableItemsList isNotEqualTo []) then {
_contentPanelCtrl lnbSetColor [[_newRow, 1], [1, 1, 1, 0.25]];
};
};
@@ -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
@@ -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
diff --git a/addons/arsenal/XEH_preInit.sqf b/addons/arsenal/XEH_preInit.sqf
index 0227e18f0a..10cc3989e9 100644
--- a/addons/arsenal/XEH_preInit.sqf
+++ b/addons/arsenal/XEH_preInit.sqf
@@ -48,4 +48,47 @@ call FUNC(compileStats);
// Setup Tools tab
[keys (uiNamespace getVariable [QGVAR(configItemsTools), createHashMap]), LLSTRING(toolsTab), TOOLS_TAB_ICON, -1, true] call FUNC(addRightPanelButton);
+// TODO: make IDCs able to match IDX with simple math?
+GVAR(idxMap) = createHashMapFromArray [
+ [IDC_buttonPrimaryWeapon, IDX_VIRT_PRIMARY_WEAPONS],
+ [IDC_buttonHandgun, IDX_VIRT_HANDGUN_WEAPONS],
+ [IDC_buttonSecondaryWeapon, IDX_VIRT_SECONDARY_WEAPONS],
+ [IDC_buttonHeadgear, IDX_VIRT_HEADGEAR],
+ [IDC_buttonUniform, IDX_VIRT_UNIFORM],
+ [IDC_buttonVest, IDX_VIRT_VEST],
+ [IDC_buttonBackpack, IDX_VIRT_BACKPACK],
+ [IDC_buttonGoggles, IDX_VIRT_GOGGLES],
+ [IDC_buttonNVG, IDX_VIRT_NVG],
+ [IDC_buttonBinoculars, IDX_VIRT_BINO],
+ [IDC_buttonMap, IDX_VIRT_MAP],
+ [IDC_buttonGPS, IDX_VIRT_COMMS],
+ [IDC_buttonRadio, IDX_VIRT_RADIO],
+ [IDC_buttonCompass, IDX_VIRT_COMPASS],
+ [IDC_buttonWatch, IDX_VIRT_WATCH]
+];
+
+// Make new hashmaps for face/voice/insignia so mission makers can disable them
+// Copies of hashmaps aren't final
+GVAR(faceCache) = +(uiNamespace getVariable QGVAR(faceCache));
+GVAR(voiceCache) = +(uiNamespace getVariable QGVAR(voiceCache));
+GVAR(insigniaCache) = +(uiNamespace getVariable QGVAR(insigniaCache));
+
+// Get mission/campaign insignias
+// BIS_fnc_setUnitInsignia will look in mission config, then campaign, then global config last, so overwrite accordingly
+private _insigniaCondition = toString {
+ if (isNumber (_x >> "scope")) then {
+ getNumber (_x >> "scope") == 2
+ } else {
+ true
+ };
+};
+
+// Ref fnc_addListBoxItem, 0/nil = configFile, 1 = campaignConfigFile, 2 = missionConfigFile
+{
+ GVAR(insigniaCache) set [_x, 1];
+} forEach (_insigniaCondition configClasses (campaignConfigFile >> "CfgUnitInsignia"));
+{
+ GVAR(insigniaCache) set [_x, 2];
+} forEach (_insigniaCondition configClasses (missionConfigFile >> "CfgUnitInsignia"));
+
ADDON = true;
diff --git a/addons/arsenal/defines.hpp b/addons/arsenal/defines.hpp
index ac84f0d8a4..cd6d937426 100644
--- a/addons/arsenal/defines.hpp
+++ b/addons/arsenal/defines.hpp
@@ -270,6 +270,7 @@
#define IDX_VIRT_UNIQUE_UNKNOWN_ITEMS 25
// Indexes of current items array
+// Should match IDX_VIRT_X macros for any left panel tabs
#define IDX_CURR_PRIMARY_WEAPON 0
#define IDX_CURR_SECONDARY_WEAPON 1
#define IDX_CURR_HANDGUN_WEAPON 2
@@ -489,3 +490,6 @@ if (!isNil QGVAR(customRightPanelButtons)) then {\
_contentPanelCtrl lnbSetPicture [[_newRow, 7], getText (configFile >> "CfgVehicles" >> (_loadout select IDX_LOADOUT_BACKPACK) select 0 >> "picture")];\
_contentPanelCtrl lnbSetPicture [[_newRow, 8], getText (_cfgWeapons >> _loadout select IDX_LOADOUT_HEADGEAR >> "picture")];\
_contentPanelCtrl lnbSetPicture [[_newRow, 9], getText (configFile >> "CfgGlasses" >> _loadout select IDX_LOADOUT_GOGGLES >> "picture")];
+
+#define ACTION_TYPE_TEXT 0
+#define ACTION_TYPE_BUTTON 1
diff --git a/addons/arsenal/functions/fnc_addAction.sqf b/addons/arsenal/functions/fnc_addAction.sqf
index 05557f159a..b04d56729a 100644
--- a/addons/arsenal/functions/fnc_addAction.sqf
+++ b/addons/arsenal/functions/fnc_addAction.sqf
@@ -1,4 +1,5 @@
#include "..\script_component.hpp"
+#include "..\defines.hpp"
/*
* Author: johnb43
* Adds custom action buttons.
diff --git a/addons/arsenal/functions/fnc_addListBoxItem.sqf b/addons/arsenal/functions/fnc_addListBoxItem.sqf
index 2852aa7232..4368eb6ea1 100644
--- a/addons/arsenal/functions/fnc_addListBoxItem.sqf
+++ b/addons/arsenal/functions/fnc_addListBoxItem.sqf
@@ -6,9 +6,10 @@
*
* Arguments:
* 0: Config category, must be "CfgWeapons", "CfgVehicles", "CfgMagazines", "CfgVoice" or "CfgUnitInsignia"
- * 1: Classname
+ * 1: Classname (must be in config case)
* 2: Panel control
* 3: Name of the picture entry in that Cfg class (default: "picture")
+ * 4: Config root (default: 0 -> configFile)
*
* Return Value:
* None
@@ -19,7 +20,7 @@
* Public: Yes
*/
-params ["_configCategory", "_className", "_ctrlPanel", ["_pictureEntryName", "picture", [""]]];
+params ["_configCategory", "_className", "_ctrlPanel", ["_pictureEntryName", "picture", [""]], ["_configRoot", 0, [0]]];
private _skip = GVAR(favoritesOnly) && {!(_className in GVAR(currentItems))} && {!((toLower _className) in GVAR(favorites))};
if (_skip) then {
@@ -41,10 +42,10 @@ if (_skip) then {
if (_skip) exitWith {};
-// Sanitise key, as it's public; If not in cache, find info and cache it for later use
-((uiNamespace getVariable QGVAR(addListBoxItemCache)) getOrDefaultCall [_configCategory + _className, {
+// 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 >> _configCategory >> _className;
+ private _configPath = ([configFile, campaignConfigFile, missionConfigFile] select _configRoot) >> _configCategory >> _className;
private _dlcName = _configPath call EFUNC(common,getAddon);
// If _pictureEntryName is empty, then this item has no picture (e.g. faces)
diff --git a/addons/arsenal/functions/fnc_attributeAddItems.sqf b/addons/arsenal/functions/fnc_attributeAddItems.sqf
index 5457a920a2..612e894a15 100644
--- a/addons/arsenal/functions/fnc_attributeAddItems.sqf
+++ b/addons/arsenal/functions/fnc_attributeAddItems.sqf
@@ -46,6 +46,7 @@ private _cfgWeapons = configFile >> "CfgWeapons";
private _cfgMagazines = configFile >> "CfgMagazines";
private _cfgVehicles = configFile >> "CfgVehicles";
private _cfgGlasses = configFile >> "CfgGlasses";
+private _dlcName = "";
// Exit with current items (no specific category)
if (_category == IDX_CAT_ALL) exitWith {
@@ -73,6 +74,12 @@ if (_category == IDX_CAT_ALL) exitWith {
_listbox lnbSetData [[_index, 1], _x];
_listbox lnbSetPicture [[_index, 0], getText (_config >> "picture")];
_listbox lnbSetTooltip [[_index, 0], _x];
+
+ _dlcName = _config call EFUNC(common,getAddon);
+
+ if (_dlcName != "") then {
+ _listbox lnbSetPicture [[_index, 2], (modParams [_dlcName, ["logo"]]) param [0, ""]];
+ };
};
} forEach _attributeItems;
@@ -130,12 +137,20 @@ private _config = _cfgClass;
_alpha = 0.5;
};
- _index = _listbox lnbAddRow ["", _displayName, _symbol];
+ _index = _listbox lnbAddRow ["", _displayName, "", _symbol];
_listbox lnbSetData [[_index, 1], _x];
_listbox lnbSetPicture [[_index, 0], getText (_config >> _x >> "picture")];
_listbox lnbSetTooltip [[_index, 0], _x];
_listbox lnbSetColor [[_index, 1], [1, 1, 1, _alpha]];
- _listbox lnbSetColor [[_index, 2], [1, 1, 1, _alpha]];
+ _listbox lnbSetColor [[_index, 3], [1, 1, 1, _alpha]];
+
+ // Mod icon is in column 2
+ _dlcName = (_config >> _x) call EFUNC(common,getAddon);
+
+ if (_dlcName != "") then {
+ _listbox lnbSetPicture [[_index, 2], (modParams [_dlcName, ["logo"]]) param [0, ""]];
+ _listbox lnbSetPictureColor [[_index, 2], [1, 1, 1, _alpha]];
+ };
};
} forEach (keys _categoryItems);
diff --git a/addons/arsenal/functions/fnc_attributeSelect.sqf b/addons/arsenal/functions/fnc_attributeSelect.sqf
index 5aeb46c5a4..2f9df7775e 100644
--- a/addons/arsenal/functions/fnc_attributeSelect.sqf
+++ b/addons/arsenal/functions/fnc_attributeSelect.sqf
@@ -35,9 +35,10 @@ if (_addItem && {_itemIndex == -1}) exitWith {
_attributeItems pushBack _itemClassname;
// Change symbol and increase alpha
- _listbox lnbSetText [[_currentRow, 2], [SYMBOL_ITEM_VIRTUAL, SYMBOL_ITEM_REMOVE] select _attributeMode];
+ _listbox lnbSetText [[_currentRow, 3], [SYMBOL_ITEM_VIRTUAL, SYMBOL_ITEM_REMOVE] select _attributeMode];
_listbox lnbSetColor [[_currentRow, 1], [1, 1, 1, 1]];
- _listbox lnbSetColor [[_currentRow, 2], [1, 1, 1, 1]];
+ _listbox lnbSetPictureColor [[_currentRow, 2], [1, 1, 1, 1]]; // mod icon is in column 2
+ _listbox lnbSetColor [[_currentRow, 3], [1, 1, 1, 1]];
};
// Remove item if in list
@@ -45,7 +46,8 @@ if (!_addItem && {_itemIndex != -1}) exitWith {
_attributeItems deleteAt _itemIndex;
// Change symbol and reduce alpha
- _listbox lnbSetText [[_currentRow, 2], SYMBOL_ITEM_NONE];
+ _listbox lnbSetText [[_currentRow, 3], SYMBOL_ITEM_NONE];
_listbox lnbSetColor [[_currentRow, 1], [1, 1, 1, 0.5]];
- _listbox lnbSetColor [[_currentRow, 2], [1, 1, 1, 0.5]];
+ _listbox lnbSetPictureColor [[_currentRow, 2], [1, 1, 1, 0.5]]; // mod icon is in column 2
+ _listbox lnbSetColor [[_currentRow, 3], [1, 1, 1, 0.5]];
};
diff --git a/addons/arsenal/functions/fnc_compileActions.sqf b/addons/arsenal/functions/fnc_compileActions.sqf
index cec152bd6a..9001a5558a 100644
--- a/addons/arsenal/functions/fnc_compileActions.sqf
+++ b/addons/arsenal/functions/fnc_compileActions.sqf
@@ -1,4 +1,5 @@
#include "..\script_component.hpp"
+#include "..\defines.hpp"
/*
* Author: Brett Mayson
* Create the internal actions arrays when needed for the first time.
diff --git a/addons/arsenal/functions/fnc_fillLeftPanel.sqf b/addons/arsenal/functions/fnc_fillLeftPanel.sqf
index 26f872dfdf..1eb98d29ec 100644
--- a/addons/arsenal/functions/fnc_fillLeftPanel.sqf
+++ b/addons/arsenal/functions/fnc_fillLeftPanel.sqf
@@ -1,7 +1,7 @@
#include "..\script_component.hpp"
#include "..\defines.hpp"
/*
- * Author: Alganthe, johnb43
+ * Author: Alganthe, johnb43, LinkIsGrim
* Fills left panel.
*
* Arguments:
@@ -17,21 +17,28 @@
params ["_display", "_control", ["_animate", true]];
+private _ctrlIDC = ctrlIDC _control;
+private _ctrlPanel = _display displayCtrl IDC_leftTabContent;
+private _idxVirt = GVAR(idxMap) getOrDefault [_ctrlIDC, -1, true];
+
// Fade old control background
if (!isNil QGVAR(currentLeftPanel)) then {
private _previousCtrlBackground = _display displayCtrl (GVAR(currentLeftPanel) - 1);
_previousCtrlBackground ctrlSetFade 1;
_previousCtrlBackground ctrlCommit ([0, FADE_DELAY] select _animate);
+
+ // When switching tabs, clear searchbox
+ if (GVAR(currentLeftPanel) != _ctrlIDC) then {
+ (_display displayCtrl IDC_leftSearchbar) ctrlSetText "";
+ (_display displayCtrl IDC_rightSearchbar) ctrlSetText "";
+ };
};
// Show new control background
-private _ctrlIDC = ctrlIDC _control;
private _ctrlBackground = _display displayCtrl (_ctrlIDC - 1);
_ctrlBackground ctrlSetFade 0;
_ctrlBackground ctrlCommit ([0, FADE_DELAY] select _animate);
-private _ctrlPanel = _display displayCtrl IDC_leftTabContent;
-
// Force a "refresh" animation of the panel
if (_animate) then {
_ctrlPanel ctrlSetFade 1;
@@ -41,212 +48,82 @@ if (_animate) then {
};
_ctrlPanel lbSetCurSel -1;
+// Purge old data
+lbClear _ctrlPanel;
-// Handle icons and filling
-private _selectedItem = switch (true) do {
- // Primary weapons, secondary weapons, handgun weapons
- case (_ctrlIDC in [IDC_buttonPrimaryWeapon, IDC_buttonHandgun, IDC_buttonSecondaryWeapon]): {
- // Purge old data
- lbClear _ctrlPanel;
-
- // Add "Empty" entry
- private _addEmpty = _ctrlPanel lbAdd format [" <%1>", localize "str_empty"];
- _ctrlPanel lbSetValue [_addEmpty, -1];
-
- // Add selected tab's weapons
- private _index = [IDC_buttonPrimaryWeapon, IDC_buttonSecondaryWeapon, IDC_buttonHandgun] find _ctrlIDC;
-
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys ((GVAR(virtualItems) get IDX_VIRT_WEAPONS) get _index));
-
- GVAR(currentItems) select _index
- };
- // Uniforms, vests, backpacks
- case (_ctrlIDC in [IDC_buttonUniform, IDC_buttonVest, IDC_buttonBackpack]): {
- // Purge old data
- lbClear _ctrlPanel;
-
- // Add "Empty" entry
- private _addEmpty = _ctrlPanel lbAdd format [" <%1>", localize "str_empty"];
- _ctrlPanel lbSetValue [_addEmpty, -1];
-
- switch (_ctrlIDC) do {
- // Add uniforms
- case IDC_buttonUniform: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIFORM));
-
- GVAR(currentItems) select IDX_CURR_UNIFORM
- };
- // Add vests
- case IDC_buttonVest: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_VEST));
-
- GVAR(currentItems) select IDX_CURR_VEST
- };
- // Add backpacks
- case IDC_buttonBackpack: {
- {
- ["CfgVehicles", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_BACKPACK));
-
- GVAR(currentItems) select IDX_CURR_BACKPACK
- };
- };
- };
- // Other
- default {
- // Don't reset right panel selection if left tab is binos
- if (_ctrlIDC != IDC_buttonBinoculars) then {
- GVAR(currentRightPanel) = nil;
- };
-
- lbClear _ctrlPanel;
-
- // For every left tab except faces and voices, add "Empty" entry
- if !(_ctrlIDC in [IDC_buttonFace, IDC_buttonVoice]) then {
- private _addEmpty = _ctrlPanel lbAdd format [" <%1>", localize "str_empty"];
- _ctrlPanel lbSetValue [_addEmpty, -1];
- };
-
- switch (_ctrlIDC) do {
- // Headgear
- case IDC_buttonHeadgear: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_HEADGEAR));
-
- GVAR(currentItems) select IDX_CURR_HEADGEAR
- };
- // Facewear
- case IDC_buttonGoggles: {
- {
- ["CfgGlasses", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_GOGGLES));
-
- GVAR(currentItems) select IDX_CURR_GOGGLES
- };
- // NVGs
- case IDC_buttonNVG: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_NVG));
-
- GVAR(currentItems) select IDX_CURR_NVG
- };
- // Binoculars
- case IDC_buttonBinoculars: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_BINO));
-
- GVAR(currentItems) select IDX_CURR_BINO
- };
- // Maps
- case IDC_buttonMap: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_MAP));
-
- GVAR(currentItems) select IDX_CURR_MAP
- };
- // Compasses
- case IDC_buttonCompass: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_COMPASS));
-
- GVAR(currentItems) select IDX_CURR_COMPASS
- };
- // Radios
- case IDC_buttonRadio: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_RADIO));
-
- GVAR(currentItems) select IDX_CURR_RADIO
- };
- // Watches
- case IDC_buttonWatch: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_WATCH));
-
- GVAR(currentItems) select IDX_CURR_WATCH
- };
- // GPS and UAV Terminals
- case IDC_buttonGPS: {
- {
- ["CfgWeapons", _x, _ctrlPanel] call FUNC(addListBoxItem);
- } forEach (keys (GVAR(virtualItems) get IDX_VIRT_COMMS));
-
- GVAR(currentItems) select IDX_CURR_COMMS
- };
- // Faces
- case IDC_buttonFace: {
- private _lbAdd = -1;
-
- {
- _y params ["_displayName", "_modPicture"];
-
- _lbAdd = _ctrlPanel lbAdd _displayName;
- _ctrlPanel lbSetData [_lbAdd, _x];
- _ctrlPanel lbSetTooltip [_lbAdd, format ["%1\n%2", _displayName, _x]];
- _ctrlPanel lbSetPictureRight [_lbAdd, ["", _modPicture] select GVAR(enableModIcons)];
- } forEach (uiNamespace getVariable QGVAR(faceCache));
-
- GVAR(currentFace)
- };
- // Voices
- case IDC_buttonVoice: {
- {
- ["CfgVoice", _x, _ctrlPanel, "icon"] call FUNC(addListBoxItem);
- } forEach (uiNamespace getVariable QGVAR(voiceCache));
-
- GVAR(currentVoice)
- };
- // Insignia
- case IDC_buttonInsignia: {
- // Insignia from config
- {
- ["CfgUnitInsignia", _x, _ctrlPanel, "texture"] call FUNC(addListBoxItem);
- } forEach (uiNamespace getVariable QGVAR(insigniaCache));
-
- private _displayName = "";
- private _className = "";
- private _lbAdd = -1;
-
- // Insignia from mission file
- {
- _className = configName _x;
- _displayName = getText (_x >> "displayName");
- _lbAdd = _ctrlPanel lbAdd _displayName;
-
- _ctrlPanel lbSetData [_lbAdd, _className];
- _ctrlPanel lbSetPicture [_lbAdd, getText (_x >> "texture")];
- _ctrlPanel lbSetTooltip [_lbAdd, format ["%1\n%2", _displayName, _className]];
- } forEach ("(if (isNumber (_x >> 'scope')) then {getNumber (_x >> 'scope')} else {2}) == 2" configClasses (missionConfigFile >> "CfgUnitInsignia"));
-
- GVAR(currentInsignia)
- };
- // Unknown
- default {""};
- };
- };
+// For every left tab except faces and voices, add "Empty" entry
+if !(_ctrlIDC in [IDC_buttonFace, IDC_buttonVoice]) then {
+ private _addEmpty = _ctrlPanel lbAdd format [" <%1>", localize "str_empty"];
+ _ctrlPanel lbSetValue [_addEmpty, -1];
};
-// When switching tabs, clear searchbox
-if (GVAR(currentLeftPanel) != _ctrlIDC) then {
- (_display displayCtrl IDC_leftSearchbar) ctrlSetText "";
- (_display displayCtrl IDC_rightSearchbar) ctrlSetText "";
+// Don't reset the current right panel for weapons, binos and containers
+if !(_idxVirt in [IDX_VIRT_PRIMARY_WEAPONS, IDX_VIRT_SECONDARY_WEAPONS, IDX_VIRT_HANDGUN_WEAPONS, IDX_VIRT_BINO, IDX_VIRT_UNIFORM, IDX_VIRT_VEST, IDX_VIRT_BACKPACK]) then {
+ GVAR(currentRightPanel) = nil;
+};
+GVAR(currentLeftPanel) = _ctrlIDC;
+
+// Add items to the listbox
+private _selectedItem = if (_idxVirt != -1) then { // Items
+ private _configParent = switch (_idxVirt) do {
+ case IDX_VIRT_GOGGLES: {"CfgGlasses"};
+ case IDX_VIRT_BACKPACK: {"CfgVehicles"};
+ default {"CfgWeapons"};
+ };
+
+ private _items = if (_idxVirt < IDX_VIRT_HEADGEAR) then {
+ keys ((GVAR(virtualItems) get IDX_VIRT_WEAPONS) get _idxVirt)
+ } else {
+ keys (GVAR(virtualItems) get _idxVirt)
+ };
+
+ {
+ [_configParent, _x, _ctrlPanel] call FUNC(addListBoxItem);
+ } forEach _items;
+
+ GVAR(currentItems) select _idxVirt
+} else { // Special cases
+ switch (_ctrlIDC) do {
+ // Faces
+ case IDC_buttonFace: {
+ private _lbAdd = -1; // micro-optimization
+ // Faces need to be added like this because their config path is
+ // configFile >> "CfgFaces" >> face category >> className
+ {
+ _y params ["_displayName", "_modPicture"];
+ _lbAdd = _ctrlPanel lbAdd _displayName;
+ _ctrlPanel lbSetData [_lbAdd, _x];
+ _ctrlPanel lbSetTooltip [_lbAdd, format ["%1\n%2", _displayName, _x]];
+ _ctrlPanel lbSetPictureRight [_lbAdd, ["", _modPicture] select GVAR(enableModIcons)];
+ } forEach GVAR(faceCache); // HashMap, not array
+
+ GVAR(currentFace)
+ };
+ // Voices
+ case IDC_buttonVoice: {
+ {
+ ["CfgVoice", _x, _ctrlPanel, "icon"] call FUNC(addListBoxItem);
+ } forEach (keys GVAR(voiceCache));
+
+ GVAR(currentVoice)
+ };
+ // Insignia
+ case IDC_buttonInsignia: {
+ {
+ ["CfgUnitInsignia", _x, _ctrlPanel, "texture", _y] call FUNC(addListBoxItem);
+ } forEach GVAR(insigniaCache);
+
+ GVAR(currentInsignia)
+ };
+ // Unknown
+ default {
+ WARNING_1("Unknown arsenal left panel with IDC %1, update ace_arsenal_idxMap and relevant macros if adding a new tab",_ctrlIDC);
+ ""
+ };
+ };
};
// Trigger event
-GVAR(currentLeftPanel) = _ctrlIDC;
[QGVAR(leftPanelFilled), [_display, _ctrlIDC, GVAR(currentRightPanel)]] call CBA_fnc_localEvent;
// Sort
diff --git a/addons/arsenal/functions/fnc_fillLoadoutsList.sqf b/addons/arsenal/functions/fnc_fillLoadoutsList.sqf
index 7d5152dfdd..6174193b73 100644
--- a/addons/arsenal/functions/fnc_fillLoadoutsList.sqf
+++ b/addons/arsenal/functions/fnc_fillLoadoutsList.sqf
@@ -1,12 +1,16 @@
#include "..\script_component.hpp"
#include "..\defines.hpp"
/*
- * Author: Alganthe, johnb43
- * Fill loadouts list.
+ * Author: Alganthe, johnb43, LinkIsGrim
+ * Fill loadouts list over multiple frames. LOADOUTS_PER_FRAME macro does what it says on the tin.
+ * Should only ever be called by display load (with optional params as default) and by itself.
+ * Listen to ace_arsenal_loadoutsListFilled event if you need to iterate over the loadouts list.
*
* Arguments:
* 0: Loadouts display
* 1: Tab control
+ * 2: Current frame filling loadouts list (default: 0)
+ * 3: Frames necessary to fill loadouts list (default: -1)
*
* Return Value:
* None
@@ -14,29 +18,46 @@
* Public: No
*/
-params ["_display", "_control"];
+// Can just be modified directly, no further setup needed
+#define LOADOUTS_PER_FRAME 10
-(_display displayCtrl IDC_textEditBox) ctrlSetText "";
+params ["_display", "_control", ["_currentFrame", 0], ["_framesToFill", -1]];
+
+if (isNull _display) exitWith {
+ TRACE_2("display closed, aborting",_currentFrame,_framesToFill);
+};
private _contentPanelCtrl = _display displayCtrl IDC_contentPanel;
+if (_currentFrame == 0) then {
+ (_display displayCtrl IDC_textEditBox) ctrlSetText "";
-// Force a "refresh" animation of the panel
-_contentPanelCtrl ctrlSetFade 1;
-_contentPanelCtrl ctrlCommit 0;
-_contentPanelCtrl ctrlSetFade 0;
-_contentPanelCtrl ctrlCommit FADE_DELAY;
+ // Force a "refresh" animation of the panel
+ _contentPanelCtrl ctrlSetFade 1;
+ _contentPanelCtrl ctrlCommit 0;
+ _contentPanelCtrl ctrlSetFade 0;
+ _contentPanelCtrl ctrlCommit FADE_DELAY;
-_contentPanelCtrl lnbSetCurSelRow -1;
-lnbClear _contentPanelCtrl;
+ _contentPanelCtrl lnbSetCurSelRow -1;
+ lnbClear _contentPanelCtrl;
+};
private _sharedLoadoutsVars = GVAR(sharedLoadoutsNamespace) getVariable QGVAR(sharedLoadoutsVars);
-private _cfgWeapons = configFile >> "CfgWeapons";
+private _cfgWeapons = configFile >> "CfgWeapons"; // Used by ADD_LOADOUTS_LIST_PICTURES macro, do not remove
private _newRow = -1;
if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
private _loadoutNameAndTab = "";
private _loadoutCachedInfo = "";
private _sharingEnabled = GVAR(allowSharedLoadouts) && {isMultiplayer};
+ private _loadouts = [
+ profileNamespace getVariable [QGVAR(saved_loadouts), []],
+ GVAR(defaultLoadoutsList)
+ ] select (ctrlIDC _control == IDC_buttonDefaultLoadouts);
+ if (_currentFrame == 0) then {
+ _framesToFill = floor ((count _loadouts) / LOADOUTS_PER_FRAME);
+ TRACE_2("filling loadouts list",_currentFrame,_framesToFill);
+ _this set [3, _framesToFill];
+ };
// Add all loadouts to loadout list
{
@@ -50,15 +71,16 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
_loadoutCachedInfo = [_loadoutData] call FUNC(verifyLoadout);
_contentPanelCtrl setVariable [_loadoutNameAndTab, _loadoutCachedInfo];
- _loadoutCachedInfo params ["", "_nullItemsAmount", "_unavailableItemsAmount", "_nullItemsList", "_unavailableItemsList"];
+ _loadoutCachedInfo params ["", "_nullItemsList", "_unavailableItemsList", "_missingExtendedInfo"];
// Log missing / nil items to RPT (only once per arsenal session)
- if (GVAR(EnableRPTLog) && {(_nullItemsAmount > 0) || {_unavailableItemsAmount > 0}}) 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]);
};
};
@@ -69,18 +91,18 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
_contentPanelCtrl lnbSetColumnsPos [0, 0.05, 0.40, 0.50, 0.60, 0.70, 0.75, 0.80, 0.85, 0.90];
};
- _loadoutCachedInfo params ["_extendedLoadout", "_nullItemsAmount", "_unavailableItemsAmount"];
- _extendedLoadout params ["_loadout"];
+ _loadoutCachedInfo params ["_extendedLoadout", "_nullItemsList", "_unavailableItemsList"];
+ _extendedLoadout params ["_loadout"]; // Used by ADD_LOADOUTS_LIST_PICTURES macro, do not remove
_newRow = _contentPanelCtrl lnbAddRow ["", _loadoutName];
ADD_LOADOUTS_LIST_PICTURES
// Change color on loadout lines that have items that aren't available or don't exist
- if (_nullItemsAmount > 0) then {
+ if (_nullItemsList isNotEqualTo []) then {
_contentPanelCtrl lnbSetColor [[_newRow, 1], [1, 0, 0, 0.8]]; // Red
} else {
- if (_unavailableItemsAmount > 0) then {
+ if (_unavailableItemsList isNotEqualTo []) then {
_contentPanelCtrl lnbSetColor [[_newRow, 1], [1, 1, 1, 0.25]]; // Gray
};
};
@@ -90,10 +112,16 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
_contentPanelCtrl lnbSetPicture [[_newRow, 0], QPATHTOF(data\iconPublic.paa)];
_contentPanelCtrl lnbSetValue [[_newRow, 0], 1];
};
- } forEach ([profileNamespace getVariable [QGVAR(saved_loadouts), []], GVAR(defaultLoadoutsList)] select (ctrlIDC _control == IDC_buttonDefaultLoadouts));
+ } forEach (_loadouts select [_currentFrame * LOADOUTS_PER_FRAME, [LOADOUTS_PER_FRAME, count _loadouts] select is3DEN]);
} else {
private _allPlayerNames = allPlayers apply {name _x};
+ private _loadouts = _sharedLoadoutsVars apply {GVAR(sharedLoadoutsNamespace) getVariable _x};
private _loadoutVar = "";
+ if (_currentFrame == 0) then {
+ _framesToFill = floor ((count _loadouts) / LOADOUTS_PER_FRAME);
+ TRACE_2("filling loadouts list",_currentFrame,_framesToFill);
+ _this set [3, _framesToFill];
+ };
{
_x params ["_playerName", "_loadoutName", "_loadoutData"];
@@ -107,8 +135,8 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
[QGVAR(loadoutUnshared), [_contentPanelCtrl, profileName, _loadoutName]] call CBA_fnc_remoteEvent;
} else {
- ([_loadoutData] call FUNC(verifyLoadout)) params ["_extendedLoadout", "_nullItemsAmount", "_unavailableItemsAmount"];
- _extendedLoadout params ["_loadout"];
+ ([_loadoutData] call FUNC(verifyLoadout)) params ["_extendedLoadout", "_nullItemsList", "_unavailableItemsList"];
+ _extendedLoadout params ["_loadout"]; // Used by ADD_LOADOUTS_LIST_PICTURES macro, do not remove
_contentPanelCtrl lnbSetColumnsPos [0, 0.15, 0.40, 0.50, 0.60, 0.70, 0.75, 0.80, 0.85, 0.90];
_newRow = _contentPanelCtrl lnbAddRow [_playerName, _loadoutName];
@@ -118,17 +146,23 @@ if (GVAR(currentLoadoutsTab) != IDC_buttonSharedLoadouts) then {
_contentPanelCtrl lnbSetData [[_newRow, 1], _loadoutVar];
// Change color on loadout lines that have items that aren't available or don't exist
- if (_nullItemsAmount > 0) then {
+ if (_nullItemsList isNotEqualTo []) then {
_contentPanelCtrl lnbSetColor [[_newRow, 1], [1, 0, 0, 0.8]]; // Red
} else {
- if (_unavailableItemsAmount > 0) then {
+ if (_unavailableItemsList isNotEqualTo []) then {
_contentPanelCtrl lnbSetColor [[_newRow, 1], [1, 1, 1, 0.25]]; // Gray
};
};
};
- } forEach (_sharedLoadoutsVars apply {GVAR(sharedLoadoutsNamespace) getVariable _x});
+ } forEach (_loadouts select [_currentFrame * LOADOUTS_PER_FRAME, [LOADOUTS_PER_FRAME, count _loadouts] select is3DEN]);
};
+if (!is3DEN && _currentFrame != _framesToFill) exitWith {
+ _this set [2, _currentFrame + 1];
+ [FUNC(fillLoadoutsList), _this] call CBA_fnc_execNextFrame;
+};
+TRACE_3("finished",_currentFrame,_framesToFill,lnbSize _contentPanelCtrl);
+
[QGVAR(loadoutsListFilled), [_display, _control]] call CBA_fnc_localEvent;
// Sort loadouts alphabetically
diff --git a/addons/arsenal/functions/fnc_handleActions.sqf b/addons/arsenal/functions/fnc_handleActions.sqf
index f28e448256..03c25f77df 100644
--- a/addons/arsenal/functions/fnc_handleActions.sqf
+++ b/addons/arsenal/functions/fnc_handleActions.sqf
@@ -47,7 +47,7 @@ private _groups = (GVAR(actionList) select _panel) select {
private _show = _groups isNotEqualTo [];
private _actionsBoxCtrl = _display displayCtrl IDC_actionsBox;
_actionsBoxCtrl ctrlShow _show;
-_actionsBoxCtrl ctrlCommit 0.15;
+_actionsBoxCtrl ctrlCommit FADE_DELAY;
if (!_show) exitWith {};
@@ -77,7 +77,6 @@ private _items = _group select 3 select {
};
_actionsCurrentPageCtrl ctrlSetText (_group select 1);
-_actionsCurrentPageCtrl ctrlSetFade 0;
_actionsCurrentPageCtrl ctrlShow true;
_actionsCurrentPageCtrl ctrlCommit 0;
@@ -85,36 +84,22 @@ private _activeCtrls = [];
{
_x params ["", "_type", "_label", "_statement"];
- private _idc = IDC_actionsText1 + _forEachIndex * 2;
- private _actionTextCtrl = _display displayCtrl _idc;
- private _actionButtonCtrl = _display displayCtrl (_idc + 1);
+ private _idc = IDC_actionsText1 + _type + _forEachIndex * 2;
+ private _actionCtrl = _display displayCtrl _idc;
switch (_type) do {
case ACTION_TYPE_BUTTON: {
- _actionButtonCtrl ctrlRemoveAllEventHandlers "ButtonClick";
- _actionButtonCtrl ctrlAddEventHandler ["ButtonClick", {
+ _actionCtrl ctrlRemoveAllEventHandlers "ButtonClick";
+ _actionCtrl ctrlAddEventHandler ["ButtonClick", {
if (is3DEN) exitWith {[true] call FUNC(refresh)};
[{
[true] call FUNC(refresh);
}] call CBA_fnc_execNextFrame;
}];
- if (_activeCtrls isNotEqualTo []) then {
- (ctrlPosition (_activeCtrls select -1)) params ["", "_lastPosY", "", "_lastPosH"];
- _actionButtonCtrl ctrlSetPositionY (_lastPosY + _lastPosH + GRID_H);
- } else {
- _actionButtonCtrl ctrlSetPositionY (6 * GRID_H);
- };
-
- _actionButtonCtrl ctrlAddEventHandler ["ButtonClick", _statement];
- _actionButtonCtrl ctrlSetText _label;
- _actionButtonCtrl ctrlSetFade 0;
- _actionButtonCtrl ctrlEnable true;
- _actionButtonCtrl ctrlCommit 0;
- _actionTextCtrl ctrlSetFade 1;
- _actionTextCtrl ctrlEnable false;
- _actionTextCtrl ctrlCommit 0;
- _activeCtrls pushBack _actionButtonCtrl;
+ _actionCtrl ctrlAddEventHandler ["ButtonClick", _statement];
+ _actionCtrl ctrlSetText _label;
+ _actionCtrl ctrlEnable true;
};
case ACTION_TYPE_TEXT: {
private _text = call _statement;
@@ -125,47 +110,35 @@ private _activeCtrls = [];
if (_text isEqualType []) then {
_text = _text joinString endl;
};
- if (_activeCtrls isNotEqualTo []) then {
- (ctrlPosition (_activeCtrls select -1)) params ["", "_lastPosY", "", "_lastPosH"];
- _actionTextCtrl ctrlSetPositionY (_lastPosY + _lastPosH + GRID_H);
- } else {
- _actionTextCtrl ctrlSetPositionY (5 * GRID_H);
- };
- _actionTextCtrl ctrlSetText _text;
- _actionTextCtrl ctrlSetPositionH (ctrlTextHeight _actionTextCtrl);
- _actionTextCtrl ctrlSetFade 0;
- _actionTextCtrl ctrlEnable false;
- _actionTextCtrl ctrlCommit 0;
- _actionButtonCtrl ctrlSetFade 1;
- _actionButtonCtrl ctrlEnable false;
- _actionButtonCtrl ctrlCommit 0;
- _activeCtrls pushBack _actionTextCtrl;
- };
- default {
- _actionTextCtrl ctrlSetFade 1;
- _actionTextCtrl ctrlCommit 0;
- _actionButtonCtrl ctrlSetFade 1;
- _actionButtonCtrl ctrlEnable false;
- _actionButtonCtrl ctrlCommit 0;
+ _actionCtrl ctrlSetText _text;
+ _actionCtrl ctrlSetPositionH (ctrlTextHeight _actionCtrl);
+ _actionCtrl ctrlEnable false;
};
};
+
+ if (_activeCtrls isNotEqualTo []) then {
+ (ctrlPosition (_activeCtrls select -1)) params ["", "_lastPosY", "", "_lastPosH"];
+ _actionCtrl ctrlSetPositionY (_lastPosY + _lastPosH + GRID_H);
+ } else {
+ _actionCtrl ctrlSetPositionY ((5 + _type) * GRID_H);
+ };
+
+ _actionCtrl ctrlShow true;
+ _actionCtrl ctrlCommit 0;
+ _activeCtrls pushBack _actionCtrl;
} forEach _items;
-private _actionCount = count _items;
-
{
- private _idc = IDC_actionsText1 + _x * 2;
- private _actionTextCtrl = _display displayCtrl _idc;
- private _actionButtonCtrl = _display displayCtrl (_idc + 1);
+ private _idc = ctrlIDC _x;
+ if (_idc < IDC_actionsText1 || _idc > IDC_actionsButton5) then {continue};
- _actionTextCtrl ctrlSetFade 1;
- _actionTextCtrl ctrlCommit 0;
- _actionButtonCtrl ctrlSetFade 1;
- _actionButtonCtrl ctrlCommit 0;
-} forEach ([0, 1, 2, 3, 4] select [_actionCount, 5]);
+ _x ctrlShow false;
+ _x ctrlEnable false;
+ _x ctrlSetPositionY 0;
+ _x ctrlCommit 0;
+} forEach ((allControls _actionsBoxCtrl) select {!(_x in _activeCtrls)});
-private _pos = ctrlPosition _actionsBoxCtrl;
(ctrlPosition (_activeCtrls select -1)) params ["", "_lastPosY", "", "_lastPosH"];
private _actionsBoxHeight = _lastPosY + _lastPosH + GRID_H;
_actionsBoxCtrl ctrlSetPositionH _actionsBoxHeight;
diff --git a/addons/arsenal/functions/fnc_onArsenalOpen.sqf b/addons/arsenal/functions/fnc_onArsenalOpen.sqf
index 9077a13a7a..f307c932b1 100644
--- a/addons/arsenal/functions/fnc_onArsenalOpen.sqf
+++ b/addons/arsenal/functions/fnc_onArsenalOpen.sqf
@@ -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";
diff --git a/addons/arsenal/functions/fnc_onSelChangedLeft.sqf b/addons/arsenal/functions/fnc_onSelChangedLeft.sqf
index 3d356fc207..5bf08245c8 100644
--- a/addons/arsenal/functions/fnc_onSelChangedLeft.sqf
+++ b/addons/arsenal/functions/fnc_onSelChangedLeft.sqf
@@ -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;
+
+ 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
- if (isNull _unitInsigniaConfig) then {
- [_display, _control, _curSel, missionConfigFile >> "CfgUnitInsignia" >> _item] call FUNC(itemInfo);
- } else {
- [_display, _control, _curSel, _unitInsigniaConfig] call FUNC(itemInfo);
- };
+ [_display, _control, _curSel, _itemCfg] call FUNC(itemInfo);
};
};
diff --git a/addons/arsenal/functions/fnc_sortPanel.sqf b/addons/arsenal/functions/fnc_sortPanel.sqf
index bbe48d6e35..7a8a8978eb 100644
--- a/addons/arsenal/functions/fnc_sortPanel.sqf
+++ b/addons/arsenal/functions/fnc_sortPanel.sqf
@@ -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;
@@ -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 {
@@ -126,7 +131,6 @@ private _selected = if (_right) then {
_panel lbData _curSel
};
-private _originalNames = createHashMap;
private _item = "";
private _quantity = "";
private _itemCfg = configNull;
@@ -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
@@ -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 {
@@ -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])
@@ -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
};
};
@@ -216,37 +228,29 @@ _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];
+ // Remove sorting text, as it blocks the item name otherwise
+ _panel lnbSetTextRight [[_i, 1], ""];
- _panel lnbSetText [[_i, 1], _originalNames get _item];
-
- // 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
@@ -254,17 +258,17 @@ if (_right) then {
};
};
} 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;
diff --git a/addons/arsenal/functions/fnc_verifyLoadout.sqf b/addons/arsenal/functions/fnc_verifyLoadout.sqf
index adc76f391a..f321293fe9 100644
--- a/addons/arsenal/functions/fnc_verifyLoadout.sqf
+++ b/addons/arsenal/functions/fnc_verifyLoadout.sqf
@@ -19,279 +19,74 @@ private _extendedInfo = createHashMap;
// Check if the provided loadout is a CBA extended loadout
if (count _loadout == 2) then {
- _extendedInfo = _loadout select 1;
+ _extendedInfo = +(_loadout select 1); // Copy the hashmap to prevent events from modifiyng the profileNamespace extendedInfo
_loadout = _loadout select 0;
};
-private _cfgWeapons = configFile >> "CfgWeapons";
-private _cfgMagazines = configFile >> "CfgMagazines";
-private _cfgVehicles = configFile >> "CfgVehicles";
-private _cfgGlasses = configFile >> "CfgGlasses";
-
-private _weapons = GVAR(virtualItems) get IDX_VIRT_WEAPONS;
-private _attachments = GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS;
-
private _name = "";
-private _nullItemsAmount = 0;
-private _unavailableItemsAmount = 0;
+private _itemArray = [];
private _nullItemsList = [];
private _unavailableItemsList = [];
+private _missingExtendedInfo = [];
-// Search for all items and turn them into config case; Don't touch other value types
-private _fnc_toConfigCase = {
+// Search for all items and check their availability
+private _fnc_filterLoadout = {
_this apply {
- if (_x isEqualType "") then {
- if (_x != "") then {
- _name = _x call EFUNC(common,getConfigName);
+ if (_x isEqualType "" && {_x != ""}) then {
+ _name = _x call EFUNC(common,getConfigName);
- // If item doesn't exist in config, "" is returned
- // Just return unaltered item name in that case, so it can be documented as being unavailable
- [_x, _name] select (_name != "");
+ // If item doesn't exist in config, "" is returned
+ if (_name == "") then {
+ _nullItemsList pushBack _x;
} else {
- _x
+ // Check if item or its base weapon exist in the arsenal
+ if !(_name in GVAR(virtualItemsFlat)) then {
+ _name = _name call FUNC(baseWeapon);
+ if !(_name in GVAR(virtualItemsFlat)) then {
+ _unavailableItemsList pushBack _name;
+ _name = "";
+ };
+ };
};
+
+ _name
} else {
// Handle arrays
if (_x isEqualType []) then {
- _x call _fnc_toConfigCase
+ _itemArray = _x call _fnc_filterLoadout;
+ // If "" is given as a container, an error is thrown, therefore, filter out all unavailable/null containers
+ if (count _itemArray == 2 && {(_itemArray select 0) isEqualTo ""} && {(_itemArray select 1) isEqualType []}) then {
+ _itemArray = [];
+ };
+ _itemArray
} else {
- // All other types
+ // All other types and empty strings
_x
};
};
};
};
-// Convert loadout to config case
+// Convert loadout to config case and replace null/unavailable items
// Loadout might come from a different modpack, which might have different config naming
-_loadout = _loadout call _fnc_toConfigCase;
+_loadout = _loadout call _fnc_filterLoadout;
-// Check a weapon, with its attachments and magazines, if items are available
-private _fnc_weaponCheck = {
- params ["_weaponArray", ["_index", -1]];
+{
+ private _class = _extendedInfo getOrDefault [_x, ""];
+ private _cache = missionNamespace getVariable (_x + "Cache");
- {
- // Weapons and attachments
- if (_x isEqualType "") then {
- if (_x != "") then {
- // Check if item exists
- if (isClass (_cfgWeapons >> _x)) then {
- // Get base weapon
- _x = _x call FUNC(baseWeapon);
-
- // Check if item is available in arsenal
- if !(
- // Weapon class name is at the very start of the array
- if (_forEachIndex == 0) then {
- // If the type of weapon is known, only look through that array
- if (_index != -1) then {
- // If binos, choose differently
- if (_index == IDX_LOADOUT_BINO) then {
- _x in (GVAR(virtualItems) get IDX_VIRT_BINO)
- } else {
- _x in (_weapons get _index)
- };
- } else {
- _x in (_weapons get IDX_VIRT_PRIMARY_WEAPONS) ||
- {_x in (_weapons get IDX_VIRT_SECONDARY_WEAPONS)} ||
- {_x in (_weapons get IDX_VIRT_HANDGUN_WEAPONS)} ||
- {_x in (GVAR(virtualItems) get IDX_VIRT_BINO)}
- };
- } else {
- _x in (_attachments get IDX_VIRT_OPTICS_ATTACHMENTS) ||
- {_x in (_attachments get IDX_VIRT_FLASHLIGHT_ATTACHMENTS)} ||
- {_x in (_attachments get IDX_VIRT_MUZZLE_ATTACHMENTS)} ||
- {_x in (_attachments get IDX_VIRT_BIPOD_ATTACHMENTS)}
- }
- ) then {
- _unavailableItemsList pushBackUnique _x;
- _weaponArray set [_forEachIndex, ""];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _x;
- _weaponArray set [_forEachIndex, ""];
- INC(_nullItemsAmount);
- };
- };
- } else {
- // Magazines
- if (_x isNotEqualTo []) then {
- _x params ["_magazine"];
-
- // Check if item exists
- if (isClass (_cfgMagazines >> _magazine)) then {
- // Check if item is available in arsenal
- if !(_magazine in (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL)) then {
- _unavailableItemsList pushBackUnique _magazine;
- _weaponArray set [_forEachIndex, []];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _magazine;
- _weaponArray set [_forEachIndex, []];
- INC(_nullItemsAmount);
- };
- };
- };
- } forEach _weaponArray;
-};
-
-private _item = "";
-
-// Go through entire loadout to check if items are available in current arsenal
-for "_dataIndex" from IDX_LOADOUT_PRIMARY_WEAPON to IDX_LOADOUT_ASSIGNEDITEMS do {
- switch (_dataIndex) do {
- // Primary weapon, Secondary weapon, Handgun weapon, Binoculars
- case IDX_LOADOUT_PRIMARY_WEAPON;
- case IDX_LOADOUT_SECONDARY_WEAPON;
- case IDX_LOADOUT_HANDGUN_WEAPON;
- case IDX_LOADOUT_BINO: {
- [_loadout select _dataIndex, _dataIndex] call _fnc_weaponCheck;
- };
- // Uniform, vest, backpack
- case IDX_LOADOUT_UNIFORM;
- case IDX_LOADOUT_VEST;
- case IDX_LOADOUT_BACKPACK: {
- (_loadout select _dataIndex) params [["_item", ""], ["_containerItems", []]];
-
- if (_item != "") then {
- // Check if item exists
- if (isClass (_cfgVehicles >> _item) || {isClass (_cfgWeapons >> _item)}) then {
- // Check if item is available in arsenal
- if !(_item in (GVAR(virtualItems) get (_dataIndex + 1))) then {
- _unavailableItemsList pushBackUnique _item;
- _loadout set [_dataIndex, []];
- INC(_unavailableItemsAmount);
- } else {
- {
- switch (true) do {
- // Magazines have each 3 entries: Name, number of magazines and ammo count
- case (_x isEqualTypeArray ["", 0, 0]): {
- _x params ["_item"];
-
- // Check if item exists
- if (isClass (_cfgMagazines >> _item)) then {
- // Check if item is available in arsenal
- if !(
- _item in (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL) ||
- {_item in (GVAR(virtualItems) get IDX_VIRT_GRENADES)} ||
- {_item in (GVAR(virtualItems) get IDX_VIRT_EXPLOSIVES)} ||
- {_item in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)}
- ) then {
- _unavailableItemsList pushBackUnique _item;
- ((_loadout select _dataIndex) select 1) set [_forEachIndex, []];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _item;
- ((_loadout select _dataIndex) select 1) set [_forEachIndex, []];
- INC(_nullItemsAmount);
- };
- };
- // Weapons have 2 entries: Weapon info array and amount
- case (_x isEqualTypeArray [[], 0]): {
- [_x select 0] call _fnc_weaponCheck;
- };
- // Misc. items have 2 entries: Name and amount, containers have 2 entries: Name and isBackpack
- default {
- _x params ["_item"];
-
- // Check if item exists
- if (
- isClass (_cfgWeapons >> _item) ||
- {isClass (_cfgMagazines >> _item)} ||
- {isClass (_cfgGlasses >> _item)} ||
- {isClass (_cfgVehicles >> _item)}
- ) then {
- // Check if item is available in arsenal
- if !(_item in GVAR(virtualItemsFlat)) then {
- _unavailableItemsList pushBackUnique _item;
- ((_loadout select _dataIndex) select 1) set [_forEachIndex, []];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _item;
- ((_loadout select _dataIndex) select 1) set [_forEachIndex, []];
- INC(_nullItemsAmount);
- };
- };
-
- };
- } forEach _containerItems;
- };
- } else {
- _nullItemsList pushBackUnique _item;
- _loadout set [_dataIndex, []];
- INC(_nullItemsAmount);
- };
- };
- };
- // Headgear
- case IDX_LOADOUT_HEADGEAR: {
- _item = _loadout select _dataIndex;
-
- if (_item != "") then {
- // Check if item exists
- if (isClass (_cfgWeapons >> _item)) then {
- // Check if item is available in arsenal
- if !(_item in (GVAR(virtualItems) get IDX_VIRT_HEADGEAR)) then {
- _unavailableItemsList pushBackUnique _item;
- _loadout set [_dataIndex, ""];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _item;
- _loadout set [_dataIndex, ""];
- INC(_nullItemsAmount);
- };
- };
- };
- // Facewear
- case IDX_LOADOUT_GOGGLES: {
- _item = _loadout select _dataIndex;
-
- if (_item != "") then {
- // Check if item exists
- if (isClass (_cfgGlasses >> _item)) then {
- // Check if item is available in arsenal
- if !(_item in (GVAR(virtualItems) get IDX_VIRT_GOGGLES)) then {
- _unavailableItemsList pushBackUnique _item;
- _loadout set [_dataIndex, ""];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _item;
- _loadout set [_dataIndex, ""];
- INC(_nullItemsAmount);
- };
- };
- };
- // Assigned items: Map, Compass, Watch, GPS / UAV Terminal, Radio, NVGs
- case IDX_LOADOUT_ASSIGNEDITEMS: {
- private _assignedItems = _loadout select _dataIndex;
-
- for "_subIndex" from 0 to 5 do {
- _item = _assignedItems select _subIndex;
-
- if (_item != "") then {
- // Check if item exists
- if (isClass (_cfgWeapons >> _item)) then {
- // Check if item is available in arsenal
- if !(_item in (GVAR(virtualItems) get (IDX_VIRT_NVG + ([2, 6, 4, 3, 5, 0] select _subIndex)))) then {
- _unavailableItemsList pushBackUnique _item;
- _assignedItems set [_subIndex, ""];
- INC(_unavailableItemsAmount);
- };
- } else {
- _nullItemsList pushBackUnique _item;
- _assignedItems set [_subIndex, ""];
- INC(_nullItemsAmount);
- };
- };
- };
- };
+ // 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)];
-[[_loadout, _extendedInfo], _nullItemsAmount, _unavailableItemsAmount, _nullItemsList, _unavailableItemsList]
+// Raise event for 3rd party: mostly for handling extended info
+// Pass all items, including duplicates
+[QGVAR(loadoutVerified), [_loadout, _extendedInfo, _nullItemsList, _unavailableItemsList, _missingExtendedInfo]] call CBA_fnc_localEvent;
+
+[[_loadout, _extendedInfo], _nullItemsList arrayIntersect _nullItemsList, _unavailableItemsList arrayIntersect _unavailableItemsList, _missingExtendedInfo]
diff --git a/addons/arsenal/script_component.hpp b/addons/arsenal/script_component.hpp
index 0f7348b9db..2eb9c3f170 100644
--- a/addons/arsenal/script_component.hpp
+++ b/addons/arsenal/script_component.hpp
@@ -15,6 +15,3 @@
#endif
#include "\z\ace\addons\main\script_macros.hpp"
-
-#define ACTION_TYPE_BUTTON 0
-#define ACTION_TYPE_TEXT 1
diff --git a/addons/arsenal/stringtable.xml b/addons/arsenal/stringtable.xml
index f308765540..081f5cecf4 100644
--- a/addons/arsenal/stringtable.xml
+++ b/addons/arsenal/stringtable.xml
@@ -1241,10 +1241,12 @@
Thermal integrated
熱画像装置内蔵
+ Интегрирован в тепловизор.
Thermal & Primary integrated
熱画像装置内蔵・プライマリに内蔵
+ Интегрирован в тепловизор и осн.прицел.
Not Supported
@@ -1600,6 +1602,7 @@
내림차순
Décroissant
Decrescente
+ Нисходящий
Ascending
@@ -1610,6 +1613,7 @@
오름차순
Croissant
Crescente
+ Восходящий
Tools
@@ -1636,6 +1640,7 @@
장탄 수
Nombre de munitions
Quantidade de munição
+ Количество боеприпасов
Illuminators
@@ -1645,6 +1650,7 @@
조명
Iluminadores
イルミネーター
+ Осветители
Default to Favorites
@@ -1655,6 +1661,7 @@
즐겨찾기 기본값
Favoris par défaut
Favoritos por padrão
+ По умолчанию - Избранное
Controls whether the ACE Arsenal defaults to showing all items or favorites.
@@ -1665,6 +1672,7 @@
ACE 아스널이 기본적으로 모든 아이템 또는 즐겨찾기를 표시할 지 여부를 조정합니다.
Contrôle si l'arsenal ACE affiche par défaut tous les éléments ou les favoris.
Controla se o Arsenal ACE exibe por padrão todos os itens ou favoritos.
+ Определяет, будет ли в арсенале ACE по умолчанию отображаться все предметы или избранное.
Favorites Color
@@ -1675,6 +1683,7 @@
즐겨찾기 색상
Couleurs favorites
Cor dos favoritos
+ Избранный цвет
Highlight color for favorited items.
@@ -1685,6 +1694,7 @@
즐겨찾기한 아이템을 색상으로 강조합니다.
Met en surbrillance les éléments favoris.
Cor de destaque para itens favoritados.
+ Выделите цветом любимые предметы.
Switch between displaying all items or your favorites.\nDouble click while holding Shift to add or remove an item.
@@ -1695,6 +1705,7 @@
모든 아이템을 표시하거나 즐겨찾기를 표시할 때 전환합니다\nShift 키를 누른 상태에서 두 번 클릭하여 아이템을 추가하거나 제거합니다.
Change entre l'affichage de tous les éléments ou de vos favoris.\nDouble-cliquez en maintenant la touche Maj enfoncée pour ajouter ou supprimer un élément.
Alterna entre a exibição de todos os itens ou seus favoritos.\nClique duas vezes enquanto mantém pressionada a tecla Shift para adicionar ou remover um item.
+ Переключайтесь между отображением всех элементов или ваших избранных.\nДважды щелкните, удерживая Shift, чтобы добавить или удалить элемент.
Search\nCTRL + Click to enable live results
@@ -1702,6 +1713,7 @@
Cerca\nCTRL + Click per modificare i risultati mentre scrivi
検索\nCTRL + クリックで検索結果の即時表示を有効化
검색\nCtrl + 클릭으로 실시간 검색 결과를 활성화
+ Поиск\nCtrl + Click для включения результатов в реальном времени
diff --git a/addons/arsenal/ui/RscAttributes.hpp b/addons/arsenal/ui/RscAttributes.hpp
index 69acebc52c..dc70caa0c2 100644
--- a/addons/arsenal/ui/RscAttributes.hpp
+++ b/addons/arsenal/ui/RscAttributes.hpp
@@ -467,7 +467,6 @@ class GVAR(display) {
};
class actionsText1: RscTextMulti {
idc = IDC_actionsText1;
- fade = 1;
x = QUOTE(0 * GRID_W);
y = QUOTE(5 * GRID_H);
w = QUOTE(45 * GRID_W);
@@ -479,8 +478,6 @@ class GVAR(display) {
};
class actionsButton1: ctrlButton {
idc = IDC_actionsButton1;
- onMouseEnter = QUOTE(ctrlSetFocus (_this select 0));
- fade = 1;
text = "";
x = QUOTE(1 * GRID_W);
y = QUOTE(6 * GRID_H);
@@ -567,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);
@@ -597,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;
diff --git a/addons/arsenal/ui/script_component.hpp b/addons/arsenal/ui/script_component.hpp
deleted file mode 100644
index fcf9da9867..0000000000
--- a/addons/arsenal/ui/script_component.hpp
+++ /dev/null
@@ -1 +0,0 @@
-#include "..\script_component.hpp"
diff --git a/addons/ballistics/stringtable.xml b/addons/ballistics/stringtable.xml
index 40385e9680..aa746e543f 100644
--- a/addons/ballistics/stringtable.xml
+++ b/addons/ballistics/stringtable.xml
@@ -3539,6 +3539,7 @@
인공지능 사용
Utilisation de l'IA
Utilização por IA
+ Использование ИИ
Illum
@@ -3549,6 +3550,7 @@
조명탄
Fusées éclairantes
Sinalizadoras
+ Осветители
Smoke
@@ -3559,6 +3561,7 @@
연막탄
Fumigènes
Fumígenas
+ Дым
Inf
@@ -3569,6 +3572,7 @@
보병
Infanterie
Infantaria
+ Пехота
Veh
@@ -3579,6 +3583,7 @@
차량
Véhicule
Veículo
+ Техника
Armor
@@ -3589,6 +3594,7 @@
기갑
Blindage
Blindagem
+ Бронетехника
Air
@@ -3599,6 +3605,7 @@
항공
Aviation
Aeronaves
+ Авиация
diff --git a/addons/captives/stringtable.xml b/addons/captives/stringtable.xml
index c12a02a574..c2da8892e5 100644
--- a/addons/captives/stringtable.xml
+++ b/addons/captives/stringtable.xml
@@ -145,6 +145,7 @@
Załóż opaskę na oczy
포로 눈 가리기
目隠しをする
+ Завязать глаза пленному
Remove blindfold
@@ -154,6 +155,7 @@
Zdejmij opaskę z oczu
눈가리개 풀기
目隠しを外す
+ Снять повязку с глаз
Cable Tie
diff --git a/addons/cargo/stringtable.xml b/addons/cargo/stringtable.xml
index fb541dd693..8a5e763e98 100644
--- a/addons/cargo/stringtable.xml
+++ b/addons/cargo/stringtable.xml
@@ -35,6 +35,7 @@
Deploy
+ Разместить
Raise/Lower | (Ctrl + Scroll) Rotate
@@ -278,11 +279,13 @@
Loading %1 into %2...
Cargando %1 en %2...
%1 を %2 に積み込んでいます・・・
+ Загружаем %1 в %2...
Unloading %1 from %2...
Descargando %1 de %2...
%1 を %2 から降ろしています・・・
+ Выгружаем %1 из %2...
%1<br/>could not be loaded
@@ -323,6 +326,7 @@
Ne peut pas être déchargé
荷降ろし不可能です
하역할 수가 없습니다
+ Не может быть выгружен
Custom Name
@@ -564,9 +569,11 @@
Enable deploy
+ Включить размещение
Controls whether cargo items can be unloaded via the deploy method.
+ Определяет, можно ли выгружать грузы с помощью метода размещения.
diff --git a/addons/common/functions/fnc_cachedCall.sqf b/addons/common/functions/fnc_cachedCall.sqf
index 0062aec1f3..dbf81b7676 100644
--- a/addons/common/functions/fnc_cachedCall.sqf
+++ b/addons/common/functions/fnc_cachedCall.sqf
@@ -9,7 +9,7 @@
* 2: Namespace to store the cache on
* 3: Cache uid
* 4: Max duration of the cache
- * 5: Event that clears the cache (default: nil)
+ * 5: Events that clear the cache (default: nil)
*
* Return Value:
* Result of the function
@@ -20,41 +20,46 @@
* Public: No
*/
-params ["_params", "_function", "_namespace", "_uid", "_duration", "_event"];
+params ["_params", "_function", "_namespace", "_uid", "_duration", "_events"];
if ((_namespace getVariable [_uid, [-99999]]) select 0 < diag_tickTime) then {
_namespace setVariable [_uid, [diag_tickTime + _duration, _params call _function]];
// Does the cache need to be cleared on an event?
- if (!isNil "_event") then {
- private _varName = format [QGVAR(clearCache_%1), _event];
- private _cacheList = missionNamespace getVariable _varName;
-
- // If there was no EH to clear these caches, add one
- if (isNil "_cacheList") then {
- _cacheList = [];
- missionNamespace setVariable [_varName, _cacheList];
-
- [_event, {
- #ifdef DEBUG_MODE_FULL
- INFO_1("Clear cached variables on event: %1",_eventName);
- #endif
- // Get the list of caches to clear
- //IGNORE_PRIVATE_WARNING ["_eventName"];
- // _eventName is defined on the function that calls the event
- private _varName = format [QGVAR(clearCache_%1), _eventName];
- private _cacheList = missionNamespace getVariable [_varName, []];
- // Erase all the cached results
- {
- _x call FUNC(eraseCache);
- } forEach _cacheList;
- // Empty the list
- missionNamespace setVariable [_varName, []];
- }] call CBA_fnc_addEventHandler;
+ if (!isNil "_events") then {
+ if (_events isEqualType "") then {
+ _events = [_events];
};
+ {
+ private _event = _x;
+ private _varName = format [QGVAR(clearCache_%1), _event];
+ private _cacheList = missionNamespace getVariable _varName;
- // Add this cache to the list of the event
- _cacheList pushBack [_namespace, _uid];
+ // If there was no EH to clear these caches, add one
+ if (isNil "_cacheList") then {
+ _cacheList = [];
+ missionNamespace setVariable [_varName, _cacheList];
+
+ [_event, {
+ #ifdef DEBUG_MODE_FULL
+ INFO_1("Clear cached variables on event: %1",_eventName);
+ #endif
+ // Get the list of caches to clear
+ //IGNORE_PRIVATE_WARNING ["_eventName"];
+ // _eventName is defined on the function that calls the event
+ private _varName = format [QGVAR(clearCache_%1), _eventName];
+ private _cacheList = missionNamespace getVariable [_varName, []];
+ // Erase all the cached results
+ {
+ _x call FUNC(eraseCache);
+ } forEach _cacheList;
+ // Empty the list
+ missionNamespace setVariable [_varName, []];
+ }] call CBA_fnc_addEventHandler;
+ };
+ // Add this cache to the list of the event
+ _cacheList pushBack [_namespace, _uid];
+ } forEach _events;
};
#ifdef DEBUG_MODE_FULL
diff --git a/addons/common/functions/fnc_disableUserInput.sqf b/addons/common/functions/fnc_disableUserInput.sqf
index 3774a3fc29..8db3c7e811 100644
--- a/addons/common/functions/fnc_disableUserInput.sqf
+++ b/addons/common/functions/fnc_disableUserInput.sqf
@@ -95,7 +95,7 @@ if (_state) then {
// 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
+ {((GVAR(keyboardInputMain) getOrDefault [_mainDik, [false, 0]]) select 1) > (parseNumber _isDoubleTap)}; // check how many times the main key was pressed
// Keybind was detected
if (_return) exitWith {
diff --git a/addons/common/functions/fnc_getConfigName.sqf b/addons/common/functions/fnc_getConfigName.sqf
index 54ebf84343..3495014d55 100644
--- a/addons/common/functions/fnc_getConfigName.sqf
+++ b/addons/common/functions/fnc_getConfigName.sqf
@@ -17,7 +17,7 @@
params ["_className"];
-(uiNamespace getVariable QGVAR(configNames)) getOrDefaultCall [toLower _className, {
+(uiNamespace getVariable QGVAR(configNames)) getOrDefaultCall [toLowerANSI _className, {
private _config = configNull;
{
diff --git a/addons/compat_ws/compat_ws_realisticnames/stringtable.xml b/addons/compat_ws/compat_ws_realisticnames/stringtable.xml
index db4dc2b6d5..b38f1a867e 100644
--- a/addons/compat_ws/compat_ws_realisticnames/stringtable.xml
+++ b/addons/compat_ws/compat_ws_realisticnames/stringtable.xml
@@ -7,6 +7,7 @@
AA12
AA12
AA12
+ AA12
AA12 (Sand)
@@ -14,6 +15,7 @@
AA12 (Sand)
AA12 (Sabbia)
AA12 (サンド)
+ AA12 (Песочный)
AA12 (Snake)
@@ -21,6 +23,7 @@
AA12 (Schlange)
AA12 (Serpe)
AA12 (ヘビ柄)
+ AA12 (Змея)
Galil ARM
@@ -28,6 +31,7 @@
Galil ARM
Galil ARM
ガリル ARM
+ Galil ARM
Galil ARM (Old)
@@ -35,6 +39,7 @@
Galil ARM (Alt)
Galil ARM (Vecchio)
ガリル ARM (使い古し)
+ Galil ARM (Старый)
GLX 160
@@ -42,6 +47,7 @@
GLX 160
GLX-160
GLX 160
+ GLX 160
GLX 160 (Snake)
@@ -49,6 +55,7 @@
GLX 160 (Schlange)
GLX-160 (Serpe)
GLX 160 (ヘビ柄)
+ GLX 160 (Змея)
GLX 160 (Hex)
@@ -56,6 +63,7 @@
GLX 160 (Hex)
GLX-160 (Hex)
GLX 160 (六角形迷彩)
+ GLX 160 (Гекс)
GLX 160 (Green Hex)
@@ -63,6 +71,7 @@
GLX 160 (Grün Hex)
GLX-160 (Hex Verde)
GLX 160 (緑六角形迷彩)
+ GLX 160 (Зеленый Гекс)
GLX 160 (Camo)
@@ -70,6 +79,7 @@
GLX 160 (Tarn)
GLX-160 (Mimetica)
GLX 160 (迷彩)
+ GLX 160 (Камуфляж)
GLX 160 (Sand)
@@ -77,6 +87,7 @@
GLX 160 (Sand)
GLX-160 (Sabbia)
GLX 160 (サンド)
+ GLX 160 (Песочный)
Mk14 Mod 1 EBR (Black)
@@ -84,6 +95,7 @@
Mk14 Mod 1 EBR (Schwarz)
Mk14 Mod 1 EBR (Nero)
Mk14 Mod 1 EBR (ブラック)
+ Mk14 Mod 1 EBR (Черный)
Mk14 Mod 1 EBR (Snake)
@@ -91,12 +103,14 @@
Mk14 Mod 1 EBR (Schlange)
Mk14 Mod 1 EBR (Serpe)
Mk14 Mod 1 EBR (ヘビ柄)
+ Mk14 Mod 1 EBR (Змея)
Vektor SS-77
벡터 SS-77
Vektor SS-77
ヴェクター SS-77
+ Vektor SS-77
Vektor SS-77 (Camo)
@@ -104,6 +118,7 @@
Vektor SS-77 (Tarn)
Vektor SS-77 (Mimetica)
ヴェクター SS-77 (迷彩)
+ Vektor SS-77 (Камуфляж)
Vektor SS-77 (Hex)
@@ -111,6 +126,7 @@
Vektor SS-77 (Hex)
Vektor SS-77 (Hex)
ヴェクター SS-77 (六角形迷彩)
+ Vektor SS-77 (гекс)
Vektor SS-77 (Green Hex)
@@ -118,6 +134,7 @@
Vektor SS-77 (Grün Hex)
Vektor SS-77 (Hex Verde)
ヴェクター SS-77 (緑六角形迷彩)
+ Vektor SS-77 (зеленый гекс)
Vektor SS-77 (Desert)
@@ -125,6 +142,7 @@
Vektor SS-77 (Wüste)
Vektor SS-77 (Deserto)
ヴェクター SS-77 (砂漠迷彩)
+ Vektor SS-77 (песочныйt)
Vektor SS-77 Compact
@@ -132,6 +150,7 @@
Vektor SS-77 Kompakt
Vektor SS-77 Compatto
ヴェクター SS-77 コンパクト
+ Vektor SS-77 Compact
Vektor SS-77 Compact (Snake)
@@ -139,6 +158,7 @@
Vektor SS-77 Compact (Schlange)
Vektor SS-77 Compatto (Serpe)
ヴェクター SS-77 コンパクト (ヘビ柄)
+ Vektor SS-77 Compact (змея)
FN FAL 50.00 (Wood)
@@ -146,6 +166,7 @@
FN FAL 50.00 (Holz)
FN FAL 50.00 (Legno)
FN FAL 50.00 (森林迷彩)
+ FN FAL 50.00 (лесной)
FN FAL 50.00 GL (Wood)
@@ -153,6 +174,7 @@
FN FAL 50.00 GL (Holz)
FN FAL 50.00 GL (Legno)
FN FAL 50.00 GL (森林迷彩)
+ FN FAL 50.00 GL (лесной)
FN FAL 50.00
@@ -160,6 +182,7 @@
FN FAL 50.00
FN FAL 50.00
FN FAL 50.00
+ FN FAL 50.00
FN FAL 50.00 GL
@@ -167,6 +190,7 @@
FN FAL 50.00 GL
FN FAL 50.00 GL
FN FAL 50.00 GL
+ FN FAL 50.00 GL
FN FAL 50.00 (Desert)
@@ -174,6 +198,7 @@
FN FAL 50.00 (Wüstet)
FN FAL 50.00 (Deserto)
FN FAL 50.00 (砂漠迷彩)
+ FN FAL 50.00 (песочный)
FN FAL 50.00 (Jungle)
@@ -181,6 +206,7 @@
FN FAL 50,00 (Dschungel)
FN FAL 50,00 (Giungla)
FN FAL 50.00 (熱帯迷彩)
+ FN FAL 50.00 (джунгли)
Vektor R4
@@ -188,6 +214,7 @@
Vektor R4
Vektor R4
ヴェクター R5
+ Vektor R4
Vektor R5 Carbine
@@ -195,6 +222,7 @@
Vektor R5 Carbine
Vektor R5 Carabina
ヴェクター R5 カービン
+ Vektor R5 Carbine
Vektor R5 Carbine GL
@@ -202,6 +230,7 @@
Vektor R5 Carbine GL
Vektor R5 Carabina GL
ヴェクター R5 カービン GL
+ Vektor R5 Carbine GL
Vektor R5 Carbine (Snake)
@@ -209,6 +238,7 @@
Vektor R5 Carbine (Schlange)
Vektor R5 Carabina (Serpe)
ヴェクター R5 カービン (ヘビ柄)
+ Vektor R5 Carbine (Змея)
Vektor R5 Carbine GL (Snake)
@@ -216,6 +246,7 @@
Vektor R5 Carbine GL (Schlange)
Vektor R5 Carabina GL (Serpe)
ヴェクター R5 カービン GL (ヘビ柄)
+ Vektor R5 Carbine GL (Змея)
XMS
diff --git a/addons/cookoff/stringtable.xml b/addons/cookoff/stringtable.xml
index 76aebcad60..5f764a24b7 100644
--- a/addons/cookoff/stringtable.xml
+++ b/addons/cookoff/stringtable.xml
@@ -188,6 +188,7 @@
쿡오프 후 차량이 항상 파괴되는지 여부를 조정합니다.
Contrôle si les véhicules seront toujours détruits après l'auto-inflammation.
Define se os veículos serão sempre destruídos após cozinhamento.
+ Определяет, всегда ли транспортные средства будут уничтожаться после детонации.
Enable Cook-Off Vehicle Fire
diff --git a/addons/dragging/stringtable.xml b/addons/dragging/stringtable.xml
index 5c8a355be2..7cf53ba55c 100644
--- a/addons/dragging/stringtable.xml
+++ b/addons/dragging/stringtable.xml
@@ -166,6 +166,7 @@
가벼운 개체 들고 달리기 허용
Autoriser la course avec des objets légers
Permitir corrida com objetos leves
+ Позволяет работать с легкими объектами
Allow the player to run when carrying lightweight objects.
@@ -176,6 +177,7 @@
가벼운 개체를 들고 다닐 때 플레이어가 뛸 수 있도록 허용합니다.
Autorise le joueur à courir lorsqu'il porte un objet léger.
Permite ao jogador correr enquanto carrega objetos leves.
+ Разрешите игроку бегать при переноске легких предметов.
Skip Object Weight
@@ -186,6 +188,7 @@
개체 무게 무시
Ignorer le poids de l'objet
Ignorar Peso do Objeto
+ Игнорировать вес объекта
Determines whether object's weight is added onto weight calculations.
@@ -196,6 +199,7 @@
무게 계산에 개체의 무게를 추가할 지 여부를 결정합니다.
Défini si le poids d'un objet est ajouté aux calculs du poids.
Determina se o peso do objeto é adicionado aos cálculos de peso.
+ Определяет, добавляется ли вес объекта при расчете веса.
Max Weight Coefficient
@@ -205,6 +209,7 @@
Coeficiente Máximo de Peso
Maximaler Gewichtskoeffizient
最大重量係数
+ Максимальный коэффициент веса
Modifies weight limit calculations. Set to 0 to ignore.
@@ -214,6 +219,7 @@
Modifica os cálculos do limite de peso. Defina como 0 para ignorar.
Ändert die Berechnung der Gewichtsbegrenzung. Zum Ignorieren auf 0 setzen.
重量制限の計算を変更します。 無視するには 0 に設定します。
+ Изменяет расчеты предельного веса. Установите значение 0 для игнорирования.
diff --git a/addons/explosives/stringtable.xml b/addons/explosives/stringtable.xml
index b9ed8329c8..5e672b36e2 100644
--- a/addons/explosives/stringtable.xml
+++ b/addons/explosives/stringtable.xml
@@ -72,21 +72,25 @@
Detonate All on Active Clacker
Alle auf Standardzünder zünden
Detona Tutti sul Detonatore Attivo
+ Подрыв всех на активном детонаторе
Set Active Clacker
Als Standardzünder wählen
Imposta Detonatore Attivo
+ Установить активный детонатор
Cycle Active Clacker
Standardzünder wechseln
Cambia Detonatore Attivo
+ Цикл активного детонатора
Active Clacker
Standardzünder
Detonatore Attivo
+ Активный детонатор
Explosive code: %1
diff --git a/addons/fastroping/stringtable.xml b/addons/fastroping/stringtable.xml
index ef613c633e..b68da23d28 100644
--- a/addons/fastroping/stringtable.xml
+++ b/addons/fastroping/stringtable.xml
@@ -324,6 +324,7 @@
FRIES 로프 자동 장착
Equipement automatique FRIES
Auto-equipar FRIES
+ Авто-подготовка канатов
Automatically add FRIES to helicopters that support them.
@@ -334,6 +335,7 @@
로프를 지원하는 헬기에 자동으로 FRIES 로프를 추가합니다.
Ajoute automatiquement des FRIES aux hélicoptères qui les supportent.
Adiciona automaticamente FRIES a helicópteros que os suportam.
+ Автоматически добавляйте канаты в вертолеты, которые их поддерживают.
diff --git a/addons/fieldmanual/stringtable.xml b/addons/fieldmanual/stringtable.xml
index ae71211c6a..647a5bad43 100644
--- a/addons/fieldmanual/stringtable.xml
+++ b/addons/fieldmanual/stringtable.xml
@@ -26,6 +26,7 @@
Fame
Hunger
空腹
+ Голод
%3Hunger%4 increases linearly with soldier's movement speed. Restore by eating food.<br/><br/>%3Usage:%4<br/>%2Pick up food.<br/>%2Use [%3%12%4] and select %3Survival%4.<br/>%2Choose an item to consume.
@@ -35,6 +36,7 @@
%3Hunger%4 steigt linear mit der Bewegungsgeschwindigkeit des Soldaten. Regeneriert sich, indem Nahrung zu sich genommen wird.<br/><br/>%3Verwende:%4<br/>%2Nahrung einsammeln.<br/>%2Verwende [%3%12%4] und wählen %3Überleben%4.<br />%2Wähle einen Gegenstand zum Verzehr aus.
%3Fame%4 aumenta linearmente con la velocità di movimento del soldato. Si rigenera consumando cibo.<br/><br/>%3Usa:%4<br/>%2Raccogli cibo.<br/>%2Usa [%3%12%4] e scegli %3sopravvivenza%4.<br />%2Scegli un articolo da mangiare.
%3空腹度%4は兵士の移動速度に比例して増加します。食べ物を食べることで回復します。<br/><br/>%3使用方法:%4<br/>%2食べ物を持つ。<br/>%2[%3%12%4] を使って%3サバイバル%4を選択。<br/>%2食べたいものを選ぶ。
+ %3Голод%4 линейно увеличивается со скоростью передвижения солдата. Восстанавливайтесь, употребляя пищу.<br/><br/>%3 Использование:%4<br/>%2Возьмите еду.<br/>%2Используйте [%3%12%4] и выберите %3Выживание% 4.<br/>%2Выберите продукт для потребления.
Thirst
@@ -44,6 +46,7 @@
Sete
Durst
渇き
+ Жажда
%3Thirst%4 increases linearly with soldier's movement speed. Restore by drinking liquids.<br/><br/>%3Usage:%4<br/>%2Pick up a drink.<br/>%2Use [%3%12%4] and select %3Survival%4.<br/>%2Choose an item to consume.
@@ -53,6 +56,7 @@
%3Durst%4 steigt linear mit der Bewegungsgeschwindigkeit des Soldaten. Regeneriert sich durch das Trinken von Flüssigkeiten.<br/><br/>%3Verwende:%4<br/>%2Holen ein Getränk.<br/>%2Verwende [%3%12%4] und wähle %3Überleben%4.< br/>%2Wähle einen Gegenstand zum Verzehr aus.
%3Sete%4 aumenta linearmente con la velocità di movimento del soldato. Si rigenera bevendo liquidi.<br/><br/>%3Usa:%4<br/>%2Raccogli bevanda.<br/>%2Usa [%3%12%4] e scegli %3sopravvivenza%4.<br />%2Scegli un articolo da bere.
%3喉の渇き%4は兵士の移動速度に比例して増加します。飲み物を飲むことで回復します。<br/><br/>%3使用方法:%4<br/>%2飲み物を持つ。<br/>%2[%3%12%4] を使って%3サバイバル%4を選択。<br/>%2飲みたいものを選ぶ。
+ %3Жажда%4 линейно увеличивается со скоростью передвижения солдата. Восстанавливайтесь, употребляя напитки.<br/><br/>%3 Использование:%4<br/>%2Возьмите напиток.<br/>%2Используйте [%3%12%4] и выберите %3Выживание% 4.<br/>%2Выберите напиток для потребления.
Medical Treatment
@@ -62,6 +66,7 @@
Medizinische Behandlung
Cure Mediche
治療
+ Медицинское лечение
Decrease Heart Rate
@@ -71,6 +76,7 @@
Verringere Herzfrequenz
Rallenta ritmo cardiaco
心拍数を下げる
+ Уменьшить частоту сердечных сокращений
%3Adenosine%4 is used to decrease heart rate.<br/><br/>%3Usage:%4<br/>%2Use [%3%13%4] or [%3%14%4] and select an appendage.<br/>%2Inject %3Adenosine%4.
@@ -80,6 +86,7 @@
%3Adenosin%4 wird verwendet, um die Herzfrequenz zu senken.<br/><br/>%3Verwende:%4<br/>%2Verwende [%3%13%4] oder [%3%14%4] und wählen ein Körperteil aus.<br/>%2Injiziere %3Adenosin%4.
%3Adenosina%4 è usata per rallentare il ritmo cardiaco.<br/><br/>%3Utilizzo:%4<br/>%2Usa [%3%13%4] o [%3%14%4] e seleziona un arto.<br/>%2Inject %3Adenosina%4.
%3アデノシン%4は心拍数を下げるのに使われます。<br/><br/>%3使用方法:%4<br/>%2[%3%13%4] または [%3%14%4] を使って四肢を選択します。<br/>%2そして%3アデノシン%4を注射します。
+ %3Аденозин%4 используется для снижения частоты сердечных сокращений.<br/><br/>%3Применение:%4<br/>%2Используйте [%3%13%4] или [%3%14%4] и выберите конечность.<br/>%2Введите %3Аденозин%4.
Bandages
@@ -89,6 +96,7 @@
Bandagen
Bende
包帯
+ Бинты
Close Wounds
@@ -98,6 +106,7 @@
Wunden schließen
Chiudi ferite
傷口をふさぐ
+ Закрыть раны
%3Bandages%4 stop bleeding and close wounds. Depending on your settings, bandages may reopen if surgery is not performed.<br/><br/>%2%3Field Dressing:%4<br/>%11<t color='#D9D900'>Average</t> In All Categories<br/>%2%3Packing Bandage:%4<br/>%11<t color='#D9D900'>Average</t> Treatment<br/>%11<t color='#E60000'>Higher</t> Reopen Chance<br/>%11<t color='#00CC00'>Longer</t> Reopen Delay<br/>%2%3Elastic Bandage:%4<br/>%11<t color='#00CC00'>Higher</t> Treatment<br/>%11<t color='#E60000'>Higher</t> Reopen Chance<br/>%11<t color='#E60000'>Shorter</t> Reopen Delay<br/>%2%3Quickclot:%4<br/>%11<t color='#E60000'>Lower</t> Treatment<br/>%11<t color='#00CC00'>Lower</t> Reopen Chance<br/>%11<t color='#00CC00'>Longer</t> Reopening Delay<br/><br/>%3Usage:%4<br/>%2Use [%3%13%4] or [%3%14%4] and select a injured body part.<br/>%2Bandage body part by selecting desired %3Bandage%4 type.
@@ -125,6 +134,7 @@
Blutvolumen wiederherstellen
Ristorano Volume di Sangue
血液量を回復する
+ Внутривенные жидкости
%3IV fluids%4 restore lost blood volume. Blood, Plasma, and Saline are functionally the same.<br/><br/>%3Usage:%4<br/>%2Use [%3%13%4] or [%3%14%4] and select an appendage.<br/>%2Restore blood volume by selecting desired %3IV Fluid%4 type.
@@ -143,6 +153,7 @@
Herzfrequenz erhöhen | Wache schneller auf
Aumenta ritmo cardiaco | Accelera rinvenimento
心拍数を上げる | はやく起こす
+ Увеличьте частоту сердечных сокращений | просыпайтесь быстрее
%3Epinephrine%4 increases a patient's pulse as well as potentially decreasing the time between consciousnesss checks (effectively reducing the time needed for the patient to wake up).<br/><br/>%3Usage%4<br/>%2Use [%3%13%4] or [%3%14%4] and select an appendage.<br/>%2Inject %3Epinephrine%4.
@@ -161,6 +172,7 @@
Wie neu wiederherstellen
Cura completa
生まれたてのように回復する
+ Лечение тела
The %3Personal Aid Kit%4 is an item that allows a soldier to be fully healed. Independent of %3ACE Settings%4, it requires that the patient is in %3Stable Condition%4 before use.<br/><br/>%3Stable Condition%4 qualifies as:<br/>%2Unit is %3Alive%4.<br/>%2Unit is %3Conscious%4.<br/>%2Unit has no active %3Bleeding%4.<br/>%2Heart Rate >= 40.<br/>%2Systolic BP >= 60.<br/>%2Diastolic BP >= 50.<br/><br/>%3Usage:%4<br/>%2Move to appropriate location depending on %3ACE Settings%4.<br/>%2Use [%3%13%4] or [%3%14%4] and select %3Advanced Treatments%4<br/>%2Select %3Use Personal Aid Kit%4.
@@ -179,6 +191,7 @@
Brüche richten
Risolvi frattura
骨折を治す
+ Исправлять переломы
A %3Splint%4 is used to fix fractures. The %3Splint%4 is consumed when used.<br/><br/>%3Usage:%4<br/>%2Use [%3%13%4] or [%3%14%4] and select an affected appendage.<br/>%2Select %3Apply Splint%4.
@@ -196,6 +209,7 @@
Prevenir Reabertura de Feridas
Impedisce la riapertura di ferite
傷口が開くのを防ぐ
+ Предотвратить повторное открытие ран
A %3Surgical Kit%4 is used to prevent wounds from reopening after being bandaged. Depending on settings, it can also clear trauma and may require additional %3Sutures%4 to close wounds. Sutures are consumable, much like bandages, and are not a replacement for the Surgical Kit.<br/><br/>%3Usage:%4<br/>%2Use [%3%13%4] or [%3%14%4] and select %3Advanced Treatment%4.<br/>%2Select %3Use Surgical Kit%4.
@@ -212,6 +226,7 @@
Parar o Sangramento
Ferma emorragia
出血を止める
+ Остановить кровотечение
A %3Tourniquet%4 stops bleeding temporarily so that a wound(s) can be bandaged. Can only be used on limbs.<br/><br/>%3Usage:%4<br/>%2Use [%3%13%4] or [%3%14%4] and select an affected appendage.<br/>%2Select %3Apply Tourniquet%4.
@@ -354,6 +369,7 @@
내비게이션입니다
Naviga
測位
+ Навигация
The %3DAGR%4 is a simpler version of the %3MicroDAGR GPS%4. It has similar features but lacks the topographic and satellite imaging functions of the %3MicroDAGR GPS%4.<br/><br/>%3Usage:%4<br/>%2Equip a %3DAGR%4.<br/>%2Use [%3%12%4] and select %3Configure%4 or %3Toggle%4.<br/><br/>The following menus are available when configuring your %3DAGR:%4<br/>%11%2Data View: WIP<br/>%11%2GoTo WP: Select a waypoint to track.<br/>%11%2WP List: Add/Edit/Remove waypoints.<br/>%11%2Connect To: Connect %3DAGR%4 to the %3Vector 21 Rangefinder%4.<br/>%11%2Options
@@ -368,6 +384,7 @@
'폭발'적인 복수입니다
Vendetta Esplosiva
爆発的な復讐
+ Взрывная месть
The %3Dead Man's Switch%4 is a device that allows a soldier to detonate an %3Explosive%4 when the soldier dies.<br/><br/>%3Usage:%4<br/>%2Use [%3%12%4] and select %3Explosives%4.<br/>%2Select %3Dead Man's Switch%4 and connect the desired %3Explosive%4.<br/>%2Repeat the process and disconnect to reverse.
@@ -389,6 +406,7 @@
폭발물을 해체합니다
Disinnesca Esplosivi
爆発物の解除
+ Обезвреживание взрывчатки
Protect Your Hearing
@@ -396,6 +414,7 @@
청력을 보호합니다
Proteggi il tuo Udito
聴覚の保護
+ Защитите свой слух
%3Ear Plugs%4 help prevent hearing damage from repeat loud noises near a soldier. Insert %3Ear Plugs%4 to lower volume of a soldier's environment and prevent %3Combat Deafness%4.<br/><br/>%3Usage:%4<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Insert %3Ear Plugs%4.
@@ -410,6 +429,7 @@
엄폐하십시오
Mettiti in Copertura
遮蔽を造り出す
+ Добраться до укрытия
The %3Entrenching Tool%4 allows soldiers to dig trenches to help defend their position. The soldier must be on soil in order to dig a trench.<br/><br/>%3Usage:%4<br/>%2Equip an %3Entrenching Tool%4.<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Select the type of trench you wish to build.
@@ -424,6 +444,7 @@
Torce
손전등
フラッシュライト
+ Фонари
Illuminate Your Map
@@ -431,6 +452,7 @@
Illumina la tua Mappa
지도를 밝혀줍니다
地図に光あれ
+ Осветите свою карту
%3Flashlights%4 give you the ability to read your map, even in dark environments. However, when using %3Flashlights%4, you will have a slight glow around you.<br/><br/>%3Usage:%4<br/>%2On the map screen, use [%3%12%4] and select %3Flashlights%4.<br/>%2Select the %3Flashlight%4 you want to use and select %3On%4.<br/><br/>%3Available Flashlight Items%4:<br/>%2 Fulton MX-991<br/>%2 KSF-1<br/>%2 Maglite XL50<br/><br/>%3NOTE:%4<br/>Flashlight states are persistent.
@@ -445,6 +467,7 @@
Osserva dal Cielo
하늘에서 관측합니다
空から戦場を見てみよう
+ Наблюдайте с Небес
The %3High-Altitude Unit Navigated Tactical Imaging Round (HuntIR)%4 is designed to be fired from a grenade launcher. After being fired in the air, the built-in parachute will be deployed and the IR CMOS camera will activate, providing a video stream until it touches the ground or is shot down.<br/><br/>%3Usage:%4<br/>%2Equip a %3HuntIR Monitor%4 and compatible ammunition.<br/>%2Fire the %3HuntIR Round%4 as high as possible over the area you want to observe.<br/>%2Open the %3HuntIR Monitor%4.<br/>%2Use [%3%12%4], select %3Equipment%4.<br/>%2Select %3Activate HuntIR Monitor%4.
@@ -459,6 +482,7 @@
Traccia la tua squadra con discrezione
은신하여 팀을 찾아냅니다
自分の部隊を追う
+ Следите за своей командой незаметно
The %3IR Strobe%4 is a throwable that emits an IR light pulse intermittently. The %3IR Strobe%4 can also be attached to a soldier, making it useful for tracking teammates under night vision devices.<br/><br/>%3Usage:%4<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Select %3Attach%4 and select the %3IR Strobe%4.
@@ -473,6 +497,7 @@
Stazione Meteo Tascabile
휴대용 기상 관측 장비입니다
携帯気象予報所
+ Карманная метеостанция
The %3Kestrel 4500 Pocket Weather Tracker%4 is a mini weather station useful for collecting the the following weather data:<br/>%2Heading and wind direction<br/>%2Crosswind and headwind<br/>%2Altitude and barometric pressure<br/>%2Wet bulb temperature<br/>%2Humidity and dewpoint<br/>%2Density altitude<br/>%2Wind chill and temperature<br/>%2Time and date<br/>%2Minimum, maximum, and average values<br/><br/>%3Usage:%4<br/>%2Equip a %3Kestrel%4.<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Select %3Open%4.
@@ -487,6 +512,7 @@
Triangola la tua posizione
위치를 삼각측량합니다
三角測量で位置を特定
+ Передавайте свое местоположение
The %3Map Tools%4 are a set of tools that allows a soldier to measure distances and angles. Useful for land, and calculating firing solutions for artillery.<br/><br/>%3Usage:%4<br/>%2Open %3Map%4.<br/>%2Use [%3%12%4] and select %3Map Tools%4.<br/>%2 The Tool can be moved by dragging with [%3Left-Click%4] while holding [%3ALT%4].
@@ -501,6 +527,7 @@
DAGR Avanzato
고급형 DAGR입니다
より高度なDAGR
+ Продвинутый DAGR
The %3MicroDAGR GPS%4 is an advanced version of the %3DAGR%4. It provides position, navigation, and timing (PNT) data to include:<br/>%2Compass and heading<br/>%2Date and hour synced to the mission<br/>%2Elevation (relative to sea level)<br/>%2Current speed<br/>%2GPS with topographic and satellite view<br/>%2Creating, naming, and deleting waypoints<br/>%2Friendly identification (Requires ACE BLUFOR Tracker Setting)<br/>Connection to the Vector-21 Rangefinder for data import (waypoint creation and grid reference of ranged targets)<br/><br/>%3Usage:%4<br/>%2For usage instructions, please visit the dedicated %3MicroDAGR%4 wiki.
@@ -515,6 +542,7 @@
Tavole di Tiro
사거리표
射表
+ Таблицы диапазонов
Get A Firing Solution
@@ -522,6 +550,7 @@
Per una soluzione di tiro
사격 솔루션을 제공합니다
撃ち方の解を得る
+ Получите расчёт
%3Range Tables%4 allow for a soldier to estimate accurate shot placement on direct or indirect targets (depending on asset). The %3Range Table%4 will automatically fill depending on the soldiers selected weapon/vehicle.<br/><br/>%3Usage:%4<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Select the desired %3Range Table%4.
@@ -536,6 +565,7 @@
Corde
로프
ロープ
+ Канаты
Tow With Ease
@@ -543,6 +573,7 @@
Rimorchia con facilità
쉽게 견인을 할 수 있습니다
楽々けん引
+ Буксируйте с легкостью
%3Ropes%4 have multiple uses including %3Towing%4 vehicles and %3Fast Roping%4 from helicopters.<br/><br/>%3Towing:%4<br/>%2Approach a vehicle.<br/>%2Use [%3%13%4] and select %3Towing%4.<br/>%2Select rope length.<br/>%2Select attachment point on towing vehicle.<br/>%2Select attachment on towed vehicle.<br/><br/>%3Available Rope Lengths:%4<br/>%2 3.2 meters<br/>%2 6.2 meters<br/>%2 12.2 meters<br/>%2 15.2 meters<br/>%2 18.3 meters<br/>%2 27.4 meters<br/>%2 36.6 meters
@@ -557,6 +588,7 @@
Espandi le tue Fortificazioni
당신의 요새를 확장합니다
要塞を拡張する
+ Расширить свои укрепления
%3Sandbags%4 are sacks made of sturdy material, filled with sand, used for a variety of purposes such as creating barriers or providing stability in construction projects. Useful in expanding larger placed fortifications.<br/><br/>%3Usage:%4<br/>%2Equip a %3Sandbag (Empty)%4.<br/>%2Use [%3%12%4] and select %3Deploy Sandbag%4.<br/>%2Follow on-screen instructions for placement.
@@ -571,6 +603,7 @@
Raffredda l'Arma
총기의 온도를 낮춥니다
銃の熱を冷ます
+ Понизьте температуру оружия
%3Spare Barrels%4 allow a soldier to reduce their weapon's heat significantly. After a short delay, the weapon's barrel will be swapped and its heat reduced. A soldier may also check the temperature of any barrels within their inventory. Not all weapons support swapping barrels.<br/><br/>%3Usage:%4<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Select %3Swap Barrel%4.<br/>%2Resume operation after barrel swap is complete.
@@ -585,6 +618,7 @@
Bomboletta Spray
스프레이 페인트
ペイントスプレー
+ Аэрозольная краска
Tag Your Territory
@@ -592,6 +626,7 @@
Marca il tuo territorio
당신의 영역을 지정합니다
自分のテリトリーをマーキング
+ Пометьте свою территорию
%3Spray Paint%4 is used to tag surfaces with various symbols.<br/><br/>%3Usage:%4<br/>%2Move close to a surface (wall, vehicle, ground, etc).<br/>%2Use [%3%12%4] and select %3Tag%4.<br/>%2Choose a symbol.<br/><br/>%3Available Colors:%4<br/>%2Black<br/>%2Blue<br/>%2Green<br/>%2Red
@@ -606,6 +641,7 @@
Stabilizzati Ovunque
어느 곳에나 지지대를 배치할 수 있습니다
どこでも支持器
+ Опора может быть установлена в любом месте
The %3SSWT Kit%4 is a deployable tripod that allows a soldier to brace their aim when deployed. Use it when you need an elevated shooting position and there are no other objects around.<br/><br/>%3Usage:%4<br/>%2Use [%3%12%4] and select %3Equipment%4.<br/>%2Select %3SSWT Kit%4 and follow the on screen prompts to place.
@@ -620,6 +656,7 @@
Tieni gli occhi nel cielo
하늘에서 계속 내려다봅니다
空の目を維持する
+ Не Отрывай Глаз От Неба
%3UAV Batteries%4 are used to recharge a UAV's energy storage. Especially useful for small UAVs.<br/><br/>%3Usage:%4<br/>%2Equip a %3UAV Battery%4<br/>%2Approach a %3UAV%4 with its %3Engine Off%4.<br/>%2Use [%3%13%4] and select %3Recharge%4.
@@ -634,6 +671,7 @@
Fai un'entrata
진입로를 만듭니다
堂々入場する
+ Создание собственного входа
%3Wirecutters%4 are a tool that allows a soldier to bypass wired fencing. Useful for creating backdoor entrances into secure areas.<br/><br/>%3Usage:%4<br/>%2Move close to a fence.<br/>%2Use [%3%12%4] and select %3Cut Fence%4.
@@ -664,6 +702,7 @@
ACE3
ACE3
ACE 3
+ ACE3
Build Fortifications
@@ -671,6 +710,7 @@
Costruisci Fortificazioni
요새를 건설합니다
要塞を構築する
+ Стройте укрепления
The %3Fortify Tool%4 allows soldiers to build fortifications provided by their mission creator.<br/><br/>%3Usage:%4<br/>%2Pick up a %3Fortify Tool%4.<br/>%2Use [%3%12%4] and select %3Fortify%4.<br/>%2Select an available fortification and follow the on screen prompts for placement.
@@ -685,6 +725,7 @@
Effrazione
침입용 도구입니다
破壊して乗り込む
+ Взлом и проникновение
%3Lockpicks%4 are used to gain access to locked vehicles.<br/><br/>%3Usage:%4<br/>%2Equip a %3Lockpick%4.<br/>%2Approach a %3Locked%4 vehicle.<br/>Use [%3%13%4] and select %3Lockpick Vehicle%4.<br/><br/><t underline='1'>%3Note:%4</t> Lockpicks and keys are only available via scripting or ACE Vehicle Key modules.
@@ -699,6 +740,7 @@
Chiavi dei Veicoli
차량 열쇠
車両キー
+ Взлом и проникновение
Lock/Unlock Vehicles
@@ -706,6 +748,7 @@
Blocco/Sblocco di Veicoli
차량을 잠그거나 해제합니다
車両のロック/ロック解除
+ Взлом и проникновение
%3Vehicle Keys%4 are used to lock/unlock your vehicles. Vehicle keys can exist for the whole side, or keys can be created for a particular vehicle itself.<br/><br/>%3Usage:%4<br/>%2Equip a %3Vehicle Key%4.<br/>%2Approach the vehicle that the key belongs to.<br/>Use [%3%13%4] and select %3Lock/Unlock Vehicle%4.<br/><br/><t underline='1'>%3Note:%4</t> Lockpicks and keys are only available via scripting or ACE Vehicle Key modules.
diff --git a/addons/grenades/functions/fnc_flashbangExplosionEH.sqf b/addons/grenades/functions/fnc_flashbangExplosionEH.sqf
index bba3cffd4d..36b84f942f 100644
--- a/addons/grenades/functions/fnc_flashbangExplosionEH.sqf
+++ b/addons/grenades/functions/fnc_flashbangExplosionEH.sqf
@@ -63,6 +63,7 @@ _affected = _affected - [ACE_player];
if (_flashReactionDebounce < CBA_missionTime) then {
// Not used interally but could be useful for other mods
_unit setVariable [QGVAR(flashStrength), _strength, true];
+ [QGVAR(flashbangedAI), [_unit, _strength, _grenadePosASL]] call CBA_fnc_localEvent;
{
_unit setSkill [_x, (_unit skill _x) / 50];
} forEach SUBSKILLS;
@@ -162,5 +163,7 @@ if (hasInterface && {!isNull ACE_player} && {alive ACE_player}) then {
private _maxFlinch = linearConversion [0.2, 1, _strength, 0, 95, true];
private _flinch = (_minFlinch + random (_maxFlinch - _minFlinch)) * selectRandom [-1, 1];
ACE_player setDir (getDir ACE_player + _flinch);
+
+ [QGVAR(flashbangedPlayer), [_strength, _grenadePosASL]] call CBA_fnc_localEvent;
};
true
diff --git a/addons/gunbag/XEH_preInit.sqf b/addons/gunbag/XEH_preInit.sqf
index 2bb35513a2..c37533493d 100644
--- a/addons/gunbag/XEH_preInit.sqf
+++ b/addons/gunbag/XEH_preInit.sqf
@@ -26,17 +26,41 @@ PREP_RECOMPILE_END;
}, _this] call CBA_fnc_execNextFrame;
}] call CBA_fnc_addClassEventHandler;
+[QEGVAR(arsenal,loadoutVerified), {
+ 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 {
+ _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, ""];
+ if !(_class != "" && {_class in EGVAR(arsenal,virtualItemsFlat)}) then {
+ _missingItems pushBack _class;
+ _magazines set [_forEachIndex, ["", 0]];
+ };
+ } forEach _magazines;
+ if (_missingItems isNotEqualTo []) then {
+ _missingExtendedInfo pushBack [QGVAR(gunbagWeapon), _missingItems];
+ };
+}] call CBA_fnc_addEventHandler;
+
["CBA_loadoutSet", {
params ["_unit", "_loadout", "_extendedInfo"];
private _gunbagWeapon = _extendedInfo getOrDefault [QGVAR(gunbagWeapon), []];
if (_gunbagWeapon isNotEqualTo []) then {
- if (!isNil QEGVAR(arsenal,virtualItemsFlatAll)) then {
- private _weapon = (_gunbagWeapon select 0) call EFUNC(arsenal,baseWeapon);
- if !(_weapon in EGVAR(arsenal,virtualItemsFlatAll)) then {
- INFO_1("removing [%1] from loadout",_gunbagWeapon);
- _gunbagWeapon = [];
- };
- };
(backpackContainer _unit) setVariable [QGVAR(gunbagWeapon), _gunbagWeapon, true];
};
}] call CBA_fnc_addEventHandler;
diff --git a/addons/inventory/XEH_preStart.sqf b/addons/inventory/XEH_preStart.sqf
index faa0e1691e..cc01ae5ef3 100644
--- a/addons/inventory/XEH_preStart.sqf
+++ b/addons/inventory/XEH_preStart.sqf
@@ -21,10 +21,6 @@ uiNamespace setVariable [QGVAR(backpackKeyCache), compileFinal createHashMapFrom
if (_picture select [0, 1] == "\") then {
_picture = _picture select [1];
};
- if (count _picture > 0 && !(_picture regexMatch ".*?\.paa")) then { // handle missing file extension
- if (!fileExists (_picture + ".paa")) exitWith {};
- _picture = _picture + ".paa";
- };
// Handle missing file extension, as inventory returns path with extension
if (count _picture > 0 && !(_picture regexMatch ".*?\.paa")) then {
diff --git a/addons/irlight/stringtable.xml b/addons/irlight/stringtable.xml
index ac874759a4..ab70abdebd 100644
--- a/addons/irlight/stringtable.xml
+++ b/addons/irlight/stringtable.xml
@@ -10,6 +10,7 @@
DBAL-A3 (rouge)
DBAL-A3 (vermelho)
DBAL-A3 (赤)
+ DBAL-A3 (красный)
DBAL-A3 (green)
@@ -20,6 +21,7 @@
DBAL-A3 (vert)
DBAL-A3 (verde)
DBAL-A3 (緑)
+ DBAL-A3 (зеленый)
<t color='#9cf953'>Use: </t>Turn Laser ON/OFF<br>Double click to switch mode
@@ -30,6 +32,7 @@
<t color='#9cf953'>Utilisation: </t>Allumer/Eteindre le laser<br>Double clic pour changer de mode
<t color='#9cf953'>Uso: </t>Ligar/Desligar Laser<br>Duplo clique para mudar o modo
<t color='#9cf953'>使用方法: </t>レーザーのオン/オフ切り替え<br>ダブルクリックでモード切り替え
+ <t color='#9cf953'>Использование: </t>Включение / выключение лазера <br>Двойной щелчок для переключения режима
Dual Beam Aiming Laser
@@ -40,6 +43,7 @@
Viseur laser à double faisceau
Laser de Pontaria de Duplo Feixe
複合ビーム照準レーザー
+ Двухлучевой прицельный лазер
Visible Laser
@@ -50,6 +54,7 @@
Laser visible
Laser Visível
可視光レーザー
+ Видимый лазер
IR Laser
@@ -60,6 +65,7 @@
Laser IR
Laser IR
IRレーザー
+ ИК-лазер
IR Illuminator
@@ -70,6 +76,7 @@
Illuminateur IR
Iluminador IR
IRイルミネーター
+ ИК-осветитель
IR Laser and Illuminator
@@ -80,6 +87,7 @@
Illuminateur et laser IR
Laser e Iluminador IR
IRレーザーとイルミネーター
+ ИК-лазер и осветитель
Wide Beam
@@ -90,6 +98,7 @@
Faisceau large
Feixe Largo
広角ビーム
+ Широкий луч
Medium Beam
@@ -100,6 +109,7 @@
Faisceau moyen
Feixe Médio
標準ビーム
+ Средний луч
Narrow Beam
@@ -110,6 +120,7 @@
Faisceau étroit
Feixe Estreito
狭角ビーム
+ Узкий луч
<t color='#9cf953'>Use: </t>Turn Light ON/OFF<br>Double click to switch mode
@@ -120,6 +131,7 @@
<t color='#9cf953'>Utilisation: </t>Allumer/Eteindre la lumière<br>Double clic pour changer de mode
<t color='#9cf953'>Uso: </t>Ligar/Desligar Iluminador<br>Duplo clique para mudar o modo
<t color='#9cf953'>使用方法: </t>ライトのオン/オフ<br>ダブルクリックでモード切り替え
+ <t color='#9cf953'>Использование: </t>Включение / выключение освещения <br>Двойной щелчок для переключения режима
Special Purpose IR LED Illuminator
@@ -130,6 +142,7 @@
Illuminateur LED IR à usage spécial
Iluminador LED IR de Uso Especial
特殊用途のIR LEDイルミネーター
+ ИК-светодиодный осветитель специального назначения
Illuminator / Laser Momentary Switch
@@ -140,6 +153,7 @@
Commutateur temporaire illuminateur/laser
Interruptor Momentâneo Iluminador/Laser
イルミネーター/レーザーモーメンタリースイッチ
+ Мгновенный переключатель осветителя/лазера
diff --git a/addons/killtracker/CfgEventHandlers.hpp b/addons/killtracker/CfgEventHandlers.hpp
index 9cc1b0427b..4300a157b9 100644
--- a/addons/killtracker/CfgEventHandlers.hpp
+++ b/addons/killtracker/CfgEventHandlers.hpp
@@ -1,3 +1,9 @@
+class Extended_PreInit_EventHandlers {
+ class ADDON {
+ init = QUOTE(call COMPILE_SCRIPT(XEH_preInit));
+ };
+};
+
class Extended_PostInit_EventHandlers {
class ADDON {
init = QUOTE(call COMPILE_SCRIPT(XEH_postInit));
diff --git a/addons/killtracker/XEH_postInit.sqf b/addons/killtracker/XEH_postInit.sqf
index 9cef418ece..c5adc26692 100644
--- a/addons/killtracker/XEH_postInit.sqf
+++ b/addons/killtracker/XEH_postInit.sqf
@@ -136,7 +136,9 @@ GVAR(killCount) = 0;
_unitName = format ["*AI* - %1", getText ((configOf _unit) >> "displayName")];
};
};
- TRACE_3("send kill event",_killer,_unitName,_killInfo);
- [QGVAR(kill), [_unitName, _killInfo], _killer] call CBA_fnc_targetEvent;
+ if (_unitIsPlayer || GVAR(trackAI)) then {
+ TRACE_3("send kill event",_killer,_unitName,_killInfo);
+ [QGVAR(kill), [_unitName, _killInfo], _killer] call CBA_fnc_targetEvent;
+ };
};
}] call CBA_fnc_addEventHandler;
diff --git a/addons/killtracker/XEH_preInit.sqf b/addons/killtracker/XEH_preInit.sqf
new file mode 100644
index 0000000000..7c7b764686
--- /dev/null
+++ b/addons/killtracker/XEH_preInit.sqf
@@ -0,0 +1,7 @@
+#include "script_component.hpp"
+
+ADDON = false;
+
+#include "initSettings.inc.sqf"
+
+ADDON = true;
diff --git a/addons/killtracker/initSettings.inc.sqf b/addons/killtracker/initSettings.inc.sqf
new file mode 100644
index 0000000000..ebe1e55ccb
--- /dev/null
+++ b/addons/killtracker/initSettings.inc.sqf
@@ -0,0 +1,8 @@
+[
+ QGVAR(trackAI),
+ "CHECKBOX",
+ [LSTRING(TrackAI_DisplayName), LSTRING(TrackAI_Description)],
+ LSTRING(Category),
+ true,
+ 1
+] call CBA_fnc_addSetting;
diff --git a/addons/killtracker/stringtable.xml b/addons/killtracker/stringtable.xml
index 4aa7308924..906e2ca45e 100644
--- a/addons/killtracker/stringtable.xml
+++ b/addons/killtracker/stringtable.xml
@@ -1,6 +1,11 @@
+
+ ACE Kill Tracker
+ ACE Kill Tracker
+ ACE Отслеживание убийств
+
ACE Killed Events
ACE キルトラッカー
@@ -86,5 +91,15 @@
同士討ち
Dost Atışı
+
+ Track AI units killed by player
+ Sledovat AI zabité hráči
+ Отслеживание юнитов ИИ, убитых игроком
+
+
+ Defines if killed AIs will be shown in the kill tracker during mission debriefing.
+ Udává zdali se zabité AI budou ukazovat v kill trackeru v průběhu debriefingu po misi.
+ Определяет, убит ИИ, как будет показано в трекере убийств во время разбора миссии.
+
diff --git a/addons/laser/stringtable.xml b/addons/laser/stringtable.xml
index 7c07582725..f0977c84f7 100644
--- a/addons/laser/stringtable.xml
+++ b/addons/laser/stringtable.xml
@@ -128,6 +128,7 @@
레이저 스팟 추적기: 켬
Traqueur laser : activé
Rastreador a Laser: Ligado
+ Лазерный точечный трекер: Включен
Laser Spot Tracker: Off
@@ -138,6 +139,7 @@
레이저 스팟 추적기: 끔
Traqueur laser : désactivé
Rastreador a Laser: Desligado
+ Лазерный точечный трекер: выключен
Draw Laser on Map
diff --git a/addons/maptools/stringtable.xml b/addons/maptools/stringtable.xml
index fc719473b8..7f02337a17 100644
--- a/addons/maptools/stringtable.xml
+++ b/addons/maptools/stringtable.xml
@@ -39,11 +39,13 @@
Plotting Board
플로팅 보드
標定盤
+ Графическая доска
The Plotting Board is a map tool designed for use in the directing of short range indirect fires.
플로팅 보드는 단거리 간접 사격을 지시하는 데 사용하도록 설계된 독도용 도구입니다.
標定盤(プロッティング・ボード)は、短距離の間接射撃の指示に使用するために設計されたマップツールです。
+ Графическая доска - это картографический инструмент, предназначенный для использования при ведении непрямого огня с малой дистанции.
Channels in which plotting board drawing is enabled.
どのチャンネルで標定盤の書き込みを有効化するか。
플로팅 보드 그리기가 활성화된 채널입니다.
+ Каналы, в которых включено рисование на графической плате.
Allow Direct Comms Only (Polylines Only)
直接チャンネルのみ許可 (線のみ)
직접교신만 허용 (선 긋기만)
+ Разрешать только прямую связь (только полилинии)
Allow Direct/Group Comms (Polylines and Group Markers)
直接/グループチャンネルを許可 (線とグループマーカー)
직접교신/그룹무전망 허용 (선 긋기와 그룹 마커)
+ Разрешить прямую/групповую связь (полилинии и групповые маркеры)
Plotting Board
標定盤
플로팅 보드
+ Графическая доска
Plotting Board Acrylic
標定盤の アクリル板
플로팅 보드 (아크릴)
+ Графическая доска акрилловая
Plotting Board Ruler
標定盤の 定規
플로팅 보드 (자)
+ Линейка для черчения на доске
To Plotting Board
標定盤に
플로팅 보드에
+ К чертежной доске
To Plotting Board Acrylic
標定盤の アクリル板に
플로팅 보드 (아크릴)에
+ К чертежной доске акрилловой
To Plotting Board Ruler
標定盤の 定規に
플로팅 보드 (자)에
+ К линейке для построения чертежной доски
Wipe all markers off Plotting Board
標定盤の 全マーカーを 拭き消す
플로팅 보드에 있는 모든 마커 지우기
+ Сотрите все маркеры с доски для черчения
Show Plotting Board
標定盤を 表示
플로팅 보드 보이기
+ Скрыть графическую доску
Hide Plotting Board
標定盤を 隠す
플로팅 보드 숨기기
+ Переключение линейки для построения графической доски
Toggle Plotting Board Ruler
標定盤の 定規を 表示切替
플로팅 보드 (자) 토글
+ Переключение линейки для построения графической доски
Align
@@ -378,11 +394,13 @@
Up
上に
위로
+ Вверх
To Maptool
マップツールに
독도용 도구로
+ К инструментам карты
diff --git a/addons/markers/stringtable.xml b/addons/markers/stringtable.xml
index 285dd007e8..f08406fce0 100644
--- a/addons/markers/stringtable.xml
+++ b/addons/markers/stringtable.xml
@@ -410,6 +410,7 @@
"MS" - Milissegundos (de 0 a 59)
"MS" - 밀리초 (0부터 59까지)
"MM" - ミリ秒 (0から59)
+ "ММ" - миллисекунды (от 0 до 59)
"mmm" - Milliseconds (from 0 to 999)
@@ -418,6 +419,7 @@
"mmm" - Milissegundos (de 0 a 999)
"mmm" - 밀리초 (0부터 999까지)
"mmm" - ミリ秒 (0から599)
+ "ммм" - миллисекунды (от 0 до 999)
Timestamp Hour Format
diff --git a/addons/medical_ai/stringtable.xml b/addons/medical_ai/stringtable.xml
index 61cebf9fb5..7f5680dc3f 100644
--- a/addons/medical_ai/stringtable.xml
+++ b/addons/medical_ai/stringtable.xml
@@ -57,6 +57,7 @@
Items requis
Exigir Itens
アイテムを要求
+ Требуемые предметы
AI will only perform medical treatment if they have the necessary items in their inventory.
@@ -67,6 +68,7 @@
Les IA n'effectueront un traitement médical que si elles ont le matériel nécessaire dans leur inventaire.
A IA só irá realizar tratamento médico se tiver os itens necessários em seu inventário.
AIのインベントリに必要なアイテムがある場合にのみ治療を実行します。
+ Искусственный интеллект будет оказывать медицинскую помощь только в том случае, если в его инвентаре есть необходимые предметы.
Auto Convert Items for AI
@@ -77,6 +79,7 @@
Conversione automatica di risorse mediche per IA
Conversão automática de itens para IA
AIのアイテムを自動変換
+ Автоматическое преобразование элементов для ИИ
diff --git a/addons/medical_engine/script_macros_medical.hpp b/addons/medical_engine/script_macros_medical.hpp
index 5fecd36413..6f96478406 100644
--- a/addons/medical_engine/script_macros_medical.hpp
+++ b/addons/medical_engine/script_macros_medical.hpp
@@ -53,7 +53,8 @@
#define BLOOD_VOLUME_CLASS_2_HEMORRHAGE 5.100 // lost more than 15% blood, Class II Hemorrhage
#define BLOOD_VOLUME_CLASS_3_HEMORRHAGE 4.200 // lost more than 30% blood, Class III Hemorrhage
#define BLOOD_VOLUME_CLASS_4_HEMORRHAGE 3.600 // lost more than 40% blood, Class IV Hemorrhage
-#define BLOOD_VOLUME_FATAL 3.0 // Lost more than 50% blood, Unrecoverable
+// Lost more than 50% blood, Unrecoverable
+#define BLOOD_VOLUME_FATAL 3.0
// Minimum blood volume, in liters, for a patient to have the chance to wake up
#define MINIMUM_BLOOD_FOR_STABLE_VITALS EGVAR(medical,const_stableVitalsBloodThreshold)
diff --git a/addons/medical_engine/stringtable.xml b/addons/medical_engine/stringtable.xml
index 9a4179a38c..c79b35ad22 100644
--- a/addons/medical_engine/stringtable.xml
+++ b/addons/medical_engine/stringtable.xml
@@ -36,6 +36,7 @@
Fattore di Trapasso Armatura
Efeito de Penetração de Blindagem
装甲貫通効果
+ Эффект сквозного прохождения брони
Controls effect of armor 'passThrough' on final damage. Makes high armor values, like ones used in GL rigs, less effective.\nUse 0% for pre 3.16.0 armor behavior.\nOnly touch this if you know what you're doing!
@@ -46,6 +47,7 @@
Determina l'effetto di danni sul corpo che 'trapassano' l'armatura. Rende alti valori di protezione, come quelli su corpetti GL, meno efficaci.\nUtilizza 0% per il comportamento prima di v3.16.0.\nModifica questo valore solo se sai cosa stai facendo!
Controla o efeito de penetração (passThrough) da blindagem no dano final. Torna valores de blindagem altos, como os usados em coletes GL, menos eficazes.\nUse 0% para o comportamento de blindagem anterior à versão 3.16.0.\nSó mexa nisso se souber o que está fazendo!
ボディアーマーの'passThrough'値が最終的な身体ダメージに与える影響を調整します。擲弾兵リグで使用されるような高い装甲値では効果が低くなります。\n3.16.0以前の挙動にするには0%にしてください。\nこれが何かわからない場合は変更しないことをお勧めします。
+ Контролирует эффект "прохождения" брони при нанесении конечного урона. Делает высокие значения брони, подобные тем, которые используются в GL rigs, менее эффективными.n\используйте 0% для поведения брони до версии 3.16.0.n\прикасайтесь к этому, только если знаете, что делаете!
diff --git a/addons/medical_gui/stringtable.xml b/addons/medical_gui/stringtable.xml
index 438b160bb2..405ee9d9af 100644
--- a/addons/medical_gui/stringtable.xml
+++ b/addons/medical_gui/stringtable.xml
@@ -292,6 +292,7 @@
Sbircia Info Mediche
Medizinische Info anzeigen
医療情報一時表示
+ Просмотрите медицинскую информацию
Medical Peek Duration
@@ -301,6 +302,7 @@
Durata di sbirciamento di info mediche
Dauer zum Anzeigen der medizinischen Info
医療情報一時表示の表示時間
+ Продолжительность медицинского осмотра
How long the medical info peek remains open after releasing the key.
@@ -310,6 +312,7 @@
Wie lange die medizinische Info-Anzeige nach dem Loslassen der Taste geöffnet bleibt.
Durata di visualizzazione delle Info Mediche dopo aver rilasciato il tasto.
医療情報一時表示キーを放してからどれだけ長く情報表示するか。
+ Как долго окно просмотра медицинской информации остается открытым после отпускания клавиши.
Load Patient
@@ -562,6 +565,7 @@
Wechseln zu selbst
Passa a te stesso
自分に切り替え
+ Переключиться на себя
Switch to target
@@ -571,6 +575,7 @@
Wechseln zu Ziel
Passa al paziente
相手に切り替え
+ Переключиться на цель
Head
@@ -996,6 +1001,7 @@
Keine Blutung
Nessuna emorragia
出血はしていない
+ Кровотечения нет
Slow bleeding
@@ -1005,6 +1011,7 @@
Langsame Blutung
Debole emorragia
出血は穏やか
+ Медленное кровотечение
Moderate bleeding
@@ -1014,6 +1021,7 @@
Mäßige Blutung
Emorraggia moderata
出血はそこそこ速い
+ Умеренное кровотечение
Severe bleeding
@@ -1023,6 +1031,7 @@
Schwere Blutung
Forte emorragia
出血は激しい
+ Сильное кровотечение
Massive bleeding
@@ -1032,6 +1041,7 @@
Massive Blutung
Gravissima emorragia
出血は酷く多い
+ Сильное кровотечение
in Pain
@@ -1105,6 +1115,7 @@
Kein Blutverlust
Nessuna perdita di sangue
失血なし
+ Потери крови нет
@@ -1355,6 +1366,7 @@
Mostra info mediche se colpito
Zeige medizinische Info beim Treffer an
被弾時の医療情報一時表示
+ Просмотрите медицинскую информацию о попадании
Temporarily show medical info when injured.
@@ -1365,6 +1377,7 @@
Mostra temporaneamente le info mediche quando si viene feriti.
Bei Verletzungen vorübergehend medizinische Info anzeigen.
被弾時に医療情報を一時的に表示します。
+ Временно показывать медицинскую информацию при травме.
Medical Peek Duration on Hit
@@ -1375,6 +1388,7 @@
Durata di info mediche quando colpito
Dauer der Anzeige bei einem Treffer.
被弾時の医療情報一時表示の表示時間
+ Продолжительность медицинского осмотра при попадании
How long the medical info peek remains open after being injured.
@@ -1385,6 +1399,7 @@
Quanto tempo verranno visualizzate le info mediche quando si viene feriti.
Wie lange die medizinische Info nach einer Verletzung angezeigt wird.
被弾時の医療情報の一時表示をどれだけ長く表示するか。
+ Как долго окно просмотра медицинской информации остается открытым после получения травмы.
Show Trauma Sustained
@@ -1396,6 +1411,7 @@
외상 지속 표시
显示遭受的创伤
Afficher les traumatismes subis
+ Показать полученную травму
Show trauma sustained in the injury list.
@@ -1407,6 +1423,7 @@
부상 목록에 발생한 외상을 표시합니다.
在伤情表上显示创伤
Afficher les traumatismes subis dans la liste des blessures.
+ Показать полученную травму в списке травм.
Body Part Outline Color
@@ -1417,6 +1434,7 @@
Colore del contorno di parti del corpo
Umrissfarbe des Körperteils
身体部位の輪郭表示の色
+ Цвет контура части тела
Color of outline around selected body part.
@@ -1427,6 +1445,7 @@
Colore del contorno della parte del corpo selezionata.
Farbe des Umrisses um das ausgewählten Körperteil.
選択した身体部位の輪郭表示の色。
+ Цвет контура вокруг выбранной части тела.
Minor Trauma
@@ -1438,6 +1457,7 @@
약한 외상
轻微创伤
Traumatisme mineur
+ Незначительная травма
Major Trauma
@@ -1449,6 +1469,7 @@
중간 외상
中度创伤
Traumatisme majeur
+ Серьезная травма
Severe Trauma
@@ -1460,6 +1481,7 @@
강한 외상
重度创伤
Traumatisme grave
+ Тяжелая травма
Chronic Trauma
@@ -1471,6 +1493,7 @@
심각한 외상
慢性创伤
Traumatisme chronique
+ Хроническая травма
L
@@ -1481,6 +1504,7 @@
Sx
L
左
+ Лево
R
@@ -1491,6 +1515,7 @@
Dx
R
右
+ Право
in your inventory
@@ -1501,6 +1526,7 @@
Nel proprio inventario
im Inventar
個あなたが保有
+ в вашем инвентаре
in patient's inventory
@@ -1511,6 +1537,7 @@
Nell'inventario del paziente
im Inventar des Patienten
個患者が保有
+ в инвентаре пациента
in vehicle's inventory
@@ -1521,6 +1548,7 @@
im Inventar des Fahrzeuges
Nell'inventario del veicolo
個車両内に保有
+ в инвентаре транспорта
No effect until tourniquet removed
@@ -1530,6 +1558,7 @@
Keine Wirkung, bis das Tourniquet entfernt wurde
Nessun effetto fino alla rimozione del laccio emostatico
止血帯を外すまで効果を発揮しません
+ Никакого эффекта до тех пор, пока жгут не будет снят
Show Tourniquet Warning
@@ -1539,6 +1568,7 @@
Tourniquet-Warnung anzeigen
Mostra avviso di laccio emostatico
止血帯の警告を表示
+ Показать предупреждение о наложении жгута
Show a warning tooltip when a tourniquet will interfere with a medical action.
@@ -1548,6 +1578,7 @@
Zeigt einen Hinweis an, wenn ein Tourniquet eine medizinische Maßnahme beeinträchtigt.
Mostra un avviso se un laccio emostatico impedisce un trattamento medico.
止血帯が医療行為を妨げる場合には、警告ツールチップを表示します。
+ Показать всплывающую подсказку с предупреждением, когда жгут помешает медицинскому вмешательству.
diff --git a/addons/medical_status/stringtable.xml b/addons/medical_status/stringtable.xml
index f3f3d605d5..01c2cc21c6 100644
--- a/addons/medical_status/stringtable.xml
+++ b/addons/medical_status/stringtable.xml
@@ -125,6 +125,7 @@
무기 떨어뜨릴 확률
Risque de perte d'arme
武器を落とす確率
+ Шанс выпадения оружия
Chance for a player to drop their weapon when going unconscious.\nHas no effect on AI.
@@ -134,6 +135,7 @@
플레이어가 기절할 때 무기를 떨어뜨릴 확률입니다.\nAI는 영향을 받지 않습니다.
Pourcentage de chances pour un joueur de lâcher son arme lorsqu'il perd connaissance.\nAucun effet sur les IA.
プレーヤーが意識を失ったときに武器を落とす可能性。\nAI には影響しません。
+ Шанс для игрока выронить свое оружие, когда он теряет сознание.n\Не влияет на ИИ
diff --git a/addons/medical_treatment/ACE_Medical_Treatment.hpp b/addons/medical_treatment/ACE_Medical_Treatment.hpp
index d1ea741cb3..267a45dd44 100644
--- a/addons/medical_treatment/ACE_Medical_Treatment.hpp
+++ b/addons/medical_treatment/ACE_Medical_Treatment.hpp
@@ -565,8 +565,11 @@ class ADDON {
timeInSystem = 120;
// How long until the maximum effect is reached
timeTillMaxEffect = 30;
- // How many of this type of medication can be in the system before the patient overdoses?
+ // How many of this type of medication can be in the system before the patient can possibly overdose?
maxDose = 4;
+ // The number of doses over maxDose where there is a chance to overdose.
+ // Example with maxDose = 4 and maxDoseDeviation = 2: Dose 4: Safe | Dose 5 and 6: Possible overdose | Dose 7: Guaranteed overdose
+ maxDoseDeviation = 2;
// Function to execute upon overdose. Arguments passed to call back are 0: unit