Added options for miss on purpose and scenic AAA

This commit is contained in:
Pax1601 2023-10-03 15:25:45 +02:00
parent 4da407008e
commit ce5f00e075
23 changed files with 9430 additions and 7539 deletions

View File

@ -48,7 +48,7 @@ const DEMO_UNIT_DATA = {
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
contacts: [{ID: 1, detectionMethod: 16}],
activePath: [ ]
}, ["4"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "Gepard", unitName: "Cool guy 2-1", groupName: "Cool group 4", state: 1, task: "Being cool",
}, ["4"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 0, country: 0, name: "Gepard", unitName: "Cool guy 2-1", groupName: "Cool group 4", state: 1, task: "Being cool",
hasTask: false, position: { lat: 37.2, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
formationOffset: { x: 0, y: 0, z: 0 },
@ -64,7 +64,7 @@ const DEMO_UNIT_DATA = {
contacts: [{ID: 1001, detectionMethod: 16}],
activePath: [ ],
isLeader: true
}, ["5"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "S_75M_Volhov", unitName: "Cool guy 2-2", groupName: "Cool group 4", state: 1, task: "Being cool",
}, ["5"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 0, country: 0, name: "Gepard", unitName: "Cool guy 2-2", groupName: "Cool group 4", state: 1, task: "Being cool",
hasTask: false, position: { lat: 37.21, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
formationOffset: { x: 0, y: 0, z: 0 },

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -326,9 +326,9 @@
#unit-contextmenu div:before {
display: inline-block;
filter: invert(100%);
height: 16px;
height: 20px;
margin-right: 15px;
width: 16px;
width: 20px;
}
.ol-select>.ol-select-options>div button.country-dropdown-element {
@ -377,6 +377,30 @@
content: url("/resources/theme/images/icons/follow.svg");
}
#scenic-aaa-red::before {
content: url("/resources/theme/images/icons/scenic-red.svg");
}
#scenic-aaa-blue::before {
content: url("/resources/theme/images/icons/scenic-blue.svg");
}
#miss-aaa-red::before {
content: url("/resources/theme/images/icons/miss-red.svg");
}
#miss-aaa-blue::before {
content: url("/resources/theme/images/icons/miss-blue.svg");
}
#group-ground::before {
content: url("/resources/theme/images/icons/group-ground.svg");
}
#group-navy::before {
content: url("/resources/theme/images/icons/group-navy.svg");
}
#trail::before {
content: url("/resources/theme/images/icons/trail.svg");
}

View File

@ -203,6 +203,22 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
content: "NO";
}
#operate-as-switch[data-value="true"] .ol-switch-fill {
background-color: var(--accent-light-blue);
}
#operate-as-switch[data-value="false"] .ol-switch-fill {
background-color: var(--primary-red);
}
#operate-as-switch[data-value="true"]>.ol-switch-fill::before {
content: "BLUE" !important;
}
#operate-as-switch[data-value="false"]>.ol-switch-fill::before {
content: "RED" !important;
}
#advanced-settings-div {
column-gap: 5px;
display: flex;
@ -225,6 +241,7 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
#unit-control-panel:not([data-show-emissions-countermeasures]) #emissions-countermeasures,
#unit-control-panel:not([data-show-on-off]) #ai-on-off,
#unit-control-panel:not([data-show-follow-roads]) #follow-roads,
#unit-control-panel:not([data-show-operate-as]) #operate-as,
#unit-control-panel:not([data-show-advanced-settings-button]) #advanced-settings-button,
#advanced-settings-dialog:not([data-show-settings]) #general-settings,
#advanced-settings-dialog:not([data-show-tasking]) #tasking,

View File

@ -678,6 +678,13 @@ nav.ol-panel> :last-child {
stroke: white;
}
#rapid-controls button:before {
display: inline-block;
filter: invert(100%);
height: 20px;
width: 20px;
}
/****************************************************************************************/
#splash-screen {
border-radius: var(--border-radius-md);

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M37.6 4.2C28-2.3 15.2-1.1 7 7s-9.4 21-2.8 30.5l112 163.3L16.6 233.2C6.7 236.4 0 245.6 0 256s6.7 19.6 16.6 22.8l103.1 33.4L66.8 412.8c-4.9 9.3-3.2 20.7 4.3 28.1s18.8 9.2 28.1 4.3l100.6-52.9 33.4 103.1c3.2 9.9 12.4 16.6 22.8 16.6s19.6-6.7 22.8-16.6l33.4-103.1 100.6 52.9c9.3 4.9 20.7 3.2 28.1-4.3s9.2-18.8 4.3-28.1L392.3 312.2l103.1-33.4c9.9-3.2 16.6-12.4 16.6-22.8s-6.7-19.6-16.6-22.8L388.9 198.7l25.7-70.4c3.2-8.8 1-18.6-5.6-25.2s-16.4-8.8-25.2-5.6l-70.4 25.7L278.8 16.6C275.6 6.7 266.4 0 256 0s-19.6 6.7-22.8 16.6l-32.3 99.6L37.6 4.2z"/></svg>

After

Width:  |  Height:  |  Size: 783 B

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1156"
sodipodi:docname="group-ground.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1160" /><sodipodi:namedview
id="namedview1158"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.3838301"
inkscape:cx="350.83787"
inkscape:cy="229.07436"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1156" /><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><g
id="g17054"
transform="matrix(1.0569047,0,0,1.0569047,-16.868728,-5.190059)"><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="rect13768"
width="162.59222"
height="162.59222"
x="200.25279"
y="-165.09651"
ry="1.6436043"
transform="rotate(45)" /><circle
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:10;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path15109"
cx="258.34097"
cy="139.82932"
r="52.56604" /></g><g
id="g17054-1"
transform="matrix(1.0569047,0,0,1.0569047,110.67584,204.85819)"><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="rect13768-9"
width="162.59222"
height="162.59222"
x="200.25279"
y="-165.09651"
ry="1.6436043"
transform="rotate(45)" /><circle
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:10;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path15109-6"
cx="258.34097"
cy="139.82932"
r="52.56604" /></g><g
id="g17054-3"
transform="matrix(1.0569047,0,0,1.0569047,-141.52275,204.13556)"><rect
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:10;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="rect13768-7"
width="162.59222"
height="162.59222"
x="200.25279"
y="-165.09651"
ry="1.6436043"
transform="rotate(45)" /><circle
style="fill:#000000;fill-opacity:1;stroke:#ffffff;stroke-width:10;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path15109-8"
cx="258.34097"
cy="139.82932"
r="52.56604" /></g></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1156"
sodipodi:docname="group-navy.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1160" /><sodipodi:namedview
id="namedview1158"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.9570312"
inkscape:cx="262.38723"
inkscape:cy="288.19162"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1156" /><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:65.39;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path15424"
sodipodi:type="arc"
sodipodi:cx="259.66818"
sodipodi:cy="230.83046"
sodipodi:rx="226.81407"
sodipodi:ry="212.6382"
sodipodi:start="4.1887902"
sodipodi:end="5.2359878"
sodipodi:arc-type="slice"
d="m 146.26115,46.680378 a 226.81407,212.6382 0 0 1 226.81408,4e-6 L 259.66818,230.83046 Z" /><path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:65.39;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path15424-9"
sodipodi:type="arc"
sodipodi:cx="386.81033"
sodipodi:cy="495.42886"
sodipodi:rx="226.81407"
sodipodi:ry="212.6382"
sodipodi:start="4.1887902"
sodipodi:end="5.2359878"
sodipodi:arc-type="slice"
d="m 273.4033,311.27878 a 226.81407,212.6382 0 0 1 226.81408,1e-5 L 386.81033,495.42886 Z" /><path
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:65.39;stroke-linecap:round;stroke-dasharray:none;stroke-opacity:1"
id="path15424-4"
sodipodi:type="arc"
sodipodi:cx="127.74452"
sodipodi:cy="495.42886"
sodipodi:rx="226.81407"
sodipodi:ry="212.6382"
sodipodi:start="4.1887902"
sodipodi:end="5.2359878"
sodipodi:arc-type="slice"
d="m 14.337485,311.27878 a 226.81407,212.6382 0 0 1 226.814085,1e-5 L 127.74452,495.42886 Z" /></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M270.7 9.7C268.2 3.8 262.4 0 256 0s-12.2 3.8-14.7 9.7L197.2 112.6c-3.4 8-5.2 16.5-5.2 25.2v77l-144 84V280c0-13.3-10.7-24-24-24s-24 10.7-24 24v56 32 24c0 13.3 10.7 24 24 24s24-10.7 24-24v-8H192v32.7L133.5 468c-3.5 3-5.5 7.4-5.5 12v16c0 8.8 7.2 16 16 16h96V448c0-8.8 7.2-16 16-16s16 7.2 16 16v64h96c8.8 0 16-7.2 16-16V480c0-4.6-2-9-5.5-12L320 416.7V384H464v8c0 13.3 10.7 24 24 24s24-10.7 24-24V368 336 280c0-13.3-10.7-24-24-24s-24 10.7-24 24v18.8l-144-84v-77c0-8.7-1.8-17.2-5.2-25.2L270.7 9.7z"/></svg>

After

Width:  |  Height:  |  Size: 739 B

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1156"
sodipodi:docname="miss-blue.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1160" />
<sodipodi:namedview
id="namedview1158"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.3838301"
inkscape:cx="310.37048"
inkscape:cy="217.51226"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1156" />
<!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path
d="m 376.91839,231.41639 c -1.31238,-3.09721 -4.35709,-5.09202 -7.71677,-5.09202 -3.35968,0 -6.40439,1.99481 -7.71677,5.09202 l -23.1503,54.01737 c -1.78483,4.1996 -2.72974,8.66167 -2.72974,13.22874 v 40.42116 l -75.59281,44.0958 v -9.86906 c 0,-6.98183 -5.61697,-12.5988 -12.5988,-12.5988 -6.98184,0 -12.59881,5.61697 -12.59881,12.5988 v 29.39721 16.7984 12.5988 c 0,6.98184 5.61697,12.59881 12.59881,12.59881 6.98183,0 12.5988,-5.61697 12.5988,-12.59881 v -4.1996 h 75.59281 v 17.16587 l -30.70958,26.92994 c -1.83732,1.57485 -2.88722,3.88463 -2.88722,6.2994 v 8.3992 c 0,4.61956 3.77964,8.39921 8.3992,8.39921 h 50.39521 v -33.59681 c 0,-4.61956 3.77964,-8.3992 8.3992,-8.3992 4.61956,0 8.3992,3.77964 8.3992,8.3992 v 33.59681 h 50.39521 c 4.61956,0 8.3992,-3.77965 8.3992,-8.39921 v -8.3992 c 0,-2.41477 -1.0499,-4.72455 -2.88722,-6.2994 l -30.70958,-26.92994 v -17.16587 h 75.59281 v 4.1996 c 0,6.98184 5.61697,12.59881 12.5988,12.59881 6.98184,0 12.59881,-5.61697 12.59881,-12.59881 v -12.5988 -16.7984 -29.39721 c 0,-6.98183 -5.61697,-12.5988 -12.59881,-12.5988 -6.98183,0 -12.5988,5.61697 -12.5988,12.5988 v 9.86906 l -75.59281,-44.0958 V 298.6625 c 0,-4.56707 -0.94491,-9.02914 -2.72974,-13.22874 z"
id="path1154"
style="fill:#db841d;fill-opacity:1;stroke:none;stroke-width:0.52495;stroke-opacity:1" />
<path
d="m 184.66044,8.5185895 c 12.17907,0 22.01865,9.8395825 22.01865,22.0186445 v 7.15606 C 271.15243,47.257643 322.07055,98.244571 331.6349,162.6491 h 7.15606 c 12.17906,0 22.01864,9.83958 22.01864,22.01864 0,12.17907 -9.83958,22.01865 -22.01864,22.01865 h -7.15606 c -9.56435,64.47334 -60.55128,115.39146 -124.95581,124.95581 v 7.15606 c 0,12.17906 -9.83958,22.01864 -22.01865,22.01864 -12.17906,0 -22.01864,-9.83958 -22.01864,-22.01864 V 331.6422 C 98.168455,322.07785 47.250339,271.15973 37.68599,206.68639 h -7.156059 c -12.179063,0 -22.0186444,-9.83958 -22.0186444,-22.01865 0,-12.17906 9.8395814,-22.01864 22.0186444,-22.01864 H 37.68599 C 47.250339,98.175761 98.168455,47.257643 162.6418,37.693294 v -7.15606 c 0,-12.179062 9.83958,-22.0186445 22.01864,-22.0186445 z M 82.411363,206.68639 c 8.601033,40.11522 40.184027,71.6294 80.230437,80.23043 v -14.1745 c 0,-12.17906 9.83958,-22.01864 22.01864,-22.01864 12.17907,0 22.01865,9.83958 22.01865,22.01864 v 14.1745 c 40.11522,-8.60103 71.6294,-40.18402 80.23044,-80.23043 h -14.17451 c -12.17906,0 -22.01864,-9.83958 -22.01864,-22.01865 0,-12.17906 9.83958,-22.01864 22.01864,-22.01864 h 14.17451 C 278.30849,122.53388 246.79431,91.019701 206.67909,82.418665 v 14.174506 c 0,12.179059 -9.83958,22.018639 -22.01865,22.018639 -12.17906,0 -22.01864,-9.83958 -22.01864,-22.018639 V 82.418665 C 122.52658,91.019701 91.012396,122.53388 82.411363,162.6491 h 14.174502 c 12.179065,0 22.018645,9.83958 22.018645,22.01864 0,12.17907 -9.83958,22.01865 -22.018645,22.01865 z M 184.66044,162.6491 a 22.018645,22.018645 0 1 1 0,44.03729 22.018645,22.018645 0 1 1 0,-44.03729 z"
id="path2"
style="stroke-width:0.688083" />
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1156"
sodipodi:docname="miss-red.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<defs
id="defs1160" />
<sodipodi:namedview
id="namedview1158"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.3838301"
inkscape:cx="310.37048"
inkscape:cy="217.51226"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1156" />
<!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
<path
d="m 376.91839,231.41639 c -1.31238,-3.09721 -4.35709,-5.09202 -7.71677,-5.09202 -3.35968,0 -6.40439,1.99481 -7.71677,5.09202 l -23.1503,54.01737 c -1.78483,4.1996 -2.72974,8.66167 -2.72974,13.22874 v 40.42116 l -75.59281,44.0958 v -9.86906 c 0,-6.98183 -5.61697,-12.5988 -12.5988,-12.5988 -6.98184,0 -12.59881,5.61697 -12.59881,12.5988 v 29.39721 16.7984 12.5988 c 0,6.98184 5.61697,12.59881 12.59881,12.59881 6.98183,0 12.5988,-5.61697 12.5988,-12.59881 v -4.1996 h 75.59281 v 17.16587 l -30.70958,26.92994 c -1.83732,1.57485 -2.88722,3.88463 -2.88722,6.2994 v 8.3992 c 0,4.61956 3.77964,8.39921 8.3992,8.39921 h 50.39521 v -33.59681 c 0,-4.61956 3.77964,-8.3992 8.3992,-8.3992 4.61956,0 8.3992,3.77964 8.3992,8.3992 v 33.59681 h 50.39521 c 4.61956,0 8.3992,-3.77965 8.3992,-8.39921 v -8.3992 c 0,-2.41477 -1.0499,-4.72455 -2.88722,-6.2994 l -30.70958,-26.92994 v -17.16587 h 75.59281 v 4.1996 c 0,6.98184 5.61697,12.59881 12.5988,12.59881 6.98184,0 12.59881,-5.61697 12.59881,-12.59881 v -12.5988 -16.7984 -29.39721 c 0,-6.98183 -5.61697,-12.5988 -12.59881,-12.5988 -6.98183,0 -12.5988,5.61697 -12.5988,12.5988 v 9.86906 l -75.59281,-44.0958 V 298.6625 c 0,-4.56707 -0.94491,-9.02914 -2.72974,-13.22874 z"
id="path1154"
style="fill:#00a7a7;fill-opacity:1;stroke:none;stroke-width:0.52495;stroke-opacity:1" />
<path
d="m 184.66044,8.5185895 c 12.17907,0 22.01865,9.8395825 22.01865,22.0186445 v 7.15606 C 271.15243,47.257643 322.07055,98.244571 331.6349,162.6491 h 7.15606 c 12.17906,0 22.01864,9.83958 22.01864,22.01864 0,12.17907 -9.83958,22.01865 -22.01864,22.01865 h -7.15606 c -9.56435,64.47334 -60.55128,115.39146 -124.95581,124.95581 v 7.15606 c 0,12.17906 -9.83958,22.01864 -22.01865,22.01864 -12.17906,0 -22.01864,-9.83958 -22.01864,-22.01864 V 331.6422 C 98.168455,322.07785 47.250339,271.15973 37.68599,206.68639 h -7.156059 c -12.179063,0 -22.0186444,-9.83958 -22.0186444,-22.01865 0,-12.17906 9.8395814,-22.01864 22.0186444,-22.01864 H 37.68599 C 47.250339,98.175761 98.168455,47.257643 162.6418,37.693294 v -7.15606 c 0,-12.179062 9.83958,-22.0186445 22.01864,-22.0186445 z M 82.411363,206.68639 c 8.601033,40.11522 40.184027,71.6294 80.230437,80.23043 v -14.1745 c 0,-12.17906 9.83958,-22.01864 22.01864,-22.01864 12.17907,0 22.01865,9.83958 22.01865,22.01864 v 14.1745 c 40.11522,-8.60103 71.6294,-40.18402 80.23044,-80.23043 h -14.17451 c -12.17906,0 -22.01864,-9.83958 -22.01864,-22.01865 0,-12.17906 9.83958,-22.01864 22.01864,-22.01864 h 14.17451 C 278.30849,122.53388 246.79431,91.019701 206.67909,82.418665 v 14.174506 c 0,12.179059 -9.83958,22.018639 -22.01865,22.018639 -12.17906,0 -22.01864,-9.83958 -22.01864,-22.018639 V 82.418665 C 122.52658,91.019701 91.012396,122.53388 82.411363,162.6491 h 14.174502 c 12.179065,0 22.018645,9.83958 22.018645,22.01864 0,12.17907 -9.83958,22.01865 -22.018645,22.01865 z M 184.66044,162.6491 a 22.018645,22.018645 0 1 1 0,44.03729 22.018645,22.018645 0 1 1 0,-44.03729 z"
id="path2"
style="stroke-width:0.688083" />
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1156"
sodipodi:docname="scenic-blue.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1160" /><sodipodi:namedview
id="namedview1158"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.3838301"
inkscape:cx="350.11524"
inkscape:cy="229.07437"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1156" /><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path
d="m 376.91839,231.41639 c -1.31238,-3.09721 -4.35709,-5.09202 -7.71677,-5.09202 -3.35968,0 -6.40439,1.99481 -7.71677,5.09202 l -23.1503,54.01737 c -1.78483,4.1996 -2.72974,8.66167 -2.72974,13.22874 v 40.42116 l -75.59281,44.0958 v -9.86906 c 0,-6.98183 -5.61697,-12.5988 -12.5988,-12.5988 -6.98184,0 -12.59881,5.61697 -12.59881,12.5988 v 29.39721 16.7984 12.5988 c 0,6.98184 5.61697,12.59881 12.59881,12.59881 6.98183,0 12.5988,-5.61697 12.5988,-12.59881 v -4.1996 h 75.59281 v 17.16587 l -30.70958,26.92994 c -1.83732,1.57485 -2.88722,3.88463 -2.88722,6.2994 v 8.3992 c 0,4.61956 3.77964,8.39921 8.3992,8.39921 h 50.39521 v -33.59681 c 0,-4.61956 3.77964,-8.3992 8.3992,-8.3992 4.61956,0 8.3992,3.77964 8.3992,8.3992 v 33.59681 h 50.39521 c 4.61956,0 8.3992,-3.77965 8.3992,-8.39921 v -8.3992 c 0,-2.41477 -1.0499,-4.72455 -2.88722,-6.2994 l -30.70958,-26.92994 v -17.16587 h 75.59281 v 4.1996 c 0,6.98184 5.61697,12.59881 12.5988,12.59881 6.98184,0 12.59881,-5.61697 12.59881,-12.59881 v -12.5988 -16.7984 -29.39721 c 0,-6.98183 -5.61697,-12.5988 -12.59881,-12.5988 -6.98183,0 -12.5988,5.61697 -12.5988,12.5988 v 9.86906 l -75.59281,-44.0958 V 298.6625 c 0,-4.56707 -0.94491,-9.02914 -2.72974,-13.22874 z"
id="path1154"
style="fill:#db841d;fill-opacity:1;stroke:none;stroke-width:0.52495;stroke-opacity:1" /><path
style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 90.329008,471.87874 294.83388,138.74536"
id="path9928"
sodipodi:nodetypes="cc" /><path
style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 37.215553,461.40058 33.602384,51.668198"
id="path9928-3"
sodipodi:nodetypes="cc" /><path
style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 61.785043,466.45901 134.77088,205.58883"
id="path9928-31"
sodipodi:nodetypes="cc" /><path
d="m 97.776883,46.496287 c -2.69052,-1.821707 -6.27788,-1.485392 -8.576032,0.784735 -2.298159,2.270126 -2.634474,5.885513 -0.784735,8.548007 l 31.389404,45.766871 -27.914144,9.08052 c -2.774607,0.89684 -4.652369,3.47525 -4.652369,6.38998 0,2.91473 1.877762,5.49315 4.652369,6.38999 l 28.895064,9.36076 -14.82589,28.19441 c -1.37329,2.60645 -0.89684,5.80143 1.20513,7.87538 2.10197,2.07394 5.26893,2.57842 7.87538,1.20513 l 28.19442,-14.82589 9.36076,28.89507 c 0.89684,2.7746 3.47525,4.65236 6.38998,4.65236 2.91474,0 5.49316,-1.87776 6.39,-4.65236 l 9.36076,-28.89507 28.19441,14.82589 c 2.60645,1.37329 5.80144,0.89684 7.87539,-1.20513 2.07393,-2.10197 2.57841,-5.26893 1.20512,-7.87538 l -14.82589,-28.19441 28.89507,-9.36076 c 2.7746,-0.89684 4.65236,-3.47526 4.65236,-6.38999 0,-2.91473 -1.87776,-5.49314 -4.65236,-6.38998 l -29.84797,-9.66907 7.20276,-19.730481 c 0.89684,-2.466311 0.28026,-5.212883 -1.56947,-7.062617 -1.84974,-1.849732 -4.59631,-2.46631 -7.06262,-1.56947 l -19.73049,7.202748 -9.69707,-29.875988 c -0.89684,-2.7746 -3.47526,-4.652359 -6.39,-4.652359 -2.91473,0 -5.49314,1.877759 -6.38998,4.652359 l -9.05248,27.91415 z"
id="path10424"
style="stroke-width:0.280262" /></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 512 512"
version="1.1"
id="svg1156"
sodipodi:docname="scenic-red.svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xml:space="preserve"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><defs
id="defs1160" /><sodipodi:namedview
id="namedview1158"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
showgrid="false"
inkscape:zoom="1.3838301"
inkscape:cx="350.11524"
inkscape:cy="229.07437"
inkscape:window-width="2560"
inkscape:window-height="1377"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1156" /><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path
d="m 376.91839,231.41639 c -1.31238,-3.09721 -4.35709,-5.09202 -7.71677,-5.09202 -3.35968,0 -6.40439,1.99481 -7.71677,5.09202 l -23.1503,54.01737 c -1.78483,4.1996 -2.72974,8.66167 -2.72974,13.22874 v 40.42116 l -75.59281,44.0958 v -9.86906 c 0,-6.98183 -5.61697,-12.5988 -12.5988,-12.5988 -6.98184,0 -12.59881,5.61697 -12.59881,12.5988 v 29.39721 16.7984 12.5988 c 0,6.98184 5.61697,12.59881 12.59881,12.59881 6.98183,0 12.5988,-5.61697 12.5988,-12.59881 v -4.1996 h 75.59281 v 17.16587 l -30.70958,26.92994 c -1.83732,1.57485 -2.88722,3.88463 -2.88722,6.2994 v 8.3992 c 0,4.61956 3.77964,8.39921 8.3992,8.39921 h 50.39521 v -33.59681 c 0,-4.61956 3.77964,-8.3992 8.3992,-8.3992 4.61956,0 8.3992,3.77964 8.3992,8.3992 v 33.59681 h 50.39521 c 4.61956,0 8.3992,-3.77965 8.3992,-8.39921 v -8.3992 c 0,-2.41477 -1.0499,-4.72455 -2.88722,-6.2994 l -30.70958,-26.92994 v -17.16587 h 75.59281 v 4.1996 c 0,6.98184 5.61697,12.59881 12.5988,12.59881 6.98184,0 12.59881,-5.61697 12.59881,-12.59881 v -12.5988 -16.7984 -29.39721 c 0,-6.98183 -5.61697,-12.5988 -12.59881,-12.5988 -6.98183,0 -12.5988,5.61697 -12.5988,12.5988 v 9.86906 l -75.59281,-44.0958 V 298.6625 c 0,-4.56707 -0.94491,-9.02914 -2.72974,-13.22874 z"
id="path1154"
style="fill:#00a7a7;fill-opacity:1;stroke:none;stroke-width:0.52495;stroke-opacity:1" /><path
style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 90.329008,471.87874 294.83388,138.74536"
id="path9928"
sodipodi:nodetypes="cc" /><path
style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 37.215553,461.40058 33.602384,51.668198"
id="path9928-3"
sodipodi:nodetypes="cc" /><path
style="fill:none;stroke:#000000;stroke-width:10;stroke-linecap:round;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1"
d="M 61.785043,466.45901 134.77088,205.58883"
id="path9928-31"
sodipodi:nodetypes="cc" /><path
d="m 97.776883,46.496287 c -2.69052,-1.821707 -6.27788,-1.485392 -8.576032,0.784735 -2.298159,2.270126 -2.634474,5.885513 -0.784735,8.548007 l 31.389404,45.766871 -27.914144,9.08052 c -2.774607,0.89684 -4.652369,3.47525 -4.652369,6.38998 0,2.91473 1.877762,5.49315 4.652369,6.38999 l 28.895064,9.36076 -14.82589,28.19441 c -1.37329,2.60645 -0.89684,5.80143 1.20513,7.87538 2.10197,2.07394 5.26893,2.57842 7.87538,1.20513 l 28.19442,-14.82589 9.36076,28.89507 c 0.89684,2.7746 3.47525,4.65236 6.38998,4.65236 2.91474,0 5.49316,-1.87776 6.39,-4.65236 l 9.36076,-28.89507 28.19441,14.82589 c 2.60645,1.37329 5.80144,0.89684 7.87539,-1.20513 2.07393,-2.10197 2.57841,-5.26893 1.20512,-7.87538 l -14.82589,-28.19441 28.89507,-9.36076 c 2.7746,-0.89684 4.65236,-3.47526 4.65236,-6.38999 0,-2.91473 -1.87776,-5.49314 -4.65236,-6.38998 l -29.84797,-9.66907 7.20276,-19.730481 c 0.89684,-2.466311 0.28026,-5.212883 -1.56947,-7.062617 -1.84974,-1.849732 -4.59631,-2.46631 -7.06262,-1.56947 l -19.73049,7.202748 -9.69707,-29.875988 c -0.89684,-2.7746 -3.47526,-4.652359 -6.39,-4.652359 -2.91473,0 -5.49314,1.877759 -6.38998,4.652359 l -9.05248,27.91415 z"
id="path10424"
style="stroke-width:0.280262" /></svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@ -688,7 +688,6 @@ export class Map extends L.Map {
this.#isZooming = false;
}
#panToUnit(unit: Unit) {
var unitPosition = new L.LatLng(unit.getPosition().lat, unit.getPosition().lng);
this.setView(unitPosition, this.getZoom(), { animate: false });

View File

@ -17,6 +17,7 @@ export class UnitControlPanel extends Panel {
#speedTypeSwitch: Switch;
#onOffSwitch: Switch;
#followRoadsSwitch: Switch;
#operateAs: Switch;
#TACANXYDropdown: Dropdown;
#radioDecimalsDropdown: Dropdown;
#radioCallsignDropdown: Dropdown;
@ -67,6 +68,11 @@ export class UnitControlPanel extends Panel {
getApp().getUnitsManager().selectedUnitsSetFollowRoads(value);
});
/* Operate as */
this.#operateAs = new Switch("operate-as-switch", (value: boolean) => {
//getApp().getUnitsManager().selectedUnitsSetFollowRoads(value);
});
/* Advanced settings dialog */
this.#advancedSettingsDialog = <HTMLElement> document.querySelector("#advanced-settings-dialog");
@ -80,21 +86,28 @@ export class UnitControlPanel extends Panel {
/* Events and timer */
window.setInterval(() => {this.update();}, 25);
document.addEventListener("unitsSelection", (e: CustomEvent<Unit[]>) => { this.show(); this.addButtons();});
document.addEventListener("clearSelection", () => { this.hide() });
document.addEventListener("unitsSelection", (e: CustomEvent<Unit[]>) => {
this.show();
this.addButtons();
this.#updateRapidControls();
});
document.addEventListener("clearSelection", () => {
this.hide();
this.#updateRapidControls();
});
document.addEventListener("applyAdvancedSettings", () => {this.#applyAdvancedSettings();})
document.addEventListener("showAdvancedSettings", () => {
this.#updateAdvancedSettingsDialog(getApp().getUnitsManager().getSelectedUnits());
this.#advancedSettingsDialog.classList.remove("hide");
});
this.hide();
// This is for when a ctrl-click happens on the map for deselection and we need to remove the selected unit from the panel
/* This is for when a ctrl-click happens on the map for deselection and we need to remove the selected unit from the panel */
document.addEventListener( "unitDeselection", ( ev:CustomEventInit ) => {
this.getElement().querySelector( `button[data-unit-id="${ev.detail.ID}"]` )?.remove();
this.#updateRapidControls();
});
this.hide();
}
show() {
@ -157,6 +170,7 @@ export class UnitControlPanel extends Panel {
element.toggleAttribute("data-show-emissions-countermeasures", (this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")) && !(this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")));
element.toggleAttribute("data-show-on-off", (this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")) && !(this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")));
element.toggleAttribute("data-show-follow-roads", (this.#selectedUnitsTypes.length == 1 && this.#selectedUnitsTypes.includes("GroundUnit")));
element.toggleAttribute("data-show-operate-as", getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getCoalition()}) === "neutral");
element.toggleAttribute("data-show-advanced-settings-button", this.#units.length == 1);
if (this.#selectedUnitsTypes.length == 1) {
@ -208,6 +222,59 @@ export class UnitControlPanel extends Panel {
}
}
#updateRapidControls() {
var options: { [key: string]: { text: string, tooltip: string, type: string } } | null = null;
var selectedUnits = getApp().getUnitsManager().getSelectedUnits();
var showAltitudeChange = selectedUnits.some((unit: Unit) => {return ["Aircraft", "Helicopter"].includes(unit.getCategory());});
this.getElement().querySelector("#climb")?.classList.toggle("hide", !showAltitudeChange);
this.getElement().querySelector("#descend")?.classList.toggle("hide", !showAltitudeChange);
/* Keep only the common "and" options, unless a single unit is selected */
selectedUnits.forEach((unit: Unit) => {
var unitOptions = unit.getActions();
if (options === null) {
options = unitOptions;
} else {
/* Delete all the "or" type options */
for (let optionKey in options) {
if (options[optionKey].type == "or") {
delete options[optionKey];
}
}
/* Options of "and" type get shown if ALL units have it */
for (let optionKey in options) {
if (!(optionKey in unitOptions)) {
delete options[optionKey];
}
}
}
});
options = options ?? {};
const rapidControlsContainer = this.getElement().querySelector("#rapid-controls") as HTMLElement;
const unitActionButtons = rapidControlsContainer.querySelectorAll(".unit-action-button");
for (let button of unitActionButtons) {
rapidControlsContainer.removeChild(button);
}
for (let option in options) {
let button = document.createElement("button");
button.title = options[option].tooltip;
button.classList.add("ol-button", "unit-action-button");
button.id = option;
rapidControlsContainer.appendChild(button);
button.onclick = () => {
/* Since only common actions are shown in the rapid controls, we execute it only on the first unit */
if (selectedUnits.length > 0)
selectedUnits[0].executeAction(null, option);
}
}
}
#updateAdvancedSettingsDialog(units: Unit[])
{
if (units.length == 1)

View File

@ -329,14 +329,14 @@ export class ServerManager {
this.PUT(data, callback);
}
scenicAAA(ID: number, callback: CallableFunction = () => {}) {
var command = { "ID": ID }
scenicAAA(ID: number, coalition: string, callback: CallableFunction = () => {}) {
var command = { "ID": ID, "coalition": coalition }
var data = { "scenicAAA": command }
this.PUT(data, callback);
}
missOnPurpose(ID: number, callback: CallableFunction = () => {}) {
var command = { "ID": ID }
missOnPurpose(ID: number, coalition: string, callback: CallableFunction = () => {}) {
var command = { "ID": ID, "coalition": coalition }
var data = { "missOnPurpose": command }
this.PUT(data, callback);
}

View File

@ -588,15 +588,7 @@ export class Unit extends CustomMarker {
}
isInViewport() {
const mapBounds = getApp().getMap().getBounds();
const unitPos = this.getPosition();
return (unitPos.lng > mapBounds.getWest()
&& unitPos.lng < mapBounds.getEast()
&& unitPos.lat > mapBounds.getSouth()
&& unitPos.lat < mapBounds.getNorth());
return getApp().getMap().getBounds().contains(this.getPosition());
}
/********************** Unit commands *************************/
@ -739,14 +731,40 @@ export class Unit extends CustomMarker {
});
}
scenicAAA() {
getApp().getServerManager().scenicAAA(this.ID);
scenicAAA(coalition: string) {
getApp().getServerManager().scenicAAA(this.ID, coalition);
}
missOnPurpose() {
getApp().getServerManager().missOnPurpose(this.ID);
missOnPurpose(coalition: string) {
getApp().getServerManager().missOnPurpose(this.ID, coalition);
}
/***********************************************/
getActions(): { [key: string]: { text: string, tooltip: string, type: string } } {
/* To be implemented by child classes */ // TODO make Unit an abstract class
return {};
}
executeAction(e: any, action: string) {
if (action === "center-map")
getApp().getMap().centerOnUnit(this.ID);
if (action === "attack")
getApp().getUnitsManager().selectedUnitsAttackUnit(this.ID);
else if (action === "refuel")
getApp().getUnitsManager().selectedUnitsRefuel();
else if (action === "group-ground" || action === "group-navy")
getApp().getUnitsManager().selectedUnitsCreateGroup();
else if (action === "scenic-aaa-red")
getApp().getUnitsManager().selectedUnitsScenicAAA("red");
else if (action === "scenic-aaa-blue")
getApp().getUnitsManager().selectedUnitsScenicAAA("blue");
else if (action === "miss-aaa-red")
getApp().getUnitsManager().selectedUnitsMissOnPurpose("red");
else if (action === "miss-aaa-blue")
getApp().getUnitsManager().selectedUnitsMissOnPurpose("blue");
else if (action === "follow")
this.#showFollowOptions(e);
}
/***********************************************/
onAdd(map: Map): this {
@ -761,18 +779,18 @@ export class Unit extends CustomMarker {
if (this.#waitingForDoubleClick) {
return;
}
// We'll wait for a doubleclick
this.#waitingForDoubleClick = true;
this.#doubleClickTimer = window.setTimeout(() => {
this.#doubleClickTimer = window.setTimeout(() => {
// Still waiting so no doubleclick; do the click action
if (this.#waitingForDoubleClick) {
if (getApp().getMap().getState() === IDLE || getApp().getMap().getState() === MOVE_UNIT || e.originalEvent.ctrlKey) {
if (!e.originalEvent.ctrlKey)
getApp().getUnitsManager().deselectAllUnits();
this.setSelected(!this.getSelected());
const detail = { "detail": { "unit": this } };
if (this.getSelected())
@ -788,7 +806,6 @@ export class Unit extends CustomMarker {
}
#onDoubleClick(e: any) {
// Let single clicks work again
this.#waitingForDoubleClick = false;
clearTimeout(this.#doubleClickTimer);
@ -801,58 +818,49 @@ export class Unit extends CustomMarker {
});
}
#onContextMenu(e: any) {
var options: { [key: string]: { text: string, tooltip: string } } = {};
const selectedUnits = getApp().getUnitsManager().getSelectedUnits();
const selectedUnitTypes = getApp().getUnitsManager().getSelectedUnitsCategories();
getActionOptions() {
var options: { [key: string]: { text: string, tooltip: string, type: string } } | null = null;
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it" };
var units = getApp().getUnitsManager().getSelectedUnits();
units.push(this);
if (selectedUnits.length > 0 && !(selectedUnits.length == 1 && (selectedUnits.includes(this)))) {
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons" };
if (getApp().getUnitsManager().getSelectedUnitsCategories().length == 1 && getApp().getUnitsManager().getSelectedUnitsCategories()[0] === "Aircraft")
options["follow"] = { text: "Follow", tooltip: "Follow the unit at a user defined distance and position" };
}
else if ((selectedUnits.length > 0 && (selectedUnits.includes(this))) || selectedUnits.length == 0) {
if (this.getCategory() == "Aircraft") {
options["refuel"] = { text: "Air to air refuel", tooltip: "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB." }; // TODO Add some way of knowing which aircraft can AAR
/* Keep only the common "or" options or any "and" option */
units.forEach((unit: Unit) => {
var unitOptions = unit.getActions();
if (options === null) {
options = unitOptions;
} else {
/* Options of "or" type get shown if any one unit has it*/
for (let optionKey in unitOptions) {
if (unitOptions[optionKey].type == "or") {
options[optionKey] = unitOptions[optionKey];
}
}
/* Options of "and" type get shown if ALL units have it */
for (let optionKey in options) {
if (!(optionKey in unitOptions)) {
delete options[optionKey];
}
}
}
}
});
if (selectedUnitTypes.length === 1 && ["NavyUnit", "GroundUnit"].includes(selectedUnitTypes[0]) && getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getCoalition()}) !== undefined)
options["group"] = { text: "Create group", tooltip: "Create a group from the selected units." };
return options ?? {};
}
if (selectedUnitTypes.length === 1 && ["GroundUnit"].includes(selectedUnitTypes[0]) && selectedUnits.every((unit: Unit) => { return ["AAA"].includes(unit.getType())})) {
options["scenic-aaa"] = { text: "Scenic AAA", tooltip: "Shoot AAA in the air without aiming at any target" };
options["miss-aaa"] = { text: "Miss on purpose AAA", tooltip: "Shoot AAA towards the closes enemy, but don't aim precisely" };
}
#onContextMenu(e: any) {
var options = this.getActionOptions();
if (Object.keys(options).length > 0) {
getApp().getMap().showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
getApp().getMap().getUnitContextMenu().setOptions(options, (option: string) => {
getApp().getMap().hideUnitContextMenu();
this.#executeAction(e, option);
this.executeAction(e, option);
});
}
}
#executeAction(e: any, action: string) {
if (action === "center-map")
getApp().getMap().centerOnUnit(this.ID);
if (action === "attack")
getApp().getUnitsManager().selectedUnitsAttackUnit(this.ID);
else if (action === "refuel")
getApp().getUnitsManager().selectedUnitsRefuel();
else if (action === "group")
getApp().getUnitsManager().selectedUnitsCreateGroup();
else if (action === "scenic-aaa")
getApp().getUnitsManager().selectedUnitsScenicAAA();
else if (action === "miss-aaa")
getApp().getUnitsManager().selectedUnitsMissOnPurpose();
else if (action === "follow")
this.#showFollowOptions(e);
}
#showFollowOptions(e: any) {
var options: { [key: string]: { text: string, tooltip: string } } = {};
@ -892,14 +900,14 @@ export class Unit extends CustomMarker {
var angleRad = deg2rad(angleDeg);
var distance = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#distance`)?.querySelector("input")).value));
var upDown = ftToM(parseInt((<HTMLInputElement>dialog.querySelector(`#up-down`)?.querySelector("input")).value));
// X: front-rear, positive front
// Y: top-bottom, positive top
// Z: left-right, positive right
var x = distance * Math.cos(angleRad);
var y = upDown;
var z = distance * Math.sin(angleRad);
getApp().getUnitsManager().selectedUnitsFollowUnit(this.ID, { "x": x, "y": y, "z": z });
}
});
@ -1166,6 +1174,37 @@ export class AirUnit extends Unit {
rotateToHeading: false
};
}
getActions() {
var options: { [key: string]: { text: string, tooltip: string, type: string } } = {};
/* Options if this unit is not selected */
if (!this.getSelected()) {
/* Someone else is selected */
if (getApp().getUnitsManager().getSelectedUnits().length > 0) {
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons", type: "or" };
options["follow"] = { text: "Follow", tooltip: "Follow the unit at a user defined distance and position", type: "or" };
} else {
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
}
}
/* Options if this unit is selected*/
else if (this.getSelected()) {
/* This is the only selected unit */
if (getApp().getUnitsManager().getSelectedUnits().length == 1) {
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
} else {
/* Provision */
}
options["refuel"] = { text: "Air to air refuel", tooltip: "Refuel units at the nearest AAR Tanker. If no tanker is available the unit will RTB.", type: "and" }; // TODO Add some way of knowing which aircraft can AAR
}
/* All other options */
else {
/* Provision */
}
return options;
}
}
export class Aircraft extends AirUnit {
@ -1209,6 +1248,41 @@ export class GroundUnit extends Unit {
};
}
getActions() {
var options: { [key: string]: { text: string, tooltip: string, type: string } } = {};
/* Options if this unit is not selected */
if (!this.getSelected()) {
/* Someone else is selected */
if (getApp().getUnitsManager().getSelectedUnits().length > 0) {
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons", type: "or" };
} else {
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
}
}
/* Options if this unit is selected*/
else if (this.getSelected()) {
/* This is the only selected unit */
if (getApp().getUnitsManager().getSelectedUnits().length == 1) {
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
} else {
options["group-ground"] = { text: "Create group", tooltip: "Create a group from the selected units", type: "and" };
}
if (["AAA", "flak"].includes(this.getType())) {
options["scenic-aaa-red"] = { text: "Scenic AAA (red)", tooltip: "Shoot AAA in the air without aiming at any target, when a red air unit gets close enough", type: "and" };
options["scenic-aaa-blue"] = { text: "Scenic AAA (blue)", tooltip: "Shoot AAA in the air without aiming at any target, when a blue air unit gets close enough", type: "and" };
options["miss-aaa-red"] = { text: "Miss on purpose AAA (red)", tooltip: "Shoot AAA towards the closest red air unit, but don't aim precisely", type: "and" };
options["miss-aaa-blue"] = { text: "Miss on purpose AAA (blue)", tooltip: "Shoot AAA towards the closest blue air unit, but don't aim precisely", type: "and" };
}
}
/* All other options */
else {
/* Provision */
}
return options;
}
getCategory() {
return "GroundUnit";
}
@ -1240,6 +1314,34 @@ export class NavyUnit extends Unit {
};
}
getActions() {
var options: { [key: string]: { text: string, tooltip: string, type: string } } = {};
/* Options if this unit is not selected */
if (!this.getSelected()) {
/* Someone else is selected */
if (getApp().getUnitsManager().getSelectedUnits().length > 0) {
options["attack"] = { text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons", type: "or" };
} else {
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
}
}
/* Options if this unit is selected */
else if (this.getSelected()) {
/* This is the only selected unit */
if (getApp().getUnitsManager().getSelectedUnits().length == 1) {
options["center-map"] = { text: "Center map", tooltip: "Center the map on the unit and follow it", type: "and" };
} else {
options["group-navy"] = { text: "Create group", tooltip: "Create a group from the selected units", type: "and" };
}
}
/* All other options */
else {
/* Provision */
}
return options;
}
getMarkerCategory() {
return "navyunit";
}

View File

@ -629,21 +629,23 @@ export class UnitsManager {
/** Instruct units to enter into scenic AAA mode. Units will shoot in the air without aiming
*
*/
selectedUnitsScenicAAA() {
selectedUnitsScenicAAA(coalition: string) {
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
for (let idx in selectedUnits) {
selectedUnits[idx].scenicAAA();
selectedUnits[idx].scenicAAA(coalition);
}
this.#showActionMessage(selectedUnits, `unit set to perform scenic AAA against ${coalition} units`);
}
/** Instruct units to enter into miss on purpose mode. Units will aim to the nearest enemy unit but not precisely.
*
*/
selectedUnitsMissOnPurpose() {
selectedUnitsMissOnPurpose(coalition: string) {
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
for (let idx in selectedUnits) {
selectedUnits[idx].missOnPurpose();
selectedUnits[idx].missOnPurpose(coalition);
}
this.#showActionMessage(selectedUnits, `unit set to perform miss on purpose AAA against ${coalition} units`);
}
/*********************** Control operations on selected units ************************/

View File

@ -61,6 +61,12 @@
</div>
</div>
<div id="operate-as" class="switch-control">
<h4>Operate as</h4>
<div id="operate-as-switch" class="ol-switch"></div>
<div>Determines if the unit will target red or blue units when performing scenic tasks.</div>
</div>
<div id="ai-on-off" class="switch-control">
<h4>Unit active</h4>
<div id="on-off-switch" class="ol-switch"></div>
@ -81,11 +87,11 @@
</div>
<div id="rapid-controls" class="ol-panel">
<button title="Increase units altitude" class="ol-button" data-on-click="selectedUnitsChangeAltitude" data-on-click-params='{ "type": "climb" }'><img src="/resources/theme/images/icons/climb.svg" inject-svg></button>
<button title="Descrease units altitude" class="ol-button" data-on-click="selectedUnitsChangeAltitude" data-on-click-params='{ "type": "descend" }'><img src="/resources/theme/images/icons/descent.svg" inject-svg></button>
<button title="Increase units speed" class="ol-button" data-on-click="selectedUnitsChangeSpeed" data-on-click-params='{ "type": "fast" }'><img src="/resources/theme/images/icons/speed-increase.svg" inject-svg></button>
<button title="Decrease units speed" class="ol-button" data-on-click="selectedUnitsChangeSpeed" data-on-click-params='{ "type": "slow" }'><img src="/resources/theme/images/icons/speed-decrease.svg" inject-svg></button>
<button title="Stop unit and go back to idle state" class="ol-button" data-on-click="selectedUnitsChangeSpeed" data-on-click-params='{ "type": "stop" }'><img src="/resources/theme/images/icons/hand-solid.svg" inject-svg></button>
<button id="climb" title="Increase units altitude" class="ol-button" data-on-click="selectedUnitsChangeAltitude" data-on-click-params='{ "type": "climb" }'><img src="/resources/theme/images/icons/climb.svg" inject-svg></button>
<button id="descend" title="Descrease units altitude" class="ol-button" data-on-click="selectedUnitsChangeAltitude" data-on-click-params='{ "type": "descend" }'><img src="/resources/theme/images/icons/descent.svg" inject-svg></button>
<button id="fast" title="Increase units speed" class="ol-button" data-on-click="selectedUnitsChangeSpeed" data-on-click-params='{ "type": "fast" }'><img src="/resources/theme/images/icons/speed-increase.svg" inject-svg></button>
<button id="slow" title="Decrease units speed" class="ol-button" data-on-click="selectedUnitsChangeSpeed" data-on-click-params='{ "type": "slow" }'><img src="/resources/theme/images/icons/speed-decrease.svg" inject-svg></button>
<button id="stop" title="Stop unit and go back to idle state" class="ol-button" data-on-click="selectedUnitsChangeSpeed" data-on-click-params='{ "type": "stop" }'><img src="/resources/theme/images/icons/hand-solid.svg" inject-svg></button>
</div>
</div>

View File

@ -0,0 +1,77 @@
import sys
import json
import inspect
import difflib
from slpp import slpp as lua
SEARCH_FOLDER = "D:\\Eagle Dynamics\\DCS World OpenBeta"
sys.path.append("D:\\Documents\\dcs")
from dcs.vehicles import *
from dcs.ships import *
from dcs.planes import *
from dcs.helicopters import *
# The database file on which to operate is the first standard argument of the call
if len(sys.argv) > 1:
if (sys.argv[1] == "aircraft"):
filename = '..\\..\\client\\public\\databases\\units\\aircraftdatabase.json'
units_map = plane_map
elif (sys.argv[1] == "helicopter"):
filename = '..\\..\\client\\public\\databases\\units\\helicopterdatabase.json'
units_map = helicopter_map
elif (sys.argv[1] == "groundunit"):
filename = '..\\..\\client\\public\\databases\\units\\groundunitdatabase.json'
units_map = vehicle_map
elif (sys.argv[1] == "navyunit"):
filename = '..\\..\\client\\public\\databases\\units\\navyunitdatabase.json'
units_map = ship_map
# Loads the database
with open(filename) as f:
database = json.load(f)
for unit in units_map.values():
if unit.id not in database:
database[unit.id] = {
"name": unit.id,
"coalition": "",
"era": "",
"label": unit.name,
"shortLabel": unit.name,
"type": unit.__qualname__.split(".")[0],
"enabled": True,
"liveries": {}
}
print("Added missing unit " + unit.id)
to_remove = []
to_change_case = {}
for id in database:
found = False
for unit in units_map.values():
if unit.id == id:
found = True
elif unit.id.lower() == id.lower() :
to_change_case[unit.id] = database[id]
if not found:
to_remove.append(id)
for id in to_remove:
if database[id]["type"] == "SAM Site":
print("Skipping " + id + ", it is a SAM Site")
else:
del database[id]
print("Removed unit " + id)
for id in to_change_case:
database[id] = to_change_case[id]
print("Changed case of unit " + id)
# Dump everything in the database
with open(filename, "w") as f:
json.dump(database, f, indent=2)
print("Done!")

View File

@ -1,21 +0,0 @@
import sys
import json
import inspect
import difflib
from slpp import slpp as lua
SEARCH_FOLDER = "D:\\Eagle Dynamics\\DCS World OpenBeta"
sys.path.append("..\\..\\..\\dcs-master\\dcs-master")
from dcs.vehicles import *
with open("gundata.h", "w") as f:
for unit in vehicle_map.values():
if unit in Artillery.__dict__.values() or unit in Armor.__dict__.values() or unit in Infantry.__dict__.values():
f.write('{"' + unit.id + '", {0.9, 860}}, \n')
# Done!
print("Done!")

View File

@ -1,109 +0,0 @@
{"2B11 mortar", {0.9, 860}},
{"SAU Gvozdika", {0.9, 860}},
{"SAU Msta", {0.9, 860}},
{"SAU Akatsia", {0.9, 860}},
{"SAU 2-C9", {0.9, 860}},
{"M-109", {0.9, 860}},
{"SpGH_Dana", {0.9, 860}},
{"AAV7", {0.9, 860}},
{"BMD-1", {0.9, 860}},
{"BMP-1", {0.9, 860}},
{"BMP-2", {0.9, 860}},
{"BMP-3", {0.9, 860}},
{"BRDM-2", {0.9, 860}},
{"BTR_D", {0.9, 860}},
{"Cobra", {0.9, 860}},
{"LAV-25", {0.9, 860}},
{"M1043 HMMWV Armament", {0.9, 860}},
{"M1045 HMMWV TOW", {0.9, 860}},
{"M1126 Stryker ICV", {0.9, 860}},
{"M-113", {0.9, 860}},
{"M1134 Stryker ATGM", {0.9, 860}},
{"M-2 Bradley", {0.9, 860}},
{"MCV-80", {0.9, 860}},
{"MTLB", {0.9, 860}},
{"Marder", {0.9, 860}},
{"TPZ", {0.9, 860}},
{"Grad_FDDM", {0.9, 860}},
{"Paratrooper RPG-16", {0.9, 860}},
{"Paratrooper AKS-74", {0.9, 860}},
{"Infantry AK Ins", {0.9, 860}},
{"Soldier AK", {0.9, 860}},
{"Infantry AK", {0.9, 860}},
{"Soldier M249", {0.9, 860}},
{"Soldier M4", {0.9, 860}},
{"Soldier M4 GRG", {0.9, 860}},
{"Soldier RPG", {0.9, 860}},
{"MLRS FDDM", {0.9, 860}},
{"Infantry AK ver2", {0.9, 860}},
{"Infantry AK ver3", {0.9, 860}},
{"Grad-URAL", {0.9, 860}},
{"Uragan_BM-27", {0.9, 860}},
{"Smerch", {0.9, 860}},
{"Smerch_HE", {0.9, 860}},
{"MLRS", {0.9, 860}},
{"Challenger2", {0.9, 860}},
{"Leclerc", {0.9, 860}},
{"M-60", {0.9, 860}},
{"M1128 Stryker MGS", {0.9, 860}},
{"M-1 Abrams", {0.9, 860}},
{"T-55", {0.9, 860}},
{"T-72B", {0.9, 860}},
{"T-80UD", {0.9, 860}},
{"T-90", {0.9, 860}},
{"Leopard1A3", {0.9, 860}},
{"Merkava_Mk4", {0.9, 860}},
{"JTAC", {0.9, 860}},
{"Infantry Animated", {0.9, 860}},
{"HL_DSHK", {0.9, 860}},
{"HL_KORD", {0.9, 860}},
{"tt_DSHK", {0.9, 860}},
{"tt_KORD", {0.9, 860}},
{"HL_B8M1", {0.9, 860}},
{"tt_B8M1", {0.9, 860}},
{"M4_Sherman", {0.9, 860}},
{"M2A1_halftrack", {0.9, 860}},
{"BTR-80", {0.9, 860}},
{"T-72B3", {0.9, 860}},
{"PT_76", {0.9, 860}},
{"BTR-82A", {0.9, 860}},
{"Chieftain_mk3", {0.9, 860}},
{"Pz_IV_H", {0.9, 860}},
{"Leopard-2A5", {0.9, 860}},
{"Leopard-2", {0.9, 860}},
{"leopard-2A4", {0.9, 860}},
{"leopard-2A4_trs", {0.9, 860}},
{"Sd_Kfz_251", {0.9, 860}},
{"T155_Firtina", {0.9, 860}},
{"VAB_Mephisto", {0.9, 860}},
{"ZTZ96B", {0.9, 860}},
{"ZBD04A", {0.9, 860}},
{"PLZ05", {0.9, 860}},
{"TYPE-59", {0.9, 860}},
{"Tiger_I", {0.9, 860}},
{"Tiger_II_H", {0.9, 860}},
{"Pz_V_Panther_G", {0.9, 860}},
{"Jagdpanther_G1", {0.9, 860}},
{"JagdPz_IV", {0.9, 860}},
{"Stug_IV", {0.9, 860}},
{"SturmPzIV", {0.9, 860}},
{"Wespe124", {0.9, 860}},
{"Sd_Kfz_234_2_Puma", {0.9, 860}},
{"soldier_mauser98", {0.9, 860}},
{"Stug_III", {0.9, 860}},
{"Elefant_SdKfz_184", {0.9, 860}},
{"Pak40", {0.9, 860}},
{"LeFH_18-40-105", {0.9, 860}},
{"Cromwell_IV", {0.9, 860}},
{"M4A4_Sherman_FF", {0.9, 860}},
{"soldier_wwii_br_01", {0.9, 860}},
{"Centaur_IV", {0.9, 860}},
{"Churchill_VII", {0.9, 860}},
{"Daimler_AC", {0.9, 860}},
{"Tetrarch", {0.9, 860}},
{"M12_GMC", {0.9, 860}},
{"soldier_wwii_us", {0.9, 860}},
{"M10_GMC", {0.9, 860}},
{"M8_Greyhound", {0.9, 860}},
{"M2A1-105", {0.9, 860}},
{"M4_Tractor", {0.9, 860}},