Map Tools - Add Plotting Board (#9653)

* Initial Commit to unfuck whatever I fucked in Git.

* Update initSettings.sqf and stringtable.xml

* Implements stringtable.xml suggestion

* Fixes for plotting board

* Update addons/maptools/functions/fnc_handleMouseButton.sqf

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>

* Update addons/maptools/CfgWeapons.hpp

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>

* Update addons/maptools/XEH_postInitClient.sqf

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>

* Update addons/maptools/XEH_postInitClient.sqf

Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>

* Cleanup

* Redid calculations

* Updated docs

* More updated docs

* Update maptools.md

* Fix error and warning

---------

Co-authored-by: LorenLuke <LukeLLL@aol.com>
Co-authored-by: Grim <69561145+LinkIsGrim@users.noreply.github.com>
This commit is contained in:
johnb432 2024-01-07 19:02:05 +01:00 committed by GitHub
parent 2a2efbb73a
commit 79c43179ea
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 916 additions and 117 deletions

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(ToCompassLabel);
condition = QUOTE(GVAR(mapTool_Shown) != 0 && {ACE_player getSlotItemName TYPE_COMPASS != ''});
statement = QUOTE(GVAR(mapTool_angle) = getDir ACE_player);
EXCEPTIONS;
showDisabled = 1;
};
class ACE_MapToolsAlignNorth {
displayName = CSTRING(ToNorthLabel);
condition = QUOTE(GVAR(mapTool_Shown) != 0);
statement = QUOTE(GVAR(mapTool_angle) = 0);
EXCEPTIONS;
showDisabled = 1;
};
};
};
class ACE_PlottingBoard {
displayName = CSTRING(ShowPlottingBoard);
condition = QUOTE(GVAR(plottingBoard_Shown) < 1 && {call FUNC(canUsePlottingBoard)});
statement = QUOTE(GVAR(plottingBoard_Shown) = 1);
EXCEPTIONS;
showDisabled = 0;
};
class ACE_PlottingBoardHide {
displayName = CSTRING(HidePlottingBoard);
condition = QUOTE(GVAR(plottingBoard_Shown) != 0 && {call FUNC(canUsePlottingBoard)});
statement = QUOTE(GVAR(plottingBoard_Shown) = 0);
EXCEPTIONS;
showDisabled = 0;
class ACE_PlottingBoardRulerShow {
displayName = CSTRING(TogglePlottingBoardRuler);
condition = QUOTE(GVAR(plottingBoard_Shown) == 1);
statement = QUOTE(GVAR(plottingBoard_Shown) = 2);
EXCEPTIONS;
showDisabled = 1;
};
class ACE_MapToolsAlignCompass {
displayName = CSTRING(MapToolsAlignCompass);
condition = QUOTE(GVAR(mapTool_Shown) != 0 && {getUnitLoadout ACE_player param [ARR_2(9,[])] param [ARR_2(3,'')] != ''});
statement = QUOTE(GVAR(mapTool_angle) = getDir ACE_player;);
exceptions[] = {"isNotDragging", "notOnMap", "isNotInside", "isNotSitting"};
class ACE_PlottingBoardRulerHide {
displayName = CSTRING(TogglePlottingBoardRuler);
condition = QUOTE(GVAR(plottingBoard_Shown) == 2);
statement = QUOTE(GVAR(plottingBoard_Shown) = 1);
EXCEPTIONS;
showDisabled = 1;
};
class ACE_PlottingBoardWipe {
displayName = CSTRING(WipeBoard);
condition = QUOTE(GVAR(plottingBoard_markers) isNotEqualTo createHashMap);
statement = QUOTE(call FUNC(wipeMarkers));
EXCEPTIONS;
showDisabled = 1;
};
class ACE_PlottingBoardAlign {
displayName = CSTRING(AlignTo);
condition = QUOTE(GVAR(plottingBoard_Shown) > 0);
statement = "";
EXCEPTIONS;
showDisabled = 0;
class ACE_PlottingBoardAlignBoard {
displayName = CSTRING(PlottingBoardLabel);
condition = QUOTE(true);
statement = "";
EXCEPTIONS;
showDisabled = 0;
class ACE_PlottingBoardAlignBoardMaptool {
displayName = CSTRING(Name);
condition = QUOTE(GVAR(mapTool_Shown) > 0 && GVAR(plottingBoard_angle) != GVAR(mapTool_angle));
statement = QUOTE(GVAR(plottingBoard_angle) = GVAR(mapTool_angle));
EXCEPTIONS;
showDisabled = 0;
};
class ACE_PlottingBoardAlignBoardUp {
displayName = CSTRING(ToUpLabel);
condition = QUOTE(GVAR(plottingBoard_angle) != 0);
statement = QUOTE(GVAR(plottingBoard_angle) = 0);
EXCEPTIONS;
showDisabled = 0;
};
};
class ACE_PlottingBoardAlignAcrylic {
displayName = CSTRING(PlottingBoardAcrylicLabel);
condition = QUOTE(true);
statement = "";
EXCEPTIONS;
showDisabled = 0;
class ACE_PlottingBoardAlignAcrylicMaptool {
displayName = CSTRING(Name);
condition = QUOTE(GVAR(mapTool_Shown) > 0 && GVAR(plottingBoard_acrylicAngle) != GVAR(mapTool_angle));
statement = QUOTE(GVAR(plottingBoard_acrylicAngle) = GVAR(mapTool_angle));
EXCEPTIONS;
showDisabled = 0;
};
class ACE_PlottingBoardAlignAcrylicUp {
displayName = CSTRING(ToUpLabel);
condition = QUOTE(GVAR(plottingBoard_acrylicAngle) != 0);
statement = QUOTE(GVAR(plottingBoard_acrylicAngle) = 0);
EXCEPTIONS;
showDisabled = 0;
};
};
class ACE_PlottingBoardAlignRuler {
displayName = CSTRING(PlottingBoardRulerLabel);
condition = QUOTE(GVAR(plottingBoard_Shown) == 2);
statement = "";
EXCEPTIONS;
showDisabled = 0;
class ACE_PlottingBoardAlignRulerMaptool {
displayName = CSTRING(Name);
condition = QUOTE(GVAR(mapTool_Shown) > 0 && GVAR(plottingBoard_rulerAngle) != GVAR(mapTool_angle));
statement = QUOTE(GVAR(plottingBoard_rulerAngle) = GVAR(mapTool_angle));
EXCEPTIONS;
showDisabled = 0;
};
class ACE_PlottingBoardAlignRulerUp {
displayName = CSTRING(ToUpLabel);
condition = QUOTE(GVAR(plottingBoard_rulerAngle) != 0);
statement = QUOTE(GVAR(plottingBoard_rulerAngle) = 0);
EXCEPTIONS;
showDisabled = 0;
};
};
};
};
};
};
@ -69,30 +211,35 @@ class CfgVehicles {
class Box_NATO_Support_F: NATO_Box_Base {
class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
};
};
class Box_East_Support_F: EAST_Box_Base {
class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
};
};
class Box_IND_Support_F: IND_Box_Base {
class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
};
};
class Box_FIA_Support_F: FIA_Box_Base_F {
class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
};
};
class ACE_Box_Misc: Box_NATO_Support_F {
class TransportItems {
MACRO_ADDITEM(ACE_MapTools,12);
MACRO_ADDITEM(ACE_PlottingBoard,12);
};
};
};

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,44 +82,98 @@ if (_dir != 1) then {
GVAR(mapTool_isRotating) = false;
_handled = true;
};
if (GVAR(plottingBoard_isDragging) || GVAR(plottingBoard_isRotating) > -1) then {
GVAR(plottingBoard_isDragging) = false;
GVAR(plottingBoard_isRotating) = -1;
_handled = true;
};
} else {
// If clicking
if !(call FUNC(canUseMapTools)) exitWith {};
if (call FUNC(canUseMapTools)) then {
GVAR(mapTool_isDragging) = false;
GVAR(mapTool_isRotating) = false;
// Transform mouse screen position to coordinates
private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
_pos set [count _pos, 0];
// If no map tool marker then exit
if (GVAR(mapTool_Shown) != 0) then {
// Transform mouse screen position to coordinates
private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
GVAR(mapTool_isDragging) = false;
GVAR(mapTool_isRotating) = false;
// Check if clicking the maptool
if (_pos call FUNC(isInsideMapTool)) then {
// Store data for dragging
GVAR(mapTool_startPos) = +GVAR(mapTool_pos);
GVAR(mapTool_startDragPos) = _pos;
// If no map tool marker then exit
if (GVAR(mapTool_Shown) == 0) exitWith {};
private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do {
case 1: {_altKey};
case 2: {_ctrlKey};
case 3: {_shiftKey};
default {false};
};
// Check if clicking the maptool
if (_pos call FUNC(isInsideMapTool)) exitWith {
// Store data for dragging
GVAR(mapTool_startPos) = + GVAR(mapTool_pos);
GVAR(mapTool_startDragPos) = + _pos;
if (_rotateKeyPressed) then {
// Store data for rotating
GVAR(mapTool_startAngle) = GVAR(mapTool_angle);
private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do {
case (1): {_altKey};
case (2): {_ctrlKey};
case (3): {_shiftKey};
default {false};
private _pos = GVAR(mapTool_startDragPos) vectorDiff GVAR(mapTool_startPos);
GVAR(mapTool_startDragAngle) = ((_pos select 0) atan2 (_pos select 1) + 360) % 360;
// Start rotating
GVAR(mapTool_isRotating) = true;
} else {
// Start dragging
GVAR(mapTool_isDragging) = true;
};
_handled = true;
};
};
};
if (_rotateKeyPressed) then {
// Store data for rotating
GVAR(mapTool_startAngle) = + GVAR(mapTool_angle);
GVAR(mapTool_startDragAngle) = (180 + ((GVAR(mapTool_startDragPos) select 0) - (GVAR(mapTool_startPos) select 0)) atan2 ((GVAR(mapTool_startDragPos) select 1) - (GVAR(mapTool_startPos) select 1)) mod 360);
// Start rotating
GVAR(mapTool_isRotating) = true;
} else {
// Start dragging
GVAR(mapTool_isDragging) = true;
if (call FUNC(canUsePlottingBoard)) then {
GVAR(plottingBoard_isDragging) = false;
GVAR(plottingBoard_isRotating) = -1;
if (GVAR(plottingBoard_Shown) != 0) then {
// Transform mouse screen position to coordinates
private _pos = _control ctrlMapScreenToWorld [_screenPosX, _screenPosY];
private _click = _pos call FUNC(isInsidePlottingBoard);
if (_click > -1) then {
GVAR(plottingBoard_startPos) = +GVAR(plottingBoard_pos);
GVAR(plottingBoard_startDragPos) = _pos;
private _rotateKeyPressed = switch (GVAR(rotateModifierKey)) do {
case 1: {_altKey};
case 2: {_ctrlKey};
case 3: {_shiftKey};
default {false};
};
if (_rotateKeyPressed) then {
// Store data for rotating
private _ang = switch (_click) do {
case 1: {GVAR(plottingBoard_acrylicAngle)};
case 2: {GVAR(plottingBoard_rulerAngle)};
default {GVAR(plottingBoard_angle)};
};
GVAR(plottingBoard_startAngle) = _ang;
private _pos = GVAR(plottingBoard_startDragPos) vectorDiff GVAR(plottingBoard_startPos);
GVAR(plottingBoard_startDragAngle) = ((_pos select 0) atan2 (_pos select 1) + 360) % 360;
// Start rotating
GVAR(plottingBoard_isRotating) = _click;
} else {
// Start dragging
GVAR(plottingBoard_isDragging) = true;
};
_handled = true;
};
};
_handled = true;
};
};

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 {
_rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa);
_textureWidth = TEXTURE_WIDTH_IN_M;
} else {
_rotatingTexture = QPATHTOF(data\mapToolRotatingSmall.paa);
_textureWidth = TEXTURE_WIDTH_IN_M / 2;
if (((GVAR(mapTool_Shown) == 0) && {GVAR(plottingBoard_Shown) == 0}) || {
private _uniqueItems = ACE_player call EFUNC(common,uniqueItems);
!(("ACE_MapTools" in _uniqueItems) || {"ACE_PlottingBoard" in _uniqueItems})
}) exitWith {};
if (GVAR(plottingBoard_Shown) > 0) then {
if (GVAR(plottingBoard_moveToMouse)) then {
GVAR(plottingBoard_pos) = _mapCtrl ctrlMapScreenToWorld getMousePosition;
GVAR(plottingBoard_moveToMouse) = false; // we only need to do this once after opening the map tool
};
getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"];
private _scaleX = 32 * PLOTTINGBOARD_TEXTUREWIDTH * CONSTANT_SCALE * (call FUNC(calculateMapScale));
private _scaleY = _scaleX * ((_resWidth / _resHeight) / _aspectRatio); // handle bad aspect ratios
_mapCtrl drawIcon [QPATHTOF(data\plottingBoardBack.paa), [1, 1, 1, 1], GVAR(plottingBoard_pos), _scaleX, _scaleY, GVAR(plottingBoard_angle), "", 0];
_mapCtrl drawIcon [QPATHTOF(data\plottingBoardAcrylic.paa), [1, 1, 1, 1], GVAR(plottingBoard_pos), _scaleX, _scaleY, GVAR(plottingBoard_acrylicAngle), "", 0];
// Show ruler
if (GVAR(plottingBoard_Shown) == 2) then {
_mapCtrl drawIcon [QPATHTOF(data\plottingBoardRuler.paa), [1, 1, 1, 1], GVAR(plottingBoard_pos), _scaleX, _scaleY, GVAR(plottingBoard_rulerAngle), "", 0];
};
private _marker = "";
private _angle = GVAR(plottingBoard_acrylicAngle);
private _boardPos = GVAR(plottingBoard_pos);
private _count = -1;
private _rotatedPolyPos = [];
private _rotatedPos = [];
{
_marker = _x;
_y params ["_markerPos", "_polyline", "_lastAngle", "_lastBoardPos", "_lastAlpha"];
// Show all plotting board markers when the board is shown
if (_lastAlpha != 1) then {
_marker setMarkerAlpha 1;
_y set [4, 1];
};
// If nothing has changed, don't update marker
if (_angle == _lastAngle && {_boardPos isEqualTo _lastBoardPos}) then {
continue;
};
_count = count _polyline;
// Rotate all points of polyline
if (_count >= 4) then { // polylines need at least 2 points (2 components per point)
_rotatedPolyline = [];
for "_i" from 0 to _count - 1 step 2 do {
_rotatedPolyPos = [[0, 0], [_polyline select _i, _polyline select (_i + 1)], -_angle] call CBA_fnc_vectRotate2D;
_rotatedPolyline append (_rotatedPolyPos vectorAdd _boardPos);
};
_marker setMarkerPolyline _rotatedPolyline;
};
// Rotate marker position, regardless of marker type
_rotatedPos = [[0, 0], _markerPos, -_angle] call CBA_fnc_vectRotate2D;
_marker setMarkerPos (_boardPos vectorAdd _rotatedPos);
_y set [2, _angle];
_y set [3, +_boardPos];
} forEach GVAR(plottingBoard_markers);
};
if (GVAR(freedrawing)) then {[_theMap, _textureWidth] call FUNC(drawLinesOnRoamer);};
if (GVAR(mapTool_Shown) > 0) then {
// Open map tools in center of screen when toggled to be shown
if (GVAR(mapTool_moveToMouse)) then {
GVAR(mapTool_pos) = _mapCtrl ctrlMapScreenToWorld getMousePosition;
GVAR(mapTool_moveToMouse) = false; // we only need to do this once after opening the map tool
};
// Update scale of both parts
getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"];
private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale));
private _scaleY = _scaleX;
private _rotatingTexture = "";
private _textureWidth = 0;
// Position of the fixed part
private _xPos = GVAR(mapTool_pos) select 0;
private _yPos = (GVAR(mapTool_pos) select 1) + _textureWidth * CENTER_OFFSET_Y_PERC;
if (GVAR(mapTool_Shown) == 1) then {
_rotatingTexture = QPATHTOF(data\mapToolRotatingNormal.paa);
_textureWidth = TEXTURE_WIDTH_IN_M;
} else {
_rotatingTexture = QPATHTOF(data\mapToolRotatingSmall.paa);
_textureWidth = TEXTURE_WIDTH_IN_M / 2;
};
_theMap drawIcon [QPATHTOF(data\mapToolFixed.paa), [1,1,1,1], [_xPos,_yPos], _scaleX, _scaleY, 0, "", 0];
if (GVAR(freedrawing)) then {
[_mapCtrl, _textureWidth] call FUNC(drawLinesOnRoamer);
};
// Position and rotation of the rotating part
_xPos = (GVAR(mapTool_pos) select 0) + sin(GVAR(mapTool_angle)) * _textureWidth * CENTER_OFFSET_Y_PERC;
_yPos = (GVAR(mapTool_pos) select 1) + cos(GVAR(mapTool_angle)) * _textureWidth * CENTER_OFFSET_Y_PERC;
// Update scale of both parts
getResolution params ["_resWidth", "_resHeight", "", "", "_aspectRatio"];
private _scaleX = 32 * _textureWidth * CONSTANT_SCALE * (call FUNC(calculateMapScale));
private _scaleY = _scaleX * ((_resWidth / _resHeight) / _aspectRatio); // handle bad aspect ratios
_theMap drawIcon [_rotatingTexture, [1,1,1,1], [_xPos,_yPos], _scaleX, _scaleY, GVAR(mapTool_angle), "", 0];
// Position of the fixed part
private _pos = GVAR(mapTool_pos) vectorAdd [0, _textureWidth * CENTER_OFFSET_Y_PERC];
_mapCtrl drawIcon [QPATHTOF(data\mapToolFixed.paa), [1, 1, 1, 1], _pos, _scaleX, _scaleY, 0, "", 0];
// Position and rotation of the rotating part
_pos = GVAR(mapTool_pos) vectorAdd ([sin GVAR(mapTool_angle), cos GVAR(mapTool_angle)] vectorMultiply (_textureWidth * CENTER_OFFSET_Y_PERC));
_mapCtrl drawIcon [_rotatingTexture, [1, 1, 1, 1], _pos, _scaleX, _scaleY, GVAR(mapTool_angle), "", 0];
};

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

@ -21,7 +21,10 @@ This adds the possibility to draw accurate lines on the map screen.
### 1.2 Map tools
This adds map tools that can be used to measure distances between two points or bearings on the map.
### 1.3 GPS on map
### 1.3 Plotting Board
This adds a plotting board that can be used to aid in the rapid usage and adjustment of short-ranged indirect fires, as well as quick measurements of directions and distances between points, and general land-navigation.
### 1.4 GPS on map
If you are equipped with a vanilla GPS it will be shown on the map. (You don't need the `Map Tools` item in your inventory for this.)
## 2. Usage
@ -39,3 +42,15 @@ If you are equipped with a vanilla GPS it will be shown on the map. (You don't n
- Press <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.
- 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.