mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added "operate as" toggle
This commit is contained in:
parent
ce5f00e075
commit
569d45d58a
@ -63,7 +63,8 @@ const DEMO_UNIT_DATA = {
|
||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 1001, detectionMethod: 16}],
|
||||
activePath: [ ],
|
||||
isLeader: true
|
||||
isLeader: true,
|
||||
operateAs: 2
|
||||
}, ["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,
|
||||
@ -79,7 +80,8 @@ const DEMO_UNIT_DATA = {
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [],
|
||||
activePath: [ ],
|
||||
isLeader: false
|
||||
isLeader: false,
|
||||
operateAs: 2
|
||||
},
|
||||
["6"]:{ category: "Aircraft", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "FA-18C_hornet", unitName: "Bad boi 1-2", groupName: "Bad group 1", state: 1, task: "Being bad",
|
||||
hasTask: false, position: { lat: 36.8, lng: -116, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
@ -187,6 +189,7 @@ class DemoDataGenerator {
|
||||
array = this.appendContacts(array, unit.contacts, 36);
|
||||
array = this.appendActivePath(array, unit.activePath, 37);
|
||||
array = this.appendUint8(array, unit.isLeader, 38);
|
||||
array = this.appendUint8(array, unit.operateAs, 39);
|
||||
array = this.concat(array, this.uint8ToByteArray(255));
|
||||
}
|
||||
res.end(Buffer.from(array, 'binary'));
|
||||
|
||||
@ -377,20 +377,12 @@
|
||||
content: url("/resources/theme/images/icons/follow.svg");
|
||||
}
|
||||
|
||||
#scenic-aaa-red::before {
|
||||
content: url("/resources/theme/images/icons/scenic-red.svg");
|
||||
#scenic-aaa::before {
|
||||
content: url("/resources/theme/images/icons/scenic.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");
|
||||
#miss-aaa::before {
|
||||
content: url("/resources/theme/images/icons/miss.svg");
|
||||
}
|
||||
|
||||
#group-ground::before {
|
||||
|
||||
42
client/public/themes/olympus/images/icons/miss.svg
Normal file
42
client/public/themes/olympus/images/icons/miss.svg
Normal 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.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="311.0931"
|
||||
inkscape:cy="217.51225"
|
||||
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:#000000;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 |
49
client/public/themes/olympus/images/icons/scenic.svg
Normal file
49
client/public/themes/olympus/images/icons/scenic.svg
Normal 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.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. --><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:#000000;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 |
@ -197,5 +197,6 @@ export enum DataIndexes {
|
||||
contacts,
|
||||
activePath,
|
||||
isLeader,
|
||||
operateAs,
|
||||
endOfData = 255
|
||||
};
|
||||
@ -176,6 +176,7 @@ export interface UnitData {
|
||||
contacts: Contact[];
|
||||
activePath: LatLng[];
|
||||
isLeader: boolean;
|
||||
operateAs: string;
|
||||
}
|
||||
|
||||
export interface LoadoutItemBlueprint {
|
||||
|
||||
@ -351,6 +351,16 @@ export function enumToCoalition(coalitionID: number) {
|
||||
return "";
|
||||
}
|
||||
|
||||
export function coalitionToEnum(coalition: string) {
|
||||
switch (coalition){
|
||||
case "neutral": return 0;
|
||||
case "red": return 1;
|
||||
case "blue": return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
export function convertDateAndTimeToDate(dateAndTime: DateAndTime) {
|
||||
const date = dateAndTime.date;
|
||||
const time = dateAndTime.time;
|
||||
|
||||
@ -17,7 +17,7 @@ export class UnitControlPanel extends Panel {
|
||||
#speedTypeSwitch: Switch;
|
||||
#onOffSwitch: Switch;
|
||||
#followRoadsSwitch: Switch;
|
||||
#operateAs: Switch;
|
||||
#operateAsSwitch: Switch;
|
||||
#TACANXYDropdown: Dropdown;
|
||||
#radioDecimalsDropdown: Dropdown;
|
||||
#radioCallsignDropdown: Dropdown;
|
||||
@ -69,8 +69,8 @@ export class UnitControlPanel extends Panel {
|
||||
});
|
||||
|
||||
/* Operate as */
|
||||
this.#operateAs = new Switch("operate-as-switch", (value: boolean) => {
|
||||
//getApp().getUnitsManager().selectedUnitsSetFollowRoads(value);
|
||||
this.#operateAsSwitch = new Switch("operate-as-switch", (value: boolean) => {
|
||||
getApp().getUnitsManager().selectedUnitsSetOperateAs(value);
|
||||
});
|
||||
|
||||
/* Advanced settings dialog */
|
||||
@ -181,6 +181,7 @@ export class UnitControlPanel extends Panel {
|
||||
var desiredSpeedType = getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeedType()});
|
||||
var onOff = getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getOnOff()});
|
||||
var followRoads = getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getFollowRoads()});
|
||||
var operateAs = getApp().getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getOperateAs()});
|
||||
|
||||
this.#altitudeTypeSwitch.setValue(desiredAltitudeType != undefined? desiredAltitudeType == "ASL": undefined, false);
|
||||
this.#speedTypeSwitch.setValue(desiredSpeedType != undefined? desiredSpeedType == "CAS": undefined, false);
|
||||
@ -218,6 +219,7 @@ export class UnitControlPanel extends Panel {
|
||||
|
||||
this.#onOffSwitch.setValue(onOff, false);
|
||||
this.#followRoadsSwitch.setValue(followRoads, false);
|
||||
this.#operateAsSwitch.setValue(operateAs? operateAs === "blue": undefined, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -293,6 +293,13 @@ export class ServerManager {
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
setOperateAs(ID: number, operateAs: number, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID, "operateAs": operateAs }
|
||||
var data = { "setOperateAs": command }
|
||||
this.PUT(data, callback);
|
||||
}
|
||||
|
||||
|
||||
refuel(ID: number, callback: CallableFunction = () => {}) {
|
||||
var command = { "ID": ID };
|
||||
var data = { "refuel": command }
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map, Point } from 'leaflet';
|
||||
import { getApp } from '..';
|
||||
import { enumToCoalition, enumToEmissioNCountermeasure, getMarkerCategoryByName, enumToROE, enumToReactionToThreat, enumToState, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg, bearing, deg2rad, ftToM, getGroundElevation } from '../other/utils';
|
||||
import { enumToCoalition, enumToEmissioNCountermeasure, getMarkerCategoryByName, enumToROE, enumToReactionToThreat, enumToState, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg, bearing, deg2rad, ftToM, getGroundElevation, coalitionToEnum } from '../other/utils';
|
||||
import { CustomMarker } from '../map/markers/custommarker';
|
||||
import { SVGInjector } from '@tanem/svg-injector';
|
||||
import { UnitDatabase } from './databases/unitdatabase';
|
||||
@ -77,6 +77,7 @@ export class Unit extends CustomMarker {
|
||||
#contacts: Contact[] = [];
|
||||
#activePath: LatLng[] = [];
|
||||
#isLeader: boolean = false;
|
||||
#operateAs: string = "blue";
|
||||
|
||||
#selectable: boolean;
|
||||
#selected: boolean = false;
|
||||
@ -130,6 +131,7 @@ export class Unit extends CustomMarker {
|
||||
getContacts() { return this.#contacts };
|
||||
getActivePath() { return this.#activePath };
|
||||
getIsLeader() { return this.#isLeader };
|
||||
getOperateAs() { return this.#operateAs };
|
||||
|
||||
static getConstructor(type: string) {
|
||||
if (type === "GroundUnit") return GroundUnit;
|
||||
@ -232,6 +234,7 @@ export class Unit extends CustomMarker {
|
||||
case DataIndexes.contacts: this.#contacts = dataExtractor.extractContacts(); document.dispatchEvent(new CustomEvent("contactsUpdated", { detail: this })); break;
|
||||
case DataIndexes.activePath: this.#activePath = dataExtractor.extractActivePath(); break;
|
||||
case DataIndexes.isLeader: this.#isLeader = dataExtractor.extractBool(); break;
|
||||
case DataIndexes.operateAs: this.#operateAs = enumToCoalition(dataExtractor.extractUInt8()); break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -291,7 +294,8 @@ export class Unit extends CustomMarker {
|
||||
ammo: this.#ammo,
|
||||
contacts: this.#contacts,
|
||||
activePath: this.#activePath,
|
||||
isLeader: this.#isLeader
|
||||
isLeader: this.#isLeader,
|
||||
operateAs: this.#operateAs
|
||||
}
|
||||
}
|
||||
|
||||
@ -685,6 +689,11 @@ export class Unit extends CustomMarker {
|
||||
getApp().getServerManager().setFollowRoads(this.ID, followRoads);
|
||||
}
|
||||
|
||||
setOperateAs(operateAs: string) {
|
||||
if (!this.#human)
|
||||
getApp().getServerManager().setOperateAs(this.ID, coalitionToEnum(operateAs));
|
||||
}
|
||||
|
||||
delete(explosion: boolean, immediate: boolean) {
|
||||
getApp().getServerManager().deleteUnit(this.ID, explosion, immediate);
|
||||
}
|
||||
@ -731,11 +740,23 @@ export class Unit extends CustomMarker {
|
||||
});
|
||||
}
|
||||
|
||||
scenicAAA(coalition: string) {
|
||||
scenicAAA() {
|
||||
var coalition = "neutral";
|
||||
if (this.getCoalition() === "red")
|
||||
coalition = "blue";
|
||||
else if (this.getCoalition() == "blue")
|
||||
coalition = "red";
|
||||
//TODO
|
||||
getApp().getServerManager().scenicAAA(this.ID, coalition);
|
||||
}
|
||||
|
||||
missOnPurpose(coalition: string) {
|
||||
missOnPurpose() {
|
||||
var coalition = "neutral";
|
||||
if (this.getCoalition() === "red")
|
||||
coalition = "blue";
|
||||
else if (this.getCoalition() == "blue")
|
||||
coalition = "red";
|
||||
//TODO
|
||||
getApp().getServerManager().missOnPurpose(this.ID, coalition);
|
||||
}
|
||||
|
||||
@ -754,14 +775,10 @@ export class Unit extends CustomMarker {
|
||||
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 === "scenic-aaa")
|
||||
getApp().getUnitsManager().selectedUnitsScenicAAA();
|
||||
else if (action === "miss-aaa")
|
||||
getApp().getUnitsManager().selectedUnitsMissOnPurpose();
|
||||
else if (action === "follow")
|
||||
this.#showFollowOptions(e);
|
||||
}
|
||||
@ -1270,10 +1287,8 @@ export class GroundUnit extends Unit {
|
||||
}
|
||||
|
||||
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" };
|
||||
options["scenic-aaa"] = { text: "Scenic AAA", tooltip: "Shoot AAA in the air without aiming at any target, when a enemy unit gets close enough. WARNING: works correctly only on neutral units, blue or red units will aim", type: "and" };
|
||||
options["miss-aaa"] = { text: "Miss on purpose AAA", tooltip: "Shoot AAA towards the closest enemy unit, but don't aim precisely. WARNING: works correctly only on neutral units, blue or red units will aim", type: "and" };
|
||||
}
|
||||
}
|
||||
/* All other options */
|
||||
|
||||
@ -500,6 +500,19 @@ export class UnitsManager {
|
||||
this.#showActionMessage(selectedUnits, `follow roads set to ${followRoads}`);
|
||||
}
|
||||
|
||||
/** Instruct selected units to operate as a certain coalition
|
||||
*
|
||||
* @param operateAsBool If true, units will operate as blue
|
||||
*/
|
||||
selectedUnitsSetOperateAs(operateAsBool: boolean) {
|
||||
var operateAs = operateAsBool? "blue": "red";
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].setOperateAs(operateAs);
|
||||
}
|
||||
this.#showActionMessage(selectedUnits, `operate as set to ${operateAs}`);
|
||||
}
|
||||
|
||||
/** Instruct units to attack a specific unit
|
||||
*
|
||||
* @param ID ID of the unit to attack
|
||||
@ -629,23 +642,23 @@ export class UnitsManager {
|
||||
/** Instruct units to enter into scenic AAA mode. Units will shoot in the air without aiming
|
||||
*
|
||||
*/
|
||||
selectedUnitsScenicAAA(coalition: string) {
|
||||
selectedUnitsScenicAAA() {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].scenicAAA(coalition);
|
||||
selectedUnits[idx].scenicAAA();
|
||||
}
|
||||
this.#showActionMessage(selectedUnits, `unit set to perform scenic AAA against ${coalition} units`);
|
||||
this.#showActionMessage(selectedUnits, `unit set to perform scenic AAA`);
|
||||
}
|
||||
|
||||
/** Instruct units to enter into miss on purpose mode. Units will aim to the nearest enemy unit but not precisely.
|
||||
*
|
||||
*/
|
||||
selectedUnitsMissOnPurpose(coalition: string) {
|
||||
selectedUnitsMissOnPurpose() {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
for (let idx in selectedUnits) {
|
||||
selectedUnits[idx].missOnPurpose(coalition);
|
||||
selectedUnits[idx].missOnPurpose();
|
||||
}
|
||||
this.#showActionMessage(selectedUnits, `unit set to perform miss on purpose AAA against ${coalition} units`);
|
||||
this.#showActionMessage(selectedUnits, `unit set to perform miss on purpose AAA`);
|
||||
}
|
||||
|
||||
/*********************** Control operations on selected units ************************/
|
||||
|
||||
@ -43,6 +43,7 @@ namespace DataIndex {
|
||||
contacts,
|
||||
activePath,
|
||||
isLeader,
|
||||
operateAs,
|
||||
lastIndex,
|
||||
endOfData = 255
|
||||
};
|
||||
|
||||
@ -100,6 +100,7 @@ public:
|
||||
virtual void setContacts(vector<DataTypes::Contact> newValue);
|
||||
virtual void setActivePath(list<Coords> newValue);
|
||||
virtual void setIsLeader(bool newValue) { updateValue(isLeader, newValue, DataIndex::isLeader); }
|
||||
virtual void setOperateAs(unsigned char newValue) { updateValue(operateAs, newValue, DataIndex::operateAs); }
|
||||
|
||||
/********** Getters **********/
|
||||
virtual string getCategory() { return category; };
|
||||
@ -140,6 +141,7 @@ public:
|
||||
virtual vector<DataTypes::Contact> getTargets() { return contacts; }
|
||||
virtual list<Coords> getActivePath() { return activePath; }
|
||||
virtual bool getIsLeader() { return isLeader; }
|
||||
virtual unsigned char getOperateAs() { return operateAs; }
|
||||
|
||||
protected:
|
||||
unsigned int ID;
|
||||
@ -182,6 +184,7 @@ protected:
|
||||
vector<DataTypes::Contact> contacts;
|
||||
list<Coords> activePath;
|
||||
bool isLeader = false;
|
||||
unsigned char operateAs = 2;
|
||||
Coords activeDestination = Coords(NULL);
|
||||
|
||||
/********** Other **********/
|
||||
|
||||
@ -220,21 +220,28 @@ void GroundUnit::AIloop()
|
||||
case State::SCENIC_AAA: {
|
||||
setTask("Scenic AAA");
|
||||
|
||||
if (!getHasTask() || internalCounter == 0) {
|
||||
double r = 15; /* m */
|
||||
double barrelElevation = r * tan(acos(((double)(rand()) / (double)(RAND_MAX))));
|
||||
if ((!getHasTask() || internalCounter == 0) && getOperateAs() > 0) {
|
||||
double distance = 0;
|
||||
unsigned char targetCoalition = getOperateAs() == 2 ? 1 : 2;
|
||||
Unit* target = unitsManager->getClosestUnit(this, targetCoalition, { "Aircraft", "Helicopter" }, distance);
|
||||
|
||||
double lat = 0;
|
||||
double lng = 0;
|
||||
double randomBearing = ((double)(rand()) / (double)(RAND_MAX)) * 360;
|
||||
Geodesic::WGS84().Direct(position.lat, position.lng, randomBearing, r, lat, lng);
|
||||
/* Only run if an enemy air unit is closer than 20km to avoid useless load */
|
||||
if (distance < 20000 /* m */) {
|
||||
double r = 15; /* m */
|
||||
double barrelElevation = r * tan(acos(((double)(rand()) / (double)(RAND_MAX))));
|
||||
|
||||
std::ostringstream taskSS;
|
||||
taskSS.precision(10);
|
||||
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << position.alt + barrelElevation << ", radius = 0.001}";
|
||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||
scheduler->appendCommand(command);
|
||||
setHasTask(true);
|
||||
double lat = 0;
|
||||
double lng = 0;
|
||||
double randomBearing = ((double)(rand()) / (double)(RAND_MAX)) * 360;
|
||||
Geodesic::WGS84().Direct(position.lat, position.lng, randomBearing, r, lat, lng);
|
||||
|
||||
std::ostringstream taskSS;
|
||||
taskSS.precision(10);
|
||||
taskSS << "{id = 'FireAtPoint', lat = " << lat << ", lng = " << lng << ", alt = " << position.alt + barrelElevation << ", radius = 0.001}";
|
||||
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str(), [this]() { this->setHasTaskAssigned(true); }));
|
||||
scheduler->appendCommand(command);
|
||||
setHasTask(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (internalCounter == 0)
|
||||
@ -247,9 +254,10 @@ void GroundUnit::AIloop()
|
||||
setTask("Missing on purpose");
|
||||
|
||||
/* Only run this when the internal counter reaches 0 to avoid excessive computations when no nearby target */
|
||||
if (internalCounter == 0) {
|
||||
if (internalCounter == 0 && getOperateAs() > 0) {
|
||||
double distance = 0;
|
||||
Unit* target = unitsManager->getClosestUnit(this, 1, { "Aircraft", "Helicopter" }, distance); /* Red, TODO make assignable */
|
||||
unsigned char targetCoalition = getOperateAs() == 2 ? 1 : 2;
|
||||
Unit* target = unitsManager->getClosestUnit(this, targetCoalition, {"Aircraft", "Helicopter"}, distance);
|
||||
|
||||
/* Only do if we have a valid target close enough for AAA */
|
||||
if (target != nullptr && distance < 10000 /* m */) {
|
||||
|
||||
@ -592,7 +592,16 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
|
||||
unit->setState(State::MISS_ON_PURPOSE);
|
||||
log(username + " tasked unit " + unit->getName() + " to enter Miss On Purpose state", true);
|
||||
}
|
||||
else if (key.compare("setCommandModeOptions") == 0) {
|
||||
else if (key.compare("setOperateAs") == 0)
|
||||
{
|
||||
unsigned int ID = value[L"ID"].as_integer();
|
||||
unitsManager->acquireControl(ID);
|
||||
unsigned char operateAs = value[L"operateAs"].as_number().to_uint32();
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
unit->setOperateAs(operateAs);
|
||||
}
|
||||
else if (key.compare("setCommandModeOptions") == 0)
|
||||
{
|
||||
setCommandModeOptions(value);
|
||||
log(username + " updated the Command Mode Options", true);
|
||||
}
|
||||
|
||||
@ -191,6 +191,7 @@ void Unit::refreshLeaderData(unsigned long long time) {
|
||||
case DataIndex::radio: updateValue(radio, leader->radio, datumIndex); break;
|
||||
case DataIndex::generalSettings: updateValue(generalSettings, leader->generalSettings, datumIndex); break;
|
||||
case DataIndex::activePath: updateValue(activePath, leader->activePath, datumIndex); break;
|
||||
case DataIndex::operateAs: updateValue(operateAs, leader->operateAs, datumIndex); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -270,6 +271,7 @@ void Unit::getData(stringstream& ss, unsigned long long time)
|
||||
case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break;
|
||||
case DataIndex::activePath: appendList(ss, datumIndex, activePath); break;
|
||||
case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); break;
|
||||
case DataIndex::operateAs: appendNumeric(ss, datumIndex, operateAs); break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user