Merge remote-tracking branch 'upstream/master' into corpse-carry-continued2

This commit is contained in:
LinkIsGrim 2024-01-08 03:47:11 -03:00
commit 68f9ea2d2f
37 changed files with 1423 additions and 192 deletions

View File

@ -41,7 +41,11 @@ if (_initSpeedCoef > 0) then {
}; };
private _abAdjustText = ""; 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 _configAmmo = (configFile >> "CfgAmmo" >> (getText (_configMagazine >> "ammo")));
private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength"); private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength");
private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities"); private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities");

View File

@ -37,7 +37,10 @@ if (_magazine isEqualTo "") then {
}; };
private _abAdjustText = ""; 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 _configAmmo = (configFile >> "CfgAmmo" >> (getText (_configMagazine >> "ammo")));
private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength"); private _barrelLength = getNumber (_configWeapon >> "ACE_barrelLength");
private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities"); private _muzzleVelocityTable = getArray (_configAmmo >> "ACE_muzzleVelocities");

View File

@ -1,7 +1,8 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
#include "\a3\ui_f_curator\ui\defineResinclDesign.inc" #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. * Disables key input. ESC can still be pressed to open the menu.
* *
* Arguments: * Arguments:
@ -27,7 +28,7 @@ if (_state) then {
if (!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])) exitWith {}; if (!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])) exitWith {};
if (!isNil QGVAR(disableInputPFH)) exitWith {}; if (!isNil QGVAR(disableInputPFH)) exitWith {};
// end TFAR and ACRE2 radio transmissions // End TFAR and ACRE2 radio transmissions
call FUNC(endRadioTransmission); call FUNC(endRadioTransmission);
// Close map // Close map
@ -45,38 +46,120 @@ if (_state) then {
private _map = _display displayCtrl 101; private _map = _display displayCtrl 101;
_map ctrlMapCursor ["", QGVAR(blank)]; _map ctrlMapCursor ["", QGVAR(blank)];
GVAR(keyboardInputMain) = createHashMap;
GVAR(keyboardInputCombo) = createHashMap;
_display displayAddEventHandler ["KeyDown", { _display displayAddEventHandler ["KeyDown", {
// If input is enabled again, ignore
if (isNil QGVAR(keyboardInputMain)) exitWith {};
params ["", "_key"]; params ["", "_key"];
if (_key == 1 && {alive player}) then { // Get key info; Stored as [isPressed, pressedCount]
createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select isMultiplayer); 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; disableSerialization;
private _isMultiplayer = isMultiplayer;
private _is3DENPreview = is3DENPreview;
createDialog (["RscDisplayInterrupt", "RscDisplayMPInterrupt"] select _isMultiplayer);
private _dlg = findDisplay 49; private _dlg = findDisplay 49;
for "_index" from 100 to 2000 do { for "_index" from 100 to 2000 do {
(_dlg displayCtrl _index) ctrlEnable false; (_dlg displayCtrl _index) ctrlEnable false;
}; };
private _ctrl = _dlg displayctrl 103; private _ctrl = _dlg displayCtrl 103;
_ctrl ctrlSetEventHandler ["buttonClick", QUOTE(while {!isNull (uiNamespace getVariable [ARR_2(QUOTE(QGVAR(dlgDisableMouse)),displayNull)])} do {closeDialog 0}; failMission 'LOSER'; [false] call DFUNC(disableUserInput))]; _ctrl ctrlSetEventHandler ["ButtonClick", toString {
while {!isNull (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull])} do {
closeDialog 0
};
failMission "LOSER";
[false] call FUNC(disableUserInput);
}];
_ctrl ctrlEnable true; _ctrl ctrlEnable true;
_ctrl ctrlSetText "ABORT"; _ctrl ctrlSetText localize (["str_disp_int_abort", "STR_3DEN_RscDisplayInterrupt_ButtonAbort_3DEN_text"] select (_is3DENPreview && !_isMultiplayer));
_ctrl ctrlSetTooltip "Abort."; _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 { 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 { } else {
_ctrl ctrlSetEventHandler ["buttonClick", QUOTE(closeDialog 0; player setDamage 1; [false] call DFUNC(disableUserInput))]; player setDamage 1;
};
_ctrl ctrlEnable ((getMissionConfigValue ["respawnButton", -1]) != 0); // handles 3den attribute or description.ext
_ctrl ctrlSetText localize "$str_3den_multiplayer_attributecategory_respawn_displayname";
_ctrl ctrlSetTooltip "Respawn.";
}; };
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; (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
private _acc = accTime; private _acc = accTime;
@ -84,18 +167,20 @@ if (_state) then {
setAccTime _acc; 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; (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
openCuratorInterface; 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; (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
openMap true; openMap true;
}; };
if (isServer || {serverCommandAvailable "#kick"}) then { if (isMultiplayer && {isServer || {serverCommandAvailable "#kick"}}) then {
if (!(_key in (actionKeys "DefaultAction" + actionKeys "Throw")) && {_key in (actionKeys "Chat" + actionKeys "PrevChannel" + actionKeys "NextChannel")}) then { if (!(_defaultAction || _throw) && {_chat || _prevChannel || _nextChannel}) then {
_key = 0; _key = 0;
}; };
}; };
@ -103,7 +188,41 @@ if (_state) then {
_key > 0 _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) = [{ GVAR(disableInputPFH) = [{
@ -133,4 +252,7 @@ if (_state) then {
}; };
(uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0; (uiNamespace getVariable [QGVAR(dlgDisableMouse), displayNull]) closeDisplay 0;
GVAR(keyboardInputMain) = nil;
GVAR(keyboardInputCombo) = nil;
}; };

View File

@ -15,6 +15,8 @@
* Public: No * Public: No
*/ */
#define TEMPERATURE_SLOT_INDEX 5
private _playerDir = getDir ACE_player; private _playerDir = getDir ACE_player;
private _playerAltitude = (getPosASL ACE_player) select 2; private _playerAltitude = (getPosASL ACE_player) select 2;
private _temperature = _playerAltitude call EFUNC(weather,calculateTemperatureAtHeight); private _temperature = _playerAltitude call EFUNC(weather,calculateTemperatureAtHeight);
@ -41,9 +43,10 @@ if (isNil QGVAR(MIN) || isNil QGVAR(MAX)) then {
[0, _playerDir] call FUNC(updateMemory); [0, _playerDir] call FUNC(updateMemory);
if (GVAR(MinAvgMaxMode) == 1) then { if (GVAR(MinAvgMaxMode) == 1) then {
private _useAB = missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false];
{ {
GVAR(ENTRIES) set [_x, (GVAR(ENTRIES) select _x) + 1]; GVAR(ENTRIES) set [_x, (GVAR(ENTRIES) select _x) + 1];
} count [2, 3, 4]; } forEach [2, 3, 4];
// Wind SPD // Wind SPD
private _windSpeed = call FUNC(measureWindSpeed); private _windSpeed = call FUNC(measureWindSpeed);
@ -51,7 +54,7 @@ if (GVAR(MinAvgMaxMode) == 1) then {
// CROSSWIND // CROSSWIND
private _crosswind = 0; private _crosswind = 0;
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { if (_useAB) then {
_crosswind = abs(sin(GVAR(RefHeading) - _playerDir) * _windSpeed); _crosswind = abs(sin(GVAR(RefHeading) - _playerDir) * _windSpeed);
} else { } else {
_crosswind = abs(sin(GVAR(RefHeading)) * _windSpeed); _crosswind = abs(sin(GVAR(RefHeading)) * _windSpeed);
@ -60,7 +63,7 @@ if (GVAR(MinAvgMaxMode) == 1) then {
// HEADWIND // HEADWIND
private _headwind = 0; private _headwind = 0;
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { if (_useAB) then {
_headwind = cos(GVAR(RefHeading) - _playerDir) * _windSpeed; _headwind = cos(GVAR(RefHeading) - _playerDir) * _windSpeed;
} else { } else {
_headwind = cos(GVAR(RefHeading)) * _windSpeed; _headwind = cos(GVAR(RefHeading)) * _windSpeed;
@ -74,4 +77,18 @@ if (GVAR(MinAvgMaxMode) == 1) then {
GVAR(TOTAL) set [4, (GVAR(TOTAL) select 4) + _headwind]; 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

@ -99,7 +99,11 @@
#define TYPE_SCUBA 604 // not implemented #define TYPE_SCUBA 604 // not implemented
#define TYPE_HEADGEAR 605 #define TYPE_HEADGEAR 605
#define TYPE_FACTOR 607 #define TYPE_FACTOR 607
#define TYPE_MAP 608
#define TYPE_COMPASS 609
#define TYPE_WATCH 610
#define TYPE_RADIO 611 #define TYPE_RADIO 611
#define TYPE_GPS 612
#define TYPE_HMD 616 #define TYPE_HMD 616
#define TYPE_BINOCULAR 617 #define TYPE_BINOCULAR 617
#define TYPE_MEDIKIT 619 #define TYPE_MEDIKIT 619

View File

@ -1,62 +1,204 @@
#define EXCEPTIONS exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}
class CfgVehicles { class CfgVehicles {
class Man; class Man;
class CAManBase: Man { class CAManBase: Man {
class ACE_SelfActions { class ACE_SelfActions {
class ACE_MapGpsShow { class ACE_MapGpsShow {
displayName = CSTRING(MapGpsShow); displayName = CSTRING(MapGpsShow);
condition = QUOTE((!GVAR(mapGpsShow)) && {call FUNC(canUseMapGPS)}); condition = QUOTE(!GVAR(mapGpsShow) && {call FUNC(canUseMapGPS)});
statement = QUOTE(GVAR(mapGpsShow) = true;); statement = QUOTE(GVAR(mapGpsShow) = true);
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; EXCEPTIONS;
showDisabled = 0; showDisabled = 0;
}; };
class ACE_MapGpsHide { class ACE_MapGpsHide {
displayName = CSTRING(MapGpsHide); displayName = CSTRING(MapGpsHide);
condition = QUOTE((GVAR(mapGpsShow)) && {call FUNC(canUseMapGPS)}); condition = QUOTE(GVAR(mapGpsShow) && {call FUNC(canUseMapGPS)});
statement = QUOTE(GVAR(mapGpsShow) = false;); statement = QUOTE(GVAR(mapGpsShow) = false);
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; EXCEPTIONS;
showDisabled = 0; showDisabled = 0;
}; };
class ACE_MapTools { class ACE_MapTools {
displayName = CSTRING(MapTools_Menu); displayName = CSTRING(MapTools_Menu);
condition = QUOTE(call FUNC(canUseMapTools)); condition = QUOTE(call FUNC(canUseMapTools));
statement = ""; statement = "";
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; EXCEPTIONS;
showDisabled = 0; showDisabled = 0;
class ACE_MapToolsHide { class ACE_MapToolsHide {
displayName = CSTRING(MapToolsHide); displayName = CSTRING(MapToolsHide);
condition = QUOTE(GVAR(mapTool_Shown) != 0); condition = QUOTE(GVAR(mapTool_Shown) != 0);
statement = QUOTE(GVAR(mapTool_Shown) = 0;); statement = QUOTE(GVAR(mapTool_Shown) = 0);
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; EXCEPTIONS;
showDisabled = 1; showDisabled = 1;
}; };
class ACE_MapToolsShowNormal { class ACE_MapToolsShowNormal {
displayName = CSTRING(MapToolsShowNormal); displayName = CSTRING(MapToolsShowNormal);
condition = QUOTE(GVAR(mapTool_Shown) != 1); condition = QUOTE(GVAR(mapTool_Shown) != 1);
statement = QUOTE(if (GVAR(mapTool_Shown) == 0) then {GVAR(mapTool_moveToMouse) = true}; 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"}; EXCEPTIONS;
showDisabled = 1; showDisabled = 1;
}; };
class ACE_MapToolsShowSmall { class ACE_MapToolsShowSmall {
displayName = CSTRING(MapToolsShowSmall); displayName = CSTRING(MapToolsShowSmall);
condition = QUOTE(GVAR(mapTool_Shown) != 2); condition = QUOTE(GVAR(mapTool_Shown) != 2);
statement = QUOTE(if (GVAR(mapTool_Shown) == 0) then {GVAR(mapTool_moveToMouse) = true}; 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"}; EXCEPTIONS;
showDisabled = 1; showDisabled = 1;
}; };
class ACE_MapToolsAlignNorth { class ACE_MapToolsAlign {
displayName = CSTRING(MapToolsAlignNorth); displayName = CSTRING(AlignTo);
condition = QUOTE(GVAR(mapTool_Shown) != 0); condition = QUOTE(GVAR(mapTool_Shown) != 0);
statement = QUOTE(GVAR(mapTool_angle) = 0;); statement = "";
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; 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; showDisabled = 1;
}; };
class ACE_MapToolsAlignCompass { class ACE_MapToolsAlignCompass {
displayName = CSTRING(MapToolsAlignCompass); displayName = CSTRING(ToCompassLabel);
condition = QUOTE(GVAR(mapTool_Shown) != 0 && {getUnitLoadout ACE_player param [ARR_2(9,[])] param [ARR_2(3,'')] != ''}); condition = QUOTE(GVAR(mapTool_Shown) != 0 && {ACE_player getSlotItemName TYPE_COMPASS != ''});
statement = QUOTE(GVAR(mapTool_angle) = getDir ACE_player;); statement = QUOTE(GVAR(mapTool_angle) = getDir ACE_player);
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"}; EXCEPTIONS;
showDisabled = 1; 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 Box_NATO_Support_F: NATO_Box_Base {
class TransportItems { class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12); MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
}; };
}; };
class Box_East_Support_F: EAST_Box_Base { class Box_East_Support_F: EAST_Box_Base {
class TransportItems { class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12); MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
}; };
}; };
class Box_IND_Support_F: IND_Box_Base { class Box_IND_Support_F: IND_Box_Base {
class TransportItems { class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12); MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
}; };
}; };
class Box_FIA_Support_F: FIA_Box_Base_F { class Box_FIA_Support_F: FIA_Box_Base_F {
class TransportItems { class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12); MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
}; };
}; };
class ACE_Box_Misc: Box_NATO_Support_F { class ACE_Box_Misc: Box_NATO_Support_F {
class TransportItems { class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12); MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
}; };
}; };
}; };

View File

@ -14,4 +14,17 @@ class CfgWeapons {
mass = 0.2; 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 - Roamer
- Map drawing - Map drawing
- Showing GPS on map - Showing GPS on map
- Plotting Board

Binary file not shown.

View File

@ -7,3 +7,8 @@ PREP(handleMouseMove);
PREP(isInsideMapTool); PREP(isInsideMapTool);
PREP(openMapGpsUpdate); PREP(openMapGpsUpdate);
PREP(updateMapToolMarkers); 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" #include "script_component.hpp"
@ -15,6 +15,16 @@ GVAR(mapTool_isDragging) = false;
GVAR(mapTool_isRotating) = false; GVAR(mapTool_isRotating) = false;
GVAR(mapTool_moveToMouse) = true; // used to display it in center of screen when opened 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 //Install the event handers for the map tools on the main in-game map
[{!isNull findDisplay 12}, [{!isNull findDisplay 12},
{ {
@ -32,7 +42,13 @@ GVAR(mapTool_moveToMouse) = true; // used to display it in center of screen whe
}; };
}] call CBA_fnc_addPlayerEventHandler; }] 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(freeDrawingData) = [];
GVAR(freedrawing) = false; 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" #include "..\script_component.hpp"
/* /*
* Author: esteldunedain * Author: esteldunedain, LorenLuke
* Handle mouse buttons. * Handle mouse buttons.
* *
* Arguments: * 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> * 1: Parameters of the mouse button event <ARRAY>
* *
* Return Value: * Return Value:
* true if event was handled <BOOL> * True if event was handled <BOOL>
* *
* Example: * Example:
* [0, [array]] call ACE_maptools_fnc_handleMouseButton * [0, []] call ace_maptools_fnc_handleMouseButton
* *
* Public: No * Public: No
*/ */
@ -24,20 +24,27 @@ TRACE_2("params",_dir,_params);
if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith { if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith {
if (GVAR(freedrawing) && {_dir == 0}) then { if (GVAR(freedrawing) && {_dir == 0}) then {
GVAR(freedrawing) = false; GVAR(freedrawing) = false;
if (_shiftKey) exitWith { if (_shiftKey) exitWith {
TRACE_1("using vanilla straight line",_shiftKey); TRACE_1("using vanilla straight line",_shiftKey);
}; };
TRACE_2("Ending Line",GVAR(freedrawing),GVAR(freeDrawingData)); TRACE_2("Ending Line",GVAR(freedrawing),GVAR(freeDrawingData));
[{ [{
if (allMapMarkers isEqualTo []) exitWith {}; if (GVAR(freeDrawingData) isEqualTo []) exitWith {TRACE_1("never touched roamer",GVAR(freeDrawingData))};
private _markerName = allMapMarkers select (count allMapMarkers - 1);
private _allMarkers = allMapMarkers;
if (_allMarkers isEqualTo []) exitWith {};
private _markerName = _allMarkers select -1;
private _markerPos = getMarkerPos _markerName; private _markerPos = getMarkerPos _markerName;
private _distanceCheck = _markerPos distance2d GVAR(drawPosStart); private _distanceCheck = _markerPos distance2D GVAR(drawPosStart);
TRACE_3("Line Drawn",_markerName,_markerPos,_distanceCheck); TRACE_3("Line Drawn",_markerName,_markerPos,_distanceCheck);
if (_distanceCheck > 1) exitWith {WARNING("Wrong Marker!");}; if (_distanceCheck > 1) exitWith {WARNING("Wrong Marker!")};
if ((count GVAR(freeDrawingData)) != 3) exitWith {TRACE_1("never touched roamer",GVAR(freeDrawingData));};
GVAR(freeDrawingData) params ["", "_startStraightPos", "_endStraightPos"]; GVAR(freeDrawingData) params ["", "_startStraightPos", "_endStraightPos"];
@ -54,17 +61,20 @@ if ((_button == 0) && {GVAR(freedrawing) || _ctrlKey}) exitWith {
TRACE_2("Starting Line",GVAR(freedrawing),GVAR(drawPosStart)); TRACE_2("Starting Line",GVAR(freedrawing),GVAR(drawPosStart));
} else { } else {
GVAR(freedrawing) = false; 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; private _handled = false;
// If it's not a left button event, exit
if (_button != 0) exitWith {_handled};
// If releasing // If releasing
if (_dir != 1) then { if (_dir != 1) then {
if (GVAR(mapTool_isDragging) || GVAR(mapTool_isRotating)) then { if (GVAR(mapTool_isDragging) || GVAR(mapTool_isRotating)) then {
@ -72,45 +82,99 @@ if (_dir != 1) then {
GVAR(mapTool_isRotating) = false; GVAR(mapTool_isRotating) = false;
_handled = true; _handled = true;
}; };
if (GVAR(plottingBoard_isDragging) || GVAR(plottingBoard_isRotating) > -1) then {
GVAR(plottingBoard_isDragging) = false;
GVAR(plottingBoard_isRotating) = -1;
_handled = true;
};
} else { } else {
// If clicking // If clicking
if !(call FUNC(canUseMapTools)) exitWith {}; if (call FUNC(canUseMapTools)) then {
// Transform mouse screen position to coordinates
private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
_pos set [count _pos, 0];
GVAR(mapTool_isDragging) = false; GVAR(mapTool_isDragging) = false;
GVAR(mapTool_isRotating) = false; GVAR(mapTool_isRotating) = false;
// If no map tool marker then exit // 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 // Check if clicking the maptool
if (_pos call FUNC(isInsideMapTool)) exitWith { if (_pos call FUNC(isInsideMapTool)) then {
// Store data for dragging // Store data for dragging
GVAR(mapTool_startPos) = +GVAR(mapTool_pos); GVAR(mapTool_startPos) = +GVAR(mapTool_pos);
GVAR(mapTool_startDragPos) = + _pos; GVAR(mapTool_startDragPos) = _pos;
private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do { private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do {
case (1): {_altKey}; case 1: {_altKey};
case (2): {_ctrlKey}; case 2: {_ctrlKey};
case (3): {_shiftKey}; case 3: {_shiftKey};
default {false}; default {false};
}; };
if (_rotateKeyPressed) then { if (_rotateKeyPressed) then {
// Store data for rotating // Store data for rotating
GVAR(mapTool_startAngle) = + GVAR(mapTool_angle); 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);
private _pos = GVAR(mapTool_startDragPos) vectorDiff GVAR(mapTool_startPos);
GVAR(mapTool_startDragAngle) = ((_pos select 0) atan2 (_pos select 1) + 360) % 360;
// Start rotating // Start rotating
GVAR(mapTool_isRotating) = true; GVAR(mapTool_isRotating) = true;
} else { } else {
// Start dragging // Start dragging
GVAR(mapTool_isDragging) = true; GVAR(mapTool_isDragging) = true;
}; };
_handled = 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 _handled

View File

@ -1,47 +1,75 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: esteldunedain * Author: esteldunedain, LorenLuke
* Handle mouse movement over the map tool. * Handle mouse movement over the map tool and plotting board.
* *
* Arguments: * Arguments:
* 0: Map Control <CONTROL> * 0: Map control <CONTROL>
* 1: Mouse position on screen coordinates <ARRAY> * 1: Mouse position on screen coordinates <ARRAY>
* *
* Return Value: * Return Value:
* true if event was handled <BOOL> * If the event was handled <BOOL>
* *
* Example: * Example:
* [CONTROL, [0, 5, 1]] call ACE_maptools_fnc_handleMouseMove * [CONTROL, [0, 5]] call ace_maptools_fnc_handleMouseMove
* *
* Public: No * Public: No
*/ */
params ["_control", "_mousePosX", "_mousePosY"]; params ["_mapCtrl", "_mousePosX", "_mousePosY"];
TRACE_3("params",_control,_mousePosX,_mousePosY); TRACE_3("params",_mapCtrl,_mousePosX,_mousePosY);
// If have no map tools, then exit // 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 false
}; };
// If map tools not shown, then exit // 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 { 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) = GVAR(mapTool_startPos) vectorAdd _mousePosition vectorDiff GVAR(mapTool_startDragPos);
GVAR(mapTool_pos) set [1, (GVAR(mapTool_startPos) select 1) + (_mousePosition select 1) - (GVAR(mapTool_startDragPos) select 1)];
true true
}; };
// Rotation // Map tools - rotation
if (GVAR(mapTool_isRotating)) exitWith { if (GVAR(mapTool_isRotating)) exitWith {
// Get new angle // 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); private _pos = _mousePosition vectorDiff GVAR(mapTool_startPos);
GVAR(mapTool_angle) = GVAR(mapTool_startAngle) + _angle - GVAR(mapTool_startDragAngle); 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 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,33 +1,112 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: esteldunedain * Author: esteldunedain, LorenLuke
* Update the map tool markers, position, size, rotation and visibility. * Update the map tool and plotting board markers. Update their position, size, rotation and visibility.
* *
* Arguments: * Arguments:
* 0: The Map <CONTROL> * 0: Map control <CONTROL>
* *
* Return Value: * Return Value:
* None * None
* *
* Example: * Example:
* [CONTROL] call ACE_maptools_fnc_updateMapToolMarkers * [CONTROL] call ace_maptools_fnc_updateMapToolMarkers
* *
* Public: No * Public: No
*/ */
params ["_theMap"]; params ["_mapCtrl"];
if ((GVAR(mapTool_Shown) == 0) || {!("ACE_MapTools" in (ACE_player call EFUNC(common,uniqueItems)))}) exitWith {}; 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);
};
// open map tools in center of screen when toggled to be shown 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 { if (GVAR(mapTool_moveToMouse)) then {
private _mousePosition = _theMap ctrlMapScreenToWorld getMousePosition; GVAR(mapTool_pos) = _mapCtrl ctrlMapScreenToWorld getMousePosition;
GVAR(mapTool_pos) = _mousePosition;
GVAR(mapTool_moveToMouse) = false; // we only need to do this once after opening the map tool GVAR(mapTool_moveToMouse) = false; // we only need to do this once after opening the map tool
}; };
private _rotatingTexture = ""; private _rotatingTexture = "";
private _textureWidth = 0; private _textureWidth = 0;
if (GVAR(mapTool_Shown) == 1) then { if (GVAR(mapTool_Shown) == 1) then {
_rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa); _rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa);
_textureWidth = TEXTURE_WIDTH_IN_M; _textureWidth = TEXTURE_WIDTH_IN_M;
@ -36,21 +115,22 @@ if (GVAR(mapTool_Shown) == 1) then {
_textureWidth = TEXTURE_WIDTH_IN_M / 2; _textureWidth = TEXTURE_WIDTH_IN_M / 2;
}; };
if (GVAR(freedrawing)) then {[_theMap, _textureWidth] call FUNC(drawLinesOnRoamer);}; if (GVAR(freedrawing)) then {
[_mapCtrl, _textureWidth] call FUNC(drawLinesOnRoamer);
};
// Update scale of both parts // Update scale of both parts
getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"]; getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"];
private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale)); private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale));
private _scaleY = _scaleX; private _scaleY = _scaleX * ((_resWidth / _resHeight) / _aspectRatio); // handle bad aspect ratios
// Position of the fixed part // Position of the fixed part
private _xPos = GVAR(mapTool_pos) select 0; private _pos = GVAR(mapTool_pos) vectorAdd [0, _textureWidth * CENTER_OFFSET_Y_PERC];
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]; _mapCtrl drawIcon [QPATHTOF(data\mapToolFixed.paa), [1, 1, 1, 1], _pos, _scaleX, _scaleY, 0, "", 0];
// Position and rotation of the rotating part // Position and rotation of the rotating part
_xPos = (GVAR(mapTool_pos) select 0) + sin(GVAR(mapTool_angle)) * _textureWidth * CENTER_OFFSET_Y_PERC; _pos = GVAR(mapTool_pos) vectorAdd ([sin GVAR(mapTool_angle), cos GVAR(mapTool_angle)] vectorMultiply (_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]; _mapCtrl drawIcon [_rotatingTexture, [1, 1, 1, 1], _pos, _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, true,
0 0
] call CBA_fnc_addSetting; ] 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" #include "\z\ace\addons\main\script_macros.hpp"
#define DEGTOMILS 17.7777778
#define TEXTURE_WIDTH_IN_M 6205 #define TEXTURE_WIDTH_IN_M 6205
#define CENTER_OFFSET_Y_PERC 0.1606 #define CENTER_OFFSET_Y_PERC 0.1606
#define CONSTANT_SCALE 0.2 #define CONSTANT_SCALE 0.2
#define DIST_BOTTOM_TO_CENTER_PERC -0.33 #define DIST_BOTTOM_TO_CENTER_PERC -0.33
#define DIST_TOP_TO_CENTER_PERC 0.65 #define DIST_TOP_TO_CENTER_PERC 0.65
#define DIST_LEFT_TO_CENTER_PERC 0.30 #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> <Chinese>地圖工具能夠讓你在地圖上測量距離與角度</Chinese>
<Turkish>Harita Araçları, haritadaki mesafeleri ve açıları ölçmenize olanak tanır.</Turkish> <Turkish>Harita Araçları, haritadaki mesafeleri ve açıları ölçmenize olanak tanır.</Turkish>
</Key> </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"> <Key ID="STR_ACE_MapTools_MapTools_Menu">
<English>Map Tools</English> <English>Map Tools</English>
<Spanish>Herramientas de mapa</Spanish> <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> <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> <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>
<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> </Package>
</Project> </Project>

View File

@ -1,6 +1,6 @@
#include "..\script_component.hpp" #include "..\script_component.hpp"
/* /*
* Author: Freddo * Author: Freddo, Daniël H., johnb43
* When the confirm button is pressed. * When the confirm button is pressed.
* *
* Arguments: * Arguments:
@ -14,40 +14,100 @@
* *
* Public: No * Public: No
*/ */
params ["_buttonOk"]; params ["_buttonOk"];
private _display = ctrlParent _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; private _aceTimestamp = _display displayCtrl IDC_ACE_INSERT_MARKER_TIMESTAMP;
// handle timestamp // Handle timestamp
if (cbChecked _aceTimestamp && {ACE_player call FUNC(canTimestamp)}) then { 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 = ""; private _periodPostfix = "";
if (GVAR(timestampHourFormat) == 12) then { if (GVAR(timestampHourFormat) == 12) then {
if (floor _time == 0) exitWith { if (_hour == 0) exitWith {
_time = _time + 12; _hour = _hour + 12;
_periodPostfix = " am"; _periodPostfix = " am";
}; };
if (floor _time == 12) exitWith { if (_hour == 12) exitWith {
_periodPostfix = " pm"; _periodPostfix = " pm";
}; };
if (_time < 12) then { if (_hour < 12) then {
_periodPostfix = " am"; _periodPostfix = " am";
} else { } else {
_time = _time - 12; _hour = _hour - 12;
_periodPostfix = " pm"; _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 [ _description ctrlSetText format [
"%1 [%2%3]", "%1 [%2%3]",
ctrlText _description, ctrlText _description,
[_time, GVAR(timestampFormat)] call BIS_fnc_timeToString, _time,
_periodPostfix _periodPostfix
]; ];
}; };

View File

@ -32,6 +32,37 @@ private _categoryName = format ["ACE %1", localize ELSTRING(map,Module_DisplayNa
true true
] call CBA_fnc_addSetting; ] 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", QGVAR(timestampHourFormat), "LIST",
[LSTRING(TimestampHourFormat), LSTRING(TimestampHourFormatDescription)], [LSTRING(TimestampHourFormat), LSTRING(TimestampHourFormatDescription)],
@ -48,7 +79,8 @@ private _formatDescription = [
LLSTRING(TimestampFormatDescription1), LLSTRING(TimestampFormatDescription1),
LLSTRING(TimestampFormatDescription2), LLSTRING(TimestampFormatDescription2),
LLSTRING(TimestampFormatDescription3), LLSTRING(TimestampFormatDescription3),
LLSTRING(TimestampFormatDescription4) LLSTRING(TimestampFormatDescription4),
LLSTRING(TimestampFormatDescription5)
] joinString endl; ] joinString endl;
[ [
@ -56,8 +88,8 @@ private _formatDescription = [
[LSTRING(timestampFormat), _formatDescription], [LSTRING(timestampFormat), _formatDescription],
[_categoryName, LLSTRING(Module_DisplayName)], [_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:MM:SS.mmm"],
["HH", "HH:MM", "HH:MM:SS", "HH:MM:SS:MM"], ["HH", "HH:MM", "HH:MM:SS", "HH:MM:SS:MM", "HH:MM:SS.mmm"],
1 1
] ]
] call CBA_fnc_addSetting; ] call CBA_fnc_addSetting;

View File

@ -239,6 +239,105 @@
<Korean>시계 필요함</Korean> <Korean>시계 필요함</Korean>
<Portuguese>Relógio necessário</Portuguese> <Portuguese>Relógio necessário</Portuguese>
</Key> </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"> <Key ID="STR_ACE_Markers_TimestampFormat">
<English>Timestamp Format</English> <English>Timestamp Format</English>
<Russian>Формат времени</Russian> <Russian>Формат времени</Russian>
@ -305,17 +404,16 @@
<Portuguese>SS - Segundos</Portuguese> <Portuguese>SS - Segundos</Portuguese>
</Key> </Key>
<Key ID="STR_ACE_Markers_TimestampFormatDescription4"> <Key ID="STR_ACE_Markers_TimestampFormatDescription4">
<English>"MM" - Milliseconds</English> <English>"MM" - Milliseconds (from 0 to 59)</English>
<Russian>"МС" - Миллисекунда</Russian> <French>"MM" - Millisecondes (de 0 à 59)</French>
<French>"MM" - Millisecondes</French> <German>"MS" - Milisekunden (von 0 bis 59)</German>
<Japanese>"MM" - ミリ秒</Japanese> <Portuguese>"MS" - Milissegundos (de 0 a 59)</Portuguese>
<Spanish>"MM" - Milisegundos</Spanish> </Key>
<Polish>"MM" - Milisekundy</Polish> <Key ID="STR_ACE_Markers_TimestampFormatDescription5">
<German>"MS" - Milisekunden</German> <English>"mmm" - Milliseconds (from 0 to 999)</English>
<Italian>"MS" - Millisecondi</Italian> <French>"mmm" - Millisecondes (de 0 à 999)</French>
<Chinesesimp>"MS"—毫秒</Chinesesimp> <German>"mmm" - Milisekunden (von 0 bis 999)</German>
<Korean>"MS" - 밀리초</Korean> <Portuguese>"mmm" - Milissegundos (de 0 a 999)</Portuguese>
<Portuguese>MM - Milisegundos</Portuguese>
</Key> </Key>
<Key ID="STR_ACE_Markers_TimestampHourFormat"> <Key ID="STR_ACE_Markers_TimestampHourFormat">
<English>Timestamp Hour Format</English> <English>Timestamp Hour Format</English>

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(sendSpareBarrelsTemperaturesHint);
PREP(setAmmoTemperature); PREP(setAmmoTemperature);
PREP(setWeaponTemperature); PREP(setWeaponTemperature);
PREP(statTextStatement_boltType);
PREP(statTextStatement_allowSwapBarrel);
PREP(swapBarrel); PREP(swapBarrel);
PREP(swapBarrelAssistant); PREP(swapBarrelAssistant);
PREP(swapBarrelCallback); PREP(swapBarrelCallback);

View File

@ -26,6 +26,8 @@ class CfgPatches {
#include "ACE_Settings.hpp" #include "ACE_Settings.hpp"
#include "ACE_Arsenal_Stats.hpp"
class CfgMovesBasic { class CfgMovesBasic {
class ManActions { class ManActions {
GVAR(GestureMountMuzzle) = QGVAR(GestureMountMuzzle); 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> <Chinesesimp>备用枪管温度非常热</Chinesesimp>
<Chinese>備用槍管溫度超級熱</Chinese> <Chinese>備用槍管溫度超級熱</Chinese>
</Key> </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> </Package>
</Project> </Project>

View File

@ -49,7 +49,8 @@ private _bulletSpeed = 0;
private _gravity = [0, sin(_scopeBaseAngle) * -GRAVITY, cos(_scopeBaseAngle) * -GRAVITY]; private _gravity = [0, sin(_scopeBaseAngle) * -GRAVITY, cos(_scopeBaseAngle) * -GRAVITY];
private _deltaT = 1 / _simSteps; private _deltaT = 1 / _simSteps;
private _speedOfSound = 0; private _speedOfSound = 0;
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { private _isABenabled = missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false];
if (_isABenabled) then {
_speedOfSound = _temperature call EFUNC(weather,calculateSpeedOfSound); _speedOfSound = _temperature call EFUNC(weather,calculateSpeedOfSound);
}; };
@ -68,7 +69,7 @@ if (_useABConfig) then {
}; };
private _airFrictionCoef = 1; private _airFrictionCoef = 1;
if (!_useABConfig && (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false])) then { if (!_useABConfig && _isABenabled) then {
private _airDensity = [_temperature, _barometricPressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity); private _airDensity = [_temperature, _barometricPressure, _relativeHumidity] call EFUNC(weather,calculateAirDensity);
_airFrictionCoef = _airDensity / 1.22498; _airFrictionCoef = _airDensity / 1.22498;
}; };

View File

@ -107,12 +107,17 @@ private _transonicStabilityCoef = _ammoConfig select 4;
private _dragModel = _ammoConfig select 5; private _dragModel = _ammoConfig select 5;
private _atmosphereModel = _ammoConfig select 8; private _atmosphereModel = _ammoConfig select 8;
private _useABConfig = (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]); private _isABenabled = (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) && (_bc != 0);
if (_bc == 0) then { private _useBarrelLengthInfluence = (
_useABConfig = false; _isABenabled &&
}; {missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]}
);
private _useAmmoTemperatureInfluence = (
_isABenabled &&
{missionNamespace getVariable [QEGVAR(advanced_ballistics,ammoTemperatureEnabled), false]}
);
if (_barrelLength > 0 && _useABConfig) then { if (_barrelLength > 0 && _useBarrelLengthInfluence) then {
_muzzleVelocity = [_barrelLength, _ammoConfig select 10, _ammoConfig select 11, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift); _muzzleVelocity = [_barrelLength, _ammoConfig select 10, _ammoConfig select 11, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift);
} else { } else {
private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed"); private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed");
@ -128,7 +133,7 @@ if (_barrelLength > 0 && _useABConfig) then {
ctrlSetText [770000, format["%1'' - %2 gr (%3)", round((_ammoConfig select 1) * 39.3700787) / 1000, round((_ammoConfig select 3) * 15.4323584), _ammoClass]]; ctrlSetText [770000, format["%1'' - %2 gr (%3)", round((_ammoConfig select 1) * 39.3700787) / 1000, round((_ammoConfig select 3) * 15.4323584), _ammoClass]];
if (_barrelLength > 0) then { if (_barrelLength > 0) then {
if (_useABConfig && _barrelTwist > 0) then { if (_useBarrelLengthInfluence && _barrelTwist > 0) then {
ctrlSetText [770002, format["Barrel: %1'' 1:%2'' twist", round(2 * _barrelLength * 0.0393700787) / 2, round(_barrelTwist * 0.0393700787)]]; ctrlSetText [770002, format["Barrel: %1'' 1:%2'' twist", round(2 * _barrelLength * 0.0393700787) / 2, round(_barrelTwist * 0.0393700787)]];
} else { } else {
ctrlSetText [770002, format["Barrel: %1''", round(2 * _barrelLength * 0.0393700787) / 2]]; ctrlSetText [770002, format["Barrel: %1''", round(2 * _barrelLength * 0.0393700787) / 2]];
@ -136,7 +141,7 @@ if (_barrelLength > 0) then {
}; };
lnbAddRow [770100, ["4mps Wind(MRADs)", "1mps LEAD(MRADs)"]]; lnbAddRow [770100, ["4mps Wind(MRADs)", "1mps LEAD(MRADs)"]];
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { if (_isABenabled) then {
lnbAddRow [770100, ["Air/Ammo Temp", "Air/Ammo Temp"]]; lnbAddRow [770100, ["Air/Ammo Temp", "Air/Ammo Temp"]];
lnbAddRow [770200, ["-15°C", " -5°C", " 5°C", " 10°C", " 15°C", " 20°C", " 25°C", " 30°C", " 35°C"]]; lnbAddRow [770200, ["-15°C", " -5°C", " 5°C", " 10°C", " 15°C", " 20°C", " 25°C", " 30°C", " 35°C"]];
@ -145,7 +150,7 @@ if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) t
ctrlSetText [77003, format["%1m ZERO", round(_zeroRange)]]; ctrlSetText [77003, format["%1m ZERO", round(_zeroRange)]];
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { if (_isABenabled) then {
ctrlSetText [770001, format["Drop Tables for B.P.: %1mb; Corrected for MVV at Air/Ammo Temperatures -15-35 °C", round(EGVAR(scopes,zeroReferenceBarometricPressure) * 100) / 100]]; ctrlSetText [770001, format["Drop Tables for B.P.: %1mb; Corrected for MVV at Air/Ammo Temperatures -15-35 °C", round(EGVAR(scopes,zeroReferenceBarometricPressure) * 100) / 100]];
ctrlSetText [77004 , format["B.P.: %1mb", round(EGVAR(scopes,zeroReferenceBarometricPressure) * 100) / 100]]; ctrlSetText [77004 , format["B.P.: %1mb", round(EGVAR(scopes,zeroReferenceBarometricPressure) * 100) / 100]];
} else { } else {
@ -153,30 +158,30 @@ if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) t
ctrlSetText [77004 , ""]; ctrlSetText [77004 , ""];
}; };
private _cacheEntry = missionNamespace getVariable format[QGVAR(%1_%2_%3_%4_%5), _zeroRange, _boreHeight, _ammoClass, _weaponClass, missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]]; private _cacheEntry = missionNamespace getVariable format [QGVAR(%1_%2_%3_%4_%5_%6_%7), _zeroRange, _boreHeight, _ammoClass, _weaponClass, _isABenabled, _useBarrelLengthInfluence, _useAmmoTemperatureInfluence];
if (isNil {_cacheEntry}) then { if (isNil "_cacheEntry") then {
private _scopeBaseAngle = if (!_useABConfig) then { private _scopeBaseAngle = if (!_isABenabled) then {
private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZero:%1:%2:%3:%4", _zeroRange, _muzzleVelocity, _airFriction, _boreHeight]; private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZero:%1:%2:%3:%4", _zeroRange, _muzzleVelocity, _airFriction, _boreHeight];
(parseNumber _zeroAngle) (parseNumber _zeroAngle)
} else { } else {
private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZeroAB:%1:%2:%3:%4:%5:%6:%7:%8:%9", _zeroRange, _muzzleVelocity, _boreHeight, EGVAR(scopes,zeroReferenceTemperature), EGVAR(scopes,zeroReferenceBarometricPressure), EGVAR(scopes,zeroReferenceHumidity), _bc, _dragModel, _atmosphereModel]; private _zeroAngle = "ace_advanced_ballistics" callExtension format ["calcZeroAB:%1:%2:%3:%4:%5:%6:%7:%8:%9", _zeroRange, _muzzleVelocity, _boreHeight, EGVAR(scopes,zeroReferenceTemperature), EGVAR(scopes,zeroReferenceBarometricPressure), EGVAR(scopes,zeroReferenceHumidity), _bc, _dragModel, _atmosphereModel];
(parseNumber _zeroAngle) (parseNumber _zeroAngle)
}; };
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] && missionNamespace getVariable [QEGVAR(advanced_ballistics,ammoTemperatureEnabled), false]) then { if (_useAmmoTemperatureInfluence) then {
{ {
private _mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift); private _mvShift = [_ammoConfig select 9, _x] call EFUNC(advanced_ballistics,calculateAmmoTemperatureVelocityShift);
private _mv = _muzzleVelocity + _mvShift; private _mv = _muzzleVelocity + _mvShift;
[_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,_forEachIndex,_useABConfig] call FUNC(calculateRangeCard); [_scopeBaseAngle,_boreHeight,_airFriction,_mv,_x,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,_forEachIndex,_isABenabled] call FUNC(calculateRangeCard);
} forEach [-15, -5, 5, 10, 15, 20, 25, 30, 35]; } forEach [-15, -5, 5, 10, 15, 20, 25, 30, 35];
} else { } else {
[_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,3,_useABConfig] call FUNC(calculateRangeCard); [_scopeBaseAngle,_boreHeight,_airFriction,_muzzleVelocity,15,EGVAR(scopes,zeroReferenceBarometricPressure),EGVAR(scopes,zeroReferenceHumidity),200,4,1,GVAR(rangeCardEndRange),_bc,_dragModel,_atmosphereModel,_transonicStabilityCoef,3,_isABenabled] call FUNC(calculateRangeCard);
}; };
for "_i" from 0 to 9 do { for "_i" from 0 to 9 do {
GVAR(lastValidRow) pushBack count (GVAR(rangeCardDataElevation) select _i); GVAR(lastValidRow) pushBack count (GVAR(rangeCardDataElevation) select _i);
while {count (GVAR(rangeCardDataElevation) select _i) < 50} do { while {count (GVAR(rangeCardDataElevation) select _i) < 50} do {
if (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]) then { if (_isABenabled) then {
(GVAR(rangeCardDataElevation) select _i) pushBack "###"; (GVAR(rangeCardDataElevation) select _i) pushBack "###";
(GVAR(rangeCardDataWindage) select _i) pushBack "##"; (GVAR(rangeCardDataWindage) select _i) pushBack "##";
(GVAR(rangeCardDataLead) select _i) pushBack "##"; (GVAR(rangeCardDataLead) select _i) pushBack "##";
@ -188,7 +193,7 @@ if (isNil {_cacheEntry}) then {
}; };
}; };
missionNamespace setVariable [format[QGVAR(%1_%2_%3_%4_%5), _zeroRange, _boreHeight, _ammoClass, _weaponClass, missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]], [GVAR(rangeCardDataElevation), GVAR(rangeCardDataWindage), GVAR(rangeCardDataLead), GVAR(rangeCardDataMVs), GVAR(lastValidRow)]]; missionNamespace setVariable [format [QGVAR(%1_%2_%3_%4_%5_%6_%7), _zeroRange, _boreHeight, _ammoClass, _weaponClass, _isABenabled, _useBarrelLengthInfluence, _useAmmoTemperatureInfluence], [GVAR(rangeCardDataElevation), GVAR(rangeCardDataWindage), GVAR(rangeCardDataLead), GVAR(rangeCardDataMVs), GVAR(lastValidRow)]];
} else { } else {
GVAR(rangeCardDataElevation) = _cacheEntry select 0; GVAR(rangeCardDataElevation) = _cacheEntry select 0;
GVAR(rangeCardDataWindage) = _cacheEntry select 1; GVAR(rangeCardDataWindage) = _cacheEntry select 1;

View File

@ -24,7 +24,6 @@ private _key = format ["weaponInfoCache-%1-%2-%3",_weaponClass,_magazineClass,_a
private _weaponInfo = GVAR(data) getOrDefault [_key, []]; private _weaponInfo = GVAR(data) getOrDefault [_key, []];
if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then { if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then {
TRACE_3("new weapon/mag",_weaponClass,_magazineClass,_ammoClass); TRACE_3("new weapon/mag",_weaponClass,_magazineClass,_ammoClass);
private _useABConfig = (missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false]);
private _zeroRange = 100; private _zeroRange = 100;
private _boreHeight = [_unit, 0] call EFUNC(scopes,getBoreHeight); private _boreHeight = [_unit, 0] call EFUNC(scopes,getBoreHeight);
@ -35,8 +34,14 @@ if ((_weaponInfo isEqualTo []) && {_magazineClass != ""}) then {
_weaponConfig params ["_barrelTwist", "_twistDirection", "_barrelLength"]; _weaponConfig params ["_barrelTwist", "_twistDirection", "_barrelLength"];
private _bc = if (_ballisticCoefficients isEqualTo []) then { 0 } else { _ballisticCoefficients # 0 }; private _bc = if (_ballisticCoefficients isEqualTo []) then { 0 } else { _ballisticCoefficients # 0 };
private _useAB = (
missionNamespace getVariable [QEGVAR(advanced_ballistics,enabled), false] &&
{missionNamespace getVariable [QEGVAR(advanced_ballistics,barrelLengthInfluenceEnabled), false]} &&
{_bc != 0}
);
// Get Muzzle Velocity // Get Muzzle Velocity
private _muzzleVelocity = if (_barrelLength > 0 && _useABConfig && {_bc != 0}) then { private _muzzleVelocity = if (_barrelLength > 0 && _useAB) then {
[_barrelLength, _muzzleVelocityTable, _barrelLengthTable, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift) [_barrelLength, _muzzleVelocityTable, _barrelLengthTable, 0] call EFUNC(advanced_ballistics,calculateBarrelLengthVelocityShift)
} else { } else {
private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed"); private _initSpeed = getNumber (configFile >> "CfgMagazines" >> _magazineClass >> "initSpeed");

View File

@ -21,7 +21,10 @@ This adds the possibility to draw accurate lines on the map screen.
### 1.2 Map tools ### 1.2 Map tools
This adds map tools that can be used to measure distances between two points or bearings on the map. This adds map tools that can be used to measure distances between two points or bearings on the map.
### 1.3 GPS on map ### 1.3 Plotting Board
This adds a plotting board that can be used to aid in the rapid usage and adjustment of short-ranged indirect fires, as well as quick measurements of directions and distances between points, and general land-navigation.
### 1.4 GPS on map
If you are equipped with a vanilla GPS it will be shown on the map. (You don't need the `Map Tools` item in your inventory for this.) If you are equipped with a vanilla GPS it will be shown on the map. (You don't need the `Map Tools` item in your inventory for this.)
## 2. Usage ## 2. Usage
@ -39,3 +42,15 @@ If you are equipped with a vanilla GPS it will be shown on the map. (You don't n
- Press <kbd>ALT</kbd> + <kbd>LMB</kbd> to start the line, left click again to end it. - Press <kbd>ALT</kbd> + <kbd>LMB</kbd> to start the line, left click again to end it.
- To delete a line press <kbd>Del</kbd> around the center of the line. - To delete a line press <kbd>Del</kbd> around the center of the line.
- Note that you can change the color of the lines by clicking on one of the coloured column on top of the screen (While the map is opened). - Note that you can change the color of the lines by clicking on one of the coloured column on top of the screen (While the map is opened).
### 2.3 Using the plotting board
- To use map tools the `Plotting Board` item is required.
- Open the map <kbd>M</kbd> (Arma 3 default key bind `Map`).
- Press the self interaction key <kbd>Ctrl</kbd> + <kbd>&nbsp;Win</kbd> (ACE3 default key bind `Self Interaction Key`).
- Select `Show Plotting Board`.
- Note that you can drag the Plotting Board around with <kbd>LMB</kbd> and rotate the different parts of the Plotting Board, each independently from each other, with <kbd>Ctrl</kbd> + <kbd>LMB</kbd>.
### 2.4 Drawing lines
- You can draw lines on the plotting board.
- These lines are removed from the map once the plotting board is hidden, but they restored when the plotting board is shown again.
- These lines are moved along with the plotting board when the plotting board is dragged.