diff --git a/.github/release-drafter.yml b/.github/release-drafter.yml index f78465887e..2ba4cbfcaf 100644 --- a/.github/release-drafter.yml +++ b/.github/release-drafter.yml @@ -5,6 +5,9 @@ branches: name-template: 'Version $NEXT_PATCH_VERSION' tag-template: 'v$NEXT_PATCH_VERSION' +sort-by: title # sort alphabetically +sort-direction: ascending + categories: - title: '**ADDED:**' labels: diff --git a/.hemtt/project.toml b/.hemtt/project.toml index 60cff33c2d..206bf9573c 100644 --- a/.hemtt/project.toml +++ b/.hemtt/project.toml @@ -28,9 +28,6 @@ exclude = [ "zeus/functions/fnc_zeusAttributes.sqf", ] -[hemtt.config] -preset = "Hemtt" - [hemtt.launch] workshop = [ "450814997", # CBA_A3 diff --git a/addons/advanced_fatigue/XEH_postInit.sqf b/addons/advanced_fatigue/XEH_postInit.sqf index d447c3f651..57b57dcf22 100644 --- a/addons/advanced_fatigue/XEH_postInit.sqf +++ b/addons/advanced_fatigue/XEH_postInit.sqf @@ -60,7 +60,7 @@ if (!hasInterface) exitWith {}; }, true] call CBA_fnc_addPlayerEventHandler; // - Duty factors ------------------------------------------------------------- - if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then { + if (["ace_medical"] call EFUNC(common,isModLoaded)) then { [QEGVAR(medical,pain), { // 0->1.0, 0.5->1.05, 1->1.1 linearConversion [0, 1, (_this getVariable [QEGVAR(medical,pain), 0]), 1, 1.1, true]; }] call FUNC(addDutyFactor); @@ -68,7 +68,7 @@ if (!hasInterface) exitWith {}; linearConversion [6, 0, (_this getVariable [QEGVAR(medical,bloodVolume), 6]), 1, 2, true]; }] call FUNC(addDutyFactor); }; - if (["ACE_Dragging"] call EFUNC(common,isModLoaded)) then { + if (["ace_dragging"] call EFUNC(common,isModLoaded)) then { [QEGVAR(dragging,isCarrying), { [1, 3] select (_this getVariable [QEGVAR(dragging,isCarrying), false]); }] call FUNC(addDutyFactor); diff --git a/addons/arsenal/functions/fnc_addDefaultLoadout.sqf b/addons/arsenal/functions/fnc_addDefaultLoadout.sqf index b9b8853f15..f54ff03eeb 100644 --- a/addons/arsenal/functions/fnc_addDefaultLoadout.sqf +++ b/addons/arsenal/functions/fnc_addDefaultLoadout.sqf @@ -20,8 +20,9 @@ params [["_name", "", [""]], ["_loadout", [], [[]]], ["_global", false, [false]]]; -if (_global) then { - [QGVAR(addDefaultLoadout), [_name, _loadout]] call CBA_fnc_remoteEvent; +if (_global) exitWith { + private _eventID = format [QGVAR(loadouts_%1), _name]; + [QGVAR(addDefaultLoadout), [_name, _loadout], _eventID] call CBA_fnc_globalEventJIP; }; private _extendedInfo = createHashMap; diff --git a/addons/arsenal/functions/fnc_buttonCargo.sqf b/addons/arsenal/functions/fnc_buttonCargo.sqf index 48c5ee477e..d7713a2518 100644 --- a/addons/arsenal/functions/fnc_buttonCargo.sqf +++ b/addons/arsenal/functions/fnc_buttonCargo.sqf @@ -47,8 +47,8 @@ private _container = switch (GVAR(currentLeftPanel)) do { }; }; - /// Get all items from container (excluding container itself) - _containerItems = [GVAR(center), 0, 3, 0, 0, false] call EFUNC(common,uniqueUnitItems); + // Get all items from container + _containerItems = uniformItems GVAR(center); // Update currentItems GVAR(currentItems) set [IDX_CURR_UNIFORM_ITEMS, ((getUnitLoadout GVAR(center)) select IDX_LOADOUT_UNIFORM) param [1, []]]; @@ -75,8 +75,8 @@ private _container = switch (GVAR(currentLeftPanel)) do { }; }; - // Get all items from container (excluding container itself) - _containerItems = [GVAR(center), 0, 0, 3, 0, false] call EFUNC(common,uniqueUnitItems); + // Get all items from container + _containerItems = vestItems GVAR(center); // Update currentItems GVAR(currentItems) set [IDX_CURR_VEST_ITEMS, ((getUnitLoadout GVAR(center)) select IDX_LOADOUT_VEST) param [1, []]]; @@ -103,8 +103,8 @@ private _container = switch (GVAR(currentLeftPanel)) do { }; }; - // Get all items from container (excluding container itself) - _containerItems = [GVAR(center), 0, 0, 0, 3, false] call EFUNC(common,uniqueUnitItems); + // Get all items from container + _containerItems = backpackItems GVAR(center); // Update currentItems GVAR(currentItems) set [IDX_CURR_BACKPACK_ITEMS, ((getUnitLoadout GVAR(center)) select IDX_LOADOUT_BACKPACK) param [1, []]]; @@ -117,7 +117,7 @@ private _container = switch (GVAR(currentLeftPanel)) do { }; // Find out how many items of that type there are and update the number displayed -_ctrlList lnbSetText [[_lnbCurSel, 2], str (_containerItems getOrDefault [_item, 0])]; +_ctrlList lnbSetText [[_lnbCurSel, 2], str ({_item == _x} count _containerItems)]; [QGVAR(cargoChanged), [_display, _item, _addOrRemove, GVAR(shiftState)]] call CBA_fnc_localEvent; diff --git a/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf b/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf index 87191a99c2..d25fa485cf 100644 --- a/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf +++ b/addons/arsenal/functions/fnc_buttonLoadoutsRename.sqf @@ -43,11 +43,7 @@ private _loadoutIndex = _data findIf {(_x select 0) == _loadoutName}; (_data select _loadoutIndex) set [0, _editBoxContent]; if (GVAR(currentLoadoutsTab) == IDC_buttonDefaultLoadouts) then { - if (is3DEN) then { - set3DENMissionAttributes [[QGVAR(DummyCategory), QGVAR(DefaultLoadoutsListAttribute), GVAR(defaultLoadoutsList)]]; - } else { - [QGVAR(renameDefaultLoadout), [_loadoutName, _editBoxContent]] call CBA_fnc_remoteEvent; - }; + set3DENMissionAttributes [[QGVAR(DummyCategory), QGVAR(DefaultLoadoutsListAttribute), GVAR(defaultLoadoutsList)]]; }; private _currentLoadoutsTab = str GVAR(currentLoadoutsTab); diff --git a/addons/arsenal/functions/fnc_fillRightPanel.sqf b/addons/arsenal/functions/fnc_fillRightPanel.sqf index c562e8727d..346e07fa59 100644 --- a/addons/arsenal/functions/fnc_fillRightPanel.sqf +++ b/addons/arsenal/functions/fnc_fillRightPanel.sqf @@ -44,10 +44,14 @@ private _cfgMagazines = configFile >> "CfgMagazines"; private _cfgWeapons = configFile >> "CfgWeapons"; private _rightPanelCache = uiNamespace getVariable QGVAR(rightPanelCache); -private _currentCargo = itemsWithMagazines GVAR(center); +private _currentCargo = []; // we only need this if we're filtering for favorites +if (GVAR(favoritesOnly)) then { + _currentCargo = itemsWithMagazines GVAR(center) + backpacks GVAR(center); + _currentCargo = _currentCargo arrayIntersect _currentCargo; +}; private _fnc_fillRightContainer = { - params ["_configCategory", "_className", "_hasItemInfo", ["_isUnique", false, [false]], ["_unknownOrigin", false, [false]]]; + params ["_configCategory", "_className", ["_isUnique", false, [false]], ["_unknownOrigin", false, [false]]]; if (GVAR(favoritesOnly) && {!(_className in _currentCargo)} && {!((toLower _className) in GVAR(favorites))}) exitWith {}; @@ -64,7 +68,6 @@ private _fnc_fillRightContainer = { // "Misc. items" magazines (e.g. spare barrels, intel, photos) if (_className in (uiNamespace getVariable QGVAR(magazineMiscItems))) then { _configPath = _cfgMagazines >> _className; - _hasItemInfo = false; }; // If an item with unknown origin is in the arsenal list, try to find it @@ -75,34 +78,15 @@ private _fnc_fillRightContainer = { if (isNull _configPath) then { _configPath = _className call CBA_fnc_getObjectConfig; }; - - // Check if item is has item info - _itemInfo = isClass (_cfgWeapons >> configName _configPath); }; - // Get mass - private _mass = if (!_hasItemInfo) then { - getNumber (_configPath >> "mass") - } else { - private _mass = getNumber (_configPath >> "itemInfo" >> "mass"); - - if (_mass == 0) then { - _mass = getNumber (_configPath >> "WeaponSlotsInfo" >> "mass"); - }; - - _mass - }; - - _rightPanelCache set [_className, _mass]; // Needed because this provides more accurate weight for FUNC(updateRightPanel) - - [getText (_configPath >> "displayName"), getText (_configPath >> "picture"), _mass] - }, true]) params ["_displayName", "_picture", "_mass"]; + [getText (_configPath >> "displayName"), getText (_configPath >> "picture")] + }, true]) params ["_displayName", "_picture"]; private _lbAdd = _ctrlPanel lnbAddRow ["", _displayName, "0"]; _ctrlPanel lnbSetText [[_lbAdd, 1], _displayName]; _ctrlPanel lnbSetData [[_lbAdd, 0], _className]; _ctrlPanel lnbSetPicture [[_lbAdd, 0], _picture]; - _ctrlPanel lnbSetValue [[_lbAdd, 0], _mass]; _ctrlPanel lnbSetValue [[_lbAdd, 2], [0, 1] select _isUnique]; _ctrlPanel lnbSetTooltip [[_lbAdd, 0], format ["%1\n%2", _displayName, _className]]; if ((toLower _className) in GVAR(favorites)) then { @@ -230,11 +214,11 @@ switch (_ctrlIDC) do { } forEach _compatibleItems; } else { { - ["CfgWeapons", _x, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x] call _fnc_fillRightContainer; } forEach (keys ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get _index)); { - ["CfgWeapons", _x, true, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x, true] call _fnc_fillRightContainer; } forEach (keys ((GVAR(virtualItems) get IDX_VIRT_UNIQUE_ATTACHMENTS) get _index)); }; }; @@ -253,44 +237,44 @@ switch (_ctrlIDC) do { case IDC_buttonMag: { { if (_x in (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL)) then { - ["CfgMagazines", _x, false] call _fnc_fillRightContainer; + ["CfgMagazines", _x] call _fnc_fillRightContainer; continue; }; if (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_VIRT_ITEMS_ALL)) then { - ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer; + ["CfgMagazines", _x, true] call _fnc_fillRightContainer; }; } forEach (keys _compatibleMagsAll); }; // All magazines case IDC_buttonMagALL: { { - ["CfgMagazines", _x, false] call _fnc_fillRightContainer; + ["CfgMagazines", _x] call _fnc_fillRightContainer; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL)); { - ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer; + ["CfgMagazines", _x, true] call _fnc_fillRightContainer; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_VIRT_ITEMS_ALL)); }; // Grenades case IDC_buttonThrow: { { - ["CfgMagazines", _x, false] call _fnc_fillRightContainer; + ["CfgMagazines", _x] call _fnc_fillRightContainer; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_GRENADES)); { - ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer; + ["CfgMagazines", _x, true] call _fnc_fillRightContainer; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GRENADES)); }; // Explosives case IDC_buttonPut: { { - ["CfgMagazines", _x, false] call _fnc_fillRightContainer; + ["CfgMagazines", _x] call _fnc_fillRightContainer; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_EXPLOSIVES)); { - ["CfgMagazines", _x, false, true] call _fnc_fillRightContainer; + ["CfgMagazines", _x, true] call _fnc_fillRightContainer; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_EXPLOSIVES)); }; // Misc. items @@ -309,33 +293,35 @@ switch (_ctrlIDC) do { // "Regular" misc. items { if !(_x in _items) then { - ["CfgWeapons", _x, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x] call _fnc_fillRightContainer; }; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)); // Unique items { if !(_x in _items) then { - ["CfgWeapons", _x, true, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x, true] call _fnc_fillRightContainer; }; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_MISC_ITEMS)); // Unique backpacks { if !(_x in _items) then { - ["CfgVehicles", _x, false, true] call _fnc_fillRightContainer; + ["CfgVehicles", _x, true] call _fnc_fillRightContainer; }; } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_BACKPACKS)); // Unique goggles { if !(_x in _items) then { - ["CfgGlasses", _x, false, true] call _fnc_fillRightContainer; + // _y indicates if an item is truly unique or if it's a non-inventory item in a container (e.g. goggles in backpack) + ["CfgGlasses", _x, _y] call _fnc_fillRightContainer; }; - } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES)); + } forEach (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES); // Unknown items { if !(_x in _items) then { - ["CfgWeapons", _x, true, true, true] call _fnc_fillRightContainer; + // _y indicates if an item is truly unique or if it's a non-inventory item in a container (e.g. helmet in backpack) + ["CfgWeapons", _x, _y, true] call _fnc_fillRightContainer; }; - } forEach (keys (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS)); + } forEach (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS); // if an item is here but in virtual items, it's just in the wrong place }; // Custom buttons default { @@ -347,23 +333,23 @@ switch (_ctrlIDC) do { switch (true) do { // "Regular" misc. items case (_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)): { - ["CfgWeapons", _x, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x] call _fnc_fillRightContainer; }; // Unique items case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_MISC_ITEMS)): { - ["CfgWeapons", _x, true, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x, true] call _fnc_fillRightContainer; }; // Unique backpacks case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_BACKPACKS)): { - ["CfgVehicles", _x, false, true] call _fnc_fillRightContainer; + ["CfgVehicles", _x, true] call _fnc_fillRightContainer; }; // Unique goggles case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES)): { - ["CfgGlasses", _x, false, true] call _fnc_fillRightContainer; + ["CfgGlasses", _x, GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES get _x] call _fnc_fillRightContainer; }; // Unknown items case (_x in (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS)): { - ["CfgWeapons", _x, true, true, true] call _fnc_fillRightContainer; + ["CfgWeapons", _x, GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS get _x, true] call _fnc_fillRightContainer; }; }; } forEach _items; @@ -389,8 +375,8 @@ if (_isContainer) then { // Update load bar (_display displayCtrl IDC_loadIndicatorBar) progressSetPosition (loadUniform GVAR(center)); - // Get all items from container (excluding container itself) - _containerItems = [GVAR(center), 0, 3, 0, 0, false] call EFUNC(common,uniqueUnitItems); + // Get all items from container + _containerItems = uniformItems GVAR(center); uniformContainer GVAR(center) }; @@ -399,8 +385,8 @@ if (_isContainer) then { // Update load bar (_display displayCtrl IDC_loadIndicatorBar) progressSetPosition (loadVest GVAR(center)); - // Get all items from container (excluding container itself) - _containerItems = [GVAR(center), 0, 0, 3, 0, false] call EFUNC(common,uniqueUnitItems); + // Get all items from container + _containerItems = vestItems GVAR(center); vestContainer GVAR(center) }; @@ -409,8 +395,8 @@ if (_isContainer) then { // Update load bar (_display displayCtrl IDC_loadIndicatorBar) progressSetPosition (loadBackpack GVAR(center)); - // Get all items from container (excluding container itself) - _containerItems = [GVAR(center), 0, 0, 0, 3, false] call EFUNC(common,uniqueUnitItems); + // Get all items from container + _containerItems = backpackItems GVAR(center); backpackContainer GVAR(center) }; @@ -418,7 +404,8 @@ if (_isContainer) then { // Find out how many items of a type there are and update the number displayed for "_lbIndex" from 0 to (lnbSize _ctrlPanel select 0) - 1 do { - _ctrlPanel lnbSetText [[_lbIndex, 2], str (_containerItems getOrDefault [_ctrlPanel lnbData [_lbIndex, 0], 0])]; + private _xItem = _ctrlPanel lnbData [_lbIndex, 0]; + _ctrlPanel lnbSetText [[_lbIndex, 2], str ({_xItem == _x} count _containerItems)]; }; // Refresh availibility of items based on space remaining in container diff --git a/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf b/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf index a0203ff5b9..a8938e8c48 100644 --- a/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf +++ b/addons/arsenal/functions/fnc_loadoutsChangeTab.sqf @@ -63,6 +63,7 @@ switch (ctrlIDC _control) do { _saveButtonCtrl ctrlSetTooltip LLSTRING(buttonSaveTooltip); }; + _renameButtonCtrl ctrlEnable is3DEN; // no renaming mid-mission _saveButtonCtrl ctrlEnable call FUNC(canEditDefaultLoadout); _saveButtonCtrl ctrlCommit 0; }; diff --git a/addons/arsenal/functions/fnc_onArsenalClose.sqf b/addons/arsenal/functions/fnc_onArsenalClose.sqf index c6a1da0215..bc862f2de0 100644 --- a/addons/arsenal/functions/fnc_onArsenalClose.sqf +++ b/addons/arsenal/functions/fnc_onArsenalClose.sqf @@ -51,13 +51,6 @@ if (is3DEN) then { ["ShowInterface", true] call BIS_fnc_3DENInterface; GVAR(visionMode) call BIS_fnc_3DENVisionMode; } else { - // Select correct weapon - switch (GVAR(selectedWeaponType)) do { - case 0: {GVAR(center) selectWeapon (primaryWeapon GVAR(center))}; - case 1: {GVAR(center) selectWeapon (secondaryWeapon GVAR(center))}; - case 2: {GVAR(center) selectWeapon (handgunWeapon GVAR(center))}; - }; - if (!isNull curatorCamera && {ACE_player == player}) then { curatorCamera cameraEffect ["Internal", "BACK"]; } else { diff --git a/addons/arsenal/functions/fnc_onArsenalOpen.sqf b/addons/arsenal/functions/fnc_onArsenalOpen.sqf index 5e35500248..bcc91c133a 100644 --- a/addons/arsenal/functions/fnc_onArsenalOpen.sqf +++ b/addons/arsenal/functions/fnc_onArsenalOpen.sqf @@ -243,7 +243,15 @@ GVAR(refreshing) = false; _panel ctrlCommit 0; } forEach [IDC_leftTabContent, IDC_rightTabContent, IDC_rightTabContentListnBox]; -[_display, _display displayCtrl IDC_buttonPrimaryWeapon] call FUNC(fillLeftPanel); +// Open left panel for current weapon, do some math +GVAR(selectedWeaponType) = [primaryWeapon GVAR(center), secondaryWeapon GVAR(center), handgunWeapon GVAR(center), binocular GVAR(center)] find (currentWeapon GVAR(center)); +if (GVAR(selectedWeaponType) == -1) then { + GVAR(selectedWeaponType) = 0; // default to primary +}; + +private _leftPanelIDC = [IDC_buttonPrimaryWeapon, IDC_buttonSecondaryWeapon, IDC_buttonHandgun, IDC_buttonBinoculars] select GVAR(selectedWeaponType); + +[_display, _display displayCtrl _leftPanelIDC] call FUNC(fillLeftPanel); //--------------- Init camera if (isNil QGVAR(cameraPosition)) then { diff --git a/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf b/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf index e84aad5c04..3ca877f7fd 100644 --- a/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf +++ b/addons/arsenal/functions/fnc_removeDefaultLoadout.sqf @@ -17,8 +17,10 @@ */ params [["_name", "", [""]], ["_global", false, [false]]]; -if (_global) then { - [QGVAR(removeDefaultLoadout), [_name]] call CBA_fnc_remoteEvent; +if (_global) exitWith { + private _eventID = format [QGVAR(loadouts_%1), _name]; + [_eventID] call CBA_fnc_removeGlobalEventJIP; + [QGVAR(removeDefaultLoadout), [_name]] call CBA_fnc_globalEvent; }; GVAR(defaultLoadoutsList) deleteAt (GVAR(defaultLoadoutsList) findIf {(_x select 0) == _name}); diff --git a/addons/arsenal/functions/fnc_showItem.sqf b/addons/arsenal/functions/fnc_showItem.sqf index 76a95e6981..7ceda5f0d5 100644 --- a/addons/arsenal/functions/fnc_showItem.sqf +++ b/addons/arsenal/functions/fnc_showItem.sqf @@ -15,6 +15,10 @@ if (GVAR(centerNotPlayer)) exitWith {}; +if (EGVAR(common,isReloading)) exitWith { // if player is reloading then wait until it's done so we don't send magazines to the shadow realm + [{!EGVAR(common,isReloading)}, FUNC(showItem)] call CBA_fnc_waitUntilAndExecute; +}; + // Determine action to play based on current category selection private _nextAction = switch (GVAR(currentLeftPanel)) do { // Primary weapon @@ -54,10 +58,12 @@ if (_nextAction != GVAR(currentAction)) then { case "PrimaryWeapon": {0}; case "SecondaryWeapon": {1}; case "HandGunOn": {2}; + case "Binoculars": {3}; default {GVAR(selectedWeaponType)}; }; if (simulationEnabled GVAR(center)) then { + GVAR(center) call EFUNC(common,stopGesture); // reset gesture state (if arsenal is opened on animation transition, animations played whilst in the arsenal break) GVAR(center) playActionNow _nextAction; } else { GVAR(center) switchAction _nextAction; @@ -65,3 +71,7 @@ if (_nextAction != GVAR(currentAction)) then { GVAR(currentAction) = _nextAction; }; + +if (!(GVAR(currentAction) in ["Civil", "Salute"])) then { + GVAR(center) selectWeapon ([primaryWeapon GVAR(center), secondaryWeapon GVAR(center), handgunWeapon GVAR(center), binocular GVAR(center)] select GVAR(selectedWeaponType)); // select correct weapon, prevents floating weapons +}; diff --git a/addons/arsenal/functions/fnc_updateRightPanel.sqf b/addons/arsenal/functions/fnc_updateRightPanel.sqf index e51f923655..e43f06c74f 100644 --- a/addons/arsenal/functions/fnc_updateRightPanel.sqf +++ b/addons/arsenal/functions/fnc_updateRightPanel.sqf @@ -18,19 +18,18 @@ params ["_control", "_container", "_hasItems"]; private _loadRemaining = maxLoad _container - loadAbs _container; -private _rightPanelCache = uiNamespace getVariable [QGVAR(rightPanelCache), createHashMap]; -private _mass = -1; +private _item = ""; private _color = []; private _alpha = 1; // Grey out items that are too big to fit in remaining space of the container for "_row" from 0 to (lnbSize _control select 0) - 1 do { - _mass = _rightPanelCache getOrDefault [_control lnbData [_row, 0], 0]; + _item = _control lnbData [_row, 0]; _color = _control lnbColor [_row, 1]; // Lower alpha on color for items that can't fit - _alpha = [0.25, 1] select (_mass <= _loadRemaining); + _alpha = [0.25, 1] select (_container canAdd _item); _color set [3, _alpha]; _control lnbSetColor [[_row, 1], _color]; _control lnbSetColor [[_row, 2], [1, 1, 1, _alpha]]; @@ -55,6 +54,6 @@ private _curSel = lnbCurSelRow _control; // Disable '+' button if item is unique or too big to fit in remaining space if (_curSel != -1) then { private _plusButtonCtrl = _display displayCtrl IDC_arrowPlus; - _plusButtonCtrl ctrlEnable !((_control lnbValue [_curSel, 2]) == 1 || {(_rightPanelCache getOrDefault [_control lnbData [_curSel, 0], 0]) > _loadRemaining}); + _plusButtonCtrl ctrlEnable ((_control lnbValue [_curSel, 2]) != 1 && {_container canAdd (_control lnbData [_curSel, 0])}); _plusButtonCtrl ctrlCommit FADE_DELAY; }; diff --git a/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf b/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf index ccbf7b7abb..fddc9b3b9c 100644 --- a/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf +++ b/addons/arsenal/functions/fnc_updateUniqueItemsList.sqf @@ -125,7 +125,8 @@ private _fnc_uniqueEquipment = { }; } forEach (getUnitLoadout GVAR(center)); // Only need items, not extended loadout - +// Get all items from unit +_items = itemsWithMagazines GVAR(center) + backpacks GVAR(center); private _isMagazine = false; private _isWeapon = false; private _isGrenade = false; @@ -136,6 +137,9 @@ private _simulationType = ""; private _configItemInfo = ""; private _hasItemInfo = false; private _itemInfoType = 0; +private _baseWeapon = ""; +private _weapons = GVAR(virtualItems) get IDX_VIRT_WEAPONS; +private _attachments = GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS; { _isMagazine = isClass (_cfgMagazines >> _x); @@ -184,8 +188,13 @@ private _itemInfoType = 0; // Unknown default { // Don't add items that are part of the arsenal - if !(_x in GVAR(virtualItemsFlatAll)) then { - (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, nil]; + if ( + !(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)) && + {!(_x in (GVAR(virtualItems) get IDX_VIRT_GRENADES))} && + {!(_x in (GVAR(virtualItems) get IDX_VIRT_EXPLOSIVES))} && + {!(_x in (GVAR(virtualItems) get IDX_VIRT_ITEMS_ALL))} + ) then { + (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, true]; }; }; }; @@ -199,11 +208,17 @@ private _itemInfoType = 0; _itemInfoType = if (_hasItemInfo) then {getNumber (_configItemInfo >> "type")} else {0}; _isMiscItem = _x isKindOf ["CBA_MiscItem", _cfgWeapons]; + _baseWeapon = if (!_isMiscItem) then { + _x call FUNC(baseWeapon) + } else { + _x + }; + switch (true) do { // Optics case ( - !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_OPTICS_ATTACHMENTS)) && - {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_OPTICS_ATTACHMENTS) || + !(_baseWeapon in (_attachments get IDX_VIRT_OPTICS_ATTACHMENTS)) && + {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_OPTICS_ATTACHMENTS) || {_hasItemInfo && {!_isMiscItem} && {_itemInfoType == TYPE_OPTICS}}} @@ -212,8 +227,8 @@ private _itemInfoType = 0; }; // Flashlights case ( - !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_FLASHLIGHT_ATTACHMENTS)) && - {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_FLASHLIGHT_ATTACHMENTS) || + !(_baseWeapon in (_attachments get IDX_VIRT_FLASHLIGHT_ATTACHMENTS)) && + {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_FLASHLIGHT_ATTACHMENTS) || {_hasItemInfo && {!_isMiscItem} && {_itemInfoType == TYPE_FLASHLIGHT}}} @@ -222,8 +237,8 @@ private _itemInfoType = 0; }; // Muzzle attachments case ( - !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_MUZZLE_ATTACHMENTS)) && - {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_MUZZLE_ATTACHMENTS) || + !(_baseWeapon in (_attachments get IDX_VIRT_MUZZLE_ATTACHMENTS)) && + {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_MUZZLE_ATTACHMENTS) || {_hasItemInfo && {!_isMiscItem} && {_itemInfoType == TYPE_MUZZLE}}} @@ -232,8 +247,8 @@ private _itemInfoType = 0; }; // Bipods case ( - !(_x in ((GVAR(virtualItems) get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_BIPOD_ATTACHMENTS)) && - {_x in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_BIPOD_ATTACHMENTS) || + !(_baseWeapon in (_attachments get IDX_VIRT_BIPOD_ATTACHMENTS)) && + {_baseWeapon in ((_configItems get IDX_VIRT_ATTACHMENTS) get IDX_VIRT_BIPOD_ATTACHMENTS) || {_hasItemInfo && {!_isMiscItem} && {_itemInfoType == TYPE_BIPOD}}} @@ -242,7 +257,7 @@ private _itemInfoType = 0; }; // Misc. items case ( - !(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)) && + !(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS)) && // misc. items don't use 'baseWeapon' {_x in (_configItems get IDX_VIRT_MISC_ITEMS) || {_hasItemInfo && {_isMiscItem && @@ -254,9 +269,21 @@ private _itemInfoType = 0; }; // Unknown default { - // Don't add items that are part of the arsenal - if !(_x in GVAR(virtualItemsFlatAll)) then { - (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, nil]; + // Don't add attachments or misc. items + if ( + !(_baseWeapon in (_attachments get IDX_VIRT_OPTICS_ATTACHMENTS)) && + {!(_baseWeapon in (_attachments get IDX_VIRT_FLASHLIGHT_ATTACHMENTS))} && + {!(_baseWeapon in (_attachments get IDX_VIRT_MUZZLE_ATTACHMENTS))} && + {!(_baseWeapon in (_attachments get IDX_VIRT_BIPOD_ATTACHMENTS))} && + {!(_x in (GVAR(virtualItems) get IDX_VIRT_MISC_ITEMS))} + ) then { + // If item is a weapon (including binos), make it unique + (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, + _baseWeapon in (_weapons get IDX_VIRT_PRIMARY_WEAPONS) || + {_baseWeapon in (_weapons get IDX_VIRT_HANDGUN_WEAPONS)} || + {_baseWeapon in (_weapons get IDX_VIRT_SECONDARY_WEAPONS)} || + {_baseWeapon in (GVAR(virtualItems) get IDX_VIRT_BINO)} + ]; }; }; }; @@ -267,14 +294,14 @@ private _itemInfoType = 0; }; // Facewear case (isClass (_cfgGlasses >> _x)): { - (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES) set [_x, nil]; + (GVAR(virtualItems) get IDX_VIRT_UNIQUE_GOGGLES) set [_x, !(_x in (GVAR(virtualItems) get IDX_VIRT_GOGGLES))]; }; // Unknown default { // Don't add items that are part of the arsenal if !(_x in GVAR(virtualItemsFlatAll)) then { - (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, nil]; + (GVAR(virtualItems) get IDX_VIRT_UNIQUE_UNKNOWN_ITEMS) set [_x, true]; }; }; }; -} forEach (keys ([GVAR(center), 0, 3, 3, 3, false] call EFUNC(common,uniqueUnitItems))); // Get all items from unit +} forEach (_items arrayIntersect _items); diff --git a/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf b/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf index 207039f8ae..3ce0dd54d0 100644 --- a/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf +++ b/addons/arsenal/missions/Arsenal.VR/XEH_postInit.sqf @@ -10,16 +10,18 @@ cba_diagnostic_projectileMaxLines = 10; // Player pose [{ - switch (true) do { - case (primaryWeapon _this != ""): { - _this switchMove "amovpercmstpslowwrfldnon"; - }; - case (handgunWeapon _this != ""): { - _this switchMove "amovpercmstpslowwpstdnon"; - }; - default { + switch (currentWeapon _this) do { + case (""): { _this switchMove "amovpercmstpsnonwnondnon"; }; + case (primaryWeapon _this): { + _this switchMove "amovpercmstpslowwrfldnon"; + }; + case (handgunWeapon _this): { + _this switchMove "amovpercmstpslowwpstdnon"; + }; + case (binocular _this); + case (secondaryWeapon _this): {}; // deliberately nothing }; }, _player] call CBA_fnc_execNextFrame; @@ -88,6 +90,7 @@ cba_diagnostic_projectileMaxLines = 10; { _unit = _x; + removeVest _unit; if (vest _player != "") then { _unit addVest vest _player; }; removeBackpack _unit; diff --git a/addons/arsenal/stringtable.xml b/addons/arsenal/stringtable.xml index ce78b8df46..7f6947d913 100644 --- a/addons/arsenal/stringtable.xml +++ b/addons/arsenal/stringtable.xml @@ -1693,6 +1693,7 @@ Suche\nSTRG + Click für Live-Aktualisierung während des Schreibens Cerca\nCTRL + Click per modificare i risultati mentre scrivi 検索\nCTRL + クリックで検索結果の即時表示を有効化 + 검색\nCtrl + 클릭으로 실시간 검색 결과를 활성화 diff --git a/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf b/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf index 701ce544f7..a57a52bba7 100644 --- a/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf +++ b/addons/ballistics/functions/fnc_statTextStatement_magazineMuzzleVelocity.sqf @@ -41,7 +41,11 @@ if (_initSpeedCoef > 0) then { }; private _abAdjustText = ""; -if (_magIsForCurrentWeapon && {["ace_advanced_ballistics"] call EFUNC(common,isModLoaded)}) then { +if ( + _magIsForCurrentWeapon && + {missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]} && + {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} // this can be on while AB is off or vice-versa +) then { private _configAmmo = (configFile >> "CfgAmmo" >> (getText (_configMagazine >> "ammo"))); private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength"); private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities"); diff --git a/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf b/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf index 16ab9e2a47..e11c7cf5fb 100644 --- a/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf +++ b/addons/ballistics/functions/fnc_statTextStatement_weaponMuzzleVelocity.sqf @@ -37,7 +37,10 @@ if (_magazine isEqualTo "") then { }; private _abAdjustText = ""; - if (["ace_advanced_ballistics"] call EFUNC(common,isModLoaded)) then { + if ( + missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] && + {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} // this can be on while AB is off or vice-versa + ) then { private _configAmmo = (configFile >> "CfgAmmo" >> (getText (_configMagazine >> "ammo"))); private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength"); private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities"); diff --git a/addons/captives/functions/fnc_doEscortCaptive.sqf b/addons/captives/functions/fnc_doEscortCaptive.sqf index 1d94b30b87..817745ece3 100644 --- a/addons/captives/functions/fnc_doEscortCaptive.sqf +++ b/addons/captives/functions/fnc_doEscortCaptive.sqf @@ -50,9 +50,14 @@ if (_state) then { detach _target; _unit removeAction _actionID; _unit setVariable [QGVAR(escortedUnit), objNull, true]; + + // Public event + [QGVAR(escortingCaptive), [_target, false, _unit]] call CBA_fnc_localEvent; }; }, 0, [_unit, _target, _actionID]] call CBA_fnc_addPerFrameHandler; + // Public event + [QGVAR(escortingCaptive), [_target, true, _unit]] call CBA_fnc_localEvent; } else { _unit setVariable [QGVAR(isEscorting), false, true]; _unit setVariable [QGVAR(escortedUnit), objNull, true]; diff --git a/addons/cargo/stringtable.xml b/addons/cargo/stringtable.xml index c77be79035..5e42af6c13 100644 --- a/addons/cargo/stringtable.xml +++ b/addons/cargo/stringtable.xml @@ -310,6 +310,7 @@ Impossibile da scaricare Ne peut pas être déchargé 降ろせません + 하역할 수가 없습니다 Cargo Size: %1 @@ -317,6 +318,7 @@ Dimensione Carico: %1 Encombrement fret: %1 カーゴ サイズ: %1 + 화물 크기: %1 Custom Name diff --git a/addons/common/CfgGesturesMale.hpp b/addons/common/CfgGesturesMale.hpp new file mode 100644 index 0000000000..0d3737cb62 --- /dev/null +++ b/addons/common/CfgGesturesMale.hpp @@ -0,0 +1,14 @@ +// From ACRE +class CfgGesturesMale { + skeletonName = "OFP2_ManSkeleton"; + class States { + class GestureNod; + class GVAR(stop): GestureNod { + file = "a3\anims_f\data\anim\sdr\gst\gestureEmpty.rtm"; + disableWeapons = 0; + disableWeaponsLong = 0; + enableOptics = 1; + mask = "empty"; + }; + }; +}; diff --git a/addons/common/CfgMoves.hpp b/addons/common/CfgMoves.hpp index b0df9a4466..14686526e9 100644 --- a/addons/common/CfgMoves.hpp +++ b/addons/common/CfgMoves.hpp @@ -1,9 +1,15 @@ - class CfgMovesBasic { class Default; + // From ACRE + class ManActions { + GVAR(stop) = QGVAR(stop); + }; class Actions { + class NoActions: ManActions { + GVAR(stop)[] = {QGVAR(stop), "Gesture"}; + }; + // fixes grab animation with equipped pistol - class NoActions; class PistolStandActions: NoActions { grabDrag = "AmovPercMstpSlowWrflDnon_AcinPknlMwlkSlowWrflDb_2"; }; @@ -62,8 +68,12 @@ class CfgMovesMaleSdr: CfgMovesBasic { // fix falling back to unconsciousness animation and disable rotating in that state class Unconscious: Default { - ConnectTo[] = {}; + // Prevents AI from moving torso and head when unconscious + aiming = "aimingNo"; + aimingBody = "aimingUpNo"; head = "headNo"; + + ConnectTo[] = {}; forceAim = 1; static = 1; }; diff --git a/addons/common/XEH_PREP.hpp b/addons/common/XEH_PREP.hpp index 25899db1ae..ce6ac334ee 100644 --- a/addons/common/XEH_PREP.hpp +++ b/addons/common/XEH_PREP.hpp @@ -181,6 +181,7 @@ PREP(statusEffect_resetVariables); PREP(statusEffect_respawnEH); PREP(statusEffect_sendEffects); PREP(statusEffect_set); +PREP(stopGesture); PREP(stringCompare); PREP(stringToColoredText); PREP(swayLoop); diff --git a/addons/common/config.cpp b/addons/common/config.cpp index 758957987e..144e7d96c6 100644 --- a/addons/common/config.cpp +++ b/addons/common/config.cpp @@ -4,7 +4,7 @@ class CfgPatches { class ADDON { name = COMPONENT_NAME; units[] = {"ACE_Box_Misc", "ACE_bananaItem", "ACE_Flag_Black", "ACE_Flag_White"}; - weapons[] = {"ACE_ItemCore","ACE_FakePrimaryWeapon", "ACE_Banana"}; + weapons[] = {"ACE_ItemCore", "ACE_FakePrimaryWeapon", "ACE_Banana"}; requiredVersion = REQUIRED_VERSION; requiredAddons[] = {"ace_main","ace_modules"}; author = CSTRING(ACETeam); @@ -17,6 +17,7 @@ class CfgPatches { #include "CfgEden.hpp" #include "CfgEventHandlers.hpp" #include "CfgLocationTypes.hpp" +#include "CfgGesturesMale.hpp" #include "CfgMagazines.hpp" #include "CfgMoves.hpp" #include "CfgSounds.hpp" diff --git a/addons/common/functions/fnc_disableUserInput.sqf b/addons/common/functions/fnc_disableUserInput.sqf index 4037a168b7..6c58954b13 100644 --- a/addons/common/functions/fnc_disableUserInput.sqf +++ b/addons/common/functions/fnc_disableUserInput.sqf @@ -1,7 +1,8 @@ #include "..\script_component.hpp" #include "\a3\ui_f_curator\ui\defineResinclDesign.inc" +#include "\a3\ui_f\hpp\defineDIKCodes.inc" /* - * Author: commy2 + * Author: commy2, johnb43 * Disables key input. ESC can still be pressed to open the menu. * * Arguments: @@ -27,7 +28,7 @@ if (_state) then { if (!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])) exitWith {}; if (!isNil QGVAR(disableInputPFH)) exitWith {}; - // end TFAR and ACRE2 radio transmissions + // End TFAR and ACRE2 radio transmissions call FUNC(endRadioTransmission); // Close map @@ -45,38 +46,120 @@ if (_state) then { private _map = _display displayCtrl 101; _map ctrlMapCursor ["", QGVAR(blank)]; + GVAR(keyboardInputMain) = createHashMap; + GVAR(keyboardInputCombo) = createHashMap; + _display displayAddEventHandler ["KeyDown", { + // If input is enabled again, ignore + if (isNil QGVAR(keyboardInputMain)) exitWith {}; + params ["", "_key"]; - if (_key == 1 && {alive player}) then { - createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select isMultiplayer); + // Get key info; Stored as [isPressed, pressedCount] + private _keyPressedInfo = GVAR(keyboardInputMain) getOrDefault [_key, [false, 0], true]; + _keyPressedInfo params ["_keyPressed", "_keyPressedCount"]; + // For regular keys: If pressed, set to release and remove one key press + if (!_keyPressed) then { + _keyPressedInfo set [0, true]; + _keyPressedInfo set [1, _keyPressedCount + 1]; + }; + + // For combo keys, register only if pushed or released (no keypress count) + if !(GVAR(keyboardInputCombo) getOrDefault [_key, false]) then { + GVAR(keyboardInputCombo) set [_key, true]; + }; + + // Look if keybinds of various actions have been pressed + private _action = ""; + private _comboDikPressed = false; + private _return = false; + + // This technique has a limitation: It can't process the Escape key properly (KeyUp EH does not fire) + (["TeamSwitch", "CuratorInterface", "ShowMap", "DefaultAction", "Throw", "Chat", "PrevChannel", "NextChannel"] apply { + _action = _x; + + { + _x params ["_mainKeyArray", "_comboKeyArray", "_isDoubleTap"]; + _mainKeyArray params ["_mainDik", "_mainDevice"]; + + // If keybind doesn't contain key combo, it returns empty array; Therefore, return true + _comboDikPressed = if (_comboKeyArray isEqualTo []) then { + true + } else { + _comboKeyArray params ["_comboDik", "_comboDevice"]; + + _comboDevice == "KEYBOARD" && {GVAR(keyboardInputCombo) getOrDefault [_comboDik, false]} + }; + + // Check if the necessary keys were pressed for a keybind + _return = _comboDikPressed && + {_mainDevice == "KEYBOARD"} && + {((GVAR(keyboardInputMain) getOrDefault [_mainDik, [false, 0]]) select 1) > ([0, 1] select _isDoubleTap)}; // check how many times the main key was pressed + + // Keybind was detected + if (_return) exitWith { + TRACE_1("Action triggered: ",_action); + }; + } forEach (actionKeysEx _action); + + _return + }) params ["_teamSwitch", "_curatorInterface", "_showMap", "_defaultAction", "_throw", "_chat", "_prevChannel", "_nextChannel"]; + + // Handle Escape separately because of limitation mentioned above + if (_key == DIK_ESCAPE && {alive player}) then { disableSerialization; + private _isMultiplayer = isMultiplayer; + private _is3DENPreview = is3DENPreview; + + createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select _isMultiplayer); + private _dlg = findDisplay 49; for "_index" from 100 to 2000 do { (_dlg displayCtrl _index) ctrlEnable false; }; - private _ctrl = _dlg displayctrl 103; - _ctrl ctrlSetEventHandler ["buttonClick", QUOTE(while {!isNull (uiNamespace getVariable [ARR_2(QUOTE(QGVAR(dlgDisableMouse)),displayNull)])} do {closeDialog 0}; failMission 'LOSER'; [false] call DFUNC(disableUserInput))]; - _ctrl ctrlEnable true; - _ctrl ctrlSetText "ABORT"; - _ctrl ctrlSetTooltip "Abort."; + private _ctrl = _dlg displayCtrl 103; + _ctrl ctrlSetEventHandler ["ButtonClick", toString { + while {!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])} do { + closeDialog 0 + }; - _ctrl = _dlg displayctrl ([104, 1010] select isMultiplayer); - if (["ace_medical"] call FUNC(isModLoaded)) then { - _ctrl ctrlSetEventHandler ["buttonClick", 'closeDialog 0; [player, "respawn_button"] call EFUNC(medical_status,setDead); [false] call DFUNC(disableUserInput);']; - } else { - _ctrl ctrlSetEventHandler ["buttonClick", QUOTE(closeDialog 0; player setDamage 1; [false] call DFUNC(disableUserInput))]; - }; - _ctrl ctrlEnable ((getMissionConfigValue ["respawnButton", -1]) != 0); // handles 3den attribute or description.ext - _ctrl ctrlSetText localize "$str_3den_multiplayer_attributecategory_respawn_displayname"; - _ctrl ctrlSetTooltip "Respawn."; + failMission "LOSER"; + + [false] call FUNC(disableUserInput); + }]; + _ctrl ctrlEnable true; + _ctrl ctrlSetText localize (["str_disp_int_abort", "STR_3DEN_RscDisplayInterrupt_ButtonAbort_3DEN_text"] select (_is3DENPreview && !_isMultiplayer)); + _ctrl ctrlSetTooltip localize ([ + "STR_TOOLTIP_MAIN_ABORT_CAMPAIGN", + "STR_3DEN_RscDisplayInterrupt_ButtonAbort_3DEN_tooltip", + "STR_TOOLTIP_MAIN_ABORT" + ] select (([_is3DENPreview, _isMultiplayer] call FUNC(toBitmask)) min 2)); + + _ctrl = _dlg displayCtrl ([104, 1010] select _isMultiplayer); + _ctrl ctrlSetEventHandler ["ButtonClick", toString { + closeDialog 0; + + if (["ace_medical"] call FUNC(isModLoaded)) then { + [player, "respawn_button"] call EFUNC(medical_status,setDead); + } else { + player setDamage 1; + }; + + [false] call FUNC(disableUserInput); + }]; + + private _respawnEnabled = (getMissionConfigValue ["respawnButton", -1]) != 0; + + _ctrl ctrlEnable _respawnEnabled; // handles 3den attribute or description.ext + _ctrl ctrlSetText localize "str_disp_int_respawn"; + _ctrl ctrlSetTooltip localize (["str_3den_attributes_respawn_none_tooltip", "str_disp_int_respawn"] select _respawnEnabled); }; - if (_key in actionKeys "TeamSwitch" && {teamSwitchEnabled}) then { + if (_teamSwitch && teamSwitchEnabled) then { (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0; private _acc = accTime; @@ -84,18 +167,20 @@ if (_state) then { setAccTime _acc; }; - if (_key in actionKeys "CuratorInterface" && {getAssignedCuratorLogic player in allCurators}) then { + if (_curatorInterface && {!isNull getAssignedCuratorLogic player}) then { (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0; + openCuratorInterface; }; - if (_key in actionKeys "ShowMap" && {player getVariable ["ACE_canSwitchUnits", false]}) then { + if (_showMap && {player getVariable ["ACE_canSwitchUnits", false]}) then { (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0; + openMap true; }; - if (isServer || {serverCommandAvailable "#kick"}) then { - if (!(_key in (actionKeys "DefaultAction" + actionKeys "Throw")) && {_key in (actionKeys "Chat" + actionKeys "PrevChannel" + actionKeys "NextChannel")}) then { + if (isMultiplayer && {isServer || {serverCommandAvailable "#kick"}}) then { + if (!(_defaultAction || _throw) && {_chat || _prevChannel || _nextChannel}) then { _key = 0; }; }; @@ -103,7 +188,41 @@ if (_state) then { _key > 0 }]; - _display displayAddEventHandler ["KeyUp", {true}]; + _display displayAddEventHandler ["KeyUp", { + // If input is enabled again, ignore + if (isNil QGVAR(keyboardInputMain)) exitWith {}; + + params ["", "_key"]; + + // For combo keys: If pressed, release + if (GVAR(keyboardInputCombo) getOrDefault [_key, false]) then { + GVAR(keyboardInputCombo) deleteAt _key; + }; + + private _keyPressedInfo = GVAR(keyboardInputMain) getOrDefault [_key, [false, 0]]; + + // If pressed, release it + if (_keyPressedInfo select 0) then { + _keyPressedInfo set [0, false]; + }; + + // Cache keystrokes of regular keys for a small amount of time + [{ + // If input is enabled again, ignore + if (isNil QGVAR(keyboardInputMain)) exitWith {}; + + params ["_key"]; + + private _keyPressedInfo = GVAR(keyboardInputMain) getOrDefault [_key, [false, 0]]; + + // Release it + _keyPressedInfo set [1, ((_keyPressedInfo select 1) - 1) max 0]; + + if (_keyPressedInfo isEqualTo [false, 0]) then { + GVAR(keyboardInputMain) deleteAt _key, + }; + }, _key, 0.5] call CBA_fnc_waitAndExecute; + }]; }; GVAR(disableInputPFH) = [{ @@ -133,4 +252,7 @@ if (_state) then { }; (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0; + + GVAR(keyboardInputMain) = nil; + GVAR(keyboardInputCombo) = nil; }; diff --git a/addons/common/functions/fnc_isModLoaded.sqf b/addons/common/functions/fnc_isModLoaded.sqf index fb7b1807b6..b070b39b38 100644 --- a/addons/common/functions/fnc_isModLoaded.sqf +++ b/addons/common/functions/fnc_isModLoaded.sqf @@ -4,24 +4,17 @@ * Check in CfgPatches if modification is loaded * * Arguments: - * 0: Mod Name or Classname of the mod in CfgPatches + * 0: Classname of the mod in CfgPatches * * Return Value: - * if modification is loaded + * If modification is loaded * * Example: - * ["class"] call ace_common_fnc_isModLoaded + * "class" call ace_common_fnc_isModLoaded * * Public: Yes */ params [["_modName", "", [""]]]; -private _return = GVAR(isModLoadedCache) get _modName; - -if (isNil "_return") then { - _return = isClass (configFile >> "CfgPatches" >> _modName); - GVAR(isModLoadedCache) set [_modName, _return]; -}; - -_return +GVAR(isModLoadedCache) getOrDefaultCall [toLowerANSI _modName, {isClass (configFile >> "CfgPatches" >> _modName)}, true] diff --git a/addons/common/functions/fnc_stopGesture.sqf b/addons/common/functions/fnc_stopGesture.sqf new file mode 100644 index 0000000000..53e319b04b --- /dev/null +++ b/addons/common/functions/fnc_stopGesture.sqf @@ -0,0 +1,20 @@ +#include "..\script_component.hpp" +/* + * Author: ACRE2Team + * Stops a unit's gesture. + * + * Arguments: + * 0: Target + * + * Return Value: + * None + * + * Example: + * [bob] call ace_common_fnc_stopGesture + * + * Public: Yes + */ + +params ["_unit"]; + +[QGVAR(playActionNow), [_unit, QGVAR(stop)], _unit] call CBA_fnc_targetEvent diff --git a/addons/compat_rhs_usf3/compat_rhs_usf3_arsenal/CfgWeapons.hpp b/addons/compat_rhs_usf3/compat_rhs_usf3_arsenal/CfgWeapons.hpp index 7888e52393..8dc735265c 100644 --- a/addons/compat_rhs_usf3/compat_rhs_usf3_arsenal/CfgWeapons.hpp +++ b/addons/compat_rhs_usf3/compat_rhs_usf3_arsenal/CfgWeapons.hpp @@ -18,6 +18,8 @@ class CfgWeapons { baseWeapon = "rhsusf_acc_anpeq15_wmx"; }; class rhsusf_acc_M952V: rhsusf_acc_anpeq15_light { + rhs_acc_combo = ""; // prevent materializing a PEQ-15 if RHS's attachment switch is called + rhs_anpeq15_base = ""; // same deal baseWeapon = "rhsusf_acc_M952V"; }; class rhsusf_acc_wmx: rhsusf_acc_M952V { @@ -29,6 +31,12 @@ class CfgWeapons { class rhsusf_acc_anpeq15A: acc_pointer_IR { baseWeapon = "rhsusf_acc_anpeq15A"; }; + class rhsusf_acc_anpeq15_top: rhsusf_acc_anpeq15A { + baseWeapon = "rhsusf_acc_anpeq15_top"; + }; + class rhsusf_acc_anpeq15_bk_top: rhsusf_acc_anpeq15_top { + baseWeapon = "rhsusf_acc_anpeq15_bk_top"; + }; class rhsusf_acc_anpeq15side: acc_pointer_IR { baseWeapon = "rhsusf_acc_anpeq15side"; }; diff --git a/addons/compat_sog/functions/fnc_handlePunjiTrapTrigger.sqf b/addons/compat_sog/functions/fnc_handlePunjiTrapTrigger.sqf index 17ed92a172..d2e9abdbbc 100644 --- a/addons/compat_sog/functions/fnc_handlePunjiTrapTrigger.sqf +++ b/addons/compat_sog/functions/fnc_handlePunjiTrapTrigger.sqf @@ -15,7 +15,7 @@ * Public: No */ params ["_trap"]; -if (!(["ACE_Medical"] call EFUNC(common,isModLoaded))) exitWith {}; +if (!(["ace_medical"] call EFUNC(common,isModLoaded))) exitWith {}; private _radius = getNumber (configOf _trap >> "indirectHitRange"); private _affectedUnits = _trap nearEntities ["CAManBase", _radius]; diff --git a/addons/csw/functions/fnc_assemble_deployTripod.sqf b/addons/csw/functions/fnc_assemble_deployTripod.sqf index 2d292a52c3..d3317a4e40 100644 --- a/addons/csw/functions/fnc_assemble_deployTripod.sqf +++ b/addons/csw/functions/fnc_assemble_deployTripod.sqf @@ -53,7 +53,7 @@ [_player, "PutDown"] call EFUNC(common,doGesture); // drag after deploying - if ((missionNamespace getVariable [QGVAR(dragAfterDeploy), false]) && {["ACE_dragging"] call EFUNC(common,isModLoaded)}) then { + if ((missionNamespace getVariable [QGVAR(dragAfterDeploy), false]) && {["ace_dragging"] call EFUNC(common,isModLoaded)}) then { if ([_player, _cswTripod] call EFUNC(dragging,canCarry)) then { TRACE_1("starting carry",_cswTripod); [_player, _cswTripod] call EFUNC(dragging,startCarry); diff --git a/addons/csw/functions/fnc_staticWeaponInit.sqf b/addons/csw/functions/fnc_staticWeaponInit.sqf index 6ffd170d47..6dcbbf52e6 100644 --- a/addons/csw/functions/fnc_staticWeaponInit.sqf +++ b/addons/csw/functions/fnc_staticWeaponInit.sqf @@ -89,7 +89,7 @@ if (hasInterface && {!(_typeOf in GVAR(initializedStaticTypes))}) then { _ammoActionPath = [_typeOf, 0, ["ACE_MainActions"], _ammoAction] call EFUNC(interact_menu,addActionToClass); }; - if (["ACE_reload"] call EFUNC(common,isModLoaded)) then { + if (["ace_reload"] call EFUNC(common,isModLoaded)) then { // move reload's check ammo action to the ammo handling point (remove and re-add) [_typeOf, 0, ["ACE_MainActions", QEGVAR(reload,CheckAmmo)]] call EFUNC(interact_menu,removeActionFromClass); private _checkAmmoAction = [QGVAR(checkAmmo), localize ELSTRING(reload,checkAmmo), "", EFUNC(reload,checkAmmo), EFUNC(reload,canCheckAmmo)] call EFUNC(interact_menu,createAction); diff --git a/addons/dogtags/XEH_postInit.sqf b/addons/dogtags/XEH_postInit.sqf index 6653d80211..f683f6f253 100644 --- a/addons/dogtags/XEH_postInit.sqf +++ b/addons/dogtags/XEH_postInit.sqf @@ -7,7 +7,7 @@ // Add actions and event handlers only if ace_medical is loaded // - Adding actions via config would create a dependency -if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then { +if (["ace_medical"] call EFUNC(common,isModLoaded)) then { if (hasInterface) then { private _checkTagAction = [ "ACE_CheckDogtag", @@ -47,7 +47,7 @@ if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then { }; // If the arsenal is loaded, show the custom names for dog tags when in the arsenal -if (["ACE_Arsenal"] call EFUNC(common,isModLoaded)) then { +if (["ace_arsenal"] call EFUNC(common,isModLoaded)) then { [QEGVAR(arsenal,rightPanelFilled), { params ["_display", "_leftPanelIDC", "_rightPanelIDC"]; diff --git a/addons/dragging/functions/fnc_canCarry.sqf b/addons/dragging/functions/fnc_canCarry.sqf index dce4440a8e..caea20fb8a 100644 --- a/addons/dragging/functions/fnc_canCarry.sqf +++ b/addons/dragging/functions/fnc_canCarry.sqf @@ -33,7 +33,7 @@ if (_target isKindOf "StaticWeapon") exitWith { // Units need to be unconscious or limping; Units also need to not be in ragdoll, as that causes desync issues if (_target isKindOf "CAManBase") exitWith { - !(alive _target != isAwake _target) && + isAwake _target && // not ragdolled {lifeState _target == "INCAPACITATED" || {_target getHitPointDamage "HitLegs" >= 0.5}} }; diff --git a/addons/dragging/functions/fnc_canDrag.sqf b/addons/dragging/functions/fnc_canDrag.sqf index 7083eec76b..33dcd134b6 100644 --- a/addons/dragging/functions/fnc_canDrag.sqf +++ b/addons/dragging/functions/fnc_canDrag.sqf @@ -29,7 +29,7 @@ if (_target isKindOf "StaticWeapon") exitWith { // Units need to be unconscious or limping; Units also need to not be in ragdoll, as that causes desync issues if (_target isKindOf "CAManBase") exitWith { - !(alive _target != isAwake _target) && + isAwake _target && // not ragdolled {lifeState _target == "INCAPACITATED" || {_target getHitPointDamage "HitLegs" >= 0.5}} }; diff --git a/addons/fieldmanual/CfgHints.hpp b/addons/fieldmanual/CfgHints.hpp index 8164bd7943..6f5b0c8efe 100644 --- a/addons/fieldmanual/CfgHints.hpp +++ b/addons/fieldmanual/CfgHints.hpp @@ -37,7 +37,7 @@ class CfgHints { }; class ACE_BodyBag: ACE_FieldManual_Base { logicalOrder = 2; - arguments[] = {BASE_ARGUMENTS, QUOTE('ACE_BodyBag' call FUNC(getItemName))}; + arguments[] = {BASE_ARGUMENTS, QUOTE('ACE_BodyBag' call FUNC(getItemName)), MEDICAL_MENU_KEYBIND}; displayName = "%14"; displayNameShort = CSTRING(Items_BodyBag_ShortName); description = CSTRING(Items_BodyBag_Description); @@ -122,7 +122,7 @@ class CfgHints { }; class ACE_FortifyTool: ACE_FieldManual_Base { logicalOrder = 13; - arguments[] = {BASE_ARGUMENTS, QUOTE('ACE_FortifyTool' call FUNC(getItemName))}; + arguments[] = {BASE_ARGUMENTS, QUOTE('ACE_Fortify' call FUNC(getItemName))}; displayName = "%14"; displayNameShort = CSTRING(Items_FortifyTool_ShortName); description = CSTRING(Items_FortifyTool_Description); diff --git a/addons/fieldmanual/stringtable.xml b/addons/fieldmanual/stringtable.xml index 1371aa046a..ae71211c6a 100644 --- a/addons/fieldmanual/stringtable.xml +++ b/addons/fieldmanual/stringtable.xml @@ -48,7 +48,7 @@ %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. %3Pragnienie%4 zwiększa się liniowo wraz z prędkością ruchu. Odnawiane przez spożywanie napojów.<br/><br/>%3Użycie:%4<br/>%2Podnieś napój.<br/>%2Użyj [%3%12%4] i wybierz %3Surwiwal%4.<br/>%2Wybierz napój do wypicia. - %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섭취할 아이템을 선택하십시오. %3A sede%4 aumenta linearmente com a velocidade de movimento do soldado. Restaure bebendo líquidos.<br/><br/>%3Uso:%4<br/>%2Pegue uma bebida.<br/>%2Use [%3%12%4] e selecione %3Sobrevivência%4.<br/>%2Escolha um item para consumir. %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. @@ -75,7 +75,7 @@ %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. %3Adenozyna%4 jest używana do obniżenia tętna.<br/><br/>%3Użycie:%4<br/>%2Użyj [%3%13%4] lub [%3%14%4] i wybierz kończynę.<br/>%2Wstrzyknij %3Adenozynę%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을 주사하십시오. %3Adenosina%4 é usada para diminuir a frequência cardíaca.<br/><br/>%3Uso:%4<br/>%2Use [%3%13%4] ou [%3%14%4] e selecione um apêndice.<br/>%2Injete %3Adenosina%4. %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. @@ -102,7 +102,7 @@ %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. %3Bandaże%4 zatrzymają krwawienie i zamykają rany. W zależności od twoich ustawień, bandaże mogą się otwierać, jeżeli rany nie są zaszyte. <br/><br/>%2%3Bandaż Jałowy:%4<br/>%11<t color='#D9D900'>Przeciętne</t> We wszystkich kategoriach<br/>%2%3Bandaż Uciskowy: %4<br/>%11<t color='#D9D900'>Przeciętne</t> Leczenie<br/>%11<t color='#E60000'>Wyższa</t> Szansa Otwarcia<br/>%11<t color='#00CC00'>Dłuższe</t> Opóźnienie Otwarcia<br/>%2%3Bandaż Elastyczny: %4<br/>%11<t color='#00CC00'>Lepsze</t> Leczenie<br/>%11<t color='#E60000'>Wyższa</t> Szansa Otwarcia<br/>%11<t color='#E60000'>Krótsze</t> Opóźnienie Otwarcia<br/>%2%3Quickclot: %4<br/>%11<t color='#E60000'>Gorsze</t> Leczenie<br/>%11<t color='#00CC00'>Niższa</t> Szansa Otwarcia<br/>%11<t color='#00CC00'>Dłuższe</t> Opóźnienie Otwarcia<br/><br/>%3Użycie:%4<br/>%2Użyj [%3%13%4] lub [%3%14%4] i wybierz zranioną część ciała. <br/>%2Zabandażuj ranę wybierając typ %3Bandażu%4. - %3붕대%4는 출혈을 멈추고 상처를 치료합니다.설정에 따라 수술을 하지 않을 경우 붕대가 다시 풀릴 수 있습니다.<br/><br/>%2%3붕대(기본):%4<br/>모든 카테고리에 대해 %11<tcolor='#D9D900'>평균</t>적임<br/>%2%3붕대(거즈):%4<br/><br/>%11<t color='#D9D900'>평균</t>적인 치료 효과<br/>%11<t color='#E60000'>높은</t> 풀림 확률<br/>%11<t color='#00CC00'>긴</t> 풀림 딜레이<br/>%2%3붕대(압박):%4<br/>%11<t color='#00CC00'>높은</t> 치료 효과<br/>%11<t color='#E60000'>높은</t> 풀림 확률<br/>%11<t color='#E60000'>짧은</t> 풀림 딜레이<br/>%2%3붕대(퀵 클롯):%4<br/>%11<t color='#E60000'>낮은</t> 치료 효과<br/>%11<t color='#00CC00'>낮은</t> 풀림 확률<br/>%11<t color='#00CC00'>긴</t> 풀림 딜레이<br/><br/>%3사용 방법:%4<br/>%2[%3%13%4] 또는 [%3%14%4]를 사용하고 부상당한 신체부위를 선택하십시오.<br/>%2원하는 종류의 %3붕대%4를 선택하여 신체부위에 붕대를 감으십시오. + %3붕대%4는 출혈을 멈추고 상처를 치료합니다.설정에 따라 수술을 하지 않을 경우 붕대가 다시 풀릴 수 있습니다.<br/><br/>%2%3붕대(기본):%4<br/>모든 카테고리에 대해 %11<t color='#D9D900'>평균</t>적임<br/>%2%3붕대(거즈):<br/>%11<t color='#D9D900'>평균</t>적인 치료 효과<br/>%11<t color='#E60000'>높은</t> 풀림 확률<br/>%11<t color='#00CC00'>긴</t> 풀림 딜레이<br/>%2%3붕대(압박):%4<br/>%11<t color='#00CC00'>높은</t> 치료 효과<br/>%11<t color='#E60000'>높은</t> 풀림 확률<br/>%11<t color='#E60000'>짧은</t> 풀림 딜레이<br/>%2%3붕대(퀵 클롯):%4<br/>%11<t color='#E60000'>낮은</t> 치료 효과<br/>%11<t color='#00CC00'>낮은</t> 풀림 확률<br/>%11<t color='#00CC00'>긴</t> 풀림 딜레이<br/><br/>%3사용 방법:%4<br/>%2[%3%13%4] 또는 [%3%14%4]를 사용하고 부상당한 신체부위를 선택하십시오.<br/>%2원하는 종류의 %3붕대%4를 선택하여 신체부위에 붕대를 감으십시오. %3Bandagens%4 interrompem o sangramento e fecham feridas. A depender das suas configurações, as bandagens podem reabrir se não for feita a cirurgia.<br/><br/>%2%3Curativo de Campo:%4<br/>%11<t color='#D9D900'>Mediano</t> em todas as categorias<br/>%2%3Bandagem de Compressão:%4<br/>%11<t color='#D9D900'>Mediana</t> em tratamento<br/>%11<t color='#E60000'>Maior</t> chance de reabertura<br/>%11<t color='#00CC00'>Mais longo</t> atraso na reabertura<br/>%2%3Bandagem Elástica:%4<br/>%11<t color='#00CC00'>Melhor</t> em tratamento<br/>%11<t color='#E60000'>Maior</t> chance de reabertura<br/>%11<t color='#E60000'>Mais curto</t> atraso na reabertura<br/>%2%3QuikClot:%4<br/>%11<t color='#E60000'>Pior</t> em tratamento<br/>%11<t color='#00CC00'>Menor</t> chance de reabertura<br/>%11<t color='#00CC00'>Mais longo</t> atraso na reabertura<br/><br/>%Uso:%4<br/>%2Utilize [%3%13%4] ou [%3%14%4] e selecione uma parte do corpo ferida.<br/>%2Suture a parte do corpo selecionando o tipo desejado de %3Bandagem%4. %3Verbände%4 stoppen Blutungen und schließen Wunden. Abhängig von Ihren Einstellungen können sich Verbände wieder öffnen, wenn keine Operation durchgeführt wird.<br/><br/>%2%3Einfache Bandage:%4<br/>%11<t color='#D9D900'>Durchschnittlich</t> In allen Kategorien<br/>%2%3Mullbinde:%4<br/>%11<t color='#D9D900'>Durchschnittliche</t> Behandlung<br/>%11<t color='#E60000' >Höhere</t> Wiedereröffnungswahrscheinlichkeit<br/>%11<t color='#00CC00'>Längere</t> Wiedereröffnungsverzögerung<br/>%2%3Elastischer Verband:%4<br/>%11<t color='#00CC00'>Längere</t> Behandlung<br/>%11<t color='#E60000'>Höhere</t> Chance auf Wiedereröffnung<br/>%11<t color='#E60000'> Kürzere</t> Wiedereröffnungsverzögerung<br/>%2%3Quickclot:%4<br/>%11<t color='#E60000'>Kürzere</t> Behandlung<br/>%11<t color=' #00CC00'>Geringere</t> Wiedereröffnungswahrscheinlichkeit<br/>%11<t color='#00CC00'>Längere</t> Wiedereröffnungsverzögerung<br/><br/>%3Verwende:%4<br/> %2Verwenden Sie [%3%13%4] oder [%3%14%4] und wähle ein verletztes Körperteil aus.<br/>%2Verbinde ein Körperteil, indem der gewünschte %3Bandagen%4-Typ ausgewählt wurde. %3Bende%4 fermano emorragie e chiudono ferite. A seconda delle tue impostazioni, ferite bendate potrebbero riaprirsi se non suturate.<br/><br/>%2%3Bendaggio Basico:%4<br/>%11<t color='#D9D900'>Media</t> In tutte le categorie<br/>%2%3Bendaggio Compressivo:%4<br/>%11<t color='#D9D900'>Media</t> Trattamenti<br/>%11<t color='#E60000'>Alta</t> Probabilità di riapertura<br/>%11<t color='#00CC00'>Lungo</t> Tempo di riapertura<br/>%2%3Bendaggio Elastico:%4<br/>%11<t color='#00CC00'>Alto</t> Trattamento<br/>%11<t color='#E60000'>Alto</t> Probabilità di riapertura<br/>%11<t color='#E60000'>Breve</t> Tempo di riapertura<br/>%2%3Quickclot:%4<br/>%11<t color='#E60000'>Basso</t> Trattamento<br/>%11<t color='#00CC00'>Basso</t> Probabilità di riapertura<br/>%11<t color='#00CC00'>Lungo</t> Tempo di riapertura<br/><br/>%3Utilizzo:%4<br/>%2Usa [%3%13%4] o [%3%14%4] seleziona una parte del corpo ferita.<br/>%2Benda la parte del corpo ferita selezionando la %3Benda%4 desiderato. @@ -147,7 +147,7 @@ %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. %3Adrenalina%4 zwiększa tętno pacjenta, zmniejszając czas pomiędzy sprawdzeniami przytomności (efektywnie redukując czas potrzebny do przebudzenia się pacjenta).<br/><br/>%3Użycie%4<br/>%2Użyj [%3%13%4] lub [%3%14%4] i wybierz kończynę.<br/>%2Wstrzyknij %3Adrenalinę%4. - %3에피네프린%4는 환자의 맥박을 증가시킬 뿐만 아니라 의식 검사 사이의 시간을 감소시킬 수 있습니다(환자가 깨어나는 데 필요한 시간을 효과적으로 단축).<br>%3t사용 방법:%4<br/>%2[%3%13%4] 또는 [%3%14%4]를 선택하고 부위를 선택하십시오.<br/>%2%3에피네프린%4을 주사하십시오. + %3에피네프린%4는 환자의 맥박을 증가시킬 뿐만 아니라 의식 검사 사이의 시간을 감소시킬 수 있습니다(환자가 깨어나는 데 필요한 시간을 효과적으로 단축).<br/>%3사용 방법:%4<br/>%2[%3%13%4] 또는 [%3%14%4]를 선택하고 부위를 선택하십시오.<br/>%2%3에피네프린%4을 주사하십시오. %Epinefrina%4 aumenta o pulso do paciente, bem como potencialmente diminui o tempo entre os exames de consciência (reduzindo efetivamente o tempo necessário para que o paciente acorde).<br/><br/>%3Uso%4<br/>%2Utilize [%3%13%4] ou [%3%14%4] e selecione um apêndice.<br/>%2Injete %3Epinefrina%4. %3Epinephrine%4 erhöht den Puls eines Patienten und verkürzt möglicherweise die Zeit zwischen Bewusstseinskontrollen (wodurch die Zeit, die der Patient zum Aufwachen benötigt, effektiv verkürzt wird).<br/><br/>%3Verwendung%4<br/>%2Verwende [%3%13%4] oder [%3%14%4] und wählen ein Körperteil aus.<br/>%2Injiziere %3Epinephrine%4. %3Epinefrina%4 aumenta il ritmo cardiaco di un paziente e riduce potenzialmente gli intervalli tra verifiche di coscienza (effettivamente riducendo il tempo necessario che questo paziente si svegli).<br/><br/>%3Utilizzo%4<br/>%2Usa [%3%13%4] o [%3%14%4] e seleziona un arto.<br/>%2Inietta %3Epinefrina%4. @@ -165,7 +165,7 @@ 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. %3Apteczka Osobista%4 jest przedmiotem pozwalającym na pełne uleczenie gracza. Niezależnie od %3Ustawień ACE%4, wymagane jest, aby pacjent był w%3Stanie Stabilnym%4 przed jej użyciem.<br/><br/>%3Stan Stabilny%4 występuje gdy:<br/>%2Jednostka jest %3Żywa%4.<br/>%2Jednostka jest %3Przytomna%4.<br/>%2Jednostka nie%3Krwawu%4.<br/>%2Tętno>= 40. <br/>%2Ciśnienie Skurczowe >= 60.<br/>%2Ciśnienie Rozkurczowe >= 50.<br/><br/>%3Użycie:%4<br/>%2Udaj się do właściwej lokacji żależnej od %3Ustawień ACE%4.<br/>%2Użyj [%3%13%4] lub [%3%14%4] i wybierz %3Zaawansowane Zabiegi%4.<br/>%2Wybierz %3Użyj Apteczki Osobistej%4. - %3개인응급키트%4는 병사를 완치시킬 수 있는 아이템입니다. %3ACE 설정%4과 무관하게 사용 전에 환자가 %3안정된 상태%4로 있어야 합니다.<br/><br/>%3안정된 상태%4는 다음 조건이 필요합니다:<br/>%2유닛이 %3살아있어야%4 합니다.<br/>%2유닛은 %3의식이 있어야%4 합니다.<br/>%2유닛은 %3출혈이 일어나지 않은 상태%4여야 합니다.<br/>%2심박수가 40 이상이어야 합니다.<br/>%2수축 혈압이 60 이상이어야 합니다.<br/>이완 혈압이 50 이상이어야 합니다.<br/><br/>%3사용 방법:%4<br/>%2%3ACE 설정%4에 따라 적절한 위치로 이동하십시오.<br/>%2[%3%13%4] 또는 [%3%14%4]를 사용하여 %3고급 치료%4를 선택하십시오.<br/>%2%3개인응급키트 사용%4을 선택하십시오. + %3개인응급키트%4는 병사를 완치시킬 수 있는 아이템입니다. %3ACE 설정%4과 무관하게 사용 전에 환자가 %3안정된 상태%4로 있어야 합니다.<br/><br/>%3안정된 상태%4는 다음 조건이 필요합니다:<br/>%2유닛이 %3살아있어야%4 합니다.<br/>%2유닛은 %3의식이 있어야%4 합니다.<br/>%2유닛은 %3출혈이 일어나지 않은 상태%4여야 합니다.<br/>%2심박수가 40 이상이어야 합니다.<br/>%2수축 혈압이 60 이상이어야 합니다.<br/>%2이완 혈압이 50 이상이어야 합니다.<br/><br/>%3사용 방법:%4<br/>%2%3ACE 설정%4에 따라 적절한 위치로 이동하십시오.<br/>%2[%3%13%4] 또는 [%3%14%4]를 사용하여 %3고급 치료%4를 선택하십시오.<br/>%2%3개인응급키트 사용%4을 선택하십시오. O %3Kit De Primeiros Socorros Pessoal%4 é um item que permite a cura completa de um combatente. Independente das %3Configurações do ACE%4, é necessário que o paciente esteja em %3Condições Estáveis%4 antes do uso.<br/><br/>%3Condições estáveis%4 qualificam-se como:<br/>%2Unidade está %3Viva%4.<br/>%2Unidade está %3Consciente%4.<br/>%2Unidade não está %3Sangrando%4.<br/>%2Frequência Cardíaca >= 40.<br/>%2PA Sistólica >= 60.<br/>%2PA Diastólica >= 50.<br/><br/>%3Uso:%4<br/>%2Mover-se a uma localização apropriada, a depender das %3Configurações do ACE%4.<br/>%2Utilizar [%3%13%4] ou [%3%14%4] e selecionar %3Tratamentos Avançados%4<br/>%2Selecionar %3Usar o kit de primeiros socorros%4. Das %3Persönliche Erste Hilfe Kit%4 ist ein Gegenstand, der es einem Soldaten ermöglicht, vollständig geheilt zu werden. Unabhängig von den %3ACE-Einstellungen%4 ist es erforderlich, dass sich der Patient vor der Verwendung in einem %3stabilen Zustand%4 befindet.<br/><br/>%3Stabiler Zustand%4 gilt wenn:<br/>%2Einheit ist %3am Leben%4 .<br/>%2Einheit ist %3Bei Bewusstsein%4.<br/>%2Einheit hat keine aktive %3Blutung%4.<br/>%2Herzfrequenz >= 40.<br/>%2Systolischer Blutdruck >= 60.< br/>%2Diastolischer Blutdruck >= 50.<br/><br/>%3Verwende:%4<br/>%2Bewege den Patienten je nach %3ACE-Einstellungen%4 an den entsprechenden Ort.<br/>%2Verwende [%3% 13%4] oder [%3%14%4] und wähle %3Erweiterte Behandlungen%4<br/>%2Wähle %3Persönliche Erste Hilfe Kit verwenden%4. Il %3Kit di Pronto Soccorso%4 è un oggetto che permette di curare completamente un soldato, indipendentemente da %3impostazioni ACE%4, richiede che il paziente sia in %3condizione stabile%4 prima dell'utilizzo.<br/><br/>%3Condizione stabile%4 significa:<br/>%2Paziente è %3Vivo%4.<br/>%2Paziente è %3Conscio%4.<br/>%2Paziente non sta %3Sanguinando%4.<br/>%2Ritmo cardiaco >= 40.<br/>%2Sistolico BC >= 60.<br/>%2Diastolico BC >= 50.<br/><br/>%3Utilizzo:%4<br/>%2Sposta in luogo specifico a seconda delle %3impostazioni ACE%4.<br/>%2Usa [%3%13%4] o [%3%14%4] e seleziona %3Trattamenti avanzati%4<br/>%2Seleziona %3Usa Kit di Pronto Soccorso%4. @@ -240,7 +240,7 @@ Treatment, Simplified Leczenie, Uproszczone - 치료, 단순화 + 치료를 단순화 Cure, Semplificato Tratamento, Simplificado 治療を簡略化する @@ -248,7 +248,7 @@ The %3Medical Menu%4 is a dedicated %3interface%4 to facilitate %3medical treatment%4. The %3R%4 and %3L%4 letters indicate the side of the patient's body being treated.<br/><br/>%3Usage:%4<br/>%2Use [%3%14%4] while looking at a patient to open the Medical Menu. Opening the menu without a patient allows for self-treatment.<br/>%2Alternatively, use [%3%12%4] or [%3%13%4] and select %3Medical Menu%4.<br/><br/>%3Keybinds:%4<br/>%2Use [%3W, A, S, D, X, and Z%4] to select body parts.<br/>%2Use your %3number keys%4 to select treatment categories. %3Menu Medyczne%4 jest dedykowanym %3interfejsem%4 ułatwiającym %3zabiegi medyczne%4. Litery %3P%4 i %3L%4 wskazują, która część ciała pacjenta jest opatrywana.<br/><br/>%3Użycie:%4<br/>%2Użyj [%3%14%4] podczas patrzenia na pacjenta aby otworzyć Menu Medyczne. Otwarcie menu bez patrzenia na pacjenta otwiera menu leczenia własnej postaci.<br/>%2Alternatywnie, użyj [%3%12%4] lub [%3%13%4] i wybierz %3Menu Medyczne%4.<br/><br/>%3Przypisanie Klawiszy:%4<br/>%2Użyj [%3W, A, S, D, X, i Z%4] aby wybrać części ciała.<br/>%2Użyj %3klawiszy numerycznych%4 do wybrania kategorii leczenia. - %3의료 메뉴%4는 %3의료%4를 용이하게 사용하기 위한 전용 %3인터페이스%4입니다. %3우%4 및 %3좌%4 문자는 치료 중인 환자의 신체 측면을 나타냅니다.<br/><br/>%3사용 방법:%4<br/>%2환자를 보고 [%3%13%4]를 사용하여 의료 메뉴를 여십시오. 환자 없이 메뉴를 열면 자가 치료가 됩니다.<br/>%2아니면 [%3%12%4] 또는 [%3%13%4]를 사용하고 %3의료 메뉴%4를 선택하십시오.<br/><br/>%3키 설정%4<ㅠㄱ/>%2[%3W, A, S, D, X와 ㅋ%4]를 사용하여 신체 부위를 선택하십시오.<br/>%2%3번호판 키%4를 사용하여 치료 카테고리를 선택하십시오. + %3의료 메뉴%4는 %3의료%4를 용이하게 사용하기 위한 전용 %3인터페이스%4입니다. %3우%4 및 %3좌%4 문자는 치료 중인 환자의 신체 측면을 나타냅니다.<br/><br/>%3사용 방법:%4<br/>%2환자를 보고 [%3%13%4]를 사용하여 의료 메뉴를 여십시오. 환자 없이 메뉴를 열면 자가 치료가 됩니다.<br/>%2아니면 [%3%12%4] 또는 [%3%13%4]를 사용하고 %3의료 메뉴%4를 선택하십시오.<br/><br/>%3키 설정%4<br/>%2[%3W, A, S, D, X와 Z%4]를 사용하여 신체 부위를 선택하십시오.<br/>%2%3번호판 키%4를 사용하여 치료 카테고리를 선택하십시오. O %3Menu Médico%4 é uma %3interface%4 dedicada a facilitar o %3tratamento médico%4. As letras %3R%4 e %3L%4 indicam o lado do corpo do paciente que está recebendo o tratamento.<br/><br/>%3Uso:%4<br/>%2Utilize [%3%14%4] enquanto olha o paciente para abrir o Menu Médico. Se não houver paciente, o menu será de auto-tratamento.<br/>%2Alternativamente, utilize [%3%12%4] ou [%3%13%4] e selecione %3Menu Médico%4.<br/><br/>%3Atalhos de teclado:%4<br/>%2Utilize [%3W, A, S, D, X, e Z%4] para selecionar partes do corpo.<br/>%2Utilize as %3teclas numéricas%4 para selecionar as categorias de tratamento. Il %3Menù Medico%4 è un'%3interfaccia%4 dedicata a facilitare %3trattamenti medici%4. Le lettere %3Dx%4 e %3Sx%4 contrassegnano i lati del corpo del paziente che si stanno medicando.<br/><br/>%3Utilizzo:%4<br/>%2Usa [%3%14%4] guardando il paziente per aprire il Menù Medico. Aprire il menù senza paziente di fronte permette l'automedicazione.<br/>%2In alternativa, usa [%3%12%4] o [%3%13%4] e seleziona %3Menù Medico%4.<br/><br/>%3Comandi:%4<br/>%2Usa [%3W, A, S, D, X, and Z%4] per selezionare parti del corpo.<br/>%2Usa %3tasti numerici%4 per selezionare categorie di cure. %3医療メニュー%4は%3治療%4をしやすくするための専用%3インターフェース%4です。%3右%4と%3左%4の文字は治療を受ける患者の向きを表しています。<br/><br/>%3使用方法:%4<br/>%2[%3%14%4] を患者に視点を合わせながら押すことで患者の医療メニューを開けます。視点を合わせないで押すと、自分の医療メニューを開くことが出来ます。<br/>%2もしくは [%3%12%4] または [%3%13%4] を使って%3医療メニュー%4を選択します。<br/><br/>%3キーバインド:%4<br/>%2[%3W, A, S, D, X, と Zキー%4] を使って身体の部位を選択できます。<br/>%2%3数字キー%4を使って治療項目を選択できます。 @@ -278,12 +278,12 @@ 死者を連れ出す - %3Body Bags%4 are used to transport dead bodies. They can be dragged and loaded into vehicles.<br/><br/>%3Usage:%4<br/>%2Approach a dead body.<br/>%2Use [%3%13%4] or [%3%14%4] and select %3Place Body In Bodybag%4. - %3Worki na Zwłoki%4 są używane do transportu ciał. Worki mogą być przeciągane i ładowanie do pojazdów.<br/><br/>%3Użycie:%4<br/>%2Podejdź do martwego ciała.<br/>%2Użyj [%3%13%4] lub [%3%14%4] i wybierz %3Umieść Ciało w Worku na Zwłoki%4. - %3시체 운반용 부대%4는 시체를 운반하는 데 사용되며, 차량으로 끌고 가서 적재할 수 있습니다.<br/><br/>%3사용 방법:%4<br/>%2시체에 접근하십시오.<br/>%2[%3%13%4] 또는 [%3%14%4]를 사용하여 %3시체 운반용 부대에 담기%4를 선택하십시오. - OS %3Sacos de Cadáver%4 são utilizados para transportar cadáveres. Eles podem ser arrastados e embarcados em veículos.<br/><br/>%3Uso:%4<br/>%2Aproxime-se de um cadáver.<br/>%2Utilize [%3%13%4] ou [%3%14%4] e selecione %3Colocar cadáver dentro do saco%4. - %3Sacche per cadaveri%4 sono usate per trasportare i morti. Possono essere trascinate e caricate su veicoli.<br/><br/>%3Utilizzo:%4<br/>%2Avvicinati ad un morto.<br/>%2Usa [%3%13%4] o [%3%14%4] e seleziona %3Metti il corpo nella sacca per cadaveri%4. - %3遺体袋%4は、遺体の輸送に使用されます。引きずって車両に積み込むことができます。<br/><br/>%3使用方法:%4<br/>%2遺体に近寄る。<br/>%2[%3%13%4] または [%3%14%4] を使って%3遺体袋に入れる%4を選択して使用します。 + %3Body Bags%4 are used to transport dead bodies. They can be dragged and loaded into vehicles.<br/><br/>%3Usage:%4<br/>%2Approach a dead body.<br/>%2Use [%3%13%4] or [%3%15%4] and select %3Place Body In Bodybag%4. + %3Worki na Zwłoki%4 są używane do transportu ciał. Worki mogą być przeciągane i ładowanie do pojazdów.<br/><br/>%3Użycie:%4<br/>%2Podejdź do martwego ciała.<br/>%2Użyj [%3%13%4] lub [%3%15%4] i wybierz %3Umieść Ciało w Worku na Zwłoki%4. + %3시체 운반용 부대%4는 시체를 운반하는 데 사용되며, 차량으로 끌고 가서 적재할 수 있습니다.<br/><br/>%3사용 방법:%4<br/>%2시체에 접근하십시오.<br/>%2[%3%13%4] 또는 [%3%15%4]를 사용하여 %3시체 운반용 부대에 담기%4를 선택하십시오. + OS %3Sacos de Cadáver%4 são utilizados para transportar cadáveres. Eles podem ser arrastados e embarcados em veículos.<br/><br/>%3Uso:%4<br/>%2Aproxime-se de um cadáver.<br/>%2Utilize [%3%13%4] ou [%3%15%4] e selecione %3Colocar cadáver dentro do saco%4. + %3Sacche per cadaveri%4 sono usate per trasportare i morti. Possono essere trascinate e caricate su veicoli.<br/><br/>%3Utilizzo:%4<br/>%2Avvicinati ad un morto.<br/>%2Usa [%3%13%4] o [%3%15%4] e seleziona %3Metti il corpo nella sacca per cadaveri%4. + %3遺体袋%4は、遺体の輸送に使用されます。引きずって車両に積み込むことができます。<br/><br/>%3使用方法:%4<br/>%2遺体に近寄る。<br/>%2[%3%13%4] または [%3%15%4] を使って%3遺体袋に入れる%4を選択して使用します。 Take Prisoners @@ -296,7 +296,7 @@ %3Cable Ties%4 enable a soldier to capture and detain another soldier. Once apprehended, the captor gains the ability to inspect the prisoner's belongings, set them free, or accompany them to an alternate area. Transporting escorted prisoners is also possible, including loading them into vehicles if needed. Depending on your settings, units may need to surrender before being taken captive.<br/><br/>%3Usage:%4<br/>%2Approach the unit and use the [%3%13%4].<br/>%2The interaction is located around the hands in the form of a handcuffs icon.<br/>%2Repeat to release. %3Opaski Zaciskowe%4 umożliwiają żołnierzowi pojmanie i zatrzymanie innego żołnierza, a po zatrzymaniu pozwalają na sprawdzenia ekwipunku więźnia, uwolnienia go lub przeniesienia w inne miejsce, a także załadowania go do pojazdu, jeśli zajdzie taka potrzeba. W zależności od ustawień, jednostka może wymagać poddania się przed wzięciem do niewoli.<br/><br/>%3Użycie:%4<br/>%2Podejdź do jednostki i użyj [%3%13%4].<br/>%2Interakcja jest zlokalizowana na rękach pod postacią ikony kajdanek.<br/>%2Użyj ponownie aby uwolnić. - %3게이블 타이%4를 사용하면 병사가 다른 병사를 포로로 잡고 구금할 수 있습니다. 체포되면 포로는 포로의 소지품을 검사하여 석방하거나 대체 지역으로 동행시킬 수 있습니다. 필요하면 차량에 싣는 것을 포함하여 죄수를 호송할 수도 있습니다. 설정에 따라 유닛은 포로가 되기 전에 항복해야 할 수도 있습니다.<br/><br/>%3사용 방법:%4%2유닛에 접근하여 [%3%13%4]를 사용하십시오.<br/>%2상호작용은 수갑 아이콘의 형태로 손 부분에 위치합니다.<br/>%2해제 하려면 같은 행동을 반복하십시오. + %3케이블 타이%4를 사용하면 병사가 다른 병사를 포로로 잡고 구금할 수 있습니다. 체포되면 포로는 포로의 소지품을 검사하여 석방하거나 대체 지역으로 동행시킬 수 있습니다. 필요하면 차량에 싣는 것을 포함하여 죄수를 호송할 수도 있습니다. 설정에 따라 유닛은 포로가 되기 전에 항복해야 할 수도 있습니다.<br/><br/>%3사용 방법:%4<br/>%2유닛에 접근하여 [%3%13%4]를 사용하십시오.<br/>%2상호작용은 수갑 아이콘의 형태로 손 부분에 위치합니다.<br/>%2해제 하려면 같은 행동을 반복하십시오. As %3Algema Plásticas%4 permitem a captura e detenção de soldados. Quando apreendidos, o captor se torna capaz de inspecionar os pertences do prisioneiro, liberá-los, ou acompanhá-los a outro local. Transportes mais longos também são possíveis, podendo colocá-los em veículos, se necessário. A depender das configurações, pode ser necessário que as unidades estejam rendidas antes de serem detidas.<br/><br/>%3Uso:%4<br/>%2Aproxime-se da unidade e use [%3%13%4].<br/>%2A interação encontra-se próxima às mãos simbolizada por uma algema.<br/>%2Faça o mesmo para liberar. %3Fascette%4 permettono a soldati di catturare e ammanettare altri soldati. Una volta catturati è possibile ispezionare il loro inventario, liberarli o scortarli altrove. È inoltre possibile caricarli su veicoli se necessario. A seconda delle impostazioni, potrebbe essere necessaria la resa di unità prima di poterle ammanettare.<br/><br/>%3Uso:%4<br/>%2Avvicinati all'unità e usa [%3%13%4].<br/>%2L'interazione è localizzata intorno alle mani con l'icona di manette.<br/>%2Ripeti per liberare. %3ケーブル タイ%4は兵士が他の兵士を拘束できるようにします。一度拘束すれば、拘束者は捕虜の所持品を検査したり、釈放したり、別の場所に移送することができるようになります。必要に応じて車両に積み込むなどして捕虜の輸送や護送も可能です。設定によっては、ユニットは捕虜になる前に降伏する必要がある場合があります。<br/><br/>%3使用方法:%4<br/>%2対象に近づいて [%3%13%4] を使います。<br/>%2インタラクションは、手錠アイコンの形で手のあたりに表示されます。<br/>%2同様の方法で解放できます。 @@ -312,7 +312,7 @@ The %3Cellphone%4 is functionally a %3Clacker%4. Use it to connect and detonate an explosive device. Multiple devices can be linked to the cellphone and called within the phonebook.<br/><br/>%3Usage:%4<br/>%2Place an explosive.<br/>%2Use [%3%13%4], select %3Explosives%4, and select %3Cellphone%4.<br/>%2Open the cellphone interface with [%3%12%4].<br/>%2Navigate the phone book with the arrows and select your calling number.<br/>%2Call the number to detonate. %3Telefon%4 jest funkcjonalnie %3Detonatorem%4. Użyj go, aby podłączyć i zdetonować ładunek wybuchowy. Wiele urządzeń może być połączonych z jednym telefonem komórkowym i wywoływanych za pomocą książki telefonicznej.<br/><br/>%3Użycie:%4<br/>%2Połóż ładunek wybuchowy<br/>%2Użyj [%3%13%4], wybierz %3Ładunki Wybuchowe%4, i wybierz %3Telefon%4. <br/>%2Otwórz interfejs telefonu za pomocą [%3%12%4].<br/>%2Nawiguj po książce telefonicznej za pomocą strzałek i wybierz żądany numer.<br/>%2Zadzwoń pod niego aby wywołać wybuch. - %3휴대전화%4는 기능적으로는 %3격발기%4입니다. 폭발물 장치를 연결하여 폭발물을 터뜨릴 때 사용합니다. 여러 장치를 휴대전화와 연결하여 전화번호부 내에서 호출할 수 있습니다.<br/><br/>%3사용 방법:%4<br/>%2폭발물을 놓으십시오.<br/>%2[%313%4]를 사용하고, %3폭발물%4을 선택하고, %3휴대전화%4를 선택하십시오.<br/%2[%3%12%4]로 휴대전화 인터페이스를 여십시오.<br/>%2기폭시킬 전화번호를 선택하십시오. + %3휴대전화%4는 기능적으로는 %3격발기%4입니다. 폭발물 장치를 연결하여 폭발물을 터뜨릴 때 사용합니다. 여러 장치를 휴대전화와 연결하여 전화번호부 내에서 호출할 수 있습니다.<br/><br/>%3사용 방법:%4<br/>%2폭발물을 놓으십시오.<br/>%2[%3%13%4]를 사용하고, %3폭발물%4을 선택하고, %3휴대전화%4를 선택하십시오.<br/%2[%3%12%4]로 휴대전화 인터페이스를 여십시오.<br/>%2기폭시킬 전화번호를 선택하십시오. O %3Celular%4 serve como dispositivo de detonação ao explosivo. Utilize-o para conectar e detonar dispositivos explosivos. Múltiplos dispositivos podem estar conectados ao celular e aparecerão na lista telefônica.<br/><br/>%3Uso:%4<br/>%2Plante o explosivo.<br/>%2Utilize [%3%13%4], selecione %3Explosivos%4, e selecione %3Celular%4.<br/>%2Abra a interface do celular com [%3%12%4].<br/>%2Navegue pela lista telefônica utilizando as setas e selecione o número desejado.<br/>%2Ligue para o número para detonar. Il %3Cellulare%4 è essenzialmente una %3spoletta%4. Usalo per collegare e detonare esplosivi. Molteplici esplosivi possono essere collegati ad un cellulare e detonati chiamando numeri nella rubrica.<br/><br/>%3Utilizzo:%4<br/>%2Piazza un esplosivo.<br/>%2Usa [%3%13%4], seleziona %3Esplosivi%4, seleziona %3Cellulare%4.<br/>%2Apri l'interfaccia del telefono con [%3%12%4].<br/>%2Naviga la rubrica con le freccette e seleziona il numero da chiamare.<br/>%2Chiama il numero del dispositivo da detonare. %3携帯電話%4は%3点火装置%4として機能します。爆破装置を接続して起爆するために使用します。複数のデバイスを携帯電話に繋ぎ、電話帳から呼び出すことができます。<br/><br/>%3使用方法:%4<br/>%2爆発物を設置。<br/>%2[%3%13%4] を使い、%3爆発物%4を選択して、%3携帯電話%4を選択します。<br/>%2[%3%12%4] を使って携帯電話インターフェースを開きます。<br/>%2矢印ボタンで電話帳に移動し、発信番号を選択します。<br/>%2電話を掛けることで起爆します。 @@ -415,7 +415,7 @@ 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. %3Saperka%4 pozwala żołnierzowi kopać okopy w celu obrony swoich pozycji. Żołnierz musi być na glebie, aby wykopać okop.<br/><br/>%3Użycie:%4<br/>%2Wyekwipuj %3Saperkę%4.<br/>%2Użyj [%3%12%4] i wybierz %3Ekwipunek%4.<br/>%2Wybierz rodzaj okopu, który chcesz wykopać. La %3Pala da Trincea%4 permette a soldati di scavare trincee per difendere meglio la loro posizione. Il soldato deve trovarsi su suolo scavabile per poter creare trincee.<br/><br/>%3Utilizzo:%4<br/>%2Equipaggia una %3Pala da Trincea%4.<br/>%2Usa [%3%12%4] e seleziona %3Equipaggiamento%4.<br/>%2Seleziona il tipo di trincea che vuoi costruire. - %3야전삽%4을 사용하면 병사들의 진지 방어를 위한 참호를 팔 수 있습니다. 병사가 참호를 파려면 흙 위에 있어야 합니다.<br/><br/>%3사용 방법:%4<br/>%2%3야전삽%4을 장비하십시오.<br/>%2[%3%12%4]를 사용하여 %3장비%4를 선택하십시오.<br/>짓고 싶은 종류의 참호를 선택하십시오. + %3야전삽%4을 사용하면 병사들의 진지 방어를 위한 참호를 팔 수 있습니다. 병사가 참호를 파려면 흙 위에 있어야 합니다.<br/><br/>%3사용 방법:%4<br/>%2%3야전삽%4을 장비하십시오.<br/>%2[%3%12%4]를 사용하여 %3장비%4를 선택하십시오.<br/>%2짓고 싶은 종류의 참호를 선택하십시오. %3塹壕ツール%4を使用すると、兵士は自分の陣地を守るために塹壕を掘ることができます。塹壕を掘るには、兵士は土の上にいる必要があります。<br/><br/>%3使用方法:%4<br/>%2%3塹壕ツール%4を装備します。<br/>%2[%3%12%4] を使って%3装備%4を選択します。<br/>%2構築する塹壕の種類を選択します。 @@ -436,7 +436,7 @@ %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. %3Latarki%4 pozwalają czytać mapę, nawet w ciemnościach. Jednakże podczas używani %3Latarki%4, będziesz miał wokół siebie delikatną poświatę.<br/><br/>%3Użycie:%4<br/>%2W widoku mapy użyj [%3%12%4] i wybierz %3Latarki%4.<br/>%2Wybierz %3Latarkę%4, którą chcesz użyć i wybierz %3Włącz%4.<br/><br/>%3Dostępne latarki%4:<br/>%2 Fulton MX-991<br/>%2 KSF-1<br/>%2 Maglite XL50<br/><br/>%3NOTE:%4<br/>Stan latarki jest trwały. %3Torce%4 permettono di leggere la tua mappa anche in ambienti bui. Però quando le utilizzi avrai un leggero effetto luminoso intorno a te.<br/><br/>%3Utilizzo:%4<br/>%2Sulla mappa usa [%3%12%4] e seleziona %3Torcia%4.<br/>%2Seleziona la %3Torcia%4 che vuoi usare e seleziona %3Accendi%4.<br/><br/>%3Oggetti Torcia Disponibili%4:<br/>%2 Fulton MX-991<br/>%2 KSF-1<br/>%2 Maglite XL50<br/><br/>%3NOTE:%4<br/>Lo stato di una torcia è persistente. - %3손전등%4은 어두운 환경에서도 지도를 읽을 수 있는 기능을 제공합니다. 단, %3손전등%4을 사용할 때 주변에 약간 빛이 납니다.<br/><br/>%3사용 방법:%4<br/>%2지도 화면에서 [%3%12%4]를 사용하고 %3손전등%4을 선택하십시오.<br/>%2사용할 %3손전등%4을 선택하고 %3켜기%4를 선택하십시오.<br/><br/>%3사용 가능한 손전등 아이템%4:<br/>% 2풀턴 MX-991<br/>%2 KSF-1<br/>%2 매그라이트 XL50<br/><br/>%3참고:%4<br/>손전등 상태는 영구적입니다. + %3손전등%4은 어두운 환경에서도 지도를 읽을 수 있는 기능을 제공합니다. 단, %3손전등%4을 사용할 때 주변에 약간 빛이 납니다.<br/><br/>%3사용 방법:%4<br/>%2지도 화면에서 [%3%12%4]를 사용하고 %3손전등%4을 선택하십시오.<br/>%2사용할 %3손전등%4을 선택하고 %3켜기%4를 선택하십시오.<br/><br/>%3사용 가능한 손전등 아이템%4:<br/>%2풀턴 MX-991<br/>%2 KSF-1<br/>%2 매그라이트 XL50<br/><br/>%3참고:%4<br/>손전등 상태는 영구적입니다. %3フラッシュライト%4を使用すると、暗い環境でも地図を読むことができます。ただし、%3フラッシュライト%4を使用すると、周囲がわずかに光ります。<br/><br/>%3使用方法:%4<br/>%2マップ画面で [%3%12%4] を使用し、%3フラッシュライト%4を選択します。<br/>%2%3フラッシュライト%4を選択し、使用したいライトを%3点ける%4。<br/><br/>%3使用可能なフラッシュライトのアイテム%4:<br/>%2 フルトン MX-991<br/>%2 KSF-1<br/>%2 マグライト XL50<br/><br/>%3備考:%4<br/>フラッシュライトの状態は継続します。 @@ -478,7 +478,7 @@ 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. %3Kestrel 4500 Pocket Weather Tracker%4 jest przenośną stacją pogodową pozwalającą zbierać takie dane jak: <br/>%2Kurs i kierunek wiatru<br/>%2Wiatr boczny i czołowy<br/>%2Wysokość i ciśnienie barometryczne<br/>%2Temperatua mokrego termometru<br/>%2Wilgotność i punkt rosy<br/>%2Gęstość powietrza<br/>%2Temperatura i temperatura odczuwalna<br/>%2Czas i data<br/>%2Wartości minimalne, maksymalne oraz średnie<br/><br/>%3Użycie: %4<br/>%2Wyekwipuj %3Kestrela%4. <br/>%2Użyj [%3%12%4] i wybierz %3Ekwipunek%4.<br/>%2Wybierz %3Otwórz%4. Il %3Kestrel 4500 Indicatore Meteorologico Tascabile%4 è una mini-stazione meteo utile per ricavare le seguenti informazioni meteorologiche:<br/>%2Prua e direzione del vento<br/>%2Vento di traverso e frontale<br/>%2Altitudine and pressione barometrica<br/>%2Temperatura di bulbo umido<br/>%2Umidità e punto di rugiada<br/>%2Density altitude<br/>%2Temperatura e gelo del vento<br/>%2Data e Ora<br/>%2Valori minimi, massimi, e medi<br/><br/>%3Utilizzo:%4<br/>%2Equipaggia %3Kestrel%4.<br/>%2Usa [%3%12%4] e seleziona %3Equipaggiamento%4.<br/>%2Seleziona %3Apri%4. - %3케스트렐 4500 휴대용 기상 추적 장비%4는 다음 날씨 데이터들을 수집하는 데 유용한 소형 기상 관측 장비입니다:<br/>%2바람이 오는 방향과 가는 방향<br/>%2옆바람과 맞바람<br/>%2고도 및 기압<br/>%2습구온도<br/>%2습도 및 이슬점<br/>%2밀도고도<br/>%2체감온도<br/>%2시간 및 날짜<br/>%2최소, 최대, 평균값<br/>%3사용 방법:%4<br/>%2%3케스트렐 4500NV%4를 장착하십시오.<br/>%2[%3%12%4]를 사용하고 %3장비%4를 선택하십시오.<br/>%2%3열기%4를 선택하십시오. + %3케스트렐 4500 휴대용 기상 추적 장비%4는 다음 날씨 데이터들을 수집하는 데 유용한 소형 기상 관측 장비입니다:<br/>%2바람이 오는 방향과 가는 방향<br/>%2옆바람과 맞바람<br/>%2고도 및 기압<br/>%2습구온도<br/>%2습도 및 이슬점<br/>%2밀도고도<br/>%2체감온도<br/>%2시간 및 날짜<br/>%2최소, 최대, 평균값<br/><br/>%3사용 방법:%4<br/>%2%3케스트렐 4500NV%4를 장착하십시오.<br/>%2[%3%12%4]를 사용하고 %3장비%4를 선택하십시오.<br/>%2%3열기%4를 선택하십시오. %3ケストレル 4500 携帯気象計%4は、次の気象データの収集に役立つミニ気象ステーションです:<br/>%2方位と風向<br/>%2横風と向かい風<br/>%2高度と気圧<br/>%2湿球温度<br/>%2湿度と露点<br/>%2密度高度<br/>%2ウィンドチルと温度<br/>%2日付と時刻<br/>%2最小値、最大値、平均値<br/><br/>%3使用方法:%4<br/>%2%3ケストレル%4を装備します。<br/>%2[%3%12%4] を使って%3装備%4を選択します。<br/>%2%3ケストレルを開く%4で使用できます。 @@ -673,7 +673,7 @@ 要塞を構築する - The %3Fortify Tool%4 allows soldiers to build fortifications provided by their mission creator.<br/><br/>%3Usage:%4<br/>%2Pick up a %3FortifyTool%4.<br/>%2Use [%3%12%4] and select %3Fortify%4.<br/>%2Select an available fortification and follow the on screen prompts for placement. + 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. %3Narzędzie do fortyfikowania%4 pozwala żołnierzom budować fortyfikacje wybrane przez twórcę misji.<br/><br/>%3Użycie:%4<br/>%2Podnieś %3Narzędzie do fortyfikowania%4.<br/>%2Użyj [%3%12%4] i wybierz %3Fortyfikuj%4.<br/>%2Wybierz dostępną fortyfikację i postępuj zgodnie ze wskazówkami na ekranie. L'%3Attrezzo di Fortificazione%4 permette ai soldati di costruire fortificazioni permesse dal creatore della missione.<br/><br/>%3Utilizzo:%4<br/>%2Raccogli un %3Attrezzo di Fortificazione%4.<br/>%2Usa [%3%12%4] e seleziona %3Fortifica%4.<br/>%2Seleziona una fortificazione disponibile e segui le indicazioni di piazzamento sullo schermo. %3요새화 도구%4를 사용하면 병사들이 임무 생성자가 제공한 요새를 구축할 수 있습니다.<br/><br/>%3사용 방법:%4<br/>%2%3요새화 도구%4를 가지십시오.<br/>%2[%3%12%4]를 사용하고 %3요새화%4를 선택하십시오.<br/>%2사용 가능한 요새를 선택하고 화면의 지시에 따라 배치하십시오. diff --git a/addons/gforces/functions/fnc_pfhUpdateGForces.sqf b/addons/gforces/functions/fnc_pfhUpdateGForces.sqf index 13d08f833b..7ff3444b7d 100644 --- a/addons/gforces/functions/fnc_pfhUpdateGForces.sqf +++ b/addons/gforces/functions/fnc_pfhUpdateGForces.sqf @@ -71,7 +71,7 @@ private _suitCoef = if ((uniform ACE_player) != "") then { private _gBlackOut = MAXVIRTUALG / _classCoef + MAXVIRTUALG / _suitCoef - MAXVIRTUALG; // Unconsciousness -if ((_average > _gBlackOut) && {["ACE_Medical"] call EFUNC(common,isModLoaded) && {!(ACE_player getVariable ["ACE_isUnconscious", false])}}) then { +if ((_average > _gBlackOut) && {["ace_medical"] call EFUNC(common,isModLoaded) && {!(ACE_player getVariable ["ACE_isUnconscious", false])}}) then { [ACE_player, true, (10 + floor(random 5)), true] call EFUNC(medical,setUnconscious); }; diff --git a/addons/grenades/functions/fnc_flashbangExplosionEH.sqf b/addons/grenades/functions/fnc_flashbangExplosionEH.sqf index cc87f492d7..bba3cffd4d 100644 --- a/addons/grenades/functions/fnc_flashbangExplosionEH.sqf +++ b/addons/grenades/functions/fnc_flashbangExplosionEH.sqf @@ -110,14 +110,14 @@ if (hasInterface && {!isNull ACE_player} && {alive ACE_player}) then { _strength = _strength * _losCoefficient; // Add ace_hearing ear ringing sound effect - if (["ACE_Hearing"] call EFUNC(common,isModLoaded) && {_strength > 0 && {EGVAR(hearing,damageCoefficent) > 0.25}}) then { + if (["ace_hearing"] call EFUNC(common,isModLoaded) && {_strength > 0 && {EGVAR(hearing,damageCoefficent) > 0.25}}) then { private _earringingStrength = 40 * _strength; [_earringingStrength] call EFUNC(hearing,earRinging); TRACE_1("Earringing Strength",_earringingStrength); }; // add ace_medical pain effect: - if (["ACE_Medical"] call EFUNC(common,isModLoaded) && {_strength > 0.1}) then { + if (["ace_medical"] call EFUNC(common,isModLoaded) && {_strength > 0.1}) then { [ACE_player, _strength / 2] call EFUNC(medical,adjustPainLevel); }; diff --git a/addons/inventory/CfgEventHandlers.hpp b/addons/inventory/CfgEventHandlers.hpp index 5b92811746..f95adcb029 100644 --- a/addons/inventory/CfgEventHandlers.hpp +++ b/addons/inventory/CfgEventHandlers.hpp @@ -1,4 +1,3 @@ - class Extended_PreStart_EventHandlers { class ADDON { init = QUOTE(call COMPILE_SCRIPT(XEH_preStart)); @@ -20,5 +19,12 @@ class Extended_PostInit_EventHandlers { class Extended_DisplayLoad_EventHandlers { class RscDisplayInventory { ADDON = QUOTE(_this call FUNC(inventoryDisplayLoad)); + GVAR(displayNameWeight) = QUOTE(_this call FUNC(displayNameWeight)); // separate to allow other mods to disable them individually + }; +}; + +class Extended_DisplayUnload_EventHandlers { + class RscDisplayInventory { + ADDON = QUOTE(GVAR(unit) = ACE_player); }; }; diff --git a/addons/inventory/RscDisplayInventory.hpp b/addons/inventory/RscDisplayInventory.hpp index 3149000777..91e68f5fb1 100644 --- a/addons/inventory/RscDisplayInventory.hpp +++ b/addons/inventory/RscDisplayInventory.hpp @@ -27,26 +27,26 @@ class RscCombo; #define W_MAKEITBIGGA(num) (num * (safeZoneH / 40)) #define H_MAKEITBIGGA(num) (num * (safeZoneH / 30)) -#define X_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QUOTE(QGVAR(inventoryDisplaySize)),0)]),X_BIS(num),X_MAKEITBIGGA(num))]) -#define Y_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QUOTE(QGVAR(inventoryDisplaySize)),0)]),Y_BIS(num),Y_MAKEITBIGGA(num))]) -#define W_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QUOTE(QGVAR(inventoryDisplaySize)),0)]),W_BIS(num),W_MAKEITBIGGA(num))]) -#define H_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QUOTE(QGVAR(inventoryDisplaySize)),0)]),H_BIS(num),H_MAKEITBIGGA(num))]) +#define X_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QQGVAR(inventoryDisplaySize),0)]),X_BIS(num),X_MAKEITBIGGA(num))]) +#define Y_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QQGVAR(inventoryDisplaySize),0)]),Y_BIS(num),Y_MAKEITBIGGA(num))]) +#define W_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QQGVAR(inventoryDisplaySize),0)]),W_BIS(num),W_MAKEITBIGGA(num))]) +#define H_PART(num) QUOTE(linearConversion [ARR_5(0,2,(missionNamespace getVariable [ARR_2(QQGVAR(inventoryDisplaySize),0)]),H_BIS(num),H_MAKEITBIGGA(num))]) class RscDisplayInventory { class controls { class CA_ContainerBackground: RscText { - //crate: GroundLoad adjust size + // Crate: GroundLoad adjust size x = X_PART(1); y = Y_PART(1); w = W_PART(12); - h = H_PART(22.5); //default 23 + h = H_PART(22.5); // default 23 }; class CA_PlayerBackground: RscText { - //center player's container: decrease height because of progressbar height decrease + // Center player's container: Decrease height because of progressbar height decrease x = X_PART(14.6); y = Y_PART(2); w = W_PART(24.4); - h = H_PART(21.5); //default 22 + h = H_PART(21.5); // default 22 }; class TitleBackground: RscText { x = X_PART(14.6); @@ -98,7 +98,7 @@ class RscDisplayInventory { }; class BackgroundSlotPrimaryFlashlight: BackgroundSlotPrimary { x = X_PART(30.6); - y = Y_PART(9.2); //not sure why different (double check release) + y = Y_PART(9.2); // not sure why different (double check release) w = W_PART(1.9); h = H_PART(2); }; @@ -283,11 +283,11 @@ class RscDisplayInventory { h = H_PART(1); }; class GroundLoad: RscProgress { - //crate: GroundLoad adjust size + // Crate: GroundLoad adjust size x = X_PART(1.5); y = Y_PART(22.5); w = W_PART(11); - h = H_PART(0.5); //Default 1 + h = H_PART(0.5); // Default 1 }; class SlotPrimary: GroundTab { x = X_PART(26.6); @@ -345,7 +345,7 @@ class RscDisplayInventory { }; class SlotSecondaryUnderBarrel: SlotPrimary { x = X_PART(29); - y = Y_PART(14.59); //Why is this different? (check release) + y = Y_PART(14.59); // Why is this different? (check release) w = W_PART(2.3); h = H_PART(2); }; @@ -518,11 +518,11 @@ class RscDisplayInventory { h = H_PART(0.5); }; class TotalLoad: GroundLoad { - //center: progressbar height decrease + // Center: progressbar height decrease x = X_PART(15.1); y = Y_PART(22.5); w = W_PART(23.4); - h = H_PART(0.5); //Default 1 + h = H_PART(0.5); // default 1 }; class ContainerMarker: GroundTab { x = X_PART(0); diff --git a/addons/inventory/XEH_PREP.hpp b/addons/inventory/XEH_PREP.hpp index 7c58268e23..824ebf63d7 100644 --- a/addons/inventory/XEH_PREP.hpp +++ b/addons/inventory/XEH_PREP.hpp @@ -1,10 +1,6 @@ - PREP(addCustomFilter); PREP(currentItemListBox); -PREP(forceItemListUpdate); -PREP(inventoryDisplayLoad); -PREP(onLBSelChanged); - +PREP(displayNameWeight); PREP(filterWeapons); PREP(filterMagazines); PREP(filterItems); @@ -14,3 +10,6 @@ PREP(filterVests); PREP(filterBackpacks); PREP(filterGrenades); PREP(filterMedical); +PREP(forceItemListUpdate); +PREP(inventoryDisplayLoad); +PREP(onLBSelChanged); diff --git a/addons/inventory/XEH_postInit.sqf b/addons/inventory/XEH_postInit.sqf index c5dc6c48f6..a670a7bfd5 100644 --- a/addons/inventory/XEH_postInit.sqf +++ b/addons/inventory/XEH_postInit.sqf @@ -2,40 +2,39 @@ if (!hasInterface) exitWith {}; -// cache config -// items in the inventory display can only be distinguished by their lb names and pictures -// this can cause collisions (mainly weapons with attachments), -// but if the item has the same name and picture it at least shouldn't change the filter anyway -// luckily we don't need private items, so dummy and parent classes are out of the picture +// If medical_treatment is loaded, get its items +if (["ace_medical_treatment"] call EFUNC(common,isModLoaded)) then { + private _medicalList = +(uiNamespace getVariable [QGVAR(medicalItemList), createHashMap]); -GVAR(ItemKeyNamespace) = [] call CBA_fnc_createNamespace; -private _allItems = uiNamespace getVariable [QGVAR(ItemKeyCache), []]; //See XEH_preStart.sqf + _medicalList merge [uiNamespace getVariable [QEGVAR(medical_treatment,treatmentItems), createHashMap], true]; -// isEqualType is hacking protection as we cannot trust that the cache hasn't been manipulated -{ - if (_x isEqualType [] && {_x isEqualTypeArray ["", configNull]}) then { - GVAR(ItemKeyNamespace) setVariable _x; - }; -} forEach ([[], _allItems] select (_allItems isEqualType [])); + GVAR(medicalItemList) = compileFinal _medicalList; +} else { + GVAR(medicalItemList) = uiNamespace getVariable [QGVAR(medicalItemList), compileFinal createHashMap]; +}; GVAR(customFilters) = []; GVAR(selectedFilterIndex) = -1; -// add custom filters +// Add custom filters +[LLSTRING(Grenades), QFUNC(filterGrenades)] call FUNC(addCustomFilter); +[LLSTRING(Backpacks), QFUNC(filterBackpacks)] call FUNC(addCustomFilter); +[LLSTRING(Uniforms), QFUNC(filterUniforms)] call FUNC(addCustomFilter); +[LLSTRING(Vests), QFUNC(filterVests)] call FUNC(addCustomFilter); +[LLSTRING(Headgear), QFUNC(filterHeadgear)] call FUNC(addCustomFilter); +[LLSTRING(Medical), QFUNC(filterMedical)] call FUNC(addCustomFilter); -// get list of grenades -GVAR(Grenades_ItemList) = uiNamespace getVariable [QGVAR(Grenades_ItemList), []]; -if (!(GVAR(Grenades_ItemList) isEqualType [])) then {GVAR(Grenades_ItemList) = []}; +// Used for displaying the correct name when opening a subordinate's inventory +GVAR(unit) = ACE_player; -[localize LSTRING(Grenades), QFUNC(filterGrenades)] call FUNC(addCustomFilter); +["CAManBase", "InventoryOpened", { + params ["_unit", "_container"]; -[localize LSTRING(Backpacks), QFUNC(filterBackpacks)] call FUNC(addCustomFilter); -[localize LSTRING(Uniforms), QFUNC(filterUniforms)] call FUNC(addCustomFilter); -[localize LSTRING(Vests), QFUNC(filterVests)] call FUNC(addCustomFilter); -[localize LSTRING(Headgear), QFUNC(filterHeadgear)] call FUNC(addCustomFilter); + // GVAR(unit) is ACE_player by default + if (_unit isEqualTo ACE_player) exitWith {}; -// get list of medical items -GVAR(Medical_ItemList) = uiNamespace getVariable [QGVAR(Medical_ItemList), []]; -if (!(GVAR(Medical_ItemList) isEqualType [])) then {GVAR(Medical_ItemList) = []}; - -[localize LSTRING(Medical), QFUNC(filterMedical)] call FUNC(addCustomFilter); + // If the player is a group leader and opens a subordinate's inventory or has a subordinate open the player's backpack, update name to correct unit + if (leader ACE_player == ACE_player && {(_unit in units ACE_player) || {(objectParent _container) isEqualTo ACE_player}}) then { + GVAR(unit) = _unit; + }; +}] call CBA_fnc_addClassEventHandler; diff --git a/addons/inventory/XEH_preStart.sqf b/addons/inventory/XEH_preStart.sqf index 18999d638e..faa0e1691e 100644 --- a/addons/inventory/XEH_preStart.sqf +++ b/addons/inventory/XEH_preStart.sqf @@ -2,52 +2,53 @@ #include "XEH_PREP.hpp" -//item cache, see XEH_postInit.sqf +// Cache config +// Items in the inventory display can all use lb data to get their classname (exception: backpacks, handled separately) private _allItems = ("getNumber (_x >> 'scope') > 0" configClasses (configFile >> "CfgWeapons")); _allItems append ("getNumber (_x >> 'scope') > 0" configClasses (configFile >> "CfgGlasses")); -_allItems append ("getNumber (_x >> 'scope') == 2" configClasses (configFile >> "CfgMagazines")); -_allItems append ("getNumber (_x >> 'scope') > 0 && {getNumber (_x >> 'isBackpack') == 1}" configClasses (configFile >> "CfgVehicles")); +_allItems append ("getNumber (_x >> 'scope') > 0" configClasses (configFile >> "CfgMagazines")); -uiNamespace setVariable [QGVAR(ItemKeyCache), _allItems apply { +uiNamespace setVariable [QGVAR(itemKeyCache), compileFinal ((_allItems apply {configName _x}) createHashMapFromArray _allItems)]; + +// Backpacks in the inventory display can only be distinguished by their lb names and pictures, lb data returns "" +_allItems = "getNumber (_x >> 'scope') > 0 && {getNumber (_x >> 'isBackpack') == 1}" configClasses (configFile >> "CfgVehicles"); + +uiNamespace setVariable [QGVAR(backpackKeyCache), compileFinal createHashMapFromArray (_allItems apply { private _displayName = getText (_x >> "displayName"); private _picture = getText (_x >> "picture"); - // list box seems to delete the leading backslash - if (_picture select [0,1] == "\") then { + // List box seems to delete the leading backslash + 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"; + }; - [format ["%1:%2", _displayName, _picture], _x]; -}]; + // Handle missing file extension, as inventory returns path with extension + if (count _picture > 0 && !(_picture regexMatch ".*?\.paa")) then { + if (!fileExists (_picture + ".paa")) exitWith {}; + _picture = _picture + ".paa"; + }; -// generate list of grenades -private _grenades_ItemList = []; + // Listboxes store pictures as lowercase + [format ["%1:%2", _displayName, toLower _picture], _x] +})]; + +// Generate list of grenades +private _cfgThrow = configFile >> "CfgWeapons" >> "Throw"; +private _grenadeList = createHashMap; { - _grenades_ItemList append getArray (configFile >> "CfgWeapons" >> "Throw" >> _x >> "magazines"); -} forEach getArray (configFile >> "CfgWeapons" >> "Throw" >> "muzzles"); + _grenadeList insert [true, (getArray (_cfgThrow >> _x >> "magazines")) apply {_x call EFUNC(common,getConfigName)}, []]; +} forEach getArray (_cfgThrow >> "muzzles"); -// make list case insensitive -_grenades_ItemList = _grenades_ItemList apply {toLower _x}; +uiNamespace setVariable [QGVAR(grenadesItemList), compileFinal _grenadeList]; -// filter duplicates -_grenades_ItemList = _grenades_ItemList arrayIntersect _grenades_ItemList; +// Generate list of medical items +private _medicalList = QUOTE(getNumber (_x >> 'scope') > 0 && {getNumber (_x >> 'ItemInfo' >> 'type') in [ARR_2(TYPE_FIRST_AID_KIT,TYPE_MEDIKIT)]}) configClasses (configFile >> "CfgWeapons"); -uiNamespace setVariable [QGVAR(Grenades_ItemList), _grenades_ItemList]; +_medicalList = _medicalList apply {configName _x}; -// generate list of medical items -private _medical_ItemList = ["FirstAidKit", "Medikit"]; -{ - _medical_ItemList append getArray (_x >> "items"); -} forEach ("true" configClasses (configFile >> QEGVAR(medical_treatment,Actions))); - -// remove all numbers from list -_medical_ItemList = _medical_ItemList select {_x isEqualType ""}; - -// make list case insensitive -_medical_ItemList = _medical_ItemList apply {toLower _x}; - -// filter duplicates -_medical_ItemList = _medical_ItemList arrayIntersect _medical_ItemList; - -uiNamespace setVariable [QGVAR(Medical_ItemList), _medical_ItemList]; +uiNamespace setVariable [QGVAR(medicalItemList), compileFinal (_medicalList createHashMapFromArray [])]; diff --git a/addons/inventory/functions/fnc_addCustomFilter.sqf b/addons/inventory/functions/fnc_addCustomFilter.sqf index 6dd6e1f559..50820fa448 100644 --- a/addons/inventory/functions/fnc_addCustomFilter.sqf +++ b/addons/inventory/functions/fnc_addCustomFilter.sqf @@ -12,11 +12,13 @@ * None * * Example: - * ["displayname", "filter"] call ACE_inventory_fnc_addCustomFilter + * ["displayname", "filter"] call ace_inventory_fnc_addCustomFilter * * Public: No */ -params [["_filterName", "ERROR: No Name", [""]], ["_fncName", "", [""]]]; +params [["_filterName", "", [""]], ["_fncName", "", [""]]]; + +if (_filterName == "") exitWith {}; GVAR(customFilters) pushBack [_filterName, _fncName]; diff --git a/addons/inventory/functions/fnc_currentItemListBox.sqf b/addons/inventory/functions/fnc_currentItemListBox.sqf index b3e5ce40b8..1546e8a509 100644 --- a/addons/inventory/functions/fnc_currentItemListBox.sqf +++ b/addons/inventory/functions/fnc_currentItemListBox.sqf @@ -12,7 +12,7 @@ * Currently selected item list box * * Example: - * [DISPLAY] call ACE_inventory_fnc_currentItemListBox + * [DISPLAY] call ace_inventory_fnc_currentItemListBox * * Public: No */ @@ -27,7 +27,6 @@ scopeName "main"; if (ctrlShown _control) then { _control breakOut "main"; }; - false -} count [IDC_ITEMLIST_GROUND, IDC_ITEMLIST_SOLDIER, IDC_ITEMLIST_UNIFORM, IDC_ITEMLIST_VEST, IDC_ITEMLIST_BACKPACK]; +} forEach [IDC_ITEMLIST_GROUND, IDC_ITEMLIST_SOLDIER, IDC_ITEMLIST_UNIFORM, IDC_ITEMLIST_VEST, IDC_ITEMLIST_BACKPACK]; controlNull diff --git a/addons/movement/functions/fnc_inventoryDisplayLoad.sqf b/addons/inventory/functions/fnc_displayNameWeight.sqf similarity index 68% rename from addons/movement/functions/fnc_inventoryDisplayLoad.sqf rename to addons/inventory/functions/fnc_displayNameWeight.sqf index 95299a3b34..c480593d85 100644 --- a/addons/movement/functions/fnc_inventoryDisplayLoad.sqf +++ b/addons/inventory/functions/fnc_displayNameWeight.sqf @@ -10,26 +10,27 @@ * None * * Example: - * [DISPLAY] call ACE_movement_fnc_inventoryDisplayLoad + * [DISPLAY] call ace_inventory_fnc_displayNameWeight * * Public: No */ params ["_display"]; -// forces player name control to display irrespective of isStreamFriendlyUIEnabled +// Forces player name control to display irrespective of isStreamFriendlyUIEnabled (_display displayCtrl 111) ctrlShow true; private _fnc_update = { params ["_display"]; + private _control = _display displayCtrl 111; private _format = ["%1 - %2 %3 (%4)", "%2 %3 (%4)"] select isStreamFriendlyUIEnabled; _control ctrlSetText format [_format, - [ACE_player, false, true] call EFUNC(common,getName), - localize ELSTRING(common,Weight), - [ACE_player] call EFUNC(common,getWeight), - [ACE_player, true] call EFUNC(common,getWeight) + [GVAR(unit), false, true] call EFUNC(common,getName), + LELSTRING(common,Weight), + GVAR(unit) call EFUNC(common,getWeight), + [GVAR(unit), true] call EFUNC(common,getWeight) ]; }; diff --git a/addons/inventory/functions/fnc_filterBackpacks.sqf b/addons/inventory/functions/fnc_filterBackpacks.sqf index 6cb94f3d1c..db1edd9756 100644 --- a/addons/inventory/functions/fnc_filterBackpacks.sqf +++ b/addons/inventory/functions/fnc_filterBackpacks.sqf @@ -10,7 +10,7 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterBackpacks + * [CONFIG] call ace_inventory_fnc_filterBackpacks * * Public: No */ diff --git a/addons/inventory/functions/fnc_filterGrenades.sqf b/addons/inventory/functions/fnc_filterGrenades.sqf index 6d2b813ae4..7e871699b8 100644 --- a/addons/inventory/functions/fnc_filterGrenades.sqf +++ b/addons/inventory/functions/fnc_filterGrenades.sqf @@ -10,11 +10,11 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterGrenades + * [CONFIG] call ace_inventory_fnc_filterGrenades * * Public: No */ params ["_config"]; -toLower configName _config in GVAR(Grenades_ItemList) +(configName _config) in (uiNamespace getVariable QGVAR(grenadesItemList)) diff --git a/addons/inventory/functions/fnc_filterHeadgear.sqf b/addons/inventory/functions/fnc_filterHeadgear.sqf index 134a4fc45f..010c33040f 100644 --- a/addons/inventory/functions/fnc_filterHeadgear.sqf +++ b/addons/inventory/functions/fnc_filterHeadgear.sqf @@ -10,7 +10,7 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterHeadgear + * [CONFIG] call ace_inventory_fnc_filterHeadgear * * Public: No */ diff --git a/addons/inventory/functions/fnc_filterItems.sqf b/addons/inventory/functions/fnc_filterItems.sqf index 0bdb18310f..a3c2567233 100644 --- a/addons/inventory/functions/fnc_filterItems.sqf +++ b/addons/inventory/functions/fnc_filterItems.sqf @@ -10,11 +10,14 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterItems + * [CONFIG] call ace_inventory_fnc_filterItems * * Public: No */ params ["_config"]; -!(getNumber (_config >> "ItemInfo" >> "type") in [TYPE_UNIFORM, TYPE_VESTS, TYPE_HEADGEAR]) && {!(_this call FUNC(filterBackpacks))} +!(_this call FUNC(filterMedical)) && +{!(_this call FUNC(filterBackpacks))} && +{!(_this call FUNC(filterHeadgear))} && +{!(getNumber (_config >> "ItemInfo" >> "type") in [TYPE_UNIFORM, TYPE_VEST])} diff --git a/addons/inventory/functions/fnc_filterMagazines.sqf b/addons/inventory/functions/fnc_filterMagazines.sqf index 4b7747c5a8..e6d9237c21 100644 --- a/addons/inventory/functions/fnc_filterMagazines.sqf +++ b/addons/inventory/functions/fnc_filterMagazines.sqf @@ -10,9 +10,9 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterMagazines + * [CONFIG] call ace_inventory_fnc_filterMagazines * * Public: No */ -!(_this call FUNC(filterBackpacks)) && {!(_this call FUNC(filterGrenades))} +!(_this call FUNC(filterGrenades)) && {!(_this call FUNC(filterBackpacks))} diff --git a/addons/inventory/functions/fnc_filterMedical.sqf b/addons/inventory/functions/fnc_filterMedical.sqf index ec44ba2a76..73cfdbdffb 100644 --- a/addons/inventory/functions/fnc_filterMedical.sqf +++ b/addons/inventory/functions/fnc_filterMedical.sqf @@ -10,11 +10,11 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterMedical + * [CONFIG] call ace_inventory_fnc_filterMedical * * Public: No */ params ["_config"]; -toLower configName _config in GVAR(Medical_ItemList) +(configName _config) in GVAR(medicalItemList) diff --git a/addons/inventory/functions/fnc_filterUniforms.sqf b/addons/inventory/functions/fnc_filterUniforms.sqf index dc7d4e9287..b627475038 100644 --- a/addons/inventory/functions/fnc_filterUniforms.sqf +++ b/addons/inventory/functions/fnc_filterUniforms.sqf @@ -10,7 +10,7 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterUniforms + * [CONFIG] call ace_inventory_fnc_filterUniforms * * Public: No */ diff --git a/addons/inventory/functions/fnc_filterVests.sqf b/addons/inventory/functions/fnc_filterVests.sqf index 439d826390..2bb2af9ef4 100644 --- a/addons/inventory/functions/fnc_filterVests.sqf +++ b/addons/inventory/functions/fnc_filterVests.sqf @@ -10,7 +10,7 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterVests + * [CONFIG] call ace_inventory_fnc_filterVests * * Public: No */ diff --git a/addons/inventory/functions/fnc_filterWeapons.sqf b/addons/inventory/functions/fnc_filterWeapons.sqf index 2addf83665..db4d402099 100644 --- a/addons/inventory/functions/fnc_filterWeapons.sqf +++ b/addons/inventory/functions/fnc_filterWeapons.sqf @@ -10,7 +10,7 @@ * Item should appear in this list? * * Example: - * [CONFIG] call ACE_inventory_fnc_filterWeapons + * [CONFIG] call ace_inventory_fnc_filterWeapons * * Public: No */ diff --git a/addons/inventory/functions/fnc_forceItemListUpdate.sqf b/addons/inventory/functions/fnc_forceItemListUpdate.sqf index 165bff1e57..fb8f09b5c8 100644 --- a/addons/inventory/functions/fnc_forceItemListUpdate.sqf +++ b/addons/inventory/functions/fnc_forceItemListUpdate.sqf @@ -10,31 +10,38 @@ * None * * Example: - * [DISPLAY] call ACE_inventory_fnc_forceitemListUpdate + * [DISPLAY] call ace_inventory_fnc_forceItemListUpdate * * Public: No */ disableSerialization; + params ["_display"]; -private _index = GVAR(selectedFilterIndex); +// Get the appropriate filter +private _filterFunction = missionNamespace getVariable [(_display displayCtrl IDC_FILTERLISTS) lbData GVAR(selectedFilterIndex), ""]; + +if !(_filterFunction isEqualType {}) exitWith {}; + private _itemList = _display call FUNC(currentItemListBox); -private _filterFunction = missionNamespace getVariable ((_display displayCtrl IDC_FILTERLISTS) lbData _index); +private _itemKeyCache = uiNamespace getVariable QGVAR(itemKeyCache); +private _backpackKeyCache = uiNamespace getVariable QGVAR(backpackKeyCache); +private _config = configNull; -if (_filterFunction isEqualType {}) then { - private _i = 0; +for "_i" from (lbSize _itemList) to 0 step -1 do { + // All items have their classnames in lbData, except backpacks + _className = _itemList lbData _i; - while {_i < lbSize _itemList} do { - private _config = GVAR(ItemKeyNamespace) getVariable format ["%1:%2", _itemList lbText _i, _itemList lbPicture _i]; + _config = if (_className != "") then { + _itemKeyCache get _className + } else { + // Backpack are gotten with their display name and inventory icon + _backpackKeyCache get format ["%1:%2", _itemList lbText _i, _itemList lbPicture _i] + }; - if (!isNil "_config" && {!(_config call _filterFunction)}) then { - _itemList lbDelete _i; - - // in case the filter function returns nil. Otherwise could lock up the game. - _i = _i - 1; - }; - - _i = _i + 1; + // If item is valid and doesn't match the current filter, remove it + if (!isNil "_config" && {!(_config call _filterFunction)}) then { + _itemList lbDelete _i; }; }; diff --git a/addons/inventory/functions/fnc_inventoryDisplayLoad.sqf b/addons/inventory/functions/fnc_inventoryDisplayLoad.sqf index 1411ec6cc8..3e70bbd8d9 100644 --- a/addons/inventory/functions/fnc_inventoryDisplayLoad.sqf +++ b/addons/inventory/functions/fnc_inventoryDisplayLoad.sqf @@ -10,71 +10,60 @@ * None * * Example: - * [DISPLAY] call ACE_inventory_fnc_inventoryDisplayLoad + * [DISPLAY] call ace_inventory_fnc_inventoryDisplayLoad * * Public: No */ disableSerialization; + params ["_display"]; private _filter = _display displayCtrl IDC_FILTERLISTS; -// engine defined behaviour is the following: +// Engine defined behaviour is the following: // lb value, data and text don't matter, only the index. -// the first three indecies are hard coded: 0 - weapons , 1 - magazines, 2 - items -// all of them show backpacks, because BI -// all other indecies show everything, so all we have to do is delete stuff we dont like -_filter ctrlAddEventHandler ["LBSelChanged", {_this call FUNC(onLBSelChanged)}]; +// The first three indecies are hard coded: 0 - weapons , 1 - magazines, 2 - items +// All of them show backpacks, because BI +// All other indecies show everything, so all we have to do is delete stuff we don't like +_filter ctrlAddEventHandler ["LBSelChanged", LINKFUNC(onLBSelChanged)]; -// have to add these a frame later, because this event happens before the engine adds the default filters +// Have to add these a frame later, because this event happens before the engine adds the default filters [{ disableSerialization; + params ["_filter"]; - // remove "All", so we can push it to the back later. - // to keep localization we can keep the lbText (displayed name). + // Remove "All", so we can push it to the back later + // To keep localization we keep the lbText (displayed name) private _index = lbSize _filter - 1; private _nameAll = _filter lbText _index; _filter lbDelete _index; - // add additional filter functions to the default filters. These remove backpacks etc. + // Add additional filter functions to the default filters. These remove backpacks etc. _filter lbSetData [0, QFUNC(filterWeapons)]; _filter lbSetData [1, QFUNC(filterMagazines)]; _filter lbSetData [2, QFUNC(filterItems)]; - // add our custom filters + // Add our custom filters { _x params ["_name", "_fncName"]; _index = _filter lbAdd _name; _filter lbSetData [_index, _fncName]; + } forEach GVAR(customFilters); - false - } count GVAR(customFilters); - - // readd "All" filter to last position and select it + // Readd "All" filter to last position and select it _index = _filter lbAdd _nameAll; _filter lbSetCurSel _index; -}, [_filter]] call CBA_fnc_execNextFrame; +}, _filter] call CBA_fnc_execNextFrame; -// monitor changes that can happen and force our update +// Monitor changes that can happen and force our update private _dummyControl = _display ctrlCreate ["RscMapControl", -1]; -_dummyControl ctrlSetPosition [0,0,0,0]; +_dummyControl ctrlSetPosition [0, 0, 0, 0]; _dummyControl ctrlCommit 0; _dummyControl ctrlAddEventHandler ["Draw", { - disableSerialization; - params ["_dummyControl"]; - - private _display = ctrlParent _dummyControl; - - private _itemList = _display call FUNC(currentItemListBox); - - // monitoring is done by setting a lb value. These are unused here and are reset every time the list box updates. - if (_itemList lbValue 0 != DUMMY_VALUE) then { - _display call FUNC(forceItemListUpdate); - _itemList lbSetValue [0, DUMMY_VALUE]; - }; + (ctrlParent (_this select 0)) call FUNC(forceItemListUpdate); }]; diff --git a/addons/inventory/functions/fnc_onLBSelChanged.sqf b/addons/inventory/functions/fnc_onLBSelChanged.sqf index 6fbc7020c0..a2316dc4b6 100644 --- a/addons/inventory/functions/fnc_onLBSelChanged.sqf +++ b/addons/inventory/functions/fnc_onLBSelChanged.sqf @@ -12,19 +12,16 @@ * None * * Example: - * [CONTROL, 5] call ACE_inventory_fnc_onLBSelChanged + * [CONTROL, 5] call ace_inventory_fnc_onLBSelChanged * * Public: No */ disableSerialization; + params ["_filter", "_index"]; GVAR(selectedFilterIndex) = _index; -[{ - disableSerialization; - params ["_display"]; - - [_display] call FUNC(forceItemListUpdate); -}, [ctrlParent _filter]] call CBA_fnc_execNextFrame; +// Force update +[LINKFUNC(forceItemListUpdate), ctrlParent _filter] call CBA_fnc_execNextFrame; diff --git a/addons/kestrel4500/functions/fnc_collectData.sqf b/addons/kestrel4500/functions/fnc_collectData.sqf index 14fd6047f2..318a5a7123 100644 --- a/addons/kestrel4500/functions/fnc_collectData.sqf +++ b/addons/kestrel4500/functions/fnc_collectData.sqf @@ -15,6 +15,8 @@ * Public: No */ +#define TEMPERATURE_SLOT_INDEX 5 + private _playerDir = getDir ACE_player; private _playerAltitude = (getPosASL ACE_player) select 2; private _temperature = _playerAltitude call EFUNC(weather,calculateTemperatureAtHeight); @@ -41,9 +43,10 @@ if (isNil QGVAR(MIN) || isNil QGVAR(MAX)) then { [0, _playerDir] call FUNC(updateMemory); if (GVAR(MinAvgMaxMode) == 1) then { + private _useAB = missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]; { GVAR(ENTRIES) set [_x, (GVAR(ENTRIES) select _x) + 1]; - } count [2, 3, 4]; + } forEach [2, 3, 4]; // Wind SPD private _windSpeed = call FUNC(measureWindSpeed); @@ -51,7 +54,7 @@ if (GVAR(MinAvgMaxMode) == 1) then { // CROSSWIND private _crosswind = 0; - if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { + if (_useAB) then { _crosswind = abs(sin(GVAR(RefHeading) - _playerDir) * _windSpeed); } else { _crosswind = abs(sin(GVAR(RefHeading)) * _windSpeed); @@ -60,7 +63,7 @@ if (GVAR(MinAvgMaxMode) == 1) then { // HEADWIND private _headwind = 0; - if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { + if (_useAB) then { _headwind = cos(GVAR(RefHeading) - _playerDir) * _windSpeed; } else { _headwind = cos(GVAR(RefHeading)) * _windSpeed; @@ -74,4 +77,18 @@ if (GVAR(MinAvgMaxMode) == 1) then { GVAR(TOTAL) set [4, (GVAR(TOTAL) select 4) + _headwind]; }; -{ _x call FUNC(updateMemory); true } count [[5, _temperature],[6, _chill],[7, _humidity],[8, _heatIndex],[9, _dewPoint],[10, _wetBulb],[11, _barometricPressure],[12, _altitude],[13, _densityAltitude]]; +private _data = [ + _temperature, + _chill, + _humidity, + _heatIndex, + _dewPoint, + _wetBulb, + _barometricPressure, + _altitude, + _densityAltitude +]; + +{ + [TEMPERATURE_SLOT_INDEX + _forEachIndex, _x] call FUNC(updateMemory); +} forEach _data; diff --git a/addons/killtracker/XEH_postInit.sqf b/addons/killtracker/XEH_postInit.sqf index 2f75baa929..9cef418ece 100644 --- a/addons/killtracker/XEH_postInit.sqf +++ b/addons/killtracker/XEH_postInit.sqf @@ -19,7 +19,7 @@ if ((getText (missionconfigfile >> "CfgDebriefingSections" >> QUOTE(XADDON) >> "variable")) != QXGVAR(outputText)) exitWith { TRACE_1("no mission debriefing config",_this); }; -if (!(["ACE_Medical"] call EFUNC(common,isModLoaded))) exitWith { +if (!(["ace_medical"] call EFUNC(common,isModLoaded))) exitWith { WARNING("No ACE-Medical"); XGVAR(outputText) = "No ACE-Medical"; }; diff --git a/addons/logistics_rope/CfgWeapons.hpp b/addons/logistics_rope/CfgWeapons.hpp index c5f1b384a2..d8789c6407 100644 --- a/addons/logistics_rope/CfgWeapons.hpp +++ b/addons/logistics_rope/CfgWeapons.hpp @@ -3,7 +3,7 @@ class CfgWeapons { class ACE_ItemCore; class ACE_ropeBase: ACE_ItemCore { scope = 1; - picture = QPATHTOF(data\m_rope_ca); + picture = QPATHTOF(data\m_rope_ca.paa); // model = "\A3\Structures_F_Heli\Items\Tools\Rope_01_F.p3d"; // model is Locked to Helicopter DLC descriptionShort = CSTRING(descriptionShort); }; diff --git a/addons/magazinerepack/stringtable.xml b/addons/magazinerepack/stringtable.xml index a47b1538bf..9ec8a0fe5a 100644 --- a/addons/magazinerepack/stringtable.xml +++ b/addons/magazinerepack/stringtable.xml @@ -161,7 +161,7 @@ %1 Pieno(i) e %2 Parziale(i) %1 Total e %2 Parcial 満装填した弾倉 %1 個と<br/>部分装填の弾倉 %2 個 - %1 꽉 찼고 %2 부분적으로 참 + 꽉 찬 탄창:%1<br/>부분적으로 찬 탄창: %2 %1个满的与%2个部分的 %1個滿的與%2個部分的 %1 Dolu ve %2 Partial diff --git a/addons/main/script_macros.hpp b/addons/main/script_macros.hpp index ed3a826678..495d592e5f 100644 --- a/addons/main/script_macros.hpp +++ b/addons/main/script_macros.hpp @@ -99,7 +99,11 @@ #define TYPE_SCUBA 604 // not implemented #define TYPE_HEADGEAR 605 #define TYPE_FACTOR 607 +#define TYPE_MAP 608 +#define TYPE_COMPASS 609 +#define TYPE_WATCH 610 #define TYPE_RADIO 611 +#define TYPE_GPS 612 #define TYPE_HMD 616 #define TYPE_BINOCULAR 617 #define TYPE_MEDIKIT 619 diff --git a/addons/maptools/CfgVehicles.hpp b/addons/maptools/CfgVehicles.hpp index 8c320de321..10302a0c4f 100644 --- a/addons/maptools/CfgVehicles.hpp +++ b/addons/maptools/CfgVehicles.hpp @@ -1,62 +1,204 @@ +#define EXCEPTIONS exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"} + class CfgVehicles { class Man; class CAManBase: Man { class ACE_SelfActions { class ACE_MapGpsShow { displayName = CSTRING(MapGpsShow); - condition = QUOTE((!GVAR(mapGpsShow)) && {call FUNC(canUseMapGPS)}); - statement = QUOTE(GVAR(mapGpsShow) = true;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + condition = QUOTE(!GVAR(mapGpsShow) && {call FUNC(canUseMapGPS)}); + statement = QUOTE(GVAR(mapGpsShow) = true); + EXCEPTIONS; showDisabled = 0; }; class ACE_MapGpsHide { displayName = CSTRING(MapGpsHide); - condition = QUOTE((GVAR(mapGpsShow)) && {call FUNC(canUseMapGPS)}); - statement = QUOTE(GVAR(mapGpsShow) = false;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + condition = QUOTE(GVAR(mapGpsShow) && {call FUNC(canUseMapGPS)}); + statement = QUOTE(GVAR(mapGpsShow) = false); + EXCEPTIONS; showDisabled = 0; }; class ACE_MapTools { displayName = CSTRING(MapTools_Menu); condition = QUOTE(call FUNC(canUseMapTools)); statement = ""; - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + EXCEPTIONS; showDisabled = 0; + class ACE_MapToolsHide { displayName = CSTRING(MapToolsHide); condition = QUOTE(GVAR(mapTool_Shown) != 0); - statement = QUOTE(GVAR(mapTool_Shown) = 0;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + statement = QUOTE(GVAR(mapTool_Shown) = 0); + EXCEPTIONS; showDisabled = 1; }; class ACE_MapToolsShowNormal { displayName = CSTRING(MapToolsShowNormal); condition = QUOTE(GVAR(mapTool_Shown) != 1); - statement = QUOTE(if (GVAR(mapTool_Shown) == 0) then {GVAR(mapTool_moveToMouse) = true}; GVAR(mapTool_Shown) = 1;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + statement = QUOTE(if (GVAR(mapTool_Shown) == 0) then {GVAR(mapTool_moveToMouse) = true}; GVAR(mapTool_Shown) = 1); + EXCEPTIONS; showDisabled = 1; }; class ACE_MapToolsShowSmall { displayName = CSTRING(MapToolsShowSmall); condition = QUOTE(GVAR(mapTool_Shown) != 2); - statement = QUOTE(if (GVAR(mapTool_Shown) == 0) then {GVAR(mapTool_moveToMouse) = true}; GVAR(mapTool_Shown) = 2;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + statement = QUOTE(if (GVAR(mapTool_Shown) == 0) then {GVAR(mapTool_moveToMouse) = true}; GVAR(mapTool_Shown) = 2); + EXCEPTIONS; showDisabled = 1; }; - class ACE_MapToolsAlignNorth { - displayName = CSTRING(MapToolsAlignNorth); + class ACE_MapToolsAlign { + displayName = CSTRING(AlignTo); condition = QUOTE(GVAR(mapTool_Shown) != 0); - statement = QUOTE(GVAR(mapTool_angle) = 0;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + statement = ""; + EXCEPTIONS; + showDisabled = 0; + + class ACE_MapToolsAlignToPlottingBoardRuler { + displayName = CSTRING(ToPlottingBoardRulerLabel); + condition = QUOTE(GVAR(mapTool_Shown) != 0 && GVAR(plottingBoard_Shown) == 2); + statement = QUOTE(GVAR(mapTool_angle) = GVAR(plottingBoard_rulerAngle)); + EXCEPTIONS; + showDisabled = 1; + }; + class ACE_MapToolsAlignToPlottingBoardAcrylic { + displayName = CSTRING(ToPlottingBoardAcrylicLabel); + condition = QUOTE(GVAR(mapTool_Shown) != 0 && GVAR(plottingBoard_Shown) != 0); + statement = QUOTE(GVAR(mapTool_angle) = GVAR(plottingBoard_acrylicAngle)); + EXCEPTIONS; + showDisabled = 1; + }; + class ACE_MapToolsAlignToPlottingBoard { + displayName = CSTRING(ToPlottingBoardLabel); + condition = QUOTE(GVAR(mapTool_Shown) != 0 && GVAR(plottingBoard_Shown) != 0); + statement = QUOTE(GVAR(mapTool_angle) = GVAR(plottingBoard_angle)); + EXCEPTIONS; + showDisabled = 1; + }; + class ACE_MapToolsAlignCompass { + displayName = CSTRING(ToCompassLabel); + condition = QUOTE(GVAR(mapTool_Shown) != 0 && {ACE_player getSlotItemName TYPE_COMPASS != ''}); + statement = QUOTE(GVAR(mapTool_angle) = getDir ACE_player); + EXCEPTIONS; + showDisabled = 1; + }; + class ACE_MapToolsAlignNorth { + displayName = CSTRING(ToNorthLabel); + condition = QUOTE(GVAR(mapTool_Shown) != 0); + statement = QUOTE(GVAR(mapTool_angle) = 0); + EXCEPTIONS; + showDisabled = 1; + }; + }; + }; + class ACE_PlottingBoard { + displayName = CSTRING(ShowPlottingBoard); + condition = QUOTE(GVAR(plottingBoard_Shown) < 1 && {call FUNC(canUsePlottingBoard)}); + statement = QUOTE(GVAR(plottingBoard_Shown) = 1); + EXCEPTIONS; + showDisabled = 0; + }; + class ACE_PlottingBoardHide { + displayName = CSTRING(HidePlottingBoard); + condition = QUOTE(GVAR(plottingBoard_Shown) != 0 && {call FUNC(canUsePlottingBoard)}); + statement = QUOTE(GVAR(plottingBoard_Shown) = 0); + EXCEPTIONS; + showDisabled = 0; + + class ACE_PlottingBoardRulerShow { + displayName = CSTRING(TogglePlottingBoardRuler); + condition = QUOTE(GVAR(plottingBoard_Shown) == 1); + statement = QUOTE(GVAR(plottingBoard_Shown) = 2); + EXCEPTIONS; showDisabled = 1; }; - class ACE_MapToolsAlignCompass { - displayName = CSTRING(MapToolsAlignCompass); - condition = QUOTE(GVAR(mapTool_Shown) != 0 && {getUnitLoadout ACE_player param [ARR_2(9,[])] param [ARR_2(3,'')] != ''}); - statement = QUOTE(GVAR(mapTool_angle) = getDir ACE_player;); - exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; + class ACE_PlottingBoardRulerHide { + displayName = CSTRING(TogglePlottingBoardRuler); + condition = QUOTE(GVAR(plottingBoard_Shown) == 2); + statement = QUOTE(GVAR(plottingBoard_Shown) = 1); + EXCEPTIONS; showDisabled = 1; }; + class ACE_PlottingBoardWipe { + displayName = CSTRING(WipeBoard); + condition = QUOTE(GVAR(plottingBoard_markers) isNotEqualTo createHashMap); + statement = QUOTE(call FUNC(wipeMarkers)); + EXCEPTIONS; + showDisabled = 1; + }; + class ACE_PlottingBoardAlign { + displayName = CSTRING(AlignTo); + condition = QUOTE(GVAR(plottingBoard_Shown) > 0); + statement = ""; + EXCEPTIONS; + showDisabled = 0; + + class ACE_PlottingBoardAlignBoard { + displayName = CSTRING(PlottingBoardLabel); + condition = QUOTE(true); + statement = ""; + EXCEPTIONS; + showDisabled = 0; + + class ACE_PlottingBoardAlignBoardMaptool { + displayName = CSTRING(Name); + condition = QUOTE(GVAR(mapTool_Shown) > 0 && GVAR(plottingBoard_angle) != GVAR(mapTool_angle)); + statement = QUOTE(GVAR(plottingBoard_angle) = GVAR(mapTool_angle)); + EXCEPTIONS; + showDisabled = 0; + }; + class ACE_PlottingBoardAlignBoardUp { + displayName = CSTRING(ToUpLabel); + condition = QUOTE(GVAR(plottingBoard_angle) != 0); + statement = QUOTE(GVAR(plottingBoard_angle) = 0); + EXCEPTIONS; + showDisabled = 0; + }; + }; + class ACE_PlottingBoardAlignAcrylic { + displayName = CSTRING(PlottingBoardAcrylicLabel); + condition = QUOTE(true); + statement = ""; + EXCEPTIONS; + showDisabled = 0; + + class ACE_PlottingBoardAlignAcrylicMaptool { + displayName = CSTRING(Name); + condition = QUOTE(GVAR(mapTool_Shown) > 0 && GVAR(plottingBoard_acrylicAngle) != GVAR(mapTool_angle)); + statement = QUOTE(GVAR(plottingBoard_acrylicAngle) = GVAR(mapTool_angle)); + EXCEPTIONS; + showDisabled = 0; + }; + class ACE_PlottingBoardAlignAcrylicUp { + displayName = CSTRING(ToUpLabel); + condition = QUOTE(GVAR(plottingBoard_acrylicAngle) != 0); + statement = QUOTE(GVAR(plottingBoard_acrylicAngle) = 0); + EXCEPTIONS; + showDisabled = 0; + }; + }; + class ACE_PlottingBoardAlignRuler { + displayName = CSTRING(PlottingBoardRulerLabel); + condition = QUOTE(GVAR(plottingBoard_Shown) == 2); + statement = ""; + EXCEPTIONS; + showDisabled = 0; + + class ACE_PlottingBoardAlignRulerMaptool { + displayName = CSTRING(Name); + condition = QUOTE(GVAR(mapTool_Shown) > 0 && GVAR(plottingBoard_rulerAngle) != GVAR(mapTool_angle)); + statement = QUOTE(GVAR(plottingBoard_rulerAngle) = GVAR(mapTool_angle)); + EXCEPTIONS; + showDisabled = 0; + }; + class ACE_PlottingBoardAlignRulerUp { + displayName = CSTRING(ToUpLabel); + condition = QUOTE(GVAR(plottingBoard_rulerAngle) != 0); + statement = QUOTE(GVAR(plottingBoard_rulerAngle) = 0); + EXCEPTIONS; + showDisabled = 0; + }; + }; + }; }; }; }; @@ -69,30 +211,35 @@ class CfgVehicles { class Box_NATO_Support_F: NATO_Box_Base { class TransportItems { MACRO_ADDITEM(ACE_MapTools,12); + MACRO_ADDITEM(ACE_PlottingBoard,12); }; }; class Box_East_Support_F: EAST_Box_Base { class TransportItems { MACRO_ADDITEM(ACE_MapTools,12); + MACRO_ADDITEM(ACE_PlottingBoard,12); }; }; class Box_IND_Support_F: IND_Box_Base { class TransportItems { MACRO_ADDITEM(ACE_MapTools,12); + MACRO_ADDITEM(ACE_PlottingBoard,12); }; }; class Box_FIA_Support_F: FIA_Box_Base_F { class TransportItems { MACRO_ADDITEM(ACE_MapTools,12); + MACRO_ADDITEM(ACE_PlottingBoard,12); }; }; class ACE_Box_Misc: Box_NATO_Support_F { class TransportItems { MACRO_ADDITEM(ACE_MapTools,12); + MACRO_ADDITEM(ACE_PlottingBoard,12); }; }; }; diff --git a/addons/maptools/CfgWeapons.hpp b/addons/maptools/CfgWeapons.hpp index 62d969badb..9d2727612b 100644 --- a/addons/maptools/CfgWeapons.hpp +++ b/addons/maptools/CfgWeapons.hpp @@ -14,4 +14,17 @@ class CfgWeapons { mass = 0.2; }; }; + + class ACE_PlottingBoard: ACE_ItemCore { + displayName = CSTRING(PlottingBoard_Name); + author = ECSTRING(common,ACETeam); + descriptionShort = CSTRING(Description); + model = QPATHTOF(data\ace_MapTools.p3d); + picture = QPATHTOF(UI\plottingboard_item.paa); + scope = 2; + ACE_isTool = 1; + class ItemInfo: CBA_MiscItem_ItemInfo { + mass = 0.5; + }; + }; }; diff --git a/addons/maptools/README.md b/addons/maptools/README.md index a11f57a1a5..fe9c836c13 100644 --- a/addons/maptools/README.md +++ b/addons/maptools/README.md @@ -5,3 +5,4 @@ Adds the following map tools: - Roamer - Map drawing - Showing GPS on map +- Plotting Board diff --git a/addons/maptools/UI/plottingboard_item.paa b/addons/maptools/UI/plottingboard_item.paa new file mode 100644 index 0000000000..2d89f35514 Binary files /dev/null and b/addons/maptools/UI/plottingboard_item.paa differ diff --git a/addons/maptools/XEH_PREP.hpp b/addons/maptools/XEH_PREP.hpp index cf193698e5..ac9ed8b91f 100644 --- a/addons/maptools/XEH_PREP.hpp +++ b/addons/maptools/XEH_PREP.hpp @@ -7,3 +7,8 @@ PREP(handleMouseMove); PREP(isInsideMapTool); PREP(openMapGpsUpdate); PREP(updateMapToolMarkers); + +PREP(canUsePlottingBoard); +PREP(isInsidePlottingBoard); +PREP(handlePlottingBoardMarkers); +PREP(wipeMarkers); diff --git a/addons/maptools/XEH_postInitClient.sqf b/addons/maptools/XEH_postInitClient.sqf index eede4db015..a1b8afd08d 100644 --- a/addons/maptools/XEH_postInitClient.sqf +++ b/addons/maptools/XEH_postInitClient.sqf @@ -1,4 +1,4 @@ -// by esteldunedain +// by esteldunedain, LorenLuke #include "script_component.hpp" @@ -9,12 +9,22 @@ GVAR(mapGpsShow) = true; GVAR(mapGpsNextUpdate) = -1; GVAR(mapTool_Shown) = 0; -GVAR(mapTool_pos) = [0,0]; +GVAR(mapTool_pos) = [0, 0]; GVAR(mapTool_angle) = 0; GVAR(mapTool_isDragging) = false; GVAR(mapTool_isRotating) = false; GVAR(mapTool_moveToMouse) = true; // used to display it in center of screen when opened +GVAR(plottingBoard_Shown) = 0; +GVAR(plottingBoard_pos) = [0, 0]; +GVAR(plottingBoard_angle) = 0; +GVAR(plottingBoard_acrylicAngle) = 0; +GVAR(plottingBoard_rulerAngle) = 0; +GVAR(plottingBoard_isDragging) = false; +GVAR(plottingBoard_isRotating) = -1; +GVAR(plottingBoard_moveToMouse) = true; // used to display it in center of screen when opened +GVAR(plottingBoard_markers) = createHashMap; + //Install the event handers for the map tools on the main in-game map [{!isNull findDisplay 12}, { @@ -32,7 +42,13 @@ GVAR(mapTool_moveToMouse) = true; // used to display it in center of screen whe }; }] call CBA_fnc_addPlayerEventHandler; +addMissionEventHandler ["MarkerCreated", { + [_this, false] call FUNC(handlePlottingBoardMarkers); +}]; + +addMissionEventHandler ["MarkerDeleted", { + [[_this select 0, -1, objNull, _this select 1], true] call FUNC(handlePlottingBoardMarkers); +}]; GVAR(freeDrawingData) = []; GVAR(freedrawing) = false; - diff --git a/addons/maptools/data/plottingBoardAcrylic.paa b/addons/maptools/data/plottingBoardAcrylic.paa new file mode 100644 index 0000000000..eaa8bf2e13 Binary files /dev/null and b/addons/maptools/data/plottingBoardAcrylic.paa differ diff --git a/addons/maptools/data/plottingBoardBack.paa b/addons/maptools/data/plottingBoardBack.paa new file mode 100644 index 0000000000..79772e7cb0 Binary files /dev/null and b/addons/maptools/data/plottingBoardBack.paa differ diff --git a/addons/maptools/data/plottingBoardRuler.paa b/addons/maptools/data/plottingBoardRuler.paa new file mode 100644 index 0000000000..83160af799 Binary files /dev/null and b/addons/maptools/data/plottingBoardRuler.paa differ diff --git a/addons/maptools/functions/fnc_canUsePlottingBoard.sqf b/addons/maptools/functions/fnc_canUsePlottingBoard.sqf new file mode 100644 index 0000000000..d3394916f1 --- /dev/null +++ b/addons/maptools/functions/fnc_canUsePlottingBoard.sqf @@ -0,0 +1,22 @@ +#include "..\script_component.hpp" +/* + * Author: LorenLuke + * Returns if the plotting board can be used. + * + * Arguments: + * None + * + * Return Value: + * Plotting board can be used + * + * Example: + * call ace_maptools_fnc_canUsePlottingBoard + * + * Public: No + */ + +visibleMap && +{alive ACE_player} && +{[ACE_player, "ACE_PlottingBoard"] call EFUNC(common,hasItem)} && +{!GVAR(plottingBoard_isDragging)} && +{GVAR(plottingBoard_isRotating) == -1} diff --git a/addons/maptools/functions/fnc_handleMouseButton.sqf b/addons/maptools/functions/fnc_handleMouseButton.sqf index beee6157eb..796a84744a 100644 --- a/addons/maptools/functions/fnc_handleMouseButton.sqf +++ b/addons/maptools/functions/fnc_handleMouseButton.sqf @@ -1,17 +1,17 @@ #include "..\script_component.hpp" /* - * Author: esteldunedain + * Author: esteldunedain, LorenLuke * Handle mouse buttons. * * Arguments: - * 0: 1 if mouse down down, 0 if mouse button up + * 0: 1 if mouse down down, 0 if mouse button up * 1: Parameters of the mouse button event * * Return Value: - * true if event was handled + * True if event was handled * * Example: - * [0, [array]] call ACE_maptools_fnc_handleMouseButton + * [0, []] call ace_maptools_fnc_handleMouseButton * * Public: No */ @@ -24,20 +24,27 @@ TRACE_2("params",_dir,_params); if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith { if (GVAR(freedrawing) && {_dir == 0}) then { GVAR(freedrawing) = false; + if (_shiftKey) exitWith { TRACE_1("using vanilla straight line",_shiftKey); }; + TRACE_2("Ending Line",GVAR(freedrawing),GVAR(freeDrawingData)); + [{ - if (allMapMarkers isEqualTo []) exitWith {}; - private _markerName = allMapMarkers select (count allMapMarkers - 1); + if (GVAR(freeDrawingData) isEqualTo []) exitWith {TRACE_1("never touched roamer",GVAR(freeDrawingData))}; + + private _allMarkers = allMapMarkers; + + if (_allMarkers isEqualTo []) exitWith {}; + + private _markerName = _allMarkers select -1; private _markerPos = getMarkerPos _markerName; - private _distanceCheck = _markerPos distance2d GVAR(drawPosStart); + private _distanceCheck = _markerPos distance2D GVAR(drawPosStart); TRACE_3("Line Drawn",_markerName,_markerPos,_distanceCheck); - if (_distanceCheck > 1) exitWith {WARNING("Wrong Marker!");}; - if ((count GVAR(freeDrawingData)) != 3) exitWith {TRACE_1("never touched roamer",GVAR(freeDrawingData));}; + if (_distanceCheck > 1) exitWith {WARNING("Wrong Marker!")}; GVAR(freeDrawingData) params ["", "_startStraightPos", "_endStraightPos"]; @@ -54,17 +61,20 @@ if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith { TRACE_2("Starting Line",GVAR(freedrawing),GVAR(drawPosStart)); } else { GVAR(freedrawing) = false; - TRACE_1("weird - reseting",GVAR(freedrawing)); + TRACE_1("weird - resetting",GVAR(freedrawing)); }; }; - false + + false // return +}; + +// If it's not a left button event, exit +if (_button != 0) exitWith { + false // return }; private _handled = false; -// If it's not a left button event, exit -if (_button != 0) exitWith {_handled}; - // If releasing if (_dir != 1) then { if (GVAR(mapTool_isDragging) || GVAR(mapTool_isRotating)) then { @@ -72,44 +82,98 @@ if (_dir != 1) then { GVAR(mapTool_isRotating) = false; _handled = true; }; + + if (GVAR(plottingBoard_isDragging) || GVAR(plottingBoard_isRotating) > -1) then { + GVAR(plottingBoard_isDragging) = false; + GVAR(plottingBoard_isRotating) = -1; + _handled = true; + }; } else { // If clicking - if !(call FUNC(canUseMapTools)) exitWith {}; + if (call FUNC(canUseMapTools)) then { + GVAR(mapTool_isDragging) = false; + GVAR(mapTool_isRotating) = false; - // Transform mouse screen position to coordinates - private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY]; - _pos set [count _pos, 0]; + // If no map tool marker then exit + if (GVAR(mapTool_Shown) != 0) then { + // Transform mouse screen position to coordinates + private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY]; - GVAR(mapTool_isDragging) = false; - GVAR(mapTool_isRotating) = false; + // Check if clicking the maptool + if (_pos call FUNC(isInsideMapTool)) then { + // Store data for dragging + GVAR(mapTool_startPos) = +GVAR(mapTool_pos); + GVAR(mapTool_startDragPos) = _pos; - // If no map tool marker then exit - if (GVAR(mapTool_Shown) == 0) exitWith {}; + private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do { + case 1: {_altKey}; + case 2: {_ctrlKey}; + case 3: {_shiftKey}; + default {false}; + }; - // Check if clicking the maptool - if (_pos call FUNC(isInsideMapTool)) exitWith { - // Store data for dragging - GVAR(mapTool_startPos) = + GVAR(mapTool_pos); - GVAR(mapTool_startDragPos) = + _pos; + if (_rotateKeyPressed) then { + // Store data for rotating + GVAR(mapTool_startAngle) = GVAR(mapTool_angle); - private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do { - case (1): {_altKey}; - case (2): {_ctrlKey}; - case (3): {_shiftKey}; - default {false}; + private _pos = GVAR(mapTool_startDragPos) vectorDiff GVAR(mapTool_startPos); + GVAR(mapTool_startDragAngle) = ((_pos select 0) atan2 (_pos select 1) + 360) % 360; + + // Start rotating + GVAR(mapTool_isRotating) = true; + } else { + // Start dragging + GVAR(mapTool_isDragging) = true; + }; + + _handled = true; + }; }; + }; - if (_rotateKeyPressed) then { - // Store data for rotating - GVAR(mapTool_startAngle) = + GVAR(mapTool_angle); - GVAR(mapTool_startDragAngle) = (180 + ((GVAR(mapTool_startDragPos) select 0) - (GVAR(mapTool_startPos) select 0)) atan2 ((GVAR(mapTool_startDragPos) select 1) - (GVAR(mapTool_startPos) select 1)) mod 360); - // Start rotating - GVAR(mapTool_isRotating) = true; - } else { - // Start dragging - GVAR(mapTool_isDragging) = true; + if (call FUNC(canUsePlottingBoard)) then { + GVAR(plottingBoard_isDragging) = false; + GVAR(plottingBoard_isRotating) = -1; + + if (GVAR(plottingBoard_Shown) != 0) then { + // Transform mouse screen position to coordinates + private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY]; + private _click = _pos call FUNC(isInsidePlottingBoard); + + if (_click > -1) then { + GVAR(plottingBoard_startPos) = +GVAR(plottingBoard_pos); + GVAR(plottingBoard_startDragPos) = _pos; + + private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do { + case 1: {_altKey}; + case 2: {_ctrlKey}; + case 3: {_shiftKey}; + default {false}; + }; + + if (_rotateKeyPressed) then { + // Store data for rotating + private _ang = switch (_click) do { + case 1: {GVAR(plottingBoard_acrylicAngle)}; + case 2: {GVAR(plottingBoard_rulerAngle)}; + default {GVAR(plottingBoard_angle)}; + }; + + GVAR(plottingBoard_startAngle) = _ang; + + private _pos = GVAR(plottingBoard_startDragPos) vectorDiff GVAR(plottingBoard_startPos); + GVAR(plottingBoard_startDragAngle) = ((_pos select 0) atan2 (_pos select 1) + 360) % 360; + + // Start rotating + GVAR(plottingBoard_isRotating) = _click; + } else { + // Start dragging + GVAR(plottingBoard_isDragging) = true; + }; + + _handled = true; + }; }; - _handled = true; }; }; diff --git a/addons/maptools/functions/fnc_handleMouseMove.sqf b/addons/maptools/functions/fnc_handleMouseMove.sqf index 5af4f02e30..37c6cf4d21 100644 --- a/addons/maptools/functions/fnc_handleMouseMove.sqf +++ b/addons/maptools/functions/fnc_handleMouseMove.sqf @@ -1,47 +1,75 @@ #include "..\script_component.hpp" /* - * Author: esteldunedain - * Handle mouse movement over the map tool. + * Author: esteldunedain, LorenLuke + * Handle mouse movement over the map tool and plotting board. * * Arguments: - * 0: Map Control + * 0: Map control * 1: Mouse position on screen coordinates * * Return Value: - * true if event was handled + * If the event was handled * * Example: - * [CONTROL, [0, 5, 1]] call ACE_maptools_fnc_handleMouseMove + * [CONTROL, [0, 5]] call ace_maptools_fnc_handleMouseMove * * Public: No */ -params ["_control", "_mousePosX", "_mousePosY"]; -TRACE_3("params",_control,_mousePosX,_mousePosY); +params ["_mapCtrl", "_mousePosX", "_mousePosY"]; +TRACE_3("params",_mapCtrl,_mousePosX,_mousePosY); // If have no map tools, then exit -if (((isNull ACE_player) || {!("ACE_MapTools" in (ACE_player call EFUNC(common,uniqueItems)))})) exitWith { +if (isNull ACE_player || { + private _uniqueItems = ACE_player call EFUNC(common,uniqueItems); + + !(("ACE_MapTools" in _uniqueItems) || {"ACE_PlottingBoard" in _uniqueItems}) +}) exitWith { false }; // If map tools not shown, then exit -if (GVAR(mapTool_Shown) == 0) exitWith {false}; +if (GVAR(mapTool_Shown) == 0 && {GVAR(plottingBoard_Shown) == 0}) exitWith {false}; -private _mousePosition = _control ctrlMapScreenToWorld [_mousePosX, _mousePosY]; +private _mousePosition = _mapCtrl ctrlMapScreenToWorld [_mousePosX, _mousePosY]; -// Translation +// Map tools - translation if (GVAR(mapTool_isDragging)) exitWith { - GVAR(mapTool_pos) set [0, (GVAR(mapTool_startPos) select 0) + (_mousePosition select 0) - (GVAR(mapTool_startDragPos) select 0)]; - GVAR(mapTool_pos) set [1, (GVAR(mapTool_startPos) select 1) + (_mousePosition select 1) - (GVAR(mapTool_startDragPos) select 1)]; + GVAR(mapTool_pos) = GVAR(mapTool_startPos) vectorAdd _mousePosition vectorDiff GVAR(mapTool_startDragPos); true }; -// Rotation +// Map tools - rotation if (GVAR(mapTool_isRotating)) exitWith { // Get new angle - private _angle = (180 + ((_mousePosition select 0) - (GVAR(mapTool_startPos) select 0)) atan2 ((_mousePosition select 1) - (GVAR(mapTool_startPos) select 1)) mod 360); - GVAR(mapTool_angle) = GVAR(mapTool_startAngle) + _angle - GVAR(mapTool_startDragAngle); + private _pos = _mousePosition vectorDiff GVAR(mapTool_startPos); + private _angle = (_pos select 0) atan2 (_pos select 1); + + GVAR(mapTool_angle) = ((GVAR(mapTool_startAngle) + _angle - GVAR(mapTool_startDragAngle)) % 360 + 360) % 360; + + true +}; + +// Plotting board - translation +if (GVAR(plottingBoard_isDragging)) exitWith { + GVAR(plottingBoard_pos) = GVAR(plottingBoard_startPos) vectorAdd _mousePosition vectorDiff GVAR(plottingBoard_startDragPos); + + true +}; + +// Plotting board - rotation +if (GVAR(plottingBoard_isRotating) > -1) exitWith { + // Get new angle + private _pos = _mousePosition vectorDiff GVAR(plottingBoard_startPos); + private _angle = (_pos select 0) atan2 (_pos select 1); + private _returnAngle = ((GVAR(plottingBoard_startAngle) + _angle - GVAR(plottingBoard_startDragAngle)) % 360 + 360) % 360; + + switch (GVAR(plottingBoard_isRotating)) do { + case 0: {GVAR(plottingBoard_angle) = _returnAngle}; + case 1: {GVAR(plottingBoard_acrylicAngle) = _returnAngle}; + case 2: {GVAR(plottingBoard_rulerAngle) = _returnAngle}; + }; true }; diff --git a/addons/maptools/functions/fnc_handlePlottingBoardMarkers.sqf b/addons/maptools/functions/fnc_handlePlottingBoardMarkers.sqf new file mode 100644 index 0000000000..b73bfb7dc4 --- /dev/null +++ b/addons/maptools/functions/fnc_handlePlottingBoardMarkers.sqf @@ -0,0 +1,219 @@ +#include "..\script_component.hpp" +/* + * Author: LorenLuke, johnb43 + * Handle map marker creation. + * If a marker is (partially) on the plotting board, the parts on the plotting board are attached to the plotting board + * and move with the board accordingly. + * + * Arguments: + * 0: Arguments + * - 0: Marker name + * - 1: Chat channel number + * - 2: Marker owner + * - 3: Local origin + * 1: Deleted + * + * Return Value: + * None + * + * Example: + * [CONTROL, [0, 5]] call ace_maptools_fnc_handlePlottingBoardMarkers + * + * Public: No + */ + +params ["_args", "_deleted"]; +_args params ["_marker", "_channelNumber", "_owner", "_local"]; + +if (_deleted) exitWith { + GVAR(plottingBoard_markers) deleteAt _marker; +}; + +// Do not process non-local or already processed markers, don't check if the plotting board isn't shown +if (!_local || {GVAR(plottingBoard_Shown) < 1} || {QUOTE(ADDON) in _marker}) exitWith {}; + +// Check if the channel the marker was made in can be marked on the plotting board +private _continue = true; + +if (isMultiplayer) then { + switch (GVAR(plottingBoardAllowChannelDrawing)) do { + case 0: { + if (_channelNumber != 5) then {_continue = false}; + }; + case 1: { + if !(_channelNumber in [3, 5]) then {_continue = false}; + }; + }; +}; + +if (!_continue) exitWith {}; + +private _boardPos = GVAR(plottingBoard_pos); +private _boardAng = GVAR(plottingBoard_acrylicAngle); + +private _markerPolyline = markerPolyline _marker; +private _count = count _markerPolyline; + +// If the marker is not a polyline marker +if (_count == 0) exitWith { + private _diffPos = (getMarkerPos _marker) vectorDiff _boardPos; + + // If the marker is on the acrylic or ruler of the plotting board, save it + if (vectorMagnitude _diffPos < PLOTTINGBOARD_DRAWRANGE) then { + private _relPos = [[0, 0], _diffPos, _boardAng] call CBA_fnc_vectRotate2D; + + GVAR(plottingBoard_markers) set [_marker, [_relPos, [], _boardAng, +_boardPos, 1]]; + }; +}; + +// If the marker is a polyline marker, but doesn't have enough components (happens when you ctrl-left click on the map), ignore +if (_count <= 4) exitWith {}; + +// Polyine markers (lines) +private _startPos = []; +private _endPos = []; +private _dir = []; +private _diffPos = []; + +private _a = 0; +private _b = 0; +private _c = 0; +private _t1 = nil; +private _t2 = nil; +private _delta = 0; + +private _intersectionValid1 = false; +private _intersectionValid2 = false; +private _intersectPoint1 = []; +private _intersectPoint2 = []; +private _intersectClose = []; +private _intersectFar = []; + +private _polylineIndex = 0; +private _markerArray = [[]]; +private _insideArray = []; + +for "_i" from 0 to _count - 1 - 2 step 2 do { + _startPos = [_markerPolyline select _i, _markerPolyline select (_i + 1)]; + _endPos = [_markerPolyline select (_i + 2), _markerPolyline select (_i + 3)]; + _dir = _endPos vectorDiff _startPos; + _diffPos = _startPos vectorDiff _boardPos; + + // Circle-line intersection: Check for intersections between plotting board and current piece of polyline + // https://stackoverflow.com/a/1084899 + _a = _dir vectorDotProduct _dir; + _b = 2 * (_diffPos vectorDotProduct _dir); + _c = (_diffPos vectorDotProduct _diffPos) - PLOTTINGBOARD_DRAWRANGE^2; + + _delta = _b^2 - 4 * _a * _c; + + // Stretch factors + _t1 = nil; + _t2 = nil; + + if (_delta > 0) then { + _t1 = (-_b + sqrt _delta) / (2 * _a); + _t2 = (-_b - sqrt _delta) / (2 * _a); + + // Don't look for intersection points beyond the start or end points + if (_t1 < 0 || _t1 > 1) then { + _t1 = nil; + }; + + if (_t2 < 0 || _t2 > 1) then { + _t2 = nil; + }; + }; + + // The current point is always part of a polyline + (_markerArray param [_polylineIndex, []]) append _startPos; + _insideArray set [_polylineIndex, vectorMagnitude _diffPos < PLOTTINGBOARD_DRAWRANGE]; // keep track if point is within plotting board + + _intersectionValid1 = !isNil "_t1"; + _intersectionValid2 = !isNil "_t2"; + + // If no valid intersection points, continue + if (!_intersectionValid1 && {!_intersectionValid2}) then { + continue; + }; + + // Extremely rare case if the marker is tangential to the plotting board: Ignore + if (_intersectionValid1 && {_intersectionValid2} && {_t1 == _t2}) then { + continue; + }; + + if (_intersectionValid1) then { + _intersectPoint1 = _startPos vectorAdd (_dir vectorMultiply _t1); + }; + + if (_intersectionValid2) then { + _intersectPoint2 = _startPos vectorAdd (_dir vectorMultiply _t2); + }; + + // When a marker crosses the plotting board entirely (one straight line through the plotting board) + if (_intersectionValid1 && {_intersectionValid2}) then { + // Take the closer point first + _intersectClose = [_intersectPoint1, _intersectPoint2] select (_t1 > _t2); + + // Finish previous polyline with the last point being the intersection + (_markerArray select _polylineIndex) append _intersectClose; + + // Create a new polyline, with the first point being the closest intersection + _polylineIndex = _polylineIndex + 1; + _markerArray set [_polylineIndex, _intersectClose]; + + // Now take the point further away + _intersectFar = [_intersectPoint1, _intersectPoint2] select (_t1 < _t2); + + // Make a polyline between the intersection points + (_markerArray select _polylineIndex) append _intersectClose; + (_markerArray select _polylineIndex) append _intersectFar; + _insideArray set [_polylineIndex, true]; // with 2 intersections, this part of the polyline must be inside + + // Create a new polyline, with the first point being the furthest intersection + _polylineIndex = _polylineIndex + 1; + _markerArray set [_polylineIndex, _intersectFar]; + } else { + // Only 1 intersection (either point 1 or 2, exclusive or) + if (_intersectionValid2) then { + _intersectPoint1 = _intersectPoint2; + }; + + // Finish previous polyline with the last point being the intersection + (_markerArray select _polylineIndex) append _intersectPoint1; + + // Create a new polyline, with the first point being the intersection + _polylineIndex = _polylineIndex + 1; + _markerArray set [_polylineIndex, _intersectPoint1]; + }; +}; + +// If there were no polyline intersections and the marker was not on the plotting board, don't create new markers +if (_insideArray isEqualTo [false]) exitWith {}; + +private _color = getMarkerColor _marker; +private _name = ""; +private _polylineRelative = []; +private _relPos = []; + +{ + _name = format ["%1-%2-%3", _marker, _forEachIndex, QUOTE(ADDON)]; // adding an identifier allow to check if marker was already processed + createMarkerLocal [_name, [0, 0], _channelNumber, _owner]; + _name setMarkerColorLocal _color; + _name setMarkerPolyline _x; // global marker broadcast + + // If the marker was on the plotting board, take it's unrotated position and store it + if (_insideArray select _forEachIndex) then { + _polylineRelative = []; + + for "_i" from 0 to count _x - 1 step 2 do { + _relPos = [[0, 0], [_x select _i, _x select (_i + 1)] vectorDiff _boardPos, _boardAng] call CBA_fnc_vectRotate2D; + _polylineRelative append _relPos; + }; + + GVAR(plottingBoard_markers) set [_name, [[0, 0], +_polylineRelative, _boardAng, +_boardPos, 1]]; + }; +} forEach _markerArray; + +// Delete original marker +deleteMarker _marker; diff --git a/addons/maptools/functions/fnc_isInsidePlottingBoard.sqf b/addons/maptools/functions/fnc_isInsidePlottingBoard.sqf new file mode 100644 index 0000000000..081615d1b7 --- /dev/null +++ b/addons/maptools/functions/fnc_isInsidePlottingBoard.sqf @@ -0,0 +1,54 @@ +#include "..\script_component.hpp" +/* + * Author: LorenLuke + * Return if the position is inside the map marker (to allow dragging) or not. + * + * Arguments: + * 0: x Position (in meters) + * 1: y Position (in meters) + * + * Return Value: + * Where in the plotting board it is + * -1 - Nowhere, 0 - In the Board, 1 - In the Acrylic, 2 - In the Ruler + * + * Example: + * [0, 5] call ace_maptools_fnc_isInsidePlottingBoard + * + * Public: No + */ + +if (GVAR(plottingBoard_Shown) == 0) exitWith {-1}; + +private _relPos = _this vectorDiff GVAR(plottingBoard_pos); +private _dist = vectorMagnitude _relPos; + +private _isRuler = if (GVAR(plottingBoard_Shown) == 2) then { + // If it's within these bounds, it's going to be on the ruler + if (_dist <= PLOTTINGBOARD_RULERCENTER) exitWith {true}; + + private _rulerVector = [sin GVAR(plottingBoard_rulerAngle), cos GVAR(plottingBoard_rulerAngle)]; + private _dirRightVector = [_dirVector select 1, -(_dirVector select 0)]; + private _rulerAng = acos (_rulerVector vectorCos _relPos); + + if (cos _rulerAng > 0 && {tan (_rulerAng) * _dist < PLOTTINGBOARD_RULERHALFWIDTH}) exitWith {true}; + + _dist > PLOTTINGBOARD_RULERINNERCIRCLE && {_dist < PLOTTINGBOARD_RULEROUTERCIRCLE && {abs (_rulerAng * DEGTOMILS) < PLOTTINGBOAR_RULEROUTERHALFANGLE}} +}; + +if (_isRuler) exitWith {2}; + +// If it's within 3000 meters, it's going to be on the acrylic +if (_dist < PLOTTINGBOARD_RULEROUTERCIRCLE) exitWith {1}; + +private _dirVector = [sin GVAR(plottingBoard_angle), cos GVAR(plottingBoard_angle)]; +private _dirRightVector = [_dirVector select 1, -(_dirVector select 0)]; + +// Projection of the relative position over the longitudinal axis of the map tool +private _ang = _dirVector vectorCos _relPos; +private _ang2 = _dirRightVector vectorCos _relPos; + +private _relPosAdjusted = [_ang2 * _dist / PLOTTINGBOARD_DRAWRANGE, _ang * _dist / PLOTTINGBOARD_DRAWRANGE]; + +if ((_relPosAdjusted select 0 > 0) && (_relPosAdjusted select 0 < 1) && (abs (_relPosAdjusted select 1) < 1)) exitWith {0}; + +-1 diff --git a/addons/maptools/functions/fnc_updateMapToolMarkers.sqf b/addons/maptools/functions/fnc_updateMapToolMarkers.sqf index 34642c5c68..fbad42c36e 100644 --- a/addons/maptools/functions/fnc_updateMapToolMarkers.sqf +++ b/addons/maptools/functions/fnc_updateMapToolMarkers.sqf @@ -1,56 +1,136 @@ #include "..\script_component.hpp" /* - * Author: esteldunedain - * Update the map tool markers, position, size, rotation and visibility. + * Author: esteldunedain, LorenLuke + * Update the map tool and plotting board markers. Update their position, size, rotation and visibility. * * Arguments: - * 0: The Map + * 0: Map control * * Return Value: * None * * Example: - * [CONTROL] call ACE_maptools_fnc_updateMapToolMarkers + * [CONTROL] call ace_maptools_fnc_updateMapToolMarkers * * Public: No */ -params ["_theMap"]; +params ["_mapCtrl"]; -if ((GVAR(mapTool_Shown) == 0) || {!("ACE_MapTools" in (ACE_player call EFUNC(common,uniqueItems)))}) exitWith {}; - -// open map tools in center of screen when toggled to be shown -if (GVAR(mapTool_moveToMouse)) then { - private _mousePosition = _theMap ctrlMapScreenToWorld getMousePosition; - GVAR(mapTool_pos) = _mousePosition; - GVAR(mapTool_moveToMouse) = false; // we only need to do this once after opening the map tool +if (GVAR(plottingBoard_Shown) == 0) then { + // Hide all plotting board markers when board is put away + { + if (_y select 4 != 0) then { + _x setMarkerAlpha 0; + _y set [4, 0]; + }; + } forEach GVAR(plottingBoard_markers); }; -private _rotatingTexture = ""; -private _textureWidth = 0; -if (GVAR(mapTool_Shown) == 1) then { - _rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa); - _textureWidth = TEXTURE_WIDTH_IN_M; -} else { - _rotatingTexture = QPATHTOF(data\mapToolRotatingSmall.paa); - _textureWidth = TEXTURE_WIDTH_IN_M / 2; +if (((GVAR(mapTool_Shown) == 0) && {GVAR(plottingBoard_Shown) == 0}) || { + private _uniqueItems = ACE_player call EFUNC(common,uniqueItems); + + !(("ACE_MapTools" in _uniqueItems) || {"ACE_PlottingBoard" in _uniqueItems}) +}) exitWith {}; + +if (GVAR(plottingBoard_Shown) > 0) then { + if (GVAR(plottingBoard_moveToMouse)) then { + GVAR(plottingBoard_pos) = _mapCtrl ctrlMapScreenToWorld getMousePosition; + GVAR(plottingBoard_moveToMouse) = false; // we only need to do this once after opening the map tool + }; + + getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"]; + private _scaleX = 32 * PLOTTINGBOARD_TEXTUREWIDTH * CONSTANT_SCALE * (call FUNC(calculateMapScale)); + private _scaleY = _scaleX * ((_resWidth / _resHeight) / _aspectRatio); // handle bad aspect ratios + + _mapCtrl drawIcon [QPATHTOF(data\plottingBoardBack.paa), [1, 1, 1, 1], GVAR(plottingBoard_pos), _scaleX, _scaleY, GVAR(plottingBoard_angle), "", 0]; + _mapCtrl drawIcon [QPATHTOF(data\plottingBoardAcrylic.paa), [1, 1, 1, 1], GVAR(plottingBoard_pos), _scaleX, _scaleY, GVAR(plottingBoard_acrylicAngle), "", 0]; + + // Show ruler + if (GVAR(plottingBoard_Shown) == 2) then { + _mapCtrl drawIcon [QPATHTOF(data\plottingBoardRuler.paa), [1, 1, 1, 1], GVAR(plottingBoard_pos), _scaleX, _scaleY, GVAR(plottingBoard_rulerAngle), "", 0]; + }; + + private _marker = ""; + private _angle = GVAR(plottingBoard_acrylicAngle); + private _boardPos = GVAR(plottingBoard_pos); + private _count = -1; + private _rotatedPolyPos = []; + private _rotatedPos = []; + + { + _marker = _x; + _y params ["_markerPos", "_polyline", "_lastAngle", "_lastBoardPos", "_lastAlpha"]; + + // Show all plotting board markers when the board is shown + if (_lastAlpha != 1) then { + _marker setMarkerAlpha 1; + _y set [4, 1]; + }; + + // If nothing has changed, don't update marker + if (_angle == _lastAngle && {_boardPos isEqualTo _lastBoardPos}) then { + continue; + }; + + _count = count _polyline; + + // Rotate all points of polyline + if (_count >= 4) then { // polylines need at least 2 points (2 components per point) + _rotatedPolyline = []; + + for "_i" from 0 to _count - 1 step 2 do { + _rotatedPolyPos = [[0, 0], [_polyline select _i, _polyline select (_i + 1)], -_angle] call CBA_fnc_vectRotate2D; + _rotatedPolyline append (_rotatedPolyPos vectorAdd _boardPos); + }; + + _marker setMarkerPolyline _rotatedPolyline; + }; + + // Rotate marker position, regardless of marker type + _rotatedPos = [[0, 0], _markerPos, -_angle] call CBA_fnc_vectRotate2D; + + _marker setMarkerPos (_boardPos vectorAdd _rotatedPos); + + _y set [2, _angle]; + _y set [3, +_boardPos]; + } forEach GVAR(plottingBoard_markers); }; -if (GVAR(freedrawing)) then {[_theMap, _textureWidth] call FUNC(drawLinesOnRoamer);}; +if (GVAR(mapTool_Shown) > 0) then { + // Open map tools in center of screen when toggled to be shown + if (GVAR(mapTool_moveToMouse)) then { + GVAR(mapTool_pos) = _mapCtrl ctrlMapScreenToWorld getMousePosition; + GVAR(mapTool_moveToMouse) = false; // we only need to do this once after opening the map tool + }; -// Update scale of both parts -getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"]; -private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale)); -private _scaleY = _scaleX; + private _rotatingTexture = ""; + private _textureWidth = 0; -// Position of the fixed part -private _xPos = GVAR(mapTool_pos) select 0; -private _yPos = (GVAR(mapTool_pos) select 1) + _textureWidth * CENTER_OFFSET_Y_PERC; + if (GVAR(mapTool_Shown) == 1) then { + _rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa); + _textureWidth = TEXTURE_WIDTH_IN_M; + } else { + _rotatingTexture = QPATHTOF(data\mapToolRotatingSmall.paa); + _textureWidth = TEXTURE_WIDTH_IN_M / 2; + }; -_theMap drawIcon [QPATHTOF(data\mapToolFixed.paa), [1,1,1,1], [_xPos,_yPos], _scaleX, _scaleY, 0, "", 0]; + if (GVAR(freedrawing)) then { + [_mapCtrl, _textureWidth] call FUNC(drawLinesOnRoamer); + }; -// Position and rotation of the rotating part -_xPos = (GVAR(mapTool_pos) select 0) + sin(GVAR(mapTool_angle)) * _textureWidth * CENTER_OFFSET_Y_PERC; -_yPos = (GVAR(mapTool_pos) select 1) + cos(GVAR(mapTool_angle)) * _textureWidth * CENTER_OFFSET_Y_PERC; + // Update scale of both parts + getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"]; + private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale)); + private _scaleY = _scaleX * ((_resWidth / _resHeight) / _aspectRatio); // handle bad aspect ratios -_theMap drawIcon [_rotatingTexture, [1,1,1,1], [_xPos,_yPos], _scaleX, _scaleY, GVAR(mapTool_angle), "", 0]; + // Position of the fixed part + private _pos = GVAR(mapTool_pos) vectorAdd [0, _textureWidth * CENTER_OFFSET_Y_PERC]; + + _mapCtrl drawIcon [QPATHTOF(data\mapToolFixed.paa), [1, 1, 1, 1], _pos, _scaleX, _scaleY, 0, "", 0]; + + // Position and rotation of the rotating part + _pos = GVAR(mapTool_pos) vectorAdd ([sin GVAR(mapTool_angle), cos GVAR(mapTool_angle)] vectorMultiply (_textureWidth * CENTER_OFFSET_Y_PERC)); + + _mapCtrl drawIcon [_rotatingTexture, [1, 1, 1, 1], _pos, _scaleX, _scaleY, GVAR(mapTool_angle), "", 0]; +}; diff --git a/addons/maptools/functions/fnc_wipeMarkers.sqf b/addons/maptools/functions/fnc_wipeMarkers.sqf new file mode 100644 index 0000000000..5131e469a3 --- /dev/null +++ b/addons/maptools/functions/fnc_wipeMarkers.sqf @@ -0,0 +1,23 @@ +#include "../script_component.hpp" +/* + * Author: LorenLuke + * Delete all markers on the plotting board. + * + * Arguments: + * None + * + * Return Value: + * None + * + * Example: + * call ace_maptools_fnc_wipeMarkers + * + * Public: No + */ + +{ + deleteMarker _x; +} forEach (keys GVAR(plottingBoard_markers)); + +// Reset list +GVAR(plottingBoard_markers) = createHashMap; diff --git a/addons/maptools/initSettings.inc.sqf b/addons/maptools/initSettings.inc.sqf index cbb8e9c1b8..5eaa778e32 100644 --- a/addons/maptools/initSettings.inc.sqf +++ b/addons/maptools/initSettings.inc.sqf @@ -15,3 +15,11 @@ private _category = format ["ACE %1", localize LSTRING(Name)]; true, 0 ] call CBA_fnc_addSetting; + +[ + QGVAR(plottingBoardAllowChannelDrawing), "LIST", + [LSTRING(allowChannelDrawing_displayName), LSTRING(allowChannelDrawing_description)], + _category, + [[0, 1], [LSTRING(allowDirectCommsOnly), LSTRING(allowDirectGroupComms)], 1], + 0 +] call CBA_fnc_addSetting; diff --git a/addons/maptools/script_component.hpp b/addons/maptools/script_component.hpp index 4710caa7a3..7c1c4757d2 100644 --- a/addons/maptools/script_component.hpp +++ b/addons/maptools/script_component.hpp @@ -16,9 +16,19 @@ #include "\z\ace\addons\main\script_macros.hpp" +#define DEGTOMILS 17.7777778 + #define TEXTURE_WIDTH_IN_M 6205 #define CENTER_OFFSET_Y_PERC 0.1606 #define CONSTANT_SCALE 0.2 #define DIST_BOTTOM_TO_CENTER_PERC -0.33 #define DIST_TOP_TO_CENTER_PERC 0.65 #define DIST_LEFT_TO_CENTER_PERC 0.30 + +#define PLOTTINGBOARD_DRAWRANGE 3000 +#define PLOTTINGBOARD_TEXTUREWIDTH 6000 +#define PLOTTINGBOARD_RULERCENTER 450 +#define PLOTTINGBOARD_RULERHALFWIDTH 100 +#define PLOTTINGBOARD_RULERINNERCIRCLE 2900 +#define PLOTTINGBOARD_RULEROUTERCIRCLE 3000 +#define PLOTTINGBOARD_RULEROUTERHALFANGLE 100 diff --git a/addons/maptools/stringtable.xml b/addons/maptools/stringtable.xml index 7ab1662bb2..c7ac9a423c 100644 --- a/addons/maptools/stringtable.xml +++ b/addons/maptools/stringtable.xml @@ -35,6 +35,12 @@ 地圖工具能夠讓你在地圖上測量距離與角度 Harita Araçları, haritadaki mesafeleri ve açıları ölçmenize olanak tanır. + + Plotting Board + + + The Plotting Board is a map tool designed for use in the directing of short range indirect fires. + Map Tools Herramientas de mapa @@ -252,5 +258,89 @@ Düz çizgiler çizmek için maptools'un kenarına çizin. Not: Silmek için orta noktada fareyle üzerine gelmeniz gerekir. Dibujar sobre el borde de las herramientas de mapa para dibujar líneas rectas. Nota: Debe situarse en el punto intermedio para eliminarla. + + Allow Plotting Board Drawing channels + + + 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 + Ausrichten + Alinear + Aligner + Allinea + Alinhar + Állítása + Wyrównaj + Srovnat + Выровнять + + + To North + Nach Norden + Al norte + Sur le nord + Con il Nord + Com o Norte + Északhoz + Do północy + Na sever + На север + + + To Compass + Am Kompass + A la brújula + Sur la boussole + Con la bussola + Com a Bússola + Iránytűhöz + Do kompasu + Ke kompasu + По компасу + + + Up + + + To Maptool + diff --git a/addons/markers/functions/fnc_onButtonClickConfirm.sqf b/addons/markers/functions/fnc_onButtonClickConfirm.sqf index 2822cd69f0..622a306e38 100644 --- a/addons/markers/functions/fnc_onButtonClickConfirm.sqf +++ b/addons/markers/functions/fnc_onButtonClickConfirm.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: Freddo + * Author: Freddo, Daniël H., johnb43 * When the confirm button is pressed. * * Arguments: @@ -14,40 +14,100 @@ * * Public: No */ + params ["_buttonOk"]; private _display = ctrlParent _buttonOk; -private _description = _display displayctrl IDC_INSERT_MARKER; +private _description = _display displayCtrl IDC_INSERT_MARKER; private _aceTimestamp = _display displayCtrl IDC_ACE_INSERT_MARKER_TIMESTAMP; -// handle timestamp +// Handle timestamp if (cbChecked _aceTimestamp && {ACE_player call FUNC(canTimestamp)}) then { - private _time = daytime; + // Determine marker timestamp based on time settings + private _time = switch (GVAR(timestampTimezone)) do { + case 1: { + systemTime select [3] + }; + case 2: { + systemTimeUTC params ["", "", "", "_hour", "_min", "_sec", "_msec"]; - // add timestamp suffix + private _hourOffset = round GVAR(timestampUTCOffset); + _hour = _hour + _hourOffset; + + // Add or subtract minutes offset based on the negative or positive timezone + if (GVAR(timestampUTCMinutesOffset) != 0) then { + _min = if (_hourOffset < 0) then { _min - GVAR(timestampUTCMinutesOffset) } else { _min + GVAR(timestampUTCMinutesOffset) }; + + // Add/remove extra hours from minutes + _hour = _hour + floor (_min / 60); + _min = (_min % 60 + 60) % 60; // ensure that minutes are between 0 and 59 (included) + }; + + [(_hour % 24 + 24) % 24, _min, _sec, _msec] // ensure that hours are between 0 and 23 (included) + }; + default { + private _daytime = dayTime; + + private _hour = floor _daytime; + private _min = floor ((_daytime - _hour) * 60); + private _sec = floor ((((_daytime - _hour) * 60) - _min) * 60); + private _msec = floor ((((((_daytime - _hour) * 60) - _min) * 60) - _sec) * 1000); + + [_hour, _min, _sec, _msec] + }; + }; + + _time params ["_hour", "_min", "_sec", "_msec"]; + + // Add timestamp suffix private _periodPostfix = ""; + if (GVAR(timestampHourFormat) == 12) then { - if (floor _time == 0) exitWith { - _time = _time + 12; + if (_hour == 0) exitWith { + _hour = _hour + 12; _periodPostfix = " am"; }; - if (floor _time == 12) exitWith { + if (_hour == 12) exitWith { _periodPostfix = " pm"; }; - if (_time < 12) then { + if (_hour < 12) then { _periodPostfix = " am"; } else { - _time = _time - 12; + _hour = _hour - 12; _periodPostfix = " pm"; }; }; + private _format = switch (GVAR(timestampFormat)) do { + case "HH": {"%1"}; + case "HH:MM": {"%1:%2"}; + case "HH:MM:SS": {"%1:%2:%3"}; + case "HH:MM:SS:MM": { // milliseconds are displayed as 0 to 59 + _msec = [_msec * 60 / 1000, 2] call CBA_fnc_formatNumber; + + "%1:%2:%3:%4" + }; + case "HH:MM:SS.mmm": { // milliseconds are displayed as 0 to 999 + _msec = [_msec, 3] call CBA_fnc_formatNumber; + + "%1:%2:%3.%4" + }; + }; + + _time = format [ + _format, + [_hour, 2] call CBA_fnc_formatNumber, + [_min, 2] call CBA_fnc_formatNumber, + [_sec, 2] call CBA_fnc_formatNumber, + _msec + ]; + _description ctrlSetText format [ "%1 [%2%3]", ctrlText _description, - [_time, GVAR(timestampFormat)] call BIS_fnc_timeToString, + _time, _periodPostfix ]; }; diff --git a/addons/markers/functions/fnc_onLBSelChangedChannel.sqf b/addons/markers/functions/fnc_onLBSelChangedChannel.sqf index d8c2bc71fb..e7b696270f 100644 --- a/addons/markers/functions/fnc_onLBSelChangedChannel.sqf +++ b/addons/markers/functions/fnc_onLBSelChangedChannel.sqf @@ -1,6 +1,6 @@ #include "..\script_component.hpp" /* - * Author: commy2, LinkIsGrim + * Author: commy2, LinkIsGrim, Avokadomos * When the channel list box is changed. * * Arguments: @@ -19,6 +19,4 @@ params ["_ctrl", "_index"]; TRACE_2("params",_ctrl,_index); -private _enabledChannels = false call FUNC(getEnabledChannels); - -setCurrentChannel (_enabledChannels select _index); +setCurrentChannel (parseNumber (_ctrl lbData _index)); diff --git a/addons/markers/initSettings.inc.sqf b/addons/markers/initSettings.inc.sqf index ce8e8e0473..65bf17e8b6 100644 --- a/addons/markers/initSettings.inc.sqf +++ b/addons/markers/initSettings.inc.sqf @@ -32,6 +32,37 @@ private _categoryName = format ["ACE %1", localize ELSTRING(map,Module_DisplayNa true ] call CBA_fnc_addSetting; +[ + QGVAR(timestampTimezone), "LIST", + [LSTRING(TimestampTimezone), LSTRING(TimestampTimezoneDescription)], + [_categoryName, LLSTRING(Module_DisplayName)], + [ + [0, 1, 2], + [LSTRING(TimestampTimezoneIngameTime), LSTRING(TimestampTimezoneSystemTime), LSTRING(TimestampTimezoneUTCTime)], + 0 + ], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(timestampUTCOffset), "SLIDER", + [LSTRING(TimestampUTCOffset), LSTRING(TimestampUTCOffsetDescription)], + [_categoryName, LLSTRING(Module_DisplayName)], + [-12, 14, 0, 0], + true +] call CBA_fnc_addSetting; + +[ + QGVAR(TimestampUTCMinutesOffset), "LIST", + [LSTRING(TimestampUTCMinutesOffset), LSTRING(TimestampUTCMinutesOffsetDescription)], + [_categoryName, LLSTRING(Module_DisplayName)], + [ + [0, 15, 30, 45], + [0, 15, 30, 45], + 0 + ] +] call CBA_fnc_addSetting; + [ QGVAR(timestampHourFormat), "LIST", [LSTRING(TimestampHourFormat), LSTRING(TimestampHourFormatDescription)], @@ -48,7 +79,8 @@ private _formatDescription = [ LLSTRING(TimestampFormatDescription1), LLSTRING(TimestampFormatDescription2), LLSTRING(TimestampFormatDescription3), - LLSTRING(TimestampFormatDescription4) + LLSTRING(TimestampFormatDescription4), + LLSTRING(TimestampFormatDescription5) ] joinString endl; [ @@ -56,8 +88,8 @@ private _formatDescription = [ [LSTRING(timestampFormat), _formatDescription], [_categoryName, LLSTRING(Module_DisplayName)], [ - ["HH", "HH:MM", "HH:MM:SS", "HH:MM:SS:MM"], - ["HH", "HH:MM", "HH:MM:SS", "HH:MM:SS:MM"], + ["HH", "HH:MM", "HH:MM:SS", "HH:MM:SS:MM", "HH:MM:SS.mmm"], + ["HH", "HH:MM", "HH:MM:SS", "HH:MM:SS:MM", "HH:MM:SS.mmm"], 1 ] ] call CBA_fnc_addSetting; diff --git a/addons/markers/stringtable.xml b/addons/markers/stringtable.xml index f15394e3b5..b4a772e171 100644 --- a/addons/markers/stringtable.xml +++ b/addons/markers/stringtable.xml @@ -239,6 +239,105 @@ 시계 필요함 Relógio necessário + + Time Zone + Часовой пояс + Fuseau horaire + 時間帯 + Zona horaria + Strefa czasowa + Zeitzone + 时区 + 시간대 + + + Changes the time zone for the timestamp + Измените часовой пояс для метки времени + Modifiez le fuseau horaire pour l'horodatage + タイムスタンプの時間帯を変更します + Cambie la zona horaria para la marca de tiempo + Zmień strefę czasową dla znaczników czasu + Ändern Sie die Zeitzone für den Zeitstempel + 更改时间戳的时区 + 타임스탬프의 시간대를 변경하십시오 + + + In-game Time + Время в игре + Heure de jeu + ゲーム内時刻 + Hora del juego + Czas gry + Ingame-Zeit + 游戏内时间 + 게임 시간 + + + System Time + Системное время + Heure système + システム時刻 + Hora del sistema + Czas systemowy + Systemzeit + 系统时间 + 시스템 시간 + + + UTC Time + Время UTC + Heure UTC + UTC時刻 + Hora UTC + Czas UTC + UTC-Zeit + UTC时间 + UTC 시간 + + + UTC Offset + Смещение UTC + Décalage UTC + UTCオフセット + Desplazamiento UTC + Przesunięcie UTC + UTC-Verschiebung + UTC偏移量 + UTC 오프셋 + + + Changes the time offset for the UTC timestamp + Измените смещение времени для метки времени UTC + Modifier le décalage horaire pour l'horodatage UTC + UTCタイムスタンプの時差を変更する + Cambiar el desplazamiento horario para la marca de tiempo UTC + Zmień przesunięcie czasu dla sygnatury czasowej UTC + Ändere die Zeitverschiebung für den UTC-Zeitstempel + 更改UTC时间戳的时间偏移量 + UTC 타임 스탬프의 시간 오프셋을 변경하십시오 + + + UTC Minutes Offset + UTC Минутное Смещение + Décalage des minutes UTC + UTC分オフセット + Desplazamiento de minutos UTC + Przesunięcie minut UTC + UTC-Minutenversatz + UTC分钟偏移量 + UTC 분 오프셋 + + + Change the minute offset for the UTC timestamp + Изменить минутное смещение для времени UTC + Modifier le décalage des minutes pour l'horodatage UTC + UTCタイムスタンプの分差を変更する + Cambiar el desplazamiento de minutos para la marca de tiempo UTC + Zmień przesunięcie minut dla sygnatury czasowej UTC + Ändere den Minutenversatz für den UTC-Zeitstempel + 更改UTC时间戳的分钟偏移量 + UTC 타임 스탬프의 분 오프셋을 변경하십시오 + Timestamp Format Формат времени @@ -305,17 +404,16 @@ SS - Segundos - "MM" - Milliseconds - "МС" - Миллисекунда - "MM" - Millisecondes - "MM" - ミリ秒 - "MM" - Milisegundos - "MM" - Milisekundy - "MS" - Milisekunden - "MS" - Millisecondi - "MS"—毫秒 - "MS" - 밀리초 - MM - Milisegundos + "MM" - Milliseconds (from 0 to 59) + "MM" - Millisecondes (de 0 à 59) + "MS" - Milisekunden (von 0 bis 59) + "MS" - Milissegundos (de 0 a 59) + + + "mmm" - Milliseconds (from 0 to 999) + "mmm" - Millisecondes (de 0 à 999) + "mmm" - Milisekunden (von 0 bis 999) + "mmm" - Milissegundos (de 0 a 999) Timestamp Hour Format diff --git a/addons/medical_damage/functions/fnc_woundsHandlerVehiclehit.sqf b/addons/medical_damage/functions/fnc_woundsHandlerVehiclehit.sqf index 9c4f864f97..5f4bd35941 100644 --- a/addons/medical_damage/functions/fnc_woundsHandlerVehiclehit.sqf +++ b/addons/medical_damage/functions/fnc_woundsHandlerVehiclehit.sqf @@ -26,12 +26,21 @@ if (count _allDamages > 1) exitWith {_this}; // damage to structural is low unless it's a very large explosion, in which case it is typically >= 1 private _damageToApply = (abs (_allDamages select 0 select 0)); -private _newDamages = []; +private _damageMap = createHashMap; +private _bodyPart = ""; +private _allBodyParts = ALL_BODY_PARTS; // micro-optimization here and above, don't recreate this array every time // hitpoints are randomized, more damage means more wounds in different body parts +// use a hashmap so we only create one entry in _newDamages per body part for "_i" from 1 to (_damageToApply * 6) do { - _newDamages pushBack [_damageToApply, selectRandom ALL_BODY_PARTS, _damageToApply] + _bodyPart = selectRandom _allBodyParts; + _damageMap set [_bodyPart, (_damageMap getOrDefault [_bodyPart, 0]) + _damageToApply]; }; +private _newDamages = []; +{ + _newDamages pushBack [_damageMap get _x, _x, _damageToApply]; +} forEach (keys _damageMap); // micro-optimization again, two 'get's is still faster than iterating over a hashmap + TRACE_1("Vehicle explosion handled, passing damage", _newDamages); [_unit, _newDamages, _typeOfDamage] //return diff --git a/addons/medical_engine/CfgMoves.hpp b/addons/medical_engine/CfgMoves.hpp index 7c99321887..34f0572479 100644 --- a/addons/medical_engine/CfgMoves.hpp +++ b/addons/medical_engine/CfgMoves.hpp @@ -1,4 +1,3 @@ - class CfgMovesBasic; class CfgMovesMaleSdr: CfgMovesBasic { class States { @@ -10,6 +9,11 @@ class CfgMovesMaleSdr: CfgMovesBasic { class DeadState; class UNCON_ANIM(1): DeadState { + // Prevents AI from moving torso and head when unconscious + aiming = "aimingNo"; + aimingBody = "aimingUpNo"; + head = "headNo"; + file = QPATHTO_T(data\ace_unconscious_1.rtm); }; diff --git a/addons/medical_engine/functions/fnc_handleDamage.sqf b/addons/medical_engine/functions/fnc_handleDamage.sqf index 6483f6de64..8db9950a86 100644 --- a/addons/medical_engine/functions/fnc_handleDamage.sqf +++ b/addons/medical_engine/functions/fnc_handleDamage.sqf @@ -89,7 +89,7 @@ if ( {GET_NUMBER(_ammoCfg >> "indirectHit", 0) > 0} } ) exitwith { - TRACE_6("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage,_damages); + TRACE_5("Vehicle hit",_unit,_shooter,_instigator,_damage,_newDamage); _unit setVariable [QEGVAR(medical,lastDamageSource), _shooter]; _unit setVariable [QEGVAR(medical,lastInstigator), _instigator]; diff --git a/addons/medical_status/functions/fnc_setUnconsciousState.sqf b/addons/medical_status/functions/fnc_setUnconsciousState.sqf index 3071ae0d14..e3d34f3b5a 100644 --- a/addons/medical_status/functions/fnc_setUnconsciousState.sqf +++ b/addons/medical_status/functions/fnc_setUnconsciousState.sqf @@ -50,26 +50,16 @@ if (_active) then { _unit call EFUNC(common,throwWeapon); }; }; + // Unlock controls for copilot if unit is pilot of aircraft if (vehicle _unit isKindOf "Air" && {_unit == driver vehicle _unit}) then { TRACE_1("pilot of air vehicle - unlocking controls",vehicle _unit); // Do "Unlock controls" user action, co-pilot will then have to do the "Take Controls" actions _unit action ["UnlockVehicleControl", vehicle _unit]; }; - - // Disable AI aiming - if (!isPlayer _unit && {_unit checkAIFeature "WEAPONAIM"}) then { - _unit disableAI "WEAPONAIM"; - _unit setVariable [QGVAR(reenableWeaponAim), true, true]; - }; } else { // Unit has woken up, no longer need to track this _unit setVariable [QEGVAR(medical,lastWakeUpCheck), nil]; - - // Reenable AI aiming - if (_unit getVariable [QGVAR(reenableWeaponAim), false]) then { - _unit enableAI "WEAPONAIM"; - }; }; // This event doesn't correspond to unconscious in statemachine diff --git a/addons/medical_treatment/XEH_preStart.sqf b/addons/medical_treatment/XEH_preStart.sqf index 27f8f2d9c2..420bffaf71 100644 --- a/addons/medical_treatment/XEH_preStart.sqf +++ b/addons/medical_treatment/XEH_preStart.sqf @@ -2,4 +2,4 @@ #include "XEH_PREP.hpp" -call FUNC(scanMedicalItems) +call FUNC(scanMedicalItems); diff --git a/addons/medical_treatment/stringtable.xml b/addons/medical_treatment/stringtable.xml index ad33e4e89a..da7374984d 100644 --- a/addons/medical_treatment/stringtable.xml +++ b/addons/medical_treatment/stringtable.xml @@ -4557,6 +4557,7 @@ Umístit tělo do černého pytle na mrtvoly Vücudu siyah ceset torbasına yerleştir 遺体袋 (黒) に入れる + 시체를 검은 시체가방에 놓기 Place body in blue bodybag @@ -4568,6 +4569,7 @@ Umístit tělo do modrého pytle na mrtvoly Vücudu mavi ceset torbasına yerleştir 遺体袋 (青) に入れる + 시체를 파란 시체가방에 놓기 Place body in white bodybag @@ -4579,6 +4581,7 @@ Umístit tělo do bílého pytle na mrtvoly Vücudu beyaz ceset torbasına yerleştir 遺体袋 (白) に入れる + 시체를 흰 시체가방에 놓기 Placing body in bodybag... @@ -4921,12 +4924,14 @@ Coeff. di tempo per trattamenti Zeus Zeit-Koeffizient für Zeus Behandlungen Zeus治療時間係数 + 제우스 치료 시간 계수 Multiply all treatment times with this coefficient when in Zeus. Moltiplica il tempo di ogni trattamento per questo coefficiente quando si è Zeus. Dauer von Behandlungen als Zeus wird mit diesem Koeffizienten multipliziert. Zeus操作中は、すべての治療時間にこの係数を掛けます。 + 제우스일 때 모든 치료 시간에 이 계수를 곱합니다. diff --git a/addons/movement/CfgEventHandlers.hpp b/addons/movement/CfgEventHandlers.hpp index 2608d0260b..f6503c2479 100644 --- a/addons/movement/CfgEventHandlers.hpp +++ b/addons/movement/CfgEventHandlers.hpp @@ -15,9 +15,3 @@ class Extended_PostInit_EventHandlers { init = QUOTE(call COMPILE_SCRIPT(XEH_postInit)); }; }; - -class Extended_DisplayLoad_EventHandlers { - class RscDisplayInventory { - ADDON = QUOTE(_this call FUNC(inventoryDisplayLoad)); - }; -}; diff --git a/addons/movement/XEH_PREP.hpp b/addons/movement/XEH_PREP.hpp index ceafa7f5dc..36fe97880d 100644 --- a/addons/movement/XEH_PREP.hpp +++ b/addons/movement/XEH_PREP.hpp @@ -3,4 +3,3 @@ PREP(canClimb); PREP(climb); PREP(handleClimb); PREP(handleVirtualMass); -PREP(inventoryDisplayLoad); diff --git a/addons/overheating/ACE_Arsenal_Stats.hpp b/addons/overheating/ACE_Arsenal_Stats.hpp new file mode 100644 index 0000000000..ef1e497c55 --- /dev/null +++ b/addons/overheating/ACE_Arsenal_Stats.hpp @@ -0,0 +1,21 @@ +class EGVAR(arsenal,stats) { + class statBase; + class ACE_allowSwapBarrel: statBase { + scope = 2; + priority = -1; + stats[] = {QGVAR(allowSwapBarrel)}; + displayName = CSTRING(statBarrelType); + showText = 1; + textStatement = QUOTE(call FUNC(statTextStatement_allowSwapBarrel)); + tabs[] = {{0,1}, {}}; + }; + class ACE_boltType: statBase { + scope = 2; + priority = -1.1; + stats[] = {QGVAR(closedBolt)}; + displayName = CSTRING(statBoltType); + showText = 1; + textStatement = QUOTE(call FUNC(statTextStatement_boltType)); + tabs[] = {{0,1}, {}}; + }; +}; diff --git a/addons/overheating/XEH_PREP.hpp b/addons/overheating/XEH_PREP.hpp index 865a049569..91d345914d 100644 --- a/addons/overheating/XEH_PREP.hpp +++ b/addons/overheating/XEH_PREP.hpp @@ -25,6 +25,8 @@ PREP(overheat); PREP(sendSpareBarrelsTemperaturesHint); PREP(setAmmoTemperature); PREP(setWeaponTemperature); +PREP(statTextStatement_boltType); +PREP(statTextStatement_allowSwapBarrel); PREP(swapBarrel); PREP(swapBarrelAssistant); PREP(swapBarrelCallback); diff --git a/addons/overheating/config.cpp b/addons/overheating/config.cpp index f04238fd10..4d8fb34cc3 100644 --- a/addons/overheating/config.cpp +++ b/addons/overheating/config.cpp @@ -26,6 +26,8 @@ class CfgPatches { #include "ACE_Settings.hpp" +#include "ACE_Arsenal_Stats.hpp" + class CfgMovesBasic { class ManActions { GVAR(GestureMountMuzzle) = QGVAR(GestureMountMuzzle); diff --git a/addons/overheating/functions/fnc_statTextStatement_allowSwapBarrel.sqf b/addons/overheating/functions/fnc_statTextStatement_allowSwapBarrel.sqf new file mode 100644 index 0000000000..9713023c17 --- /dev/null +++ b/addons/overheating/functions/fnc_statTextStatement_allowSwapBarrel.sqf @@ -0,0 +1,21 @@ +#include "..\script_component.hpp" +/* + * Author: drofseh + * Barrel Type statement. + * + * Arguments: + * 0: Not used + * 1: Item config path + * + * Return Value: + * Stat Text + * + * Public: No +*/ + +params ["", "_config"]; +TRACE_1("statTextStatement_allowSwapBarrel",_config); + +if ((getNumber (_config >> QGVAR(allowSwapBarrel))) == 1) exitWith {LLSTRING(statBarrelType_removeable)}; + +LLSTRING(statBarrelType_nonRemoveable) diff --git a/addons/overheating/functions/fnc_statTextStatement_boltType.sqf b/addons/overheating/functions/fnc_statTextStatement_boltType.sqf new file mode 100644 index 0000000000..67967496c7 --- /dev/null +++ b/addons/overheating/functions/fnc_statTextStatement_boltType.sqf @@ -0,0 +1,21 @@ +#include "..\script_component.hpp" +/* + * Author: drofseh + * Bolt Type statement. + * + * Arguments: + * 0: Not used + * 1: Item config path + * + * Return Value: + * Stat Text + * + * Public: No +*/ + +params ["", "_config"]; +TRACE_1("statTextStatement_boltType",_config); + +if ((getNumber (_config >> QGVAR(closedBolt))) == 1) exitWith {LLSTRING(statBoltType_closedBolt)}; + +LLSTRING(statBoltType_openBolt) diff --git a/addons/overheating/stringtable.xml b/addons/overheating/stringtable.xml index 2c6249be2f..678a9a746a 100644 --- a/addons/overheating/stringtable.xml +++ b/addons/overheating/stringtable.xml @@ -875,5 +875,23 @@ 备用枪管温度非常热 備用槍管溫度超級熱 + + Bolt Type + + + Open Bolt + + + Closed Bolt + + + Barrel Type + + + Non-Removeable + + + Quick Change + diff --git a/addons/overpressure/functions/fnc_firedEHBB.sqf b/addons/overpressure/functions/fnc_firedEHBB.sqf index 53620da7b2..a36eb8bd56 100644 --- a/addons/overpressure/functions/fnc_firedEHBB.sqf +++ b/addons/overpressure/functions/fnc_firedEHBB.sqf @@ -53,7 +53,7 @@ if (_distance < _backblastRange) then { [_damage * 100] call BIS_fnc_bloodEffect; - if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then { + if (["ace_medical"] call EFUNC(common,isModLoaded)) then { [_unit, _damage, "body", "backblast", _unit] call EFUNC(medical,addDamageToUnit); } else { _unit setDamage (damage _unit + _damage); diff --git a/addons/overpressure/functions/fnc_overpressureDamage.sqf b/addons/overpressure/functions/fnc_overpressureDamage.sqf index 2fd0c0f7e5..812a2ab7ea 100644 --- a/addons/overpressure/functions/fnc_overpressureDamage.sqf +++ b/addons/overpressure/functions/fnc_overpressureDamage.sqf @@ -57,7 +57,7 @@ TRACE_3("cache",_overpressureAngle,_overpressureRange,_overpressureDamage); [_damage * 100] call BIS_fnc_bloodEffect; }; - if (["ACE_Medical"] call EFUNC(common,isModLoaded)) then { + if (["ace_medical"] call EFUNC(common,isModLoaded)) then { [_x, _damage, "body", "backblast", _firer] call EFUNC(medical,addDamageToUnit); } else { _x setDamage (damage _x + _damage); diff --git a/addons/rangecard/functions/fnc_calculateRangeCard.sqf b/addons/rangecard/functions/fnc_calculateRangeCard.sqf index 179437eb58..d2347b8494 100644 --- a/addons/rangecard/functions/fnc_calculateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_calculateRangeCard.sqf @@ -49,7 +49,8 @@ private _bulletSpeed = 0; private _gravity = [0, sin(_scopeBaseAngle) * -GRAVITY, cos(_scopeBaseAngle) * -GRAVITY]; private _deltaT = 1 / _simSteps; private _speedOfSound = 0; -if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { +private _isABenabled = missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]; +if (_isABenabled) then { _speedOfSound = _temperature call EFUNC(weather,calculateSpeedOfSound); }; @@ -68,7 +69,7 @@ if (_useABConfig) then { }; private _airFrictionCoef = 1; -if (!_useABConfig && (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) then { +if (!_useABConfig && _isABenabled) then { private _airDensity = [_temperature, _barometricPressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity); _airFrictionCoef = _airDensity / 1.22498; }; diff --git a/addons/rangecard/functions/fnc_updateRangeCard.sqf b/addons/rangecard/functions/fnc_updateRangeCard.sqf index d7acd46486..e8fb0f9c6c 100644 --- a/addons/rangecard/functions/fnc_updateRangeCard.sqf +++ b/addons/rangecard/functions/fnc_updateRangeCard.sqf @@ -107,12 +107,17 @@ private _transonicStabilityCoef = _ammoConfig select 4; private _dragModel = _ammoConfig select 5; private _atmosphereModel = _ammoConfig select 8; -private _useABConfig = (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]); -if (_bc == 0) then { - _useABConfig = false; -}; +private _isABenabled = (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) && (_bc != 0); +private _useBarrelLengthInfluence = ( + _isABenabled && + {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} +); +private _useAmmoTemperatureInfluence = ( + _isABenabled && + {missionNamespace getVariable [QEGVAR(advanced_ballistics,ammoTemperatureEnabled), false]} +); -if (_barrelLength > 0 && _useABConfig) then { +if (_barrelLength > 0 && _useBarrelLengthInfluence) then { _muzzleVelocity = [_barrelLength, _ammoConfig select 10, _ammoConfig select 11, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift); } else { private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed"); @@ -128,7 +133,7 @@ if (_barrelLength > 0 && _useABConfig) then { ctrlSetText [770000, format["%1'' - %2 gr (%3)", round((_ammoConfig select 1) * 39.3700787) / 1000, round((_ammoConfig select 3) * 15.4323584), _ammoClass]]; if (_barrelLength > 0) then { - if (_useABConfig && _barrelTwist > 0) then { + if (_useBarrelLengthInfluence && _barrelTwist > 0) then { ctrlSetText [770002, format["Barrel: %1'' 1:%2'' twist", round(2 * _barrelLength * 0.0393700787) / 2, round(_barrelTwist * 0.0393700787)]]; } else { ctrlSetText [770002, format["Barrel: %1''", round(2 * _barrelLength * 0.0393700787) / 2]]; @@ -136,7 +141,7 @@ if (_barrelLength > 0) then { }; lnbAddRow [770100, ["4mps Wind(MRADs)", "1mps LEAD(MRADs)"]]; -if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { +if (_isABenabled) then { lnbAddRow [770100, ["Air/Ammo Temp", "Air/Ammo Temp"]]; lnbAddRow [770200, ["-15°C", " -5°C", " 5°C", " 10°C", " 15°C", " 20°C", " 25°C", " 30°C", " 35°C"]]; @@ -145,7 +150,7 @@ if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) t ctrlSetText [77003, format["%1m ZERO", round(_zeroRange)]]; -if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { +if (_isABenabled) then { ctrlSetText [770001, format["Drop Tables for B.P.: %1mb; Corrected for MVV at Air/Ammo Temperatures -15-35 °C", round(EGVAR(scopes,zeroReferenceBarometricPressure) * 100) / 100]]; ctrlSetText [77004 , format["B.P.: %1mb", round(EGVAR(scopes,zeroReferenceBarometricPressure) * 100) / 100]]; } else { @@ -153,30 +158,30 @@ if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) t ctrlSetText [77004 , ""]; }; -private _cacheEntry = missionNamespace getVariable format[QGVAR(%1_%2_%3_%4_%5), _zeroRange, _boreHeight, _ammoClass, _weaponClass, missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]]; -if (isNil {_cacheEntry}) then { - private _scopeBaseAngle = if (!_useABConfig) then { +private _cacheEntry = missionNamespace getVariable format [QGVAR(%1_%2_%3_%4_%5_%6_%7), _zeroRange, _boreHeight, _ammoClass, _weaponClass, _isABenabled, _useBarrelLengthInfluence, _useAmmoTemperatureInfluence]; +if (isNil "_cacheEntry") then { + private _scopeBaseAngle = if (!_isABenabled) then { private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZero:%1:%2:%3:%4", _zeroRange, _muzzleVelocity, _airFriction, _boreHeight]; (parseNumber _zeroAngle) } else { private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZeroAB:%1:%2:%3:%4:%5:%6:%7:%8:%9", _zeroRange, _muzzleVelocity, _boreHeight, EGVAR(scopes,zeroReferenceTemperature), EGVAR(scopes,zeroReferenceBarometricPressure), EGVAR(scopes,zeroReferenceHumidity), _bc, _dragModel, _atmosphereModel]; (parseNumber _zeroAngle) }; - if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] && missionNamespace getVariable [QEGVAR(advanced_ballistics,ammoTemperatureEnabled), false]) then { + if (_useAmmoTemperatureInfluence) then { { private _mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift); private _mv = _muzzleVelocity + _mvShift; - [_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,_forEachIndex,_useABConfig] call FUNC(calculateRangeCard); + [_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,_forEachIndex,_isABenabled] call FUNC(calculateRangeCard); } forEach [-15, -5, 5, 10, 15, 20, 25, 30, 35]; } else { - [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,3,_useABConfig] call FUNC(calculateRangeCard); + [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,3,_isABenabled] call FUNC(calculateRangeCard); }; for "_i" from 0 to 9 do { GVAR(lastValidRow) pushBack count (GVAR(rangeCardDataElevation) select _i); while {count (GVAR(rangeCardDataElevation) select _i) < 50} do { - if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { + if (_isABenabled) then { (GVAR(rangeCardDataElevation) select _i) pushBack "###"; (GVAR(rangeCardDataWindage) select _i) pushBack "##"; (GVAR(rangeCardDataLead) select _i) pushBack "##"; @@ -188,7 +193,7 @@ if (isNil {_cacheEntry}) then { }; }; - missionNamespace setVariable [format[QGVAR(%1_%2_%3_%4_%5), _zeroRange, _boreHeight, _ammoClass, _weaponClass, missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]], [GVAR(rangeCardDataElevation), GVAR(rangeCardDataWindage), GVAR(rangeCardDataLead), GVAR(rangeCardDataMVs), GVAR(lastValidRow)]]; + missionNamespace setVariable [format [QGVAR(%1_%2_%3_%4_%5_%6_%7), _zeroRange, _boreHeight, _ammoClass, _weaponClass, _isABenabled, _useBarrelLengthInfluence, _useAmmoTemperatureInfluence], [GVAR(rangeCardDataElevation), GVAR(rangeCardDataWindage), GVAR(rangeCardDataLead), GVAR(rangeCardDataMVs), GVAR(lastValidRow)]]; } else { GVAR(rangeCardDataElevation) = _cacheEntry select 0; GVAR(rangeCardDataWindage) = _cacheEntry select 1; diff --git a/addons/refuel/stringtable.xml b/addons/refuel/stringtable.xml index 5ac37ddb4a..ed9b139593 100644 --- a/addons/refuel/stringtable.xml +++ b/addons/refuel/stringtable.xml @@ -500,30 +500,35 @@ Treibstoffkanister aufheben Raccogli contenitore di carburante 燃料キャニスターを持つ + 연료통 집어들기 Picking fuel canister up... Hebe Treibstoffkanister auf... Raccogliendo contenitore di carburante... 燃料キャニスターを持ち上げています・・・ + 연료통 집어드는 중... Connect fuel canister Treibstoffkanister anschließen Collega contenitore di carburante 燃料キャニスターを接続する + 연료통 꽂기 Connecting fuel canister... Schließe Treibstoffkanister an... Collegando contenitore di carburante... 燃料キャニスターを接続しています・・・ + 연료통 꽂는 중... Disconnect fuel canister Treibstoffkanister lösen Scollega contenitore di carburante 燃料キャニスターを外します + 연료통 빼기 Refuel hose length diff --git a/addons/reload/functions/fnc_canCheckAmmoSelf.sqf b/addons/reload/functions/fnc_canCheckAmmoSelf.sqf index b554833fb0..0427fb33e1 100644 --- a/addons/reload/functions/fnc_canCheckAmmoSelf.sqf +++ b/addons/reload/functions/fnc_canCheckAmmoSelf.sqf @@ -17,4 +17,4 @@ params ["_player"]; -_player call CBA_fnc_canUseWeapon && {!((vehicle _player) isKindOf "StaticWeapon")} +_player call CBA_fnc_canUseWeapon && {currentWeapon _player != ""} && {!((vehicle _player) isKindOf "StaticWeapon")} diff --git a/addons/xm157/functions/fnc_ballistics_getData.sqf b/addons/xm157/functions/fnc_ballistics_getData.sqf index 928936c51e..828db8e4ae 100644 --- a/addons/xm157/functions/fnc_ballistics_getData.sqf +++ b/addons/xm157/functions/fnc_ballistics_getData.sqf @@ -24,7 +24,6 @@ private _key = format ["weaponInfoCache-%1-%2-%3",_weaponClass,_magazineClass,_a private _weaponInfo = GVAR(data) getOrDefault [_key, []]; if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then { TRACE_3("new weapon/mag",_weaponClass,_magazineClass,_ammoClass); - private _useABConfig = (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]); private _zeroRange = 100; private _boreHeight = [_unit, 0] call EFUNC(scopes,getBoreHeight); @@ -35,8 +34,14 @@ if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then { _weaponConfig params ["_barrelTwist", "_twistDirection", "_barrelLength"]; private _bc = if (_ballisticCoefficients isEqualTo []) then { 0 } else { _ballisticCoefficients # 0 }; + private _useAB = ( + missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] && + {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} && + {_bc != 0} + ); + // Get Muzzle Velocity - private _muzzleVelocity = if (_barrelLength > 0 && _useABConfig && {_bc != 0}) then { + private _muzzleVelocity = if (_barrelLength > 0 && _useAB) then { [_barrelLength, _muzzleVelocityTable, _barrelLengthTable, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift) } else { private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed"); diff --git a/addons/zeus/functions/fnc_bi_moduleArsenal.sqf b/addons/zeus/functions/fnc_bi_moduleArsenal.sqf index f2be4a3838..7378cae65e 100644 --- a/addons/zeus/functions/fnc_bi_moduleArsenal.sqf +++ b/addons/zeus/functions/fnc_bi_moduleArsenal.sqf @@ -33,7 +33,7 @@ if (_activated && local _logic) then { }; if (_error == "") then { - if (["ACE_Arsenal"] call EFUNC(common,isModLoaded)) then { + if (["ace_arsenal"] call EFUNC(common,isModLoaded)) then { if (!isPlayer _unit || {player == _unit}) then { [{ diff --git a/addons/zeus/functions/fnc_moduleSetMedic.sqf b/addons/zeus/functions/fnc_moduleSetMedic.sqf index a05dc65d50..f66ca9132d 100644 --- a/addons/zeus/functions/fnc_moduleSetMedic.sqf +++ b/addons/zeus/functions/fnc_moduleSetMedic.sqf @@ -21,7 +21,7 @@ params ["_logic"]; if !(local _logic) exitWith {}; -if !(["ACE_Medical"] call EFUNC(common,isModLoaded)) then { +if !(["ace_medical"] call EFUNC(common,isModLoaded)) then { [LSTRING(RequiresAddon)] call FUNC(showMessage); } else { private _mouseOver = GETMVAR(bis_fnc_curatorObjectPlaced_mouseOver,[""]); diff --git a/addons/zeus/functions/fnc_moduleSetMedicalFacility.sqf b/addons/zeus/functions/fnc_moduleSetMedicalFacility.sqf index 8ff9b4a731..1f98212935 100644 --- a/addons/zeus/functions/fnc_moduleSetMedicalFacility.sqf +++ b/addons/zeus/functions/fnc_moduleSetMedicalFacility.sqf @@ -21,7 +21,7 @@ params ["_logic"]; if !(local _logic) exitWith {}; -if !(["ACE_Medical"] call EFUNC(common,isModLoaded)) then { +if !(["ace_medical"] call EFUNC(common,isModLoaded)) then { [LSTRING(RequiresAddon)] call FUNC(showMessage); } else { private _mouseOver = GETMVAR(bis_fnc_curatorObjectPlaced_mouseOver,[""]); diff --git a/addons/zeus/functions/fnc_moduleSetMedicalVehicle.sqf b/addons/zeus/functions/fnc_moduleSetMedicalVehicle.sqf index e3051f9824..e8189b377e 100644 --- a/addons/zeus/functions/fnc_moduleSetMedicalVehicle.sqf +++ b/addons/zeus/functions/fnc_moduleSetMedicalVehicle.sqf @@ -21,7 +21,7 @@ params ["_logic"]; if !(local _logic) exitWith {}; -if !(["ACE_Medical"] call EFUNC(common,isModLoaded)) then { +if !(["ace_medical"] call EFUNC(common,isModLoaded)) then { [LSTRING(RequiresAddon)] call FUNC(showMessage); } else { private _mouseOver = GETMVAR(bis_fnc_curatorObjectPlaced_mouseOver,[""]); diff --git a/addons/zeus/stringtable.xml b/addons/zeus/stringtable.xml index b51cc7406e..d23a7cf407 100644 --- a/addons/zeus/stringtable.xml +++ b/addons/zeus/stringtable.xml @@ -1319,6 +1319,7 @@ Aus Frachtraum ausladen Scarica dal carico カーゴから降ろす + 화물 내리기 Toggle NVGs @@ -1962,6 +1963,7 @@ Das Sanitätsmenü ist deaktiviert Il Menù Medico è disabilitato 医療メニューは無効になっています + 의료 메뉴가 비활성화되었습니다 Lay Trenchline diff --git a/docs/wiki/feature/maptools.md b/docs/wiki/feature/maptools.md index c6f4903780..4145eb1a18 100644 --- a/docs/wiki/feature/maptools.md +++ b/docs/wiki/feature/maptools.md @@ -21,7 +21,10 @@ This adds the possibility to draw accurate lines on the map screen. ### 1.2 Map tools This adds map tools that can be used to measure distances between two points or bearings on the map. -### 1.3 GPS on map +### 1.3 Plotting Board +This adds a plotting board that can be used to aid in the rapid usage and adjustment of short-ranged indirect fires, as well as quick measurements of directions and distances between points, and general land-navigation. + +### 1.4 GPS on map If you are equipped with a vanilla GPS it will be shown on the map. (You don't need the `Map Tools` item in your inventory for this.) ## 2. Usage @@ -39,3 +42,15 @@ If you are equipped with a vanilla GPS it will be shown on the map. (You don't n - Press ALT + LMB to start the line, left click again to end it. - To delete a line press Del around the center of the line. - Note that you can change the color of the lines by clicking on one of the coloured column on top of the screen (While the map is opened). + +### 2.3 Using the plotting board +- To use map tools the `Plotting Board` item is required. +- Open the map M (Arma 3 default key bind `Map`). +- Press the self interaction key Ctrl + ⊞ Win (ACE3 default key bind `Self Interaction Key`). +- Select `Show Plotting Board`. +- Note that you can drag the Plotting Board around with LMB and rotate the different parts of the Plotting Board, each independently from each other, with Ctrl + LMB. + +### 2.4 Drawing lines +- You can draw lines on the plotting board. +- These lines are removed from the map once the plotting board is hidden, but they restored when the plotting board is shown again. +- These lines are moved along with the plotting board when the plotting board is dragged. diff --git a/docs/wiki/framework/events-framework.md b/docs/wiki/framework/events-framework.md index 7244271520..c29f271719 100644 --- a/docs/wiki/framework/events-framework.md +++ b/docs/wiki/framework/events-framework.md @@ -67,6 +67,7 @@ MenuType: 0 = Interaction, 1 = Self Interaction |`ace_captiveStatusChanged` | [_unit, _state(BOOL), _reason ("SetHandcuffed" or "SetSurrendered"), _caller] | Global | Listen | Unit's captivity state changed |`ace_captives_setSurrendered` | [_unit, _state(BOOL)] | Target | Callable | Sets a unit to either start or stop surrendering |`ace_captives_setHandcuffed` | [_unit, _state(BOOL)] | Target | Callable | Sets a unit to either start or stop being handcuffed +|`ace_captives_escortingCaptive` | [_unit, _state(BOOL), _caller] | Local | Listen | Caller starting or stopping escort of unit ### 2.6 Settings (`ace_common`) diff --git a/docs/wiki/framework/vehiclelock-framework.md b/docs/wiki/framework/vehiclelock-framework.md index 751e1ba65d..8dc1aea2cf 100644 --- a/docs/wiki/framework/vehiclelock-framework.md +++ b/docs/wiki/framework/vehiclelock-framework.md @@ -27,7 +27,7 @@ Sync the module with vehicles and players. Custom keys will be handed to players ## 3. Scripting -### 3.1 Assing Vehicle Key +### 3.1 Adding Vehicle Key `ace_vehiclelock_fnc_addKeyForVehicle`