Merge branch 'master' into release-3.16.2

This commit is contained in:
PabstMirror 2024-01-08 01:01:46 -06:00
commit 4924ea64aa
115 changed files with 1868 additions and 545 deletions

View File

@ -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:

View File

@ -28,9 +28,6 @@ exclude = [
"zeus/functions/fnc_zeusAttributes.sqf",
]
[hemtt.config]
preset = "Hemtt"
[hemtt.launch]
workshop = [
"450814997", # CBA_A3

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;
};
};
private _currentLoadoutsTab = str GVAR(currentLoadoutsTab);

View File

@ -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

View File

@ -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;
};

View File

@ -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 {

View File

@ -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 {

View File

@ -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});

View File

@ -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
};

View File

@ -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;
};

View File

@ -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);

View File

@ -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;

View File

@ -1693,6 +1693,7 @@
<German>Suche\nSTRG + Click für Live-Aktualisierung während des Schreibens</German>
<Italian>Cerca\nCTRL + Click per modificare i risultati mentre scrivi</Italian>
<Japanese>検索\nCTRL + クリックで検索結果の即時表示を有効化</Japanese>
<Korean>검색\nCtrl + 클릭으로 실시간 검색 결과를 활성화</Korean>
</Key>
</Package>
</Project>

View File

@ -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");

View File

@ -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");

View File

@ -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];

View File

@ -310,6 +310,7 @@
<Italian>Impossibile da scaricare</Italian>
<French>Ne peut pas être déchargé</French>
<Japanese>降ろせません</Japanese>
<Korean>하역할 수가 없습니다</Korean>
</Key>
<Key ID="STR_ACE_Cargo_SizeMenu">
<English>Cargo Size: %1</English>
@ -317,6 +318,7 @@
<Italian>Dimensione Carico: %1</Italian>
<French>Encombrement fret: %1</French>
<Japanese>カーゴ サイズ: %1</Japanese>
<Korean>화물 크기: %1</Korean>
</Key>
<Key ID="STR_ACE_Cargo_customName_edenName">
<English>Custom Name</English>

View File

@ -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";
};
};
};

View File

@ -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;
};

View File

@ -181,6 +181,7 @@ PREP(statusEffect_resetVariables);
PREP(statusEffect_respawnEH);
PREP(statusEffect_sendEffects);
PREP(statusEffect_set);
PREP(stopGesture);
PREP(stringCompare);
PREP(stringToColoredText);
PREP(swayLoop);

View File

@ -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"

View File

@ -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))];
private _ctrl = _dlg displayCtrl 103;
_ctrl ctrlSetEventHandler ["ButtonClick", toString {
while {!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])} do {
closeDialog 0
};
failMission "LOSER";
[false] call FUNC(disableUserInput);
}];
_ctrl ctrlEnable true;
_ctrl ctrlSetText "ABORT";
_ctrl ctrlSetTooltip "Abort.";
_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;
_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);'];
[player, "respawn_button"] call EFUNC(medical_status,setDead);
} 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.";
player setDamage 1;
};
if (_key in actionKeys "TeamSwitch" && {teamSwitchEnabled}) then {
[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 (_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;
};

View File

@ -4,24 +4,17 @@
* Check in CfgPatches if modification is loaded
*
* Arguments:
* 0: Mod Name or Classname of the mod in CfgPatches <STRING>
* 0: Classname of the mod in CfgPatches <STRING>
*
* Return Value:
* if modification is loaded <BOOL>
* If modification is loaded <BOOL>
*
* 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]

View File

@ -0,0 +1,20 @@
#include "..\script_component.hpp"
/*
* Author: ACRE2Team
* Stops a unit's gesture.
*
* Arguments:
* 0: Target <OBJECT>
*
* Return Value:
* None
*
* Example:
* [bob] call ace_common_fnc_stopGesture
*
* Public: Yes
*/
params ["_unit"];
[QGVAR(playActionNow), [_unit, QGVAR(stop)], _unit] call CBA_fnc_targetEvent

View File

@ -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";
};

View File

@ -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];

View File

@ -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);

View File

@ -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);

View File

@ -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"];

View File

@ -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}}
};

View File

@ -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}}
};

View File

@ -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);

View File

@ -48,7 +48,7 @@
<Key ID="STR_ACE_FieldManual_Field_Rations_Thirst_Description">
<English>%3Thirst%4 increases linearly with soldier's movement speed. Restore by drinking liquids.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Pick up a drink.&lt;br/&gt;%2Use [%3%12%4] and select %3Survival%4.&lt;br/&gt;%2Choose an item to consume.</English>
<Polish>%3Pragnienie%4 zwiększa się liniowo wraz z prędkością ruchu. Odnawiane przez spożywanie napojów.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Podnieś napój.&lt;br/&gt;%2Użyj [%3%12%4] i wybierz %3Surwiwal%4.&lt;br/&gt;%2Wybierz napój do wypicia.</Polish>
<Korean>%3허기%4은 병사의 이동속도에 따라 선형적으로 증가합니다. 음료를 섭취하여 회복하십시오.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2음료를 집으십시오.&lt;br/&gt;%2[%3%12%4]를 사용하여 %3생존%4을 선택하십시오.&lt;br/&gt;%2섭취할 아이템을 선택하십시오.</Korean>
<Korean>%3갈증%4은 병사의 이동속도에 따라 선형적으로 증가합니다. 음료를 섭취하여 회복하십시오.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2음료를 집으십시오.&lt;br/&gt;%2[%3%12%4]를 사용하여 %3생존%4을 선택하십시오.&lt;br/&gt;%2섭취할 아이템을 선택하십시오.</Korean>
<Portuguese>%3A sede%4 aumenta linearmente com a velocidade de movimento do soldado. Restaure bebendo líquidos.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Pegue uma bebida.&lt;br/&gt;%2Use [%3%12%4] e selecione %3Sobrevivência%4.&lt;br/&gt;%2Escolha um item para consumir.</Portuguese>
<German>%3Durst%4 steigt linear mit der Bewegungsgeschwindigkeit des Soldaten. Regeneriert sich durch das Trinken von Flüssigkeiten.&lt;br/&gt;&lt;br/&gt;%3Verwende:%4&lt;br/&gt;%2Holen ein Getränk.&lt;br/&gt;%2Verwende [%3%12%4] und wähle %3Überleben%4.&lt; br/&gt;%2Wähle einen Gegenstand zum Verzehr aus.</German>
<Italian>%3Sete%4 aumenta linearmente con la velocità di movimento del soldato. Si rigenera bevendo liquidi.&lt;br/&gt;&lt;br/&gt;%3Usa:%4&lt;br/&gt;%2Raccogli bevanda.&lt;br/&gt;%2Usa [%3%12%4] e scegli %3sopravvivenza%4.&lt;br /&gt;%2Scegli un articolo da bere.</Italian>
@ -75,7 +75,7 @@
<Key ID="STR_ACE_FieldManual_Medical_Treatment_Adenosine_Description">
<English>%3Adenosine%4 is used to decrease heart rate.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Use [%3%13%4] or [%3%14%4] and select an appendage.&lt;br/&gt;%2Inject %3Adenosine%4.</English>
<Polish>%3Adenozyna%4 jest używana do obniżenia tętna.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Użyj [%3%13%4] lub [%3%14%4] i wybierz kończynę.&lt;br/&gt;%2Wstrzyknij %3Adenozynę%4.</Polish>
<Korean>%3아데노신%4은 심박수를 줄이기 위해 사용됩니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법%4&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하고 부위를 선택하십시오.&lt;br/&gt;%2%3아데노신%4을 주사하십시오.</Korean>
<Korean>%3아데노신%4은 심박수를 줄이기 위해 사용됩니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하고 부위를 선택하십시오.&lt;br/&gt;%2%3아데노신%4을 주사하십시오.</Korean>
<Portuguese>%3Adenosina%4 é usada para diminuir a frequência cardíaca.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Use [%3%13%4] ou [%3%14%4] e selecione um apêndice.&lt;br/&gt;%2Injete %3Adenosina%4.</Portuguese>
<German>%3Adenosin%4 wird verwendet, um die Herzfrequenz zu senken.&lt;br/&gt;&lt;br/&gt;%3Verwende:%4&lt;br/&gt;%2Verwende [%3%13%4] oder [%3%14%4] und wählen ein Körperteil aus.&lt;br/&gt;%2Injiziere %3Adenosin%4.</German>
<Italian>%3Adenosina%4 è usata per rallentare il ritmo cardiaco.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Usa [%3%13%4] o [%3%14%4] e seleziona un arto.&lt;br/&gt;%2Inject %3Adenosina%4.</Italian>
@ -102,7 +102,7 @@
<Key ID="STR_ACE_FieldManual_Medical_Treatment_Bandages_Description">
<English>%3Bandages%4 stop bleeding and close wounds. Depending on your settings, bandages may reopen if surgery is not performed.&lt;br/&gt;&lt;br/&gt;%2%3Field Dressing:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Average&lt;/t&gt; In All Categories&lt;br/&gt;%2%3Packing Bandage:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Average&lt;/t&gt; Treatment&lt;br/&gt;%11&lt;t color='#E60000'&gt;Higher&lt;/t&gt; Reopen Chance&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Longer&lt;/t&gt; Reopen Delay&lt;br/&gt;%2%3Elastic Bandage:%4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Higher&lt;/t&gt; Treatment&lt;br/&gt;%11&lt;t color='#E60000'&gt;Higher&lt;/t&gt; Reopen Chance&lt;br/&gt;%11&lt;t color='#E60000'&gt;Shorter&lt;/t&gt; Reopen Delay&lt;br/&gt;%2%3Quickclot:%4&lt;br/&gt;%11&lt;t color='#E60000'&gt;Lower&lt;/t&gt; Treatment&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Lower&lt;/t&gt; Reopen Chance&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Longer&lt;/t&gt; Reopening Delay&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Use [%3%13%4] or [%3%14%4] and select a injured body part.&lt;br/&gt;%2Bandage body part by selecting desired %3Bandage%4 type.</English>
<Polish>%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. &lt;br/&gt;&lt;br/&gt;%2%3Bandaż Jałowy:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Przeciętne&lt;/t&gt; We wszystkich kategoriach&lt;br/&gt;%2%3Bandaż Uciskowy: %4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Przeciętne&lt;/t&gt; Leczenie&lt;br/&gt;%11&lt;t color='#E60000'&gt;Wyższa&lt;/t&gt; Szansa Otwarcia&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Dłuższe&lt;/t&gt; Opóźnienie Otwarcia&lt;br/&gt;%2%3Bandaż Elastyczny: %4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Lepsze&lt;/t&gt; Leczenie&lt;br/&gt;%11&lt;t color='#E60000'&gt;Wyższa&lt;/t&gt; Szansa Otwarcia&lt;br/&gt;%11&lt;t color='#E60000'&gt;Krótsze&lt;/t&gt; Opóźnienie Otwarcia&lt;br/&gt;%2%3Quickclot: %4&lt;br/&gt;%11&lt;t color='#E60000'&gt;Gorsze&lt;/t&gt; Leczenie&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Niższa&lt;/t&gt; Szansa Otwarcia&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Dłuższe&lt;/t&gt; Opóźnienie Otwarcia&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Użyj [%3%13%4] lub [%3%14%4] i wybierz zranioną część ciała. &lt;br/&gt;%2Zabandażuj ranę wybierając typ %3Bandażu%4.</Polish>
<Korean>%3붕대%4는 출혈을 멈추고 상처를 치료합니다.설정에 따라 수술을 하지 않을 경우 붕대가 다시 풀릴 수 있습니다.&lt;br/&gt;&lt;br/&gt;%2%3붕대(기본):%4&lt;br/&gt;모든 카테고리에 대해 %11&lt;tcolor='#D9D900'&gt;평균&lt;/t&gt;적임&lt;br/&gt;%2%3붕대(거즈):%4&lt;br/&gt;&lt;br/&gt;%11&lt;t color='#D9D900'&gt;평균&lt;/t&gt;적인 치료 효과&lt;br/&gt;%11&lt;t color='#E60000'&gt;높은&lt;/t&gt; 풀림 확률&lt;br/&gt;%11&lt;t color='#00CC00'&gt;&lt;/t&gt; 풀림 딜레이&lt;br/&gt;%2%3붕대(압박):%4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;높은&lt;/t&gt; 치료 효과&lt;br/&gt;%11&lt;t color='#E60000'&gt;높은&lt;/t&gt; 풀림 확률&lt;br/&gt;%11&lt;t color='#E60000'&gt;짧은&lt;/t&gt; 풀림 딜레이&lt;br/&gt;%2%3붕대(퀵 클롯):%4&lt;br/&gt;%11&lt;t color='#E60000'&gt;낮은&lt;/t&gt; 치료 효과&lt;br/&gt;%11&lt;t color='#00CC00'&gt;낮은&lt;/t&gt; 풀림 확률&lt;br/&gt;%11&lt;t color='#00CC00'&gt;&lt;/t&gt; 풀림 딜레이&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하고 부상당한 신체부위를 선택하십시오.&lt;br/&gt;%2원하는 종류의 %3붕대%4를 선택하여 신체부위에 붕대를 감으십시오.</Korean>
<Korean>%3붕대%4는 출혈을 멈추고 상처를 치료합니다.설정에 따라 수술을 하지 않을 경우 붕대가 다시 풀릴 수 있습니다.&lt;br/&gt;&lt;br/&gt;%2%3붕대(기본):%4&lt;br/&gt;모든 카테고리에 대해 %11&lt;t color='#D9D900'&gt;평균&lt;/t&gt;적임&lt;br/&gt;%2%3붕대(거즈):&lt;br/&gt;%11&lt;t color='#D9D900'&gt;평균&lt;/t&gt;적인 치료 효과&lt;br/&gt;%11&lt;t color='#E60000'&gt;높은&lt;/t&gt; 풀림 확률&lt;br/&gt;%11&lt;t color='#00CC00'&gt;&lt;/t&gt; 풀림 딜레이&lt;br/&gt;%2%3붕대(압박):%4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;높은&lt;/t&gt; 치료 효과&lt;br/&gt;%11&lt;t color='#E60000'&gt;높은&lt;/t&gt; 풀림 확률&lt;br/&gt;%11&lt;t color='#E60000'&gt;짧은&lt;/t&gt; 풀림 딜레이&lt;br/&gt;%2%3붕대(퀵 클롯):%4&lt;br/&gt;%11&lt;t color='#E60000'&gt;낮은&lt;/t&gt; 치료 효과&lt;br/&gt;%11&lt;t color='#00CC00'&gt;낮은&lt;/t&gt; 풀림 확률&lt;br/&gt;%11&lt;t color='#00CC00'&gt;&lt;/t&gt; 풀림 딜레이&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하고 부상당한 신체부위를 선택하십시오.&lt;br/&gt;%2원하는 종류의 %3붕대%4를 선택하여 신체부위에 붕대를 감으십시오.</Korean>
<Portuguese>%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.&lt;br/&gt;&lt;br/&gt;%2%3Curativo de Campo:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Mediano&lt;/t&gt; em todas as categorias&lt;br/&gt;%2%3Bandagem de Compressão:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Mediana&lt;/t&gt; em tratamento&lt;br/&gt;%11&lt;t color='#E60000'&gt;Maior&lt;/t&gt; chance de reabertura&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Mais longo&lt;/t&gt; atraso na reabertura&lt;br/&gt;%2%3Bandagem Elástica:%4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Melhor&lt;/t&gt; em tratamento&lt;br/&gt;%11&lt;t color='#E60000'&gt;Maior&lt;/t&gt; chance de reabertura&lt;br/&gt;%11&lt;t color='#E60000'&gt;Mais curto&lt;/t&gt; atraso na reabertura&lt;br/&gt;%2%3QuikClot:%4&lt;br/&gt;%11&lt;t color='#E60000'&gt;Pior&lt;/t&gt; em tratamento&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Menor&lt;/t&gt; chance de reabertura&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Mais longo&lt;/t&gt; atraso na reabertura&lt;br/&gt;&lt;br/&gt;%Uso:%4&lt;br/&gt;%2Utilize [%3%13%4] ou [%3%14%4] e selecione uma parte do corpo ferida.&lt;br/&gt;%2Suture a parte do corpo selecionando o tipo desejado de %3Bandagem%4.</Portuguese>
<German>%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.&lt;br/&gt;&lt;br/&gt;%2%3Einfache Bandage:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Durchschnittlich&lt;/t&gt; In allen Kategorien&lt;br/&gt;%2%3Mullbinde:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Durchschnittliche&lt;/t&gt; Behandlung&lt;br/&gt;%11&lt;t color='#E60000' &gt;Höhere&lt;/t&gt; Wiedereröffnungswahrscheinlichkeit&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Längere&lt;/t&gt; Wiedereröffnungsverzögerung&lt;br/&gt;%2%3Elastischer Verband:%4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Längere&lt;/t&gt; Behandlung&lt;br/&gt;%11&lt;t color='#E60000'&gt;Höhere&lt;/t&gt; Chance auf Wiedereröffnung&lt;br/&gt;%11&lt;t color='#E60000'&gt; Kürzere&lt;/t&gt; Wiedereröffnungsverzögerung&lt;br/&gt;%2%3Quickclot:%4&lt;br/&gt;%11&lt;t color='#E60000'&gt;Kürzere&lt;/t&gt; Behandlung&lt;br/&gt;%11&lt;t color=' #00CC00'&gt;Geringere&lt;/t&gt; Wiedereröffnungswahrscheinlichkeit&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Längere&lt;/t&gt; Wiedereröffnungsverzögerung&lt;br/&gt;&lt;br/&gt;%3Verwende:%4&lt;br/&gt; %2Verwenden Sie [%3%13%4] oder [%3%14%4] und wähle ein verletztes Körperteil aus.&lt;br/&gt;%2Verbinde ein Körperteil, indem der gewünschte %3Bandagen%4-Typ ausgewählt wurde.</German>
<Italian>%3Bende%4 fermano emorragie e chiudono ferite. A seconda delle tue impostazioni, ferite bendate potrebbero riaprirsi se non suturate.&lt;br/&gt;&lt;br/&gt;%2%3Bendaggio Basico:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Media&lt;/t&gt; In tutte le categorie&lt;br/&gt;%2%3Bendaggio Compressivo:%4&lt;br/&gt;%11&lt;t color='#D9D900'&gt;Media&lt;/t&gt; Trattamenti&lt;br/&gt;%11&lt;t color='#E60000'&gt;Alta&lt;/t&gt; Probabilità di riapertura&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Lungo&lt;/t&gt; Tempo di riapertura&lt;br/&gt;%2%3Bendaggio Elastico:%4&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Alto&lt;/t&gt; Trattamento&lt;br/&gt;%11&lt;t color='#E60000'&gt;Alto&lt;/t&gt; Probabilità di riapertura&lt;br/&gt;%11&lt;t color='#E60000'&gt;Breve&lt;/t&gt; Tempo di riapertura&lt;br/&gt;%2%3Quickclot:%4&lt;br/&gt;%11&lt;t color='#E60000'&gt;Basso&lt;/t&gt; Trattamento&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Basso&lt;/t&gt; Probabilità di riapertura&lt;br/&gt;%11&lt;t color='#00CC00'&gt;Lungo&lt;/t&gt; Tempo di riapertura&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Usa [%3%13%4] o [%3%14%4] seleziona una parte del corpo ferita.&lt;br/&gt;%2Benda la parte del corpo ferita selezionando la %3Benda%4 desiderato.</Italian>
@ -147,7 +147,7 @@
<Key ID="STR_ACE_FieldManual_Medical_Treatment_Epinephrine_Description">
<English>%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).&lt;br/&gt;&lt;br/&gt;%3Usage%4&lt;br/&gt;%2Use [%3%13%4] or [%3%14%4] and select an appendage.&lt;br/&gt;%2Inject %3Epinephrine%4.</English>
<Polish>%3Adrenalina%4 zwiększa tętno pacjenta, zmniejszając czas pomiędzy sprawdzeniami przytomności (efektywnie redukując czas potrzebny do przebudzenia się pacjenta).&lt;br/&gt;&lt;br/&gt;%3Użycie%4&lt;br/&gt;%2Użyj [%3%13%4] lub [%3%14%4] i wybierz kończynę.&lt;br/&gt;%2Wstrzyknij %3Adrenalinę%4.</Polish>
<Korean>%3에피네프린%4는 환자의 맥박을 증가시킬 뿐만 아니라 의식 검사 사이의 시간을 감소시킬 수 있습니다(환자가 깨어나는 데 필요한 시간을 효과적으로 단축).&lt;br&gt;%3t사용 방법:%4&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 선택하고 부위를 선택하십시오.&lt;br/&gt;%2%3에피네프린%4을 주사하십시오.</Korean>
<Korean>%3에피네프린%4는 환자의 맥박을 증가시킬 뿐만 아니라 의식 검사 사이의 시간을 감소시킬 수 있습니다(환자가 깨어나는 데 필요한 시간을 효과적으로 단축).&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 선택하고 부위를 선택하십시오.&lt;br/&gt;%2%3에피네프린%4을 주사하십시오.</Korean>
<Portuguese>%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).&lt;br/&gt;&lt;br/&gt;%3Uso%4&lt;br/&gt;%2Utilize [%3%13%4] ou [%3%14%4] e selecione um apêndice.&lt;br/&gt;%2Injete %3Epinefrina%4.</Portuguese>
<German>%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).&lt;br/&gt;&lt;br/&gt;%3Verwendung%4&lt;br/&gt;%2Verwende [%3%13%4] oder [%3%14%4] und wählen ein Körperteil aus.&lt;br/&gt;%2Injiziere %3Epinephrine%4.</German>
<Italian>%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).&lt;br/&gt;&lt;br/&gt;%3Utilizzo%4&lt;br/&gt;%2Usa [%3%13%4] o [%3%14%4] e seleziona un arto.&lt;br/&gt;%2Inietta %3Epinefrina%4.</Italian>
@ -165,7 +165,7 @@
<Key ID="STR_ACE_FieldManual_Medical_Treatment_PAK_Description">
<English>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.&lt;br/&gt;&lt;br/&gt;%3Stable Condition%4 qualifies as:&lt;br/&gt;%2Unit is %3Alive%4.&lt;br/&gt;%2Unit is %3Conscious%4.&lt;br/&gt;%2Unit has no active %3Bleeding%4.&lt;br/&gt;%2Heart Rate &gt;= 40.&lt;br/&gt;%2Systolic BP &gt;= 60.&lt;br/&gt;%2Diastolic BP &gt;= 50.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Move to appropriate location depending on %3ACE Settings%4.&lt;br/&gt;%2Use [%3%13%4] or [%3%14%4] and select %3Advanced Treatments%4&lt;br/&gt;%2Select %3Use Personal Aid Kit%4.</English>
<Polish>%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.&lt;br/&gt;&lt;br/&gt;%3Stan Stabilny%4 występuje gdy:&lt;br/&gt;%2Jednostka jest %3Żywa%4.&lt;br/&gt;%2Jednostka jest %3Przytomna%4.&lt;br/&gt;%2Jednostka nie%3Krwawu%4.&lt;br/&gt;%2Tętno&gt;= 40. &lt;br/&gt;%2Ciśnienie Skurczowe &gt;= 60.&lt;br/&gt;%2Ciśnienie Rozkurczowe &gt;= 50.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Udaj się do właściwej lokacji żależnej od %3Ustawień ACE%4.&lt;br/&gt;%2Użyj [%3%13%4] lub [%3%14%4] i wybierz %3Zaawansowane Zabiegi%4.&lt;br/&gt;%2Wybierz %3Użyj Apteczki Osobistej%4.</Polish>
<Korean>%3개인응급키트%4는 병사를 완치시킬 수 있는 아이템입니다. %3ACE 설정%4과 무관하게 사용 전에 환자가 %3안정된 상태%4로 있어야 합니다.&lt;br/&gt;&lt;br/&gt;%3안정된 상태%4는 다음 조건이 필요합니다:&lt;br/&gt;%2유닛이 %3살아있어야%4 합니다.&lt;br/&gt;%2유닛은 %3의식이 있어야%4 합니다.&lt;br/&gt;%2유닛은 %3출혈이 일어나지 않은 상태%4여야 합니다.&lt;br/&gt;%2심박수가 40 이상이어야 합니다.&lt;br/&gt;%2수축 혈압이 60 이상이어야 합니다.&lt;br/&gt;이완 혈압이 50 이상이어야 합니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3ACE 설정%4에 따라 적절한 위치로 이동하십시오.&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하여 %3고급 치료%4를 선택하십시오.&lt;br/&gt;%2%3개인응급키트 사용%4을 선택하십시오.</Korean>
<Korean>%3개인응급키트%4는 병사를 완치시킬 수 있는 아이템입니다. %3ACE 설정%4과 무관하게 사용 전에 환자가 %3안정된 상태%4로 있어야 합니다.&lt;br/&gt;&lt;br/&gt;%3안정된 상태%4는 다음 조건이 필요합니다:&lt;br/&gt;%2유닛이 %3살아있어야%4 합니다.&lt;br/&gt;%2유닛은 %3의식이 있어야%4 합니다.&lt;br/&gt;%2유닛은 %3출혈이 일어나지 않은 상태%4여야 합니다.&lt;br/&gt;%2심박수가 40 이상이어야 합니다.&lt;br/&gt;%2수축 혈압이 60 이상이어야 합니다.&lt;br/&gt;%2이완 혈압이 50 이상이어야 합니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3ACE 설정%4에 따라 적절한 위치로 이동하십시오.&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하여 %3고급 치료%4를 선택하십시오.&lt;br/&gt;%2%3개인응급키트 사용%4을 선택하십시오.</Korean>
<Portuguese>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.&lt;br/&gt;&lt;br/&gt;%3Condições estáveis%4 qualificam-se como:&lt;br/&gt;%2Unidade está %3Viva%4.&lt;br/&gt;%2Unidade está %3Consciente%4.&lt;br/&gt;%2Unidade não está %3Sangrando%4.&lt;br/&gt;%2Frequência Cardíaca &gt;= 40.&lt;br/&gt;%2PA Sistólica &gt;= 60.&lt;br/&gt;%2PA Diastólica &gt;= 50.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Mover-se a uma localização apropriada, a depender das %3Configurações do ACE%4.&lt;br/&gt;%2Utilizar [%3%13%4] ou [%3%14%4] e selecionar %3Tratamentos Avançados%4&lt;br/&gt;%2Selecionar %3Usar o kit de primeiros socorros%4.</Portuguese>
<German>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.&lt;br/&gt;&lt;br/&gt;%3Stabiler Zustand%4 gilt wenn:&lt;br/&gt;%2Einheit ist %3am Leben%4 .&lt;br/&gt;%2Einheit ist %3Bei Bewusstsein%4.&lt;br/&gt;%2Einheit hat keine aktive %3Blutung%4.&lt;br/&gt;%2Herzfrequenz &gt;= 40.&lt;br/&gt;%2Systolischer Blutdruck &gt;= 60.&lt; br/&gt;%2Diastolischer Blutdruck &gt;= 50.&lt;br/&gt;&lt;br/&gt;%3Verwende:%4&lt;br/&gt;%2Bewege den Patienten je nach %3ACE-Einstellungen%4 an den entsprechenden Ort.&lt;br/&gt;%2Verwende [%3% 13%4] oder [%3%14%4] und wähle %3Erweiterte Behandlungen%4&lt;br/&gt;%2Wähle %3Persönliche Erste Hilfe Kit verwenden%4.</German>
<Italian>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.&lt;br/&gt;&lt;br/&gt;%3Condizione stabile%4 significa:&lt;br/&gt;%2Paziente è %3Vivo%4.&lt;br/&gt;%2Paziente è %3Conscio%4.&lt;br/&gt;%2Paziente non sta %3Sanguinando%4.&lt;br/&gt;%2Ritmo cardiaco &gt;= 40.&lt;br/&gt;%2Sistolico BC &gt;= 60.&lt;br/&gt;%2Diastolico BC &gt;= 50.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Sposta in luogo specifico a seconda delle %3impostazioni ACE%4.&lt;br/&gt;%2Usa [%3%13%4] o [%3%14%4] e seleziona %3Trattamenti avanzati%4&lt;br/&gt;%2Seleziona %3Usa Kit di Pronto Soccorso%4.</Italian>
@ -240,7 +240,7 @@
<Key ID="STR_ACE_FieldManual_Medical_Treatment_MedicalMenu_ShortName">
<English>Treatment, Simplified</English>
<Polish>Leczenie, Uproszczone</Polish>
<Korean>치료, 단순화</Korean>
<Korean>치료 단순화</Korean>
<Italian>Cure, Semplificato</Italian>
<Portuguese>Tratamento, Simplificado</Portuguese>
<Japanese>治療を簡略化する</Japanese>
@ -248,7 +248,7 @@
<Key ID="STR_ACE_FieldManual_Medical_Treatment_MedicalMenu_Description">
<English>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.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Use [%3%14%4] while looking at a patient to open the Medical Menu. Opening the menu without a patient allows for self-treatment.&lt;br/&gt;%2Alternatively, use [%3%12%4] or [%3%13%4] and select %3Medical Menu%4.&lt;br/&gt;&lt;br/&gt;%3Keybinds:%4&lt;br/&gt;%2Use [%3W, A, S, D, X, and Z%4] to select body parts.&lt;br/&gt;%2Use your %3number keys%4 to select treatment categories.</English>
<Polish>%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.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%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.&lt;br/&gt;%2Alternatywnie, użyj [%3%12%4] lub [%3%13%4] i wybierz %3Menu Medyczne%4.&lt;br/&gt;&lt;br/&gt;%3Przypisanie Klawiszy:%4&lt;br/&gt;%2Użyj [%3W, A, S, D, X, i Z%4] aby wybrać części ciała.&lt;br/&gt;%2Użyj %3klawiszy numerycznych%4 do wybrania kategorii leczenia.</Polish>
<Korean>%3의료 메뉴%4는 %3의료%4를 용이하게 사용하기 위한 전용 %3인터페이스%4입니다. %3우%4 및 %3좌%4 문자는 치료 중인 환자의 신체 측면을 나타냅니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2환자를 보고 [%3%13%4]를 사용하여 의료 메뉴를 여십시오. 환자 없이 메뉴를 열면 자가 치료가 됩니다.&lt;br/&gt;%2아니면 [%3%12%4] 또는 [%3%13%4]를 사용하고 %3의료 메뉴%4를 선택하십시오.&lt;br/&gt;&lt;br/&gt;%3키 설정%4&lt;ㅠㄱ/&gt;%2[%3W, A, S, D, X와 ㅋ%4]를 사용하여 신체 부위를 선택하십시오.&lt;br/&gt;%2%3번호판 키%4를 사용하여 치료 카테고리를 선택하십시오.</Korean>
<Korean>%3의료 메뉴%4는 %3의료%4를 용이하게 사용하기 위한 전용 %3인터페이스%4입니다. %3우%4 및 %3좌%4 문자는 치료 중인 환자의 신체 측면을 나타냅니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2환자를 보고 [%3%13%4]를 사용하여 의료 메뉴를 여십시오. 환자 없이 메뉴를 열면 자가 치료가 됩니다.&lt;br/&gt;%2아니면 [%3%12%4] 또는 [%3%13%4]를 사용하고 %3의료 메뉴%4를 선택하십시오.&lt;br/&gt;&lt;br/&gt;%3키 설정%4&lt;br/&gt;%2[%3W, A, S, D, X와 Z%4]를 사용하여 신체 부위를 선택하십시오.&lt;br/&gt;%2%3번호판 키%4를 사용하여 치료 카테고리를 선택하십시오.</Korean>
<Portuguese>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.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%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.&lt;br/&gt;%2Alternativamente, utilize [%3%12%4] ou [%3%13%4] e selecione %3Menu Médico%4.&lt;br/&gt;&lt;br/&gt;%3Atalhos de teclado:%4&lt;br/&gt;%2Utilize [%3W, A, S, D, X, e Z%4] para selecionar partes do corpo.&lt;br/&gt;%2Utilize as %3teclas numéricas%4 para selecionar as categorias de tratamento.</Portuguese>
<Italian>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.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Usa [%3%14%4] guardando il paziente per aprire il Menù Medico. Aprire il menù senza paziente di fronte permette l'automedicazione.&lt;br/&gt;%2In alternativa, usa [%3%12%4] o [%3%13%4] e seleziona %3Menù Medico%4.&lt;br/&gt;&lt;br/&gt;%3Comandi:%4&lt;br/&gt;%2Usa [%3W, A, S, D, X, and Z%4] per selezionare parti del corpo.&lt;br/&gt;%2Usa %3tasti numerici%4 per selezionare categorie di cure.</Italian>
<Japanese>%3医療メニュー%4は%3治療%4をしやすくするための専用%3インターフェース%4です。%3右%4と%3左%4の文字は治療を受ける患者の向きを表しています。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2[%3%14%4] を患者に視点を合わせながら押すことで患者の医療メニューを開けます。視点を合わせないで押すと、自分の医療メニューを開くことが出来ます。&lt;br/&gt;%2もしくは [%3%12%4] または [%3%13%4] を使って%3医療メニュー%4を選択します。&lt;br/&gt;&lt;br/&gt;%3キーバインド:%4&lt;br/&gt;%2[%3W, A, S, D, X, と Zキー%4] を使って身体の部位を選択できます。&lt;br/&gt;%2%3数字キー%4を使って治療項目を選択できます。</Japanese>
@ -278,12 +278,12 @@
<Japanese>死者を連れ出す</Japanese>
</Key>
<Key ID="STR_ACE_FieldManual_Items_BodyBag_Description">
<English>%3Body Bags%4 are used to transport dead bodies. They can be dragged and loaded into vehicles.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Approach a dead body.&lt;br/&gt;%2Use [%3%13%4] or [%3%14%4] and select %3Place Body In Bodybag%4.</English>
<Polish>%3Worki na Zwłoki%4 są używane do transportu ciał. Worki mogą być przeciągane i ładowanie do pojazdów.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Podejdź do martwego ciała.&lt;br/&gt;%2Użyj [%3%13%4] lub [%3%14%4] i wybierz %3Umieść Ciało w Worku na Zwłoki%4.</Polish>
<Korean>%3시체 운반용 부대%4는 시체를 운반하는 데 사용되며, 차량으로 끌고 가서 적재할 수 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2시체에 접근하십시오.&lt;br/&gt;%2[%3%13%4] 또는 [%3%14%4]를 사용하여 %3시체 운반용 부대에 담기%4를 선택하십시오.</Korean>
<Portuguese>OS %3Sacos de Cadáver%4 são utilizados para transportar cadáveres. Eles podem ser arrastados e embarcados em veículos.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Aproxime-se de um cadáver.&lt;br/&gt;%2Utilize [%3%13%4] ou [%3%14%4] e selecione %3Colocar cadáver dentro do saco%4.</Portuguese>
<Italian>%3Sacche per cadaveri%4 sono usate per trasportare i morti. Possono essere trascinate e caricate su veicoli.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Avvicinati ad un morto.&lt;br/&gt;%2Usa [%3%13%4] o [%3%14%4] e seleziona %3Metti il corpo nella sacca per cadaveri%4.</Italian>
<Japanese>%3遺体袋%4は、遺体の輸送に使用されます。引きずって車両に積み込むことができます。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2遺体に近寄る。&lt;br/&gt;%2[%3%13%4] または [%3%14%4] を使って%3遺体袋に入れる%4を選択して使用します。</Japanese>
<English>%3Body Bags%4 are used to transport dead bodies. They can be dragged and loaded into vehicles.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Approach a dead body.&lt;br/&gt;%2Use [%3%13%4] or [%3%15%4] and select %3Place Body In Bodybag%4.</English>
<Polish>%3Worki na Zwłoki%4 są używane do transportu ciał. Worki mogą być przeciągane i ładowanie do pojazdów.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Podejdź do martwego ciała.&lt;br/&gt;%2Użyj [%3%13%4] lub [%3%15%4] i wybierz %3Umieść Ciało w Worku na Zwłoki%4.</Polish>
<Korean>%3시체 운반용 부대%4는 시체를 운반하는 데 사용되며, 차량으로 끌고 가서 적재할 수 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2시체에 접근하십시오.&lt;br/&gt;%2[%3%13%4] 또는 [%3%15%4]를 사용하여 %3시체 운반용 부대에 담기%4를 선택하십시오.</Korean>
<Portuguese>OS %3Sacos de Cadáver%4 são utilizados para transportar cadáveres. Eles podem ser arrastados e embarcados em veículos.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Aproxime-se de um cadáver.&lt;br/&gt;%2Utilize [%3%13%4] ou [%3%15%4] e selecione %3Colocar cadáver dentro do saco%4.</Portuguese>
<Italian>%3Sacche per cadaveri%4 sono usate per trasportare i morti. Possono essere trascinate e caricate su veicoli.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Avvicinati ad un morto.&lt;br/&gt;%2Usa [%3%13%4] o [%3%15%4] e seleziona %3Metti il corpo nella sacca per cadaveri%4.</Italian>
<Japanese>%3遺体袋%4は、遺体の輸送に使用されます。引きずって車両に積み込むことができます。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2遺体に近寄る。&lt;br/&gt;%2[%3%13%4] または [%3%15%4] を使って%3遺体袋に入れる%4を選択して使用します。</Japanese>
</Key>
<Key ID="STR_ACE_FieldManual_Items_CableTie_ShortName">
<English>Take Prisoners</English>
@ -296,7 +296,7 @@
<Key ID="STR_ACE_FieldManual_Items_CableTie_Description">
<English>%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.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Approach the unit and use the [%3%13%4].&lt;br/&gt;%2The interaction is located around the hands in the form of a handcuffs icon.&lt;br/&gt;%2Repeat to release.</English>
<Polish>%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.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Podejdź do jednostki i użyj [%3%13%4].&lt;br/&gt;%2Interakcja jest zlokalizowana na rękach pod postacią ikony kajdanek.&lt;br/&gt;%2Użyj ponownie aby uwolnić.</Polish>
<Korean>%3이블 타이%4를 사용하면 병사가 다른 병사를 포로로 잡고 구금할 수 있습니다. 체포되면 포로는 포로의 소지품을 검사하여 석방하거나 대체 지역으로 동행시킬 수 있습니다. 필요하면 차량에 싣는 것을 포함하여 죄수를 호송할 수도 있습니다. 설정에 따라 유닛은 포로가 되기 전에 항복해야 할 수도 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4%2유닛에 접근하여 [%3%13%4]를 사용하십시오.&lt;br/&gt;%2상호작용은 수갑 아이콘의 형태로 손 부분에 위치합니다.&lt;br/&gt;%2해제 하려면 같은 행동을 반복하십시오.</Korean>
<Korean>%3이블 타이%4를 사용하면 병사가 다른 병사를 포로로 잡고 구금할 수 있습니다. 체포되면 포로는 포로의 소지품을 검사하여 석방하거나 대체 지역으로 동행시킬 수 있습니다. 필요하면 차량에 싣는 것을 포함하여 죄수를 호송할 수도 있습니다. 설정에 따라 유닛은 포로가 되기 전에 항복해야 할 수도 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2유닛에 접근하여 [%3%13%4]를 사용하십시오.&lt;br/&gt;%2상호작용은 수갑 아이콘의 형태로 손 부분에 위치합니다.&lt;br/&gt;%2해제 하려면 같은 행동을 반복하십시오.</Korean>
<Portuguese>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.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Aproxime-se da unidade e use [%3%13%4].&lt;br/&gt;%2A interação encontra-se próxima às mãos simbolizada por uma algema.&lt;br/&gt;%2Faça o mesmo para liberar.</Portuguese>
<Italian>%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.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Avvicinati all'unità e usa [%3%13%4].&lt;br/&gt;%2L'interazione è localizzata intorno alle mani con l'icona di manette.&lt;br/&gt;%2Ripeti per liberare.</Italian>
<Japanese>%3ケーブル タイ%4は兵士が他の兵士を拘束できるようにします。一度拘束すれば、拘束者は捕虜の所持品を検査したり、釈放したり、別の場所に移送することができるようになります。必要に応じて車両に積み込むなどして捕虜の輸送や護送も可能です。設定によっては、ユニットは捕虜になる前に降伏する必要がある場合があります。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2対象に近づいて [%3%13%4] を使います。&lt;br/&gt;%2インタラクションは、手錠アイコンの形で手のあたりに表示されます。&lt;br/&gt;%2同様の方法で解放できます。</Japanese>
@ -312,7 +312,7 @@
<Key ID="STR_ACE_FieldManual_Items_Cellphone_Description">
<English>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.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Place an explosive.&lt;br/&gt;%2Use [%3%13%4], select %3Explosives%4, and select %3Cellphone%4.&lt;br/&gt;%2Open the cellphone interface with [%3%12%4].&lt;br/&gt;%2Navigate the phone book with the arrows and select your calling number.&lt;br/&gt;%2Call the number to detonate.</English>
<Polish>%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.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Połóż ładunek wybuchowy&lt;br/&gt;%2Użyj [%3%13%4], wybierz %3Ładunki Wybuchowe%4, i wybierz %3Telefon%4. &lt;br/&gt;%2Otwórz interfejs telefonu za pomocą [%3%12%4].&lt;br/&gt;%2Nawiguj po książce telefonicznej za pomocą strzałek i wybierz żądany numer.&lt;br/&gt;%2Zadzwoń pod niego aby wywołać wybuch.</Polish>
<Korean>%3휴대전화%4는 기능적으로는 %3격발기%4입니다. 폭발물 장치를 연결하여 폭발물을 터뜨릴 때 사용합니다. 여러 장치를 휴대전화와 연결하여 전화번호부 내에서 호출할 수 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2폭발물을 놓으십시오.&lt;br/&gt;%2[%313%4]를 사용하고, %3폭발물%4을 선택하고, %3휴대전화%4를 선택하십시오.&lt;br/%2[%3%12%4]로 휴대전화 인터페이스를 여십시오.&lt;br/&gt;%2기폭시킬 전화번호를 선택하십시오.</Korean>
<Korean>%3휴대전화%4는 기능적으로는 %3격발기%4입니다. 폭발물 장치를 연결하여 폭발물을 터뜨릴 때 사용합니다. 여러 장치를 휴대전화와 연결하여 전화번호부 내에서 호출할 수 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2폭발물을 놓으십시오.&lt;br/&gt;%2[%3%13%4]를 사용하고, %3폭발물%4을 선택하고, %3휴대전화%4를 선택하십시오.&lt;br/%2[%3%12%4]로 휴대전화 인터페이스를 여십시오.&lt;br/&gt;%2기폭시킬 전화번호를 선택하십시오.</Korean>
<Portuguese>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.&lt;br/&gt;&lt;br/&gt;%3Uso:%4&lt;br/&gt;%2Plante o explosivo.&lt;br/&gt;%2Utilize [%3%13%4], selecione %3Explosivos%4, e selecione %3Celular%4.&lt;br/&gt;%2Abra a interface do celular com [%3%12%4].&lt;br/&gt;%2Navegue pela lista telefônica utilizando as setas e selecione o número desejado.&lt;br/&gt;%2Ligue para o número para detonar.</Portuguese>
<Italian>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.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Piazza un esplosivo.&lt;br/&gt;%2Usa [%3%13%4], seleziona %3Esplosivi%4, seleziona %3Cellulare%4.&lt;br/&gt;%2Apri l'interfaccia del telefono con [%3%12%4].&lt;br/&gt;%2Naviga la rubrica con le freccette e seleziona il numero da chiamare.&lt;br/&gt;%2Chiama il numero del dispositivo da detonare.</Italian>
<Japanese>%3携帯電話%4は%3点火装置%4として機能します。爆破装置を接続して起爆するために使用します。複数のデバイスを携帯電話に繋ぎ、電話帳から呼び出すことができます。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2爆発物を設置。&lt;br/&gt;%2[%3%13%4] を使い、%3爆発物%4を選択して、%3携帯電話%4を選択します。&lt;br/&gt;%2[%3%12%4] を使って携帯電話インターフェースを開きます。&lt;br/&gt;%2矢印ボタンで電話帳に移動し、発信番号を選択します。&lt;br/&gt;%2電話を掛けることで起爆します。</Japanese>
@ -415,7 +415,7 @@
<English>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.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Equip an %3Entrenching Tool%4.&lt;br/&gt;%2Use [%3%12%4] and select %3Equipment%4.&lt;br/&gt;%2Select the type of trench you wish to build.</English>
<Polish>%3Saperka%4 pozwala żołnierzowi kopać okopy w celu obrony swoich pozycji. Żołnierz musi być na glebie, aby wykopać okop.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Wyekwipuj %3Saperkę%4.&lt;br/&gt;%2Użyj [%3%12%4] i wybierz %3Ekwipunek%4.&lt;br/&gt;%2Wybierz rodzaj okopu, który chcesz wykopać.</Polish>
<Italian>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.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Equipaggia una %3Pala da Trincea%4.&lt;br/&gt;%2Usa [%3%12%4] e seleziona %3Equipaggiamento%4.&lt;br/&gt;%2Seleziona il tipo di trincea che vuoi costruire.</Italian>
<Korean>%3야전삽%4을 사용하면 병사들의 진지 방어를 위한 참호를 팔 수 있습니다. 병사가 참호를 파려면 흙 위에 있어야 합니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3야전삽%4을 장비하십시오.&lt;br/&gt;%2[%3%12%4]를 사용하여 %3장비%4를 선택하십시오.&lt;br/&gt;짓고 싶은 종류의 참호를 선택하십시오.</Korean>
<Korean>%3야전삽%4을 사용하면 병사들의 진지 방어를 위한 참호를 팔 수 있습니다. 병사가 참호를 파려면 흙 위에 있어야 합니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3야전삽%4을 장비하십시오.&lt;br/&gt;%2[%3%12%4]를 사용하여 %3장비%4를 선택하십시오.&lt;br/&gt;%2짓고 싶은 종류의 참호를 선택하십시오.</Korean>
<Japanese>%3塹壕ツール%4を使用すると、兵士は自分の陣地を守るために塹壕を掘ることができます。塹壕を掘るには、兵士は土の上にいる必要があります。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2%3塹壕ツール%4を装備します。&lt;br/&gt;%2[%3%12%4] を使って%3装備%4を選択します。&lt;br/&gt;%2構築する塹壕の種類を選択します。</Japanese>
</Key>
<Key ID="STR_ACE_FieldManual_Items_Flashlights_DisplayName">
@ -436,7 +436,7 @@
<English>%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.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2On the map screen, use [%3%12%4] and select %3Flashlights%4.&lt;br/&gt;%2Select the %3Flashlight%4 you want to use and select %3On%4.&lt;br/&gt;&lt;br/&gt;%3Available Flashlight Items%4:&lt;br/&gt;%2 Fulton MX-991&lt;br/&gt;%2 KSF-1&lt;br/&gt;%2 Maglite XL50&lt;br/&gt;&lt;br/&gt;%3NOTE:%4&lt;br/&gt;Flashlight states are persistent.</English>
<Polish>%3Latarki%4 pozwalają czytać mapę, nawet w ciemnościach. Jednakże podczas używani %3Latarki%4, będziesz miał wokół siebie delikatną poświatę.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2W widoku mapy użyj [%3%12%4] i wybierz %3Latarki%4.&lt;br/&gt;%2Wybierz %3Latarkę%4, którą chcesz użyć i wybierz %3Włącz%4.&lt;br/&gt;&lt;br/&gt;%3Dostępne latarki%4:&lt;br/&gt;%2 Fulton MX-991&lt;br/&gt;%2 KSF-1&lt;br/&gt;%2 Maglite XL50&lt;br/&gt;&lt;br/&gt;%3NOTE:%4&lt;br/&gt;Stan latarki jest trwały.</Polish>
<Italian>%3Torce%4 permettono di leggere la tua mappa anche in ambienti bui. Però quando le utilizzi avrai un leggero effetto luminoso intorno a te.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Sulla mappa usa [%3%12%4] e seleziona %3Torcia%4.&lt;br/&gt;%2Seleziona la %3Torcia%4 che vuoi usare e seleziona %3Accendi%4.&lt;br/&gt;&lt;br/&gt;%3Oggetti Torcia Disponibili%4:&lt;br/&gt;%2 Fulton MX-991&lt;br/&gt;%2 KSF-1&lt;br/&gt;%2 Maglite XL50&lt;br/&gt;&lt;br/&gt;%3NOTE:%4&lt;br/&gt;Lo stato di una torcia è persistente.</Italian>
<Korean>%3손전등%4은 어두운 환경에서도 지도를 읽을 수 있는 기능을 제공합니다. 단, %3손전등%4을 사용할 때 주변에 약간 빛이 납니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2지도 화면에서 [%3%12%4]를 사용하고 %3손전등%4을 선택하십시오.&lt;br/&gt;%2사용할 %3손전등%4을 선택하고 %3켜기%4를 선택하십시오.&lt;br/&gt;&lt;br/&gt;%3사용 가능한 손전등 아이템%4:&lt;br/&gt;% 2풀턴 MX-991&lt;br/&gt;%2 KSF-1&lt;br/&gt;%2 매그라이트 XL50&lt;br/&gt;&lt;br/&gt;%3참고:%4&lt;br/&gt;손전등 상태는 영구적입니다.</Korean>
<Korean>%3손전등%4은 어두운 환경에서도 지도를 읽을 수 있는 기능을 제공합니다. 단, %3손전등%4을 사용할 때 주변에 약간 빛이 납니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2지도 화면에서 [%3%12%4]를 사용하고 %3손전등%4을 선택하십시오.&lt;br/&gt;%2사용할 %3손전등%4을 선택하고 %3켜기%4를 선택하십시오.&lt;br/&gt;&lt;br/&gt;%3사용 가능한 손전등 아이템%4:&lt;br/&gt;%2풀턴 MX-991&lt;br/&gt;%2 KSF-1&lt;br/&gt;%2 매그라이트 XL50&lt;br/&gt;&lt;br/&gt;%3참고:%4&lt;br/&gt;손전등 상태는 영구적입니다.</Korean>
<Japanese>%3フラッシュライト%4を使用すると、暗い環境でも地図を読むことができます。ただし、%3フラッシュライト%4を使用すると、周囲がわずかに光ります。&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2マップ画面で [%3%12%4] を使用し、%3フラッシュライト%4を選択します。&lt;br/&gt;%2%3フラッシュライト%4を選択し、使用したいライトを%3点ける%4。&lt;br/&gt;&lt;br/&gt;%3使用可能なフラッシュライトのアイテム%4:&lt;br/&gt;%2 フルトン MX-991&lt;br/&gt;%2 KSF-1&lt;br/&gt;%2 マグライト XL50&lt;br/&gt;&lt;br/&gt;%3備考:%4&lt;br/&gt;フラッシュライトの状態は継続します。</Japanese>
</Key>
<Key ID="STR_ACE_FieldManual_Items_HuntIR_Monitor_ShortName">
@ -478,7 +478,7 @@
<English>The %3Kestrel 4500 Pocket Weather Tracker%4 is a mini weather station useful for collecting the the following weather data:&lt;br/&gt;%2Heading and wind direction&lt;br/&gt;%2Crosswind and headwind&lt;br/&gt;%2Altitude and barometric pressure&lt;br/&gt;%2Wet bulb temperature&lt;br/&gt;%2Humidity and dewpoint&lt;br/&gt;%2Density altitude&lt;br/&gt;%2Wind chill and temperature&lt;br/&gt;%2Time and date&lt;br/&gt;%2Minimum, maximum, and average values&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Equip a %3Kestrel%4.&lt;br/&gt;%2Use [%3%12%4] and select %3Equipment%4.&lt;br/&gt;%2Select %3Open%4.</English>
<Polish>%3Kestrel 4500 Pocket Weather Tracker%4 jest przenośną stacją pogodową pozwalającą zbierać takie dane jak: &lt;br/&gt;%2Kurs i kierunek wiatru&lt;br/&gt;%2Wiatr boczny i czołowy&lt;br/&gt;%2Wysokość i ciśnienie barometryczne&lt;br/&gt;%2Temperatua mokrego termometru&lt;br/&gt;%2Wilgotność i punkt rosy&lt;br/&gt;%2Gęstość powietrza&lt;br/&gt;%2Temperatura i temperatura odczuwalna&lt;br/&gt;%2Czas i data&lt;br/&gt;%2Wartości minimalne, maksymalne oraz średnie&lt;br/&gt;&lt;br/&gt;%3Użycie: %4&lt;br/&gt;%2Wyekwipuj %3Kestrela%4. &lt;br/&gt;%2Użyj [%3%12%4] i wybierz %3Ekwipunek%4.&lt;br/&gt;%2Wybierz %3Otwórz%4.</Polish>
<Italian>Il %3Kestrel 4500 Indicatore Meteorologico Tascabile%4 è una mini-stazione meteo utile per ricavare le seguenti informazioni meteorologiche:&lt;br/&gt;%2Prua e direzione del vento&lt;br/&gt;%2Vento di traverso e frontale&lt;br/&gt;%2Altitudine and pressione barometrica&lt;br/&gt;%2Temperatura di bulbo umido&lt;br/&gt;%2Umidità e punto di rugiada&lt;br/&gt;%2Density altitude&lt;br/&gt;%2Temperatura e gelo del vento&lt;br/&gt;%2Data e Ora&lt;br/&gt;%2Valori minimi, massimi, e medi&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Equipaggia %3Kestrel%4.&lt;br/&gt;%2Usa [%3%12%4] e seleziona %3Equipaggiamento%4.&lt;br/&gt;%2Seleziona %3Apri%4.</Italian>
<Korean>%3케스트렐 4500 휴대용 기상 추적 장비%4는 다음 날씨 데이터들을 수집하는 데 유용한 소형 기상 관측 장비입니다:&lt;br/&gt;%2바람이 오는 방향과 가는 방향&lt;br/&gt;%2옆바람과 맞바람&lt;br/&gt;%2고도 및 기압&lt;br/&gt;%2습구온도&lt;br/&gt;%2습도 및 이슬점&lt;br/&gt;%2밀도고도&lt;br/&gt;%2체감온도&lt;br/&gt;%2시간 및 날짜&lt;br/&gt;%2최소, 최대, 평균값&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3케스트렐 4500NV%4를 장착하십시오.&lt;br/&gt;%2[%3%12%4]를 사용하고 %3장비%4를 선택하십시오.&lt;br/&gt;%2%3열기%4를 선택하십시오.</Korean>
<Korean>%3케스트렐 4500 휴대용 기상 추적 장비%4는 다음 날씨 데이터들을 수집하는 데 유용한 소형 기상 관측 장비입니다:&lt;br/&gt;%2바람이 오는 방향과 가는 방향&lt;br/&gt;%2옆바람과 맞바람&lt;br/&gt;%2고도 및 기압&lt;br/&gt;%2습구온도&lt;br/&gt;%2습도 및 이슬점&lt;br/&gt;%2밀도고도&lt;br/&gt;%2체감온도&lt;br/&gt;%2시간 및 날짜&lt;br/&gt;%2최소, 최대, 평균값&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3케스트렐 4500NV%4를 장착하십시오.&lt;br/&gt;%2[%3%12%4]를 사용하고 %3장비%4를 선택하십시오.&lt;br/&gt;%2%3열기%4를 선택하십시오.</Korean>
<Japanese>%3ケストレル 4500 携帯気象計%4は、次の気象データの収集に役立つミニ気象ステーションです:&lt;br/&gt;%2方位と風向&lt;br/&gt;%2横風と向かい風&lt;br/&gt;%2高度と気圧&lt;br/&gt;%2湿球温度&lt;br/&gt;%2湿度と露点&lt;br/&gt;%2密度高度&lt;br/&gt;%2ウィンドチルと温度&lt;br/&gt;%2日付と時刻&lt;br/&gt;%2最小値、最大値、平均値&lt;br/&gt;&lt;br/&gt;%3使用方法:%4&lt;br/&gt;%2%3ケストレル%4を装備します。&lt;br/&gt;%2[%3%12%4] を使って%3装備%4を選択します。&lt;br/&gt;%2%3ケストレルを開く%4で使用できます。</Japanese>
</Key>
<Key ID="STR_ACE_FieldManual_Items_MapTools_ShortName">
@ -673,7 +673,7 @@
<Japanese>要塞を構築する</Japanese>
</Key>
<Key ID="STR_ACE_FieldManual_Items_FortifyTool_Description">
<English>The %3Fortify Tool%4 allows soldiers to build fortifications provided by their mission creator.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Pick up a %3FortifyTool%4.&lt;br/&gt;%2Use [%3%12%4] and select %3Fortify%4.&lt;br/&gt;%2Select an available fortification and follow the on screen prompts for placement.</English>
<English>The %3Fortify Tool%4 allows soldiers to build fortifications provided by their mission creator.&lt;br/&gt;&lt;br/&gt;%3Usage:%4&lt;br/&gt;%2Pick up a %3Fortify Tool%4.&lt;br/&gt;%2Use [%3%12%4] and select %3Fortify%4.&lt;br/&gt;%2Select an available fortification and follow the on screen prompts for placement.</English>
<Polish>%3Narzędzie do fortyfikowania%4 pozwala żołnierzom budować fortyfikacje wybrane przez twórcę misji.&lt;br/&gt;&lt;br/&gt;%3Użycie:%4&lt;br/&gt;%2Podnieś %3Narzędzie do fortyfikowania%4.&lt;br/&gt;%2Użyj [%3%12%4] i wybierz %3Fortyfikuj%4.&lt;br/&gt;%2Wybierz dostępną fortyfikację i postępuj zgodnie ze wskazówkami na ekranie.</Polish>
<Italian>L'%3Attrezzo di Fortificazione%4 permette ai soldati di costruire fortificazioni permesse dal creatore della missione.&lt;br/&gt;&lt;br/&gt;%3Utilizzo:%4&lt;br/&gt;%2Raccogli un %3Attrezzo di Fortificazione%4.&lt;br/&gt;%2Usa [%3%12%4] e seleziona %3Fortifica%4.&lt;br/&gt;%2Seleziona una fortificazione disponibile e segui le indicazioni di piazzamento sullo schermo.</Italian>
<Korean>%3요새화 도구%4를 사용하면 병사들이 임무 생성자가 제공한 요새를 구축할 수 있습니다.&lt;br/&gt;&lt;br/&gt;%3사용 방법:%4&lt;br/&gt;%2%3요새화 도구%4를 가지십시오.&lt;br/&gt;%2[%3%12%4]를 사용하고 %3요새화%4를 선택하십시오.&lt;br/&gt;%2사용 가능한 요새를 선택하고 화면의 지시에 따라 배치하십시오.</Korean>

View File

@ -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);
};

View File

@ -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);
};

View File

@ -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);
};
};

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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 [])];

View File

@ -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];

View File

@ -12,7 +12,7 @@
* Currently selected item list box <CONTROL>
*
* 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

View File

@ -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)
];
};

View File

@ -10,7 +10,7 @@
* Item should appear in this list? <BOOL>
*
* Example:
* [CONFIG] call ACE_inventory_fnc_filterBackpacks
* [CONFIG] call ace_inventory_fnc_filterBackpacks
*
* Public: No
*/

View File

@ -10,11 +10,11 @@
* Item should appear in this list? <BOOL>
*
* 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))

View File

@ -10,7 +10,7 @@
* Item should appear in this list? <BOOL>
*
* Example:
* [CONFIG] call ACE_inventory_fnc_filterHeadgear
* [CONFIG] call ace_inventory_fnc_filterHeadgear
*
* Public: No
*/

View File

@ -10,11 +10,14 @@
* Item should appear in this list? <BOOL>
*
* 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])}

View File

@ -10,9 +10,9 @@
* Item should appear in this list? <BOOL>
*
* 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))}

View File

@ -10,11 +10,11 @@
* Item should appear in this list? <BOOL>
*
* 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)

View File

@ -10,7 +10,7 @@
* Item should appear in this list? <BOOL>
*
* Example:
* [CONFIG] call ACE_inventory_fnc_filterUniforms
* [CONFIG] call ace_inventory_fnc_filterUniforms
*
* Public: No
*/

View File

@ -10,7 +10,7 @@
* Item should appear in this list? <BOOL>
*
* Example:
* [CONFIG] call ACE_inventory_fnc_filterVests
* [CONFIG] call ace_inventory_fnc_filterVests
*
* Public: No
*/

View File

@ -10,7 +10,7 @@
* Item should appear in this list? <BOOL>
*
* Example:
* [CONFIG] call ACE_inventory_fnc_filterWeapons
* [CONFIG] call ace_inventory_fnc_filterWeapons
*
* Public: No
*/

View File

@ -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 item is valid and doesn't match the current filter, remove it
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;
};
};

View File

@ -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);
}];

View File

@ -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;

View File

@ -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;

View File

@ -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";
};

View File

@ -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);
};

View File

@ -161,7 +161,7 @@
<Italian>%1 Pieno(i) e %2 Parziale(i)</Italian>
<Portuguese>%1 Total e %2 Parcial </Portuguese>
<Japanese>満装填した弾倉 %1 個と&lt;br/&gt;部分装填の弾倉 %2 個</Japanese>
<Korean>%1 꽉 찼고 %2 부분적으로 참</Korean>
<Korean>꽉 찬 탄창:%1&lt;br/&gt;부분적으로 찬 탄창: %2</Korean>
<Chinesesimp>%1个满的与%2个部分的</Chinesesimp>
<Chinese>%1個滿的與%2個部分的</Chinese>
<Turkish>%1 Dolu ve %2 Partial</Turkish>

View File

@ -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

View File

@ -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(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"};
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_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);
};
};
};

View File

@ -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;
};
};
};

View File

@ -5,3 +5,4 @@ Adds the following map tools:
- Roamer
- Map drawing
- Showing GPS on map
- Plotting Board

Binary file not shown.

View File

@ -7,3 +7,8 @@ PREP(handleMouseMove);
PREP(isInsideMapTool);
PREP(openMapGpsUpdate);
PREP(updateMapToolMarkers);
PREP(canUsePlottingBoard);
PREP(isInsidePlottingBoard);
PREP(handlePlottingBoardMarkers);
PREP(wipeMarkers);

View File

@ -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;

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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 <BOOL>
*
* 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}

View File

@ -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 <Number>
* 0: 1 if mouse down down, 0 if mouse button up <NUMBER>
* 1: Parameters of the mouse button event <ARRAY>
*
* Return Value:
* true if event was handled <BOOL>
* True if event was handled <BOOL>
*
* 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,45 +82,99 @@ 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 {};
// Transform mouse screen position to coordinates
private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
_pos set [count _pos, 0];
if (call FUNC(canUseMapTools)) then {
GVAR(mapTool_isDragging) = false;
GVAR(mapTool_isRotating) = false;
// If no map tool marker then exit
if (GVAR(mapTool_Shown) == 0) exitWith {};
if (GVAR(mapTool_Shown) != 0) then {
// Transform mouse screen position to coordinates
private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
// Check if clicking the maptool
if (_pos call FUNC(isInsideMapTool)) exitWith {
if (_pos call FUNC(isInsideMapTool)) then {
// Store data for dragging
GVAR(mapTool_startPos) = + GVAR(mapTool_pos);
GVAR(mapTool_startDragPos) = + _pos;
GVAR(mapTool_startPos) = +GVAR(mapTool_pos);
GVAR(mapTool_startDragPos) = _pos;
private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do {
case (1): {_altKey};
case (2): {_ctrlKey};
case (3): {_shiftKey};
case 1: {_altKey};
case 2: {_ctrlKey};
case 3: {_shiftKey};
default {false};
};
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);
GVAR(mapTool_startAngle) = GVAR(mapTool_angle);
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 (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

View File

@ -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 <CONTROL>
* 0: Map control <CONTROL>
* 1: Mouse position on screen coordinates <ARRAY>
*
* Return Value:
* true if event was handled <BOOL>
* If the event was handled <BOOL>
*
* 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
};

View File

@ -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 <ARRAY>
* - 0: Marker name <STRING>
* - 1: Chat channel number <NUMBER>
* - 2: Marker owner <OBJECT>
* - 3: Local origin <BOOL>
* 1: Deleted <BOOL>
*
* 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;

View File

@ -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) <NUMBER>
* 1: y Position (in meters) <NUMBER>
*
* Return Value:
* Where in the plotting board it is <NUMBER>
* -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

View File

@ -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 <CONTROL>
* 0: Map control <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 {
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(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
};
private _rotatingTexture = "";
private _textureWidth = 0;
if (GVAR(mapTool_Shown) == 1) then {
_rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa);
_textureWidth = TEXTURE_WIDTH_IN_M;
} else {
} else {
_rotatingTexture = QPATHTOF(data\mapToolRotatingSmall.paa);
_textureWidth = TEXTURE_WIDTH_IN_M / 2;
};
if (GVAR(freedrawing)) then {
[_mapCtrl, _textureWidth] call FUNC(drawLinesOnRoamer);
};
// 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
// 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];
};
if (GVAR(freedrawing)) then {[_theMap, _textureWidth] call FUNC(drawLinesOnRoamer);};
// Update scale of both parts
getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"];
private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale));
private _scaleY = _scaleX;
// Position of the fixed part
private _xPos = GVAR(mapTool_pos) select 0;
private _yPos = (GVAR(mapTool_pos) select 1) + _textureWidth * CENTER_OFFSET_Y_PERC;
_theMap drawIcon [QPATHTOF(data\mapToolFixed.paa), [1,1,1,1], [_xPos,_yPos], _scaleX, _scaleY, 0, "", 0];
// 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;
_theMap drawIcon [_rotatingTexture, [1,1,1,1], [_xPos,_yPos], _scaleX, _scaleY, GVAR(mapTool_angle), "", 0];

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -35,6 +35,12 @@
<Chinese>地圖工具能夠讓你在地圖上測量距離與角度</Chinese>
<Turkish>Harita Araçları, haritadaki mesafeleri ve açıları ölçmenize olanak tanır.</Turkish>
</Key>
<Key ID="STR_ACE_MapTools_PlottingBoard_Name">
<English>Plotting Board</English>
</Key>
<Key ID="STR_ACE_MapTools_PlottingBoard_Description">
<English>The Plotting Board is a map tool designed for use in the directing of short range indirect fires.</English>
</Key>
<Key ID="STR_ACE_MapTools_MapTools_Menu">
<English>Map Tools</English>
<Spanish>Herramientas de mapa</Spanish>
@ -252,5 +258,89 @@
<Turkish>Düz çizgiler çizmek için maptools'un kenarına çizin. Not: Silmek için orta noktada fareyle üzerine gelmeniz gerekir.</Turkish>
<Spanish>Dibujar sobre el borde de las herramientas de mapa para dibujar líneas rectas. Nota: Debe situarse en el punto intermedio para eliminarla.</Spanish>
</Key>
<Key ID="STR_ACE_MapTools_allowChannelDrawing_displayName">
<English>Allow Plotting Board Drawing channels</English>
</Key>
<Key ID="STR_ACE_MapTools_allowChannelDrawing_description">
<English>Channels in which plotting board drawing is enabled.</English>
</Key>
<Key ID="STR_ACE_MapTools_allowDirectCommsOnly">
<English>Allow Direct Comms Only (Polylines Only)</English>
</Key>
<Key ID="STR_ACE_MapTools_allowDirectGroupComms">
<English>Allow Direct/Group Comms (Polylines and Group Markers)</English>
</Key>
<Key ID="STR_ACE_MapTools_PlottingBoardLabel">
<English>Plotting Board</English>
</Key>
<Key ID="STR_ACE_MapTools_PlottingBoardAcrylicLabel">
<English>Plotting Board Acrylic</English>
</Key>
<Key ID="STR_ACE_MapTools_PlottingBoardRulerLabel">
<English>Plotting Board Ruler</English>
</Key>
<Key ID="STR_ACE_MapTools_ToPlottingBoardLabel">
<English>To Plotting Board</English>
</Key>
<Key ID="STR_ACE_MapTools_ToPlottingBoardAcrylicLabel">
<English>To Plotting Board Acrylic</English>
</Key>
<Key ID="STR_ACE_MapTools_ToPlottingBoardRulerLabel">
<English>To Plotting Board Ruler</English>
</Key>
<Key ID="STR_ACE_MapTools_WipeBoard">
<English>Wipe all markers off Plotting Board</English>
</Key>
<Key ID="STR_ACE_MapTools_ShowPlottingBoard">
<English>Show Plotting Board</English>
</Key>
<Key ID="STR_ACE_MapTools_HidePlottingBoard">
<English>Hide Plotting Board</English>
</Key>
<Key ID="STR_ACE_MapTools_TogglePlottingBoardRuler">
<English>Toggle Plotting Board Ruler</English>
</Key>
<Key ID="STR_ACE_MapTools_AlignTo">
<English>Align</English>
<German>Ausrichten</German>
<Spanish>Alinear</Spanish>
<French>Aligner</French>
<Italian>Allinea</Italian>
<Portuguese>Alinhar</Portuguese>
<Hungarian>Állítása</Hungarian>
<Polish>Wyrównaj</Polish>
<Czech>Srovnat</Czech>
<Russian>Выровнять</Russian>
</Key>
<Key ID="STR_ACE_MapTools_ToNorthLabel">
<English>To North</English>
<German>Nach Norden</German>
<Spanish>Al norte</Spanish>
<French>Sur le nord</French>
<Italian>Con il Nord</Italian>
<Portuguese>Com o Norte</Portuguese>
<Hungarian>Északhoz</Hungarian>
<Polish>Do północy</Polish>
<Czech>Na sever</Czech>
<Russian>На север</Russian>
</Key>
<Key ID="STR_ACE_MapTools_ToCompassLabel">
<English>To Compass</English>
<German>Am Kompass</German>
<Spanish>A la brújula</Spanish>
<French>Sur la boussole</French>
<Italian>Con la bussola</Italian>
<Portuguese>Com a Bússola</Portuguese>
<Hungarian>Iránytűhöz</Hungarian>
<Polish>Do kompasu</Polish>
<Czech>Ke kompasu</Czech>
<Russian>По компасу</Russian>
</Key>
<Key ID="STR_ACE_MapTools_ToUpLabel">
<English>Up</English>
</Key>
<Key ID="STR_ACE_MapTools_ToMapToolLabel">
<English>To Maptool</English>
</Key>
</Package>
</Project>

View File

@ -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
];
};

View File

@ -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));

View File

@ -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;

View File

@ -239,6 +239,105 @@
<Korean>시계 필요함</Korean>
<Portuguese>Relógio necessário</Portuguese>
</Key>
<Key ID="STR_ACE_Markers_TimestampTimezone">
<English>Time Zone</English>
<Russian>Часовой пояс</Russian>
<French>Fuseau horaire</French>
<Japanese>時間帯</Japanese>
<Spanish>Zona horaria</Spanish>
<Polish>Strefa czasowa</Polish>
<German>Zeitzone</German>
<Chinesesimp>时区</Chinesesimp>
<Korean>시간대</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampTimezoneDescription">
<English>Changes the time zone for the timestamp</English>
<Russian>Измените часовой пояс для метки времени</Russian>
<French>Modifiez le fuseau horaire pour l'horodatage</French>
<Japanese>タイムスタンプの時間帯を変更します</Japanese>
<Spanish>Cambie la zona horaria para la marca de tiempo</Spanish>
<Polish>Zmień strefę czasową dla znaczników czasu</Polish>
<German>Ändern Sie die Zeitzone für den Zeitstempel</German>
<Chinesesimp>更改时间戳的时区</Chinesesimp>
<Korean>타임스탬프의 시간대를 변경하십시오</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampTimezoneIngameTime">
<English>In-game Time</English>
<Russian>Время в игре</Russian>
<French>Heure de jeu</French>
<Japanese>ゲーム内時刻</Japanese>
<Spanish>Hora del juego</Spanish>
<Polish>Czas gry</Polish>
<German>Ingame-Zeit</German>
<Chinesesimp>游戏内时间</Chinesesimp>
<Korean>게임 시간</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampTimezoneSystemTime">
<English>System Time</English>
<Russian>Системное время</Russian>
<French>Heure système</French>
<Japanese>システム時刻</Japanese>
<Spanish>Hora del sistema</Spanish>
<Polish>Czas systemowy</Polish>
<German>Systemzeit</German>
<Chinesesimp>系统时间</Chinesesimp>
<Korean>시스템 시간</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampTimezoneUTCTime">
<English>UTC Time</English>
<Russian>Время UTC</Russian>
<French>Heure UTC</French>
<Japanese>UTC時刻</Japanese>
<Spanish>Hora UTC</Spanish>
<Polish>Czas UTC</Polish>
<German>UTC-Zeit</German>
<Chinesesimp>UTC时间</Chinesesimp>
<Korean>UTC 시간</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampUTCOffset">
<English>UTC Offset</English>
<Russian>Смещение UTC</Russian>
<French>Décalage UTC</French>
<Japanese>UTCオフセット</Japanese>
<Spanish>Desplazamiento UTC</Spanish>
<Polish>Przesunięcie UTC</Polish>
<German>UTC-Verschiebung</German>
<Chinesesimp>UTC偏移量</Chinesesimp>
<Korean>UTC 오프셋</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampUTCOffsetDescription">
<English>Changes the time offset for the UTC timestamp</English>
<Russian>Измените смещение времени для метки времени UTC</Russian>
<French>Modifier le décalage horaire pour l'horodatage UTC</French>
<Japanese>UTCタイムスタンプの時差を変更する</Japanese>
<Spanish>Cambiar el desplazamiento horario para la marca de tiempo UTC</Spanish>
<Polish>Zmień przesunięcie czasu dla sygnatury czasowej UTC</Polish>
<German>Ändere die Zeitverschiebung für den UTC-Zeitstempel</German>
<Chinesesimp>更改UTC时间戳的时间偏移量</Chinesesimp>
<Korean>UTC 타임 스탬프의 시간 오프셋을 변경하십시오</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampUTCMinutesOffset">
<English>UTC Minutes Offset</English>
<Russian>UTC Минутное Смещение</Russian>
<French>Décalage des minutes UTC</French>
<Japanese>UTC分オフセット</Japanese>
<Spanish>Desplazamiento de minutos UTC</Spanish>
<Polish>Przesunięcie minut UTC</Polish>
<German>UTC-Minutenversatz</German>
<Chinesesimp>UTC分钟偏移量</Chinesesimp>
<Korean>UTC 분 오프셋</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampUTCMinutesOffsetDescription">
<English>Change the minute offset for the UTC timestamp</English>
<Russian>Изменить минутное смещение для времени UTC</Russian>
<French>Modifier le décalage des minutes pour l'horodatage UTC</French>
<Japanese>UTCタイムスタンプの分差を変更する</Japanese>
<Spanish>Cambiar el desplazamiento de minutos para la marca de tiempo UTC</Spanish>
<Polish>Zmień przesunięcie minut dla sygnatury czasowej UTC</Polish>
<German>Ändere den Minutenversatz für den UTC-Zeitstempel</German>
<Chinesesimp>更改UTC时间戳的分钟偏移量</Chinesesimp>
<Korean>UTC 타임 스탬프의 분 오프셋을 변경하십시오</Korean>
</Key>
<Key ID="STR_ACE_Markers_TimestampFormat">
<English>Timestamp Format</English>
<Russian>Формат времени</Russian>
@ -305,17 +404,16 @@
<Portuguese>SS - Segundos</Portuguese>
</Key>
<Key ID="STR_ACE_Markers_TimestampFormatDescription4">
<English>"MM" - Milliseconds</English>
<Russian>"МС" - Миллисекунда</Russian>
<French>"MM" - Millisecondes</French>
<Japanese>"MM" - ミリ秒</Japanese>
<Spanish>"MM" - Milisegundos</Spanish>
<Polish>"MM" - Milisekundy</Polish>
<German>"MS" - Milisekunden</German>
<Italian>"MS" - Millisecondi</Italian>
<Chinesesimp>"MS"—毫秒</Chinesesimp>
<Korean>"MS" - 밀리초</Korean>
<Portuguese>MM - Milisegundos</Portuguese>
<English>"MM" - Milliseconds (from 0 to 59)</English>
<French>"MM" - Millisecondes (de 0 à 59)</French>
<German>"MS" - Milisekunden (von 0 bis 59)</German>
<Portuguese>"MS" - Milissegundos (de 0 a 59)</Portuguese>
</Key>
<Key ID="STR_ACE_Markers_TimestampFormatDescription5">
<English>"mmm" - Milliseconds (from 0 to 999)</English>
<French>"mmm" - Millisecondes (de 0 à 999)</French>
<German>"mmm" - Milisekunden (von 0 bis 999)</German>
<Portuguese>"mmm" - Milissegundos (de 0 a 999)</Portuguese>
</Key>
<Key ID="STR_ACE_Markers_TimestampHourFormat">
<English>Timestamp Hour Format</English>

View File

@ -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

View File

@ -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);
};

View File

@ -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];

View File

@ -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

View File

@ -2,4 +2,4 @@
#include "XEH_PREP.hpp"
call FUNC(scanMedicalItems)
call FUNC(scanMedicalItems);

View File

@ -4557,6 +4557,7 @@
<Czech>Umístit tělo do černého pytle na mrtvoly</Czech>
<Turkish>Vücudu siyah ceset torbasına yerleştir</Turkish>
<Japanese>遺体袋 (黒) に入れる</Japanese>
<Korean>시체를 검은 시체가방에 놓기</Korean>
</Key>
<Key ID="STR_ACE_Medical_Treatment_PlaceInBodyBagBlue">
<English>Place body in blue bodybag</English>
@ -4568,6 +4569,7 @@
<Czech>Umístit tělo do modrého pytle na mrtvoly</Czech>
<Turkish>Vücudu mavi ceset torbasına yerleştir</Turkish>
<Japanese>遺体袋 (青) に入れる</Japanese>
<Korean>시체를 파란 시체가방에 놓기</Korean>
</Key>
<Key ID="STR_ACE_Medical_Treatment_PlaceInBodyBagWhite">
<English>Place body in white bodybag</English>
@ -4579,6 +4581,7 @@
<Czech>Umístit tělo do bílého pytle na mrtvoly</Czech>
<Turkish>Vücudu beyaz ceset torbasına yerleştir</Turkish>
<Japanese>遺体袋 (白) に入れる</Japanese>
<Korean>시체를 흰 시체가방에 놓기</Korean>
</Key>
<Key ID="STR_ACE_Medical_Treatment_PlacingInBodyBag">
<English>Placing body in bodybag...</English>
@ -4921,12 +4924,14 @@
<Italian>Coeff. di tempo per trattamenti Zeus</Italian>
<German>Zeit-Koeffizient für Zeus Behandlungen</German>
<Japanese>Zeus治療時間係数</Japanese>
<Korean>제우스 치료 시간 계수</Korean>
</Key>
<Key ID="STR_ACE_Medical_Treatment_TreatmentTimeCoeffZeus_Description">
<English>Multiply all treatment times with this coefficient when in Zeus.</English>
<Italian>Moltiplica il tempo di ogni trattamento per questo coefficiente quando si è Zeus.</Italian>
<German>Dauer von Behandlungen als Zeus wird mit diesem Koeffizienten multipliziert.</German>
<Japanese>Zeus操作中は、すべての治療時間にこの係数を掛けます。</Japanese>
<Korean>제우스일 때 모든 치료 시간에 이 계수를 곱합니다.</Korean>
</Key>
</Package>
</Project>

View File

@ -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));
};
};

View File

@ -3,4 +3,3 @@ PREP(canClimb);
PREP(climb);
PREP(handleClimb);
PREP(handleVirtualMass);
PREP(inventoryDisplayLoad);

View File

@ -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}, {}};
};
};

View File

@ -25,6 +25,8 @@ PREP(overheat);
PREP(sendSpareBarrelsTemperaturesHint);
PREP(setAmmoTemperature);
PREP(setWeaponTemperature);
PREP(statTextStatement_boltType);
PREP(statTextStatement_allowSwapBarrel);
PREP(swapBarrel);
PREP(swapBarrelAssistant);
PREP(swapBarrelCallback);

View File

@ -26,6 +26,8 @@ class CfgPatches {
#include "ACE_Settings.hpp"
#include "ACE_Arsenal_Stats.hpp"
class CfgMovesBasic {
class ManActions {
GVAR(GestureMountMuzzle) = QGVAR(GestureMountMuzzle);

View File

@ -0,0 +1,21 @@
#include "..\script_component.hpp"
/*
* Author: drofseh
* Barrel Type statement.
*
* Arguments:
* 0: Not used
* 1: Item config path <CONFIG>
*
* Return Value:
* Stat Text <STRING>
*
* Public: No
*/
params ["", "_config"];
TRACE_1("statTextStatement_allowSwapBarrel",_config);
if ((getNumber (_config >> QGVAR(allowSwapBarrel))) == 1) exitWith {LLSTRING(statBarrelType_removeable)};
LLSTRING(statBarrelType_nonRemoveable)

View File

@ -0,0 +1,21 @@
#include "..\script_component.hpp"
/*
* Author: drofseh
* Bolt Type statement.
*
* Arguments:
* 0: Not used
* 1: Item config path <CONFIG>
*
* Return Value:
* Stat Text <STRING>
*
* Public: No
*/
params ["", "_config"];
TRACE_1("statTextStatement_boltType",_config);
if ((getNumber (_config >> QGVAR(closedBolt))) == 1) exitWith {LLSTRING(statBoltType_closedBolt)};
LLSTRING(statBoltType_openBolt)

View File

@ -875,5 +875,23 @@
<Chinesesimp>备用枪管温度非常热</Chinesesimp>
<Chinese>備用槍管溫度超級熱</Chinese>
</Key>
<Key ID="STR_ACE_Overheating_statBoltType">
<English>Bolt Type</English>
</Key>
<Key ID="STR_ACE_Overheating_statBoltType_openBolt">
<English>Open Bolt</English>
</Key>
<Key ID="STR_ACE_Overheating_statBoltType_closedBolt">
<English>Closed Bolt</English>
</Key>
<Key ID="STR_ACE_Overheating_statBarrelType">
<English>Barrel Type</English>
</Key>
<Key ID="STR_ACE_Overheating_statBarrelType_nonRemoveable">
<English>Non-Removeable</English>
</Key>
<Key ID="STR_ACE_Overheating_statBarrelType_removeable">
<English>Quick Change</English>
</Key>
</Package>
</Project>

Some files were not shown because too many files have changed in this diff Show More