mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Performance optimizations for large unit counts
This commit is contained in:
@@ -15,7 +15,7 @@ const DEMO_UNIT_DATA = {
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 2, detectionMethod: 1}],
|
||||
contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}],
|
||||
activePath: [{lat: 38, lng: -115, alt: 0}, {lat: 38, lng: -114, alt: 0}]
|
||||
},
|
||||
["2"]:{ category: "Aircraft", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "FA-18C_hornet", unitName: "Cool guy 1-2", groupName: "Cool group 2", state: 1, task: "Being cool",
|
||||
@@ -33,7 +33,7 @@ const DEMO_UNIT_DATA = {
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 1, detectionMethod: 16}],
|
||||
activePath: [ ]
|
||||
}, ["3"]:{ category: "GroundUnit", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "M-60", unitName: "Cool guy 1-3", groupName: "Cool group 3", state: 1, task: "Being cool",
|
||||
}, ["3"]:{ category: "Missile", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "", unitName: "Cool guy 1-3", groupName: "Cool group 3", state: 1, task: "Being cool",
|
||||
hasTask: false, position: { lat: 37.1, lng: -116, 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 },
|
||||
@@ -343,7 +343,7 @@ class DemoDataGenerator {
|
||||
};
|
||||
|
||||
mission(req, res){
|
||||
var ret = {mission: {theatre: "Syria"}};
|
||||
var ret = {mission: {theatre: "Nevada"}};
|
||||
ret.time = Date.now();
|
||||
var auth = req.get("Authorization");
|
||||
if (auth) {
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
width: 180px;
|
||||
width: 250px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
|
||||
html * {
|
||||
font-family: 'Open Sans', sans-serif !important;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
}
|
||||
|
||||
#connection-status-panel[data-is-connected] dt::before {
|
||||
content: "Connected";
|
||||
content: "Connected FPS: " attr(data-framerate) " Load: " attr(data-load);
|
||||
}
|
||||
|
||||
#connection-status-panel[data-is-connected] dd::after {
|
||||
|
||||
60
client/public/themes/olympus/images/units/groundunit-ewr.svg
Normal file
60
client/public/themes/olympus/images/units/groundunit-ewr.svg
Normal file
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 50 50"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="groundunit-ewr.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
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">
|
||||
<rect
|
||||
x="25"
|
||||
y="2.37241"
|
||||
width="32"
|
||||
height="32"
|
||||
rx="1.1"
|
||||
transform="rotate(45 25 2.37241)"
|
||||
stroke="none"
|
||||
stroke-width="2"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="25"
|
||||
y="5.20083"
|
||||
width="28"
|
||||
height="28"
|
||||
transform="rotate(45 25 5.20083)"
|
||||
fill="none"
|
||||
stroke="#082E44"
|
||||
stroke-width="2"
|
||||
id="rect4" />
|
||||
<path
|
||||
stroke="#082E44"
|
||||
stroke-width="1.5"
|
||||
d="m 21.956541,27.690987 5.894515,-3.34903 -3.846924,-2.326589 5.759192,-3.618211"
|
||||
id="path942"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
stroke="#082E44"
|
||||
stroke-width="1.5"
|
||||
d="m 26.663842,17.477657 3.292749,0.82871 -0.740705,2.943076"
|
||||
id="path1230" />
|
||||
<path
|
||||
stroke="#082E44"
|
||||
stroke-width="2"
|
||||
id="path1657"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="27.107115"
|
||||
sodipodi:cy="22.407019"
|
||||
sodipodi:rx="10.069912"
|
||||
sodipodi:ry="10.084956"
|
||||
sodipodi:start="1.0594149"
|
||||
sodipodi:end="3.5325464"
|
||||
sodipodi:arc-type="arc"
|
||||
d="M 32.035153,31.201799 A 10.069912,10.084956 0 0 1 20.42801,29.95437 10.069912,10.084956 0 0 1 17.797018,18.563941"
|
||||
sodipodi:open="true" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 50 50"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="groundunit-sam-launcher.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
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">
|
||||
<path
|
||||
fill="#3BB9FF"
|
||||
stroke="none"
|
||||
stroke-width="2"
|
||||
d="M45.7733 41.3423L25.9481 7.63951C25.5228 6.91648 24.4772 6.91646 24.0519 7.63951L4.22671 41.3423C3.79536 42.0756 4.32409 43 5.17484 43H44.8252C45.6759 43 46.2046 42.0756 45.7733 41.3423Z"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M6.74842 41L25 9.97231L43.2516 41H6.74842Z"
|
||||
fill="none"
|
||||
stroke="#082E44"
|
||||
stroke-width="2"
|
||||
id="path4" />
|
||||
<path
|
||||
stroke="#082E44"
|
||||
stroke-width="2"
|
||||
id="path849"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="25.284166"
|
||||
sodipodi:cy="43.365532"
|
||||
sodipodi:rx="8.2439137"
|
||||
sodipodi:ry="8.2651606"
|
||||
sodipodi:start="3.8397244"
|
||||
sodipodi:end="5.5850536"
|
||||
sodipodi:arc-type="arc"
|
||||
d="m 18.968962,38.052789 a 8.2439137,8.2651606 0 0 1 6.315204,-2.952418 8.2439137,8.2651606 0 0 1 6.315205,2.952418"
|
||||
sodipodi:open="true" />
|
||||
<path
|
||||
stroke="#082E44"
|
||||
stroke-width="1.5"
|
||||
d="M 25.114189,34.887901 V 19.887378"
|
||||
id="path1085" />
|
||||
<path
|
||||
stroke="#082E44"
|
||||
stroke-width="1.5"
|
||||
d="m 23.074458,23.244436 1.981982,-3.432894 1.923784,3.332092"
|
||||
id="path1087" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,50 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="50"
|
||||
height="50"
|
||||
viewBox="0 0 50 50"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="groundunit-sam-radar.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
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">
|
||||
<path
|
||||
d="M45.7733 41.3423L25.9481 7.63951C25.5228 6.91648 24.4772 6.91646 24.0519 7.63951L4.22671 41.3423C3.79536 42.0756 4.32409 43 5.17484 43H44.8252C45.6759 43 46.2046 42.0756 45.7733 41.3423Z"
|
||||
fill="#3BB9FF"
|
||||
stroke="none"
|
||||
stroke-width="2"
|
||||
id="path2" />
|
||||
<path
|
||||
d="M6.74842 41L25 9.97231L43.2516 41H6.74842Z"
|
||||
fill="none"
|
||||
stroke="#082E44"
|
||||
stroke-width="2"
|
||||
id="path4"
|
||||
style="fill:none;fill-opacity:1" />
|
||||
<path
|
||||
style="fill:none;stroke:#082e44;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 23.148216,33.643859 5.192016,-2.949206 -3.388454,-2.048829 5.07282,-3.186251"
|
||||
id="path942"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
<path
|
||||
style="fill:none;stroke:#082e44;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;fill-opacity:1"
|
||||
d="m 27.294508,24.649847 2.900324,0.729775 -0.652429,2.591717"
|
||||
id="path1230" />
|
||||
<path
|
||||
style="fill:none;fill-opacity:1;stroke:#082e44;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
id="path1657"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="27.684952"
|
||||
sodipodi:cy="28.990719"
|
||||
sodipodi:rx="8.8697948"
|
||||
sodipodi:ry="8.8809643"
|
||||
sodipodi:start="1.0594149"
|
||||
sodipodi:end="3.5325464"
|
||||
sodipodi:arc-type="arc"
|
||||
sodipodi:open="true"
|
||||
d="M 32.025673,36.735535 A 8.8697948,8.8809643 0 0 1 21.801853,35.63703 8.8697948,8.8809643 0 0 1 19.484418,25.606446" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.1 KiB |
1
client/src/@types/dom.d.ts
vendored
1
client/src/@types/dom.d.ts
vendored
@@ -19,6 +19,7 @@ interface CustomEventMap {
|
||||
"mapStateChanged": CustomEvent<string>,
|
||||
"mapContextMenu": CustomEvent<>,
|
||||
"visibilityModeChanged": CustomEvent<string>,
|
||||
"contactsUpdated": CustomEvent<Unit>,
|
||||
}
|
||||
|
||||
declare global {
|
||||
|
||||
@@ -142,8 +142,8 @@ export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area";
|
||||
export const visibilityControls: string[] = ["human", "dcs", "aircraft", "groundunit-sam", "groundunit-other", "navyunit", "airbase"];
|
||||
export const visibilityControlsTootlips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"];
|
||||
|
||||
export const IADSTypes = ["AAA", "MANPADS", "SAM Sites", "Radar"];
|
||||
export const IADSDensities: {[key: string]: number}= {"AAA": 0.8, "MANPADS": 0.3, "SAM Sites": 0.1, "Radar": 0.05};
|
||||
export const IADSTypes = ["AAA", "MANPADS", "SAM Site", "Radar"];
|
||||
export const IADSDensities: {[key: string]: number}= {"AAA": 0.8, "MANPADS": 0.3, "SAM Site": 0.1, "Radar": 0.05};
|
||||
|
||||
export enum DataIndexes {
|
||||
startOfData = 0,
|
||||
@@ -184,5 +184,6 @@ export enum DataIndexes {
|
||||
ammo,
|
||||
contacts,
|
||||
activePath,
|
||||
isLeader,
|
||||
endOfData = 255
|
||||
};
|
||||
@@ -67,7 +67,7 @@ export class Map extends L.Map {
|
||||
constructor(ID: string) {
|
||||
/* Init the leaflet map */
|
||||
//@ts-ignore Needed because the boxSelect option is non-standard
|
||||
super(ID, { doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: true, maxBoundsViscosity: 1.0, minZoom: 7, keyboard: true, keyboardPanDelta: 0 });
|
||||
super(ID, { preferCanvas: true, doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true, zoomAnimation: true, maxBoundsViscosity: 1.0, minZoom: 7, keyboard: true, keyboardPanDelta: 0 });
|
||||
this.setView([37.23, -115.8], 10);
|
||||
|
||||
this.#ID = ID;
|
||||
@@ -295,6 +295,10 @@ export class Map extends L.Map {
|
||||
}
|
||||
}
|
||||
|
||||
getCenterUnit() {
|
||||
return this.#centerUnit;
|
||||
}
|
||||
|
||||
setTheatre(theatre: string) {
|
||||
var bounds = new L.LatLngBounds([-90, -180], [90, 180]);
|
||||
var miniMapZoom = 5;
|
||||
@@ -424,9 +428,6 @@ export class Map extends L.Map {
|
||||
|
||||
#onDoubleClick(e: any) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
|
||||
var db = groundUnitDatabase;
|
||||
db.generateTestGrid(this.getMouseCoordinates())
|
||||
}
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
|
||||
@@ -280,9 +280,17 @@ export function getMarkerCategoryByName(name: string) {
|
||||
else if (helicopterDatabase.getByName(name) != null)
|
||||
return "helicopter";
|
||||
else if (groundUnitDatabase.getByName(name) != null){
|
||||
// TODO this is very messy
|
||||
var type = groundUnitDatabase.getByName(name)?.type;
|
||||
return (type?.includes("SAM")) ? "groundunit-sam" : "groundunit-other";
|
||||
if (type === "SAM")
|
||||
return "groundunit-sam";
|
||||
else if (type === "SAM Search radar" || type === "SAM Track radar" || type === "SAM Search/Track radar")
|
||||
return "groundunit-sam-radar";
|
||||
else if (type === "SAM Launcher")
|
||||
return "groundunit-sam-launcher";
|
||||
else if (type === "Radar")
|
||||
return "groundunit-ewr";
|
||||
else
|
||||
return "groundunit-other";
|
||||
}
|
||||
else
|
||||
return "groundunit-other"; // TODO add other unit types
|
||||
|
||||
@@ -8,4 +8,12 @@ export class ConnectionStatusPanel extends Panel {
|
||||
update(connected: boolean) {
|
||||
this.getElement().toggleAttribute( "data-is-connected", connected );
|
||||
}
|
||||
|
||||
setMetrics(frameRate: number, load: number) {
|
||||
const dt = this.getElement().querySelector("dt");
|
||||
if (dt) {
|
||||
dt.dataset["framerate"] = String(frameRate);
|
||||
dt.dataset["load"] = String(load);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ export class UnitControlPanel extends Panel {
|
||||
element.toggleAttribute("data-show-advanced-settings-button", units.length == 1);
|
||||
|
||||
/* Flight controls */
|
||||
var desiredAltitude: number | undefined = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitude()});
|
||||
var desiredAltitude = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitude()});
|
||||
var desiredAltitudeType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitudeType()});
|
||||
var desiredSpeed = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeed()});
|
||||
var desiredSpeedType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeedType()});
|
||||
|
||||
@@ -18,7 +18,7 @@ var username = "";
|
||||
var password = "";
|
||||
|
||||
var sessionHash: string | null = null;
|
||||
var lastUpdateTime = 0;
|
||||
var lastUpdateTimes: {[key: string]: number} = {}
|
||||
var demoEnabled = false;
|
||||
|
||||
export function toggleDemoEnabled() {
|
||||
@@ -54,9 +54,14 @@ export function GET(callback: CallableFunction, uri: string, options?: { time?:
|
||||
/* Success */
|
||||
setConnected(true);
|
||||
if (xmlHttp.responseType == 'arraybuffer')
|
||||
callback(xmlHttp.response);
|
||||
else
|
||||
callback(JSON.parse(xmlHttp.responseText));
|
||||
lastUpdateTimes[uri] = callback(xmlHttp.response);
|
||||
else {
|
||||
const result = JSON.parse(xmlHttp.responseText);
|
||||
lastUpdateTimes[uri] = callback(result);
|
||||
|
||||
if ("frameRate" in result && "load" in result)
|
||||
getConnectionStatusPanel().setMetrics(result.frameRate, result.load);
|
||||
}
|
||||
} else if (xmlHttp.status == 401) {
|
||||
/* Bad credentials */
|
||||
console.error("Incorrect username/password");
|
||||
@@ -103,10 +108,6 @@ export function setAddress(address: string, port: number) {
|
||||
console.log(`Setting REST address to ${REST_ADDRESS}`)
|
||||
}
|
||||
|
||||
export function setLastUpdateTime(newLastUpdateTime: number) {
|
||||
lastUpdateTime = newLastUpdateTime;
|
||||
}
|
||||
|
||||
export function getAirbases(callback: CallableFunction) {
|
||||
GET(callback, AIRBASES_URI);
|
||||
}
|
||||
@@ -115,8 +116,8 @@ export function getBullseye(callback: CallableFunction) {
|
||||
GET(callback, BULLSEYE_URI);
|
||||
}
|
||||
|
||||
export function getLogs(callback: CallableFunction) {
|
||||
GET(callback, LOGS_URI);
|
||||
export function getLogs(callback: CallableFunction, refresh: boolean = false) {
|
||||
GET(callback, LOGS_URI, { time: refresh ? 0 : lastUpdateTimes[LOGS_URI]});
|
||||
}
|
||||
|
||||
export function getMission(callback: CallableFunction) {
|
||||
@@ -124,7 +125,7 @@ export function getMission(callback: CallableFunction) {
|
||||
}
|
||||
|
||||
export function getUnits(callback: CallableFunction, refresh: boolean = false) {
|
||||
GET(callback, `${UNITS_URI}`, { time: refresh ? 0 : lastUpdateTime }, 'arraybuffer');
|
||||
GET(callback, UNITS_URI, { time: refresh ? 0 : lastUpdateTimes[UNITS_URI] }, 'arraybuffer');
|
||||
}
|
||||
|
||||
export function addDestination(ID: number, path: any) {
|
||||
@@ -327,7 +328,7 @@ export function startUpdate() {
|
||||
getMissionData()?.update(data);
|
||||
checkSessionHash(data.sessionHash);
|
||||
});
|
||||
getUnits((buffer: ArrayBuffer) => getUnitsManager()?.update(buffer), true /* Does a full refresh */);
|
||||
getUnits((buffer: ArrayBuffer) => {return getUnitsManager()?.update(buffer), true /* Does a full refresh */});
|
||||
|
||||
requestUpdate();
|
||||
requestRefresh();
|
||||
@@ -336,7 +337,7 @@ export function startUpdate() {
|
||||
export function requestUpdate() {
|
||||
/* Main update rate = 250ms is minimum time, equal to server update time. */
|
||||
if (!getPaused()) {
|
||||
getUnits((buffer: ArrayBuffer) => { getUnitsManager()?.update(buffer); }, false);
|
||||
getUnits((buffer: ArrayBuffer) => { return getUnitsManager()?.update(buffer); }, false);
|
||||
}
|
||||
window.setTimeout(() => requestUpdate(), getConnected() ? 250 : 1000);
|
||||
|
||||
@@ -348,6 +349,13 @@ export function requestRefresh() {
|
||||
if (!getPaused()) {
|
||||
getAirbases((data: AirbasesData) => getMissionData()?.update(data));
|
||||
getBullseye((data: BullseyesData) => getMissionData()?.update(data));
|
||||
getLogs((data: any) => {
|
||||
for (let key in data.logs) {
|
||||
if (key != "requestTime")
|
||||
console.log(data.logs[key]);
|
||||
}
|
||||
return data.time;
|
||||
});
|
||||
getMission((data: any) => {
|
||||
checkSessionHash(data.sessionHash);
|
||||
getMissionData()?.update(data)
|
||||
|
||||
@@ -12,7 +12,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "SA-2 SAM Battery",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"SA-3 SAM Battery": {
|
||||
"name": "SA-3 SAM Battery",
|
||||
@@ -22,7 +22,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "SA-3 SAM Battery",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"SA-6 SAM Battery": {
|
||||
"name": "SA-6 SAM Battery",
|
||||
@@ -32,7 +32,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "SA-6 SAM Battery",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"SA-10 SAM Battery": {
|
||||
"name": "SA-10 SAM Battery",
|
||||
@@ -42,7 +42,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "SA-10 SAM Battery",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"SA-11 SAM Battery": {
|
||||
"name": "SA-11 SAM Battery",
|
||||
@@ -52,7 +52,17 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "SA-11 SAM Battery",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"SA-5 SAM Battery": {
|
||||
"name": "SA-5 SAM Battery",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-5 SAM Battery",
|
||||
"shortLabel": "SA-5 SAM Battery",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"Patriot site": {
|
||||
"name": "Patriot site",
|
||||
@@ -62,7 +72,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "Patriot site",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"Hawk SAM Battery": {
|
||||
"name": "Hawk SAM Battery",
|
||||
@@ -72,7 +82,25 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "Hawk SAM Battery",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM Sites"
|
||||
"type": "SAM Site"
|
||||
},
|
||||
"SNR_75V": {
|
||||
"name": "SNR_75V",
|
||||
"coalition": "Red",
|
||||
"era": "Early Cold War",
|
||||
"label": "SA-2 Fan Song",
|
||||
"shortLabel": "SNR 75V",
|
||||
"filename": "",
|
||||
"type": "SAM Track radar"
|
||||
},
|
||||
"S_75M_Volhov": {
|
||||
"name": "S_75M_Volhov",
|
||||
"coalition": "Red",
|
||||
"era": "Early Cold War",
|
||||
"label": "SA-2 Launcher",
|
||||
"shortLabel": "S75M Volhov",
|
||||
"filename": "",
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"2B11 mortar": {
|
||||
"name": "2B11 mortar",
|
||||
@@ -457,61 +485,61 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Kub 2P25 ln",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-6 Kub 2P25 ln",
|
||||
"label": "SA-6 Launcher",
|
||||
"shortLabel": "Kub 2P25 ln",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"5p73 s-125 ln": {
|
||||
"name": "5p73 s-125 ln",
|
||||
"coalition": "Red",
|
||||
"era": "Early Cold War",
|
||||
"label": "SA-3 5p73 s-125 ln",
|
||||
"label": "SA-3 Launcher",
|
||||
"shortLabel": "5p73 s-125 ln",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"S-300PS 5P85C ln": {
|
||||
"name": "S-300PS 5P85C ln",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-10 S-300PS 5P85C ln",
|
||||
"label": "SA-10 Launcher (5P85C)",
|
||||
"shortLabel": "S-300PS 5P85C ln",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"S-300PS 5P85D ln": {
|
||||
"name": "S-300PS 5P85D ln",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-10 S-300PS 5P85D ln",
|
||||
"label": "SA-10 Launcher (5P85D)",
|
||||
"shortLabel": "S-300PS 5P85D ln",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"SA-11 Buk LN 9A310M1": {
|
||||
"name": "SA-11 Buk LN 9A310M1",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-11 Buk LN 9A310M1",
|
||||
"label": "SA-11 Launcher",
|
||||
"shortLabel": "SA-11 Buk LN 9A310M1",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"Osa 9A33 ln": {
|
||||
"name": "Osa 9A33 ln",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-8 Osa 9A33 ln",
|
||||
"label": "SA-8 Launcher",
|
||||
"shortLabel": "Osa 9A33 ln",
|
||||
"range": "Short",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"Tor 9A331": {
|
||||
"name": "Tor 9A331",
|
||||
@@ -547,11 +575,11 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "SA-11 Buk CC 9S470M1",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-11 Buk CC 9S470M1",
|
||||
"label": "SA-11 Command Post",
|
||||
"shortLabel": "SA-11 Buk CC 9S470M1",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"SA-8 Osa LD 9T217": {
|
||||
"name": "SA-8 Osa LD 9T217",
|
||||
@@ -567,21 +595,21 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Patriot AMG",
|
||||
"coalition": "Blue",
|
||||
"era": "Modern",
|
||||
"label": "Patriot AMG",
|
||||
"label": "Patriot Antenna Mast Group",
|
||||
"shortLabel": "Patriot AMG",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"Patriot ECS": {
|
||||
"name": "Patriot ECS",
|
||||
"coalition": "Blue",
|
||||
"era": "Modern",
|
||||
"label": "Patriot ECS",
|
||||
"label": "Patriot Engagement Control Station",
|
||||
"shortLabel": "Patriot ECS",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"Gepard": {
|
||||
"name": "Gepard",
|
||||
@@ -596,11 +624,11 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Hawk pcp",
|
||||
"coalition": "Blue",
|
||||
"era": "Late Cold War",
|
||||
"label": "Hawk pcp",
|
||||
"label": "Hawk Platoon Command Post",
|
||||
"shortLabel": "Hawk pcp",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"SA-18 Igla manpad": {
|
||||
"name": "SA-18 Igla manpad",
|
||||
@@ -632,6 +660,36 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"filename": "",
|
||||
"type": "MANPADS"
|
||||
},
|
||||
"RPC_5N62V": {
|
||||
"name": "RPC_5N62V",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-5 Square Pair",
|
||||
"shortLabel": "RPC 5N62V",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Track radar"
|
||||
},
|
||||
"RLS_19J6": {
|
||||
"name": "RLS_19J6",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-5 Thin Shield",
|
||||
"shortLabel": "RLS 19J6",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"S-200_Launcher": {
|
||||
"name": "S-200_Launcher",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-5 Launcher",
|
||||
"shortLabel": "S-200 Launcher",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"Vulcan": {
|
||||
"name": "Vulcan",
|
||||
"coalition": "Blue",
|
||||
@@ -645,10 +703,10 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Hawk ln",
|
||||
"coalition": "Blue",
|
||||
"era": "Late Cold War",
|
||||
"label": "Hawk ln",
|
||||
"label": "Hawk Launcher",
|
||||
"shortLabel": "Hawk ln",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"M48 Chaparral": {
|
||||
"name": "M48 Chaparral",
|
||||
@@ -672,11 +730,11 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Patriot ln",
|
||||
"coalition": "Blue",
|
||||
"era": "Late Cold War",
|
||||
"label": "Patriot ln",
|
||||
"label": "Patriot Launcher",
|
||||
"shortLabel": "Patriot ln",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Launcher"
|
||||
},
|
||||
"M1097 Avenger": {
|
||||
"name": "M1097 Avenger",
|
||||
@@ -691,21 +749,21 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Patriot EPP",
|
||||
"coalition": "Blue",
|
||||
"era": "Late Cold War",
|
||||
"label": "Patriot EPP",
|
||||
"label": "Patriot Electric Power Plant",
|
||||
"shortLabel": "Patriot EPP",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"Patriot cp": {
|
||||
"name": "Patriot cp",
|
||||
"coalition": "Blue",
|
||||
"era": "Late Cold War",
|
||||
"label": "Patriot cp",
|
||||
"label": "Patriot Command Post",
|
||||
"shortLabel": "Patriot cp",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"Roland ADS": {
|
||||
"name": "Roland ADS",
|
||||
@@ -720,11 +778,11 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "S-300PS 54K6 cp",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-10 S-300PS 54K6 cp",
|
||||
"label": "SA-10 Command Post",
|
||||
"shortLabel": "S-300PS 54K6 cp",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Support vehicle"
|
||||
},
|
||||
"Stinger manpad GRG": {
|
||||
"name": "Stinger manpad GRG",
|
||||
@@ -734,7 +792,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "Stinger manpad GRG",
|
||||
"range": "Short",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "MANPADS"
|
||||
},
|
||||
"Stinger manpad dsr": {
|
||||
"name": "Stinger manpad dsr",
|
||||
@@ -754,7 +812,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "Stinger comm dsr",
|
||||
"range": "Short",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "MANPADS"
|
||||
},
|
||||
"Stinger manpad": {
|
||||
"name": "Stinger manpad",
|
||||
@@ -774,7 +832,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"shortLabel": "Stinger comm",
|
||||
"range": "Short",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "MANPADS"
|
||||
},
|
||||
"ZSU-23-4 Shilka": {
|
||||
"name": "ZSU-23-4 Shilka",
|
||||
@@ -843,7 +901,7 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "1L13 EWR",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "1L13 EWR",
|
||||
"label": "Box Spring",
|
||||
"shortLabel": "1L13 EWR",
|
||||
"filename": "",
|
||||
"type": "Radar"
|
||||
@@ -852,37 +910,37 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "Kub 1S91 str",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-6 Kub 1S91 str",
|
||||
"label": "SA-6 Straight flush",
|
||||
"shortLabel": "Kub 1S91 str",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search/Track radar"
|
||||
},
|
||||
"S-300PS 40B6M tr": {
|
||||
"name": "S-300PS 40B6M tr",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-10 S-300PS 40B6M tr",
|
||||
"label": "SA-10 Tin Shield",
|
||||
"shortLabel": "S-300PS 40B6M tr",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Track radar"
|
||||
},
|
||||
"S-300PS 40B6MD sr": {
|
||||
"name": "S-300PS 40B6MD sr",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-10 S-300PS 40B6MD sr",
|
||||
"label": "SA-10 Clam Shell",
|
||||
"shortLabel": "S-300PS 40B6MD sr",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"55G6 EWR": {
|
||||
"name": "55G6 EWR",
|
||||
"coalition": "Red",
|
||||
"era": "Early Cold War",
|
||||
"label": "55G6 EWR",
|
||||
"label": "Tall Rack",
|
||||
"shortLabel": "55G6 EWR",
|
||||
"filename": "",
|
||||
"type": "Radar"
|
||||
@@ -891,98 +949,98 @@ export class GroundUnitDatabase extends UnitDatabase {
|
||||
"name": "S-300PS 64H6E sr",
|
||||
"coalition": "Red",
|
||||
"era": "Late Cold War",
|
||||
"label": "SA-10 S-300PS 64H6E sr",
|
||||
"label": "SA-10 Big Bird",
|
||||
"shortLabel": "S-300PS 64H6E sr",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"SA-11 Buk SR 9S18M1": {
|
||||
"name": "SA-11 Buk SR 9S18M1",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-11 Buk SR 9S18M1",
|
||||
"label": "SA-11 Snown Drift",
|
||||
"shortLabel": "SA-11 Buk SR 9S18M1",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"Dog Ear radar": {
|
||||
"name": "Dog Ear radar",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "Dog Ear radar",
|
||||
"label": "Dog Ear",
|
||||
"shortLabel": "Dog Ear radar",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"Hawk tr": {
|
||||
"name": "Hawk tr",
|
||||
"coalition": "Blue",
|
||||
"era": "Early Cold War",
|
||||
"label": "Hawk tr",
|
||||
"label": "Hawk Track radar",
|
||||
"shortLabel": "Hawk tr",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Track radar"
|
||||
},
|
||||
"Hawk sr": {
|
||||
"name": "Hawk sr",
|
||||
"coalition": "Blue",
|
||||
"era": "Early Cold War",
|
||||
"label": "Hawk sr",
|
||||
"label": "Hawk Search radar",
|
||||
"shortLabel": "Hawk sr",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"Patriot str": {
|
||||
"name": "Patriot str",
|
||||
"coalition": "Blue",
|
||||
"era": "Late Cold War",
|
||||
"label": "Patriot str",
|
||||
"label": "Patriot Search/Track radar",
|
||||
"shortLabel": "Patriot str",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search/Track radar"
|
||||
},
|
||||
"Hawk cwar": {
|
||||
"name": "Hawk cwar",
|
||||
"coalition": "Blue",
|
||||
"era": "Early Cold War",
|
||||
"label": "Hawk cwar",
|
||||
"label": "Hawk Continous Wave Acquisition Radar",
|
||||
"shortLabel": "Hawk cwar",
|
||||
"range": "Long",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Track radar"
|
||||
},
|
||||
"p-19 s-125 sr": {
|
||||
"name": "p-19 s-125 sr",
|
||||
"coalition": "Red",
|
||||
"era": "Mid Cold War",
|
||||
"label": "SA-3 p-19 s-125 sr",
|
||||
"shortLabel": "p-19 s-125 sr",
|
||||
"label": "SA-3 Flat Face B",
|
||||
"shortLabel": "Flat Face B",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"Roland Radar": {
|
||||
"name": "Roland Radar",
|
||||
"coalition": "Blue",
|
||||
"era": "Mid Cold War",
|
||||
"label": "Roland Radar",
|
||||
"label": "Roland Search radar",
|
||||
"shortLabel": "Roland Radar",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Search radar"
|
||||
},
|
||||
"snr s-125 tr": {
|
||||
"name": "snr s-125 tr",
|
||||
"coalition": "Red",
|
||||
"era": "Early Cold War",
|
||||
"label": "SA-3 snr s-125 tr",
|
||||
"label": "SA-3 Low Blow",
|
||||
"shortLabel": "snr s-125 tr",
|
||||
"range": "Medium",
|
||||
"filename": "",
|
||||
"type": "SAM"
|
||||
"type": "SAM Track radar"
|
||||
},
|
||||
"house1arm": {
|
||||
"name": "house1arm",
|
||||
|
||||
@@ -9,6 +9,8 @@ import { TargetMarker } from '../map/targetmarker';
|
||||
import { BLUE_COMMANDER, BOMBING, CARPET_BOMBING, DLINK, DataIndexes, FIRE_AT_AREA, GAME_MASTER, HIDE_ALL, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, RED_COMMANDER, ROEs, RWR, VISUAL, emissionsCountermeasures, reactionsToThreat, states } from '../constants/constants';
|
||||
import { Ammo, Contact, GeneralSettings, Offset, Radio, TACAN, UnitIconOptions } from '../@types/unit';
|
||||
import { DataExtractor } from './dataextractor';
|
||||
import { groundUnitDatabase } from './groundunitdatabase';
|
||||
import { navyUnitDatabase } from './navyunitdatabase';
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: '/resources/theme/images/markers/marker-icon.png',
|
||||
@@ -74,6 +76,7 @@ export class Unit extends CustomMarker {
|
||||
#ammo: Ammo[] = [];
|
||||
#contacts: Contact[] = [];
|
||||
#activePath: LatLng[] = [];
|
||||
#isLeader: boolean = false;
|
||||
|
||||
#selectable: boolean;
|
||||
#selected: boolean = false;
|
||||
@@ -126,6 +129,7 @@ export class Unit extends CustomMarker {
|
||||
getAmmo() {return this.#ammo};
|
||||
getContacts() {return this.#contacts};
|
||||
getActivePath() {return this.#activePath};
|
||||
getIsLeader() {return this.#isLeader};
|
||||
|
||||
static getConstructor(type: string) {
|
||||
if (type === "GroundUnit") return GroundUnit;
|
||||
@@ -162,6 +166,8 @@ export class Unit extends CustomMarker {
|
||||
document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => {
|
||||
window.setTimeout(() => { this.setSelected(this.getSelected() && !this.getHidden()) }, 300);
|
||||
});
|
||||
|
||||
getMap().on("zoomend", () => {this.#onZoom();})
|
||||
}
|
||||
|
||||
getCategory() {
|
||||
@@ -212,8 +218,9 @@ export class Unit extends CustomMarker {
|
||||
case DataIndexes.radio: this.#radio = dataExtractor.extractRadio(); break;
|
||||
case DataIndexes.generalSettings: this.#generalSettings = dataExtractor.extractGeneralSettings(); break;
|
||||
case DataIndexes.ammo: this.#ammo = dataExtractor.extractAmmo(); break;
|
||||
case DataIndexes.contacts: this.#contacts = dataExtractor.extractContacts(); break;
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -223,25 +230,20 @@ export class Unit extends CustomMarker {
|
||||
if (updateMarker)
|
||||
this.#updateMarker();
|
||||
|
||||
document.dispatchEvent(new CustomEvent("unitUpdated", { detail: this }));
|
||||
if (this.getSelected() || getMap().getCenterUnit() === this)
|
||||
document.dispatchEvent(new CustomEvent("unitUpdated", { detail: this }));
|
||||
}
|
||||
|
||||
drawLines() {
|
||||
// TODO dont delete the polylines of the detected units
|
||||
this.#clearContacts();
|
||||
if (this.getSelected()) {
|
||||
this.#drawPath();
|
||||
this.#drawContacts();
|
||||
this.#drawTarget();
|
||||
}
|
||||
else {
|
||||
this.#clearPath();
|
||||
this.#clearTarget();
|
||||
}
|
||||
this.#drawPath();
|
||||
this.#drawContacts();
|
||||
this.#drawTarget();
|
||||
}
|
||||
|
||||
getData() {
|
||||
return {
|
||||
category: this.getCategory(),
|
||||
ID: this.ID,
|
||||
alive: this.#alive,
|
||||
human: this.#human,
|
||||
controlled: this.#controlled,
|
||||
@@ -277,7 +279,8 @@ export class Unit extends CustomMarker {
|
||||
generalSettings: this.#generalSettings,
|
||||
ammo: this.#ammo,
|
||||
contacts: this.#contacts,
|
||||
activePath: this.#activePath
|
||||
activePath: this.#activePath,
|
||||
isLeader: this.#isLeader
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +318,7 @@ export class Unit extends CustomMarker {
|
||||
/* Only alive units can be selected. Some units are not selectable (weapons) */
|
||||
if ((this.#alive || !selected) && this.getSelectable() && this.getSelected() != selected && this.belongsToCommandedCoalition()) {
|
||||
this.#selected = selected;
|
||||
this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-selected", selected);
|
||||
|
||||
if (selected) {
|
||||
document.dispatchEvent(new CustomEvent("unitSelection", { detail: this }));
|
||||
this.#updateMarker();
|
||||
@@ -326,6 +329,15 @@ export class Unit extends CustomMarker {
|
||||
this.#clearPath();
|
||||
this.#clearTarget();
|
||||
}
|
||||
|
||||
this.getElement()?.querySelector(`.unit`)?.toggleAttribute("data-is-selected", selected);
|
||||
if (getMap().getZoom() < 13) {
|
||||
if (this.#isLeader)
|
||||
this.getGroupMembers().forEach((unit: Unit) => unit.setSelected(selected));
|
||||
else
|
||||
this.#updateMarker();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -376,6 +388,10 @@ export class Unit extends CustomMarker {
|
||||
return true;
|
||||
}
|
||||
|
||||
getType() {
|
||||
return "";
|
||||
}
|
||||
|
||||
/********************** Icon *************************/
|
||||
createIcon(): void {
|
||||
/* Set the icon */
|
||||
@@ -478,21 +494,16 @@ export class Unit extends CustomMarker {
|
||||
|
||||
/********************** Visibility *************************/
|
||||
updateVisibility() {
|
||||
var hidden = false;
|
||||
const hiddenUnits = getUnitsManager().getHiddenTypes();
|
||||
if (this.#human && hiddenUnits.includes("human"))
|
||||
hidden = true;
|
||||
if (this.#controlled == false && hiddenUnits.includes("dcs"))
|
||||
hidden = true;
|
||||
if (hiddenUnits.includes(this.getMarkerCategory()))
|
||||
hidden = true;
|
||||
if (hiddenUnits.includes(this.#coalition))
|
||||
hidden = true;
|
||||
if (getUnitsManager().getCommandMode() === HIDE_ALL)
|
||||
hidden = true;
|
||||
if (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0) {
|
||||
hidden = true;
|
||||
}
|
||||
var hidden = ((this.#human && hiddenUnits.includes("human")) ||
|
||||
(this.#controlled == false && hiddenUnits.includes("dcs")) ||
|
||||
(hiddenUnits.includes(this.getMarkerCategory())) ||
|
||||
(hiddenUnits.includes(this.#coalition)) ||
|
||||
(getUnitsManager().getCommandMode() === HIDE_ALL) ||
|
||||
(!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0) ||
|
||||
(!this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13)) &&
|
||||
!(this.getSelected());
|
||||
|
||||
this.setHidden(hidden || !this.#alive);
|
||||
}
|
||||
|
||||
@@ -718,7 +729,7 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
else if ((selectedUnits.length > 0 && (selectedUnits.includes(this))) || selectedUnits.length == 0) {
|
||||
if (this.getCategory() == "Aircraft") {
|
||||
options["refuel"] = { text: "Air to air refuel", tooltip: "Refuel unit at the nearest AAR Tanker. If no tanker is available the unit will RTB." }; // TODO Add some way of knowing which aircraft can AAR
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -730,10 +741,13 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
if ((selectedUnits.length === 0 && this.getCategory() == "GroundUnit") || selectedUnitTypes.length === 1 && ["GroundUnit"].includes(selectedUnitTypes[0])) {
|
||||
if (selectedUnits.concat([this]).every((unit: Unit) => { return unit.canFulfillRole(["Gun Artillery", "Rocket Artillery", "Infantry", "IFV", "Tank"]) }))
|
||||
if (selectedUnits.concat([this]).every((unit: Unit) => { return ["Gun Artillery", "Rocket Artillery", "Infantry", "IFV", "Tank"].includes(this.getType()) }))
|
||||
options["fire-at-area"] = { text: "Fire at area", tooltip: "Fire at a large area" };
|
||||
}
|
||||
|
||||
if (selectedUnitTypes.length === 1 && ["NavyUnit", "GroundUnit"].includes(selectedUnitTypes[0]) && getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getCoalition()}) !== undefined)
|
||||
options["group"] = { text: "Create group", tooltip: "Create a group from the selected units." };
|
||||
|
||||
if (Object.keys(options).length > 0) {
|
||||
getMap().showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
|
||||
getMap().getUnitContextMenu().setOptions(options, (option: string) => {
|
||||
@@ -750,6 +764,8 @@ export class Unit extends CustomMarker {
|
||||
getUnitsManager().selectedUnitsAttackUnit(this.ID);
|
||||
else if (action === "refuel")
|
||||
getUnitsManager().selectedUnitsRefuel();
|
||||
else if (action === "group")
|
||||
getUnitsManager().selectedUnitsCreateGroup();
|
||||
else if (action === "follow")
|
||||
this.#showFollowOptions(e);
|
||||
else if (action === "bomb")
|
||||
@@ -758,6 +774,7 @@ export class Unit extends CustomMarker {
|
||||
getMap().setState(CARPET_BOMBING);
|
||||
else if (action === "fire-at-area")
|
||||
getMap().setState(FIRE_AT_AREA);
|
||||
|
||||
}
|
||||
|
||||
#showFollowOptions(e: any) {
|
||||
@@ -949,10 +966,11 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
|
||||
#drawContacts() {
|
||||
this.#clearContacts();
|
||||
for (let index in this.#contacts) {
|
||||
var contactData = this.#contacts[index];
|
||||
var contact = getUnitsManager().getUnitByID(contactData.ID)
|
||||
if (contact != null) {
|
||||
if (contact != null && contact.getAlive()) {
|
||||
var startLatLng = new LatLng(this.#position.lat, this.#position.lng);
|
||||
var endLatLng: LatLng;
|
||||
if (contactData.detectionMethod === RWR) {
|
||||
@@ -1017,6 +1035,10 @@ export class Unit extends CustomMarker {
|
||||
if (getMap().hasLayer(this.#targetPositionPolyline))
|
||||
this.#targetPositionPolyline.removeFrom(getMap());
|
||||
}
|
||||
|
||||
#onZoom() {
|
||||
this.#updateMarker();
|
||||
}
|
||||
}
|
||||
|
||||
export class AirUnit extends Unit {
|
||||
@@ -1079,6 +1101,11 @@ export class GroundUnit extends Unit {
|
||||
getCategory() {
|
||||
return "GroundUnit";
|
||||
}
|
||||
|
||||
getType() {
|
||||
var blueprint = groundUnitDatabase.getByName(this.getName());
|
||||
return blueprint?.type? blueprint.type: "";
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnit extends Unit {
|
||||
@@ -1108,6 +1135,11 @@ export class NavyUnit extends Unit {
|
||||
getCategory() {
|
||||
return "NavyUnit";
|
||||
}
|
||||
|
||||
getType() {
|
||||
var blueprint = navyUnitDatabase.getByName(this.getName());
|
||||
return blueprint?.type? blueprint.type: "";
|
||||
}
|
||||
}
|
||||
|
||||
export class Weapon extends Unit {
|
||||
@@ -1115,21 +1147,6 @@ export class Weapon extends Unit {
|
||||
super(ID);
|
||||
this.setSelectable(false);
|
||||
}
|
||||
|
||||
getIconOptions() {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: false,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: false,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: false,
|
||||
showCallsign: false,
|
||||
rotateToHeading: true
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class Missile extends Weapon {
|
||||
@@ -1142,7 +1159,25 @@ export class Missile extends Weapon {
|
||||
}
|
||||
|
||||
getMarkerCategory() {
|
||||
return "missile";
|
||||
if (this.belongsToCommandedCoalition() || this.getDetectionMethods().includes(VISUAL) || this.getDetectionMethods().includes(OPTIC))
|
||||
return "missile";
|
||||
else
|
||||
return "aircraft";
|
||||
}
|
||||
|
||||
getIconOptions() {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: (!this.belongsToCommandedCoalition() && !this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)) && this.getDetectionMethods().some(value => [RADAR, IRST, DLINK].includes(value))),
|
||||
showHotgroup: false,
|
||||
showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: false,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: (!this.belongsToCommandedCoalition() && !this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)) && this.getDetectionMethods().some(value => [RADAR, IRST, DLINK].includes(value))),
|
||||
showCallsign: false,
|
||||
rotateToHeading: this.belongsToCommandedCoalition() || this.getDetectionMethods().includes(VISUAL) || this.getDetectionMethods().includes(OPTIC)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1156,6 +1191,24 @@ export class Bomb extends Weapon {
|
||||
}
|
||||
|
||||
getMarkerCategory() {
|
||||
return "bomb";
|
||||
if (this.belongsToCommandedCoalition() || this.getDetectionMethods().includes(VISUAL) || this.getDetectionMethods().includes(OPTIC))
|
||||
return "bomb";
|
||||
else
|
||||
return "aircraft";
|
||||
}
|
||||
|
||||
getIconOptions() {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: (!this.belongsToCommandedCoalition() && !this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)) && this.getDetectionMethods().some(value => [RADAR, IRST, DLINK].includes(value))),
|
||||
showHotgroup: false,
|
||||
showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: false,
|
||||
showFuel: false,
|
||||
showAmmo: false,
|
||||
showSummary: (!this.belongsToCommandedCoalition() && !this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)) && this.getDetectionMethods().some(value => [RADAR, IRST, DLINK].includes(value))),
|
||||
showCallsign: false,
|
||||
rotateToHeading: this.belongsToCommandedCoalition() || this.getDetectionMethods().includes(VISUAL) || this.getDetectionMethods().includes(OPTIC)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { getHotgroupPanel, getInfoPopup, getMap } from "..";
|
||||
import { Unit } from "./unit";
|
||||
import { cloneUnit, setLastUpdateTime, spawnAircrafts, spawnGroundUnits } from "../server/server";
|
||||
import { cloneUnit, deleteUnit, spawnAircrafts, spawnGroundUnits } from "../server/server";
|
||||
import { bearingAndDistanceToLatLng, deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils";
|
||||
import { CoalitionArea } from "../map/coalitionarea";
|
||||
import { groundUnitDatabase } from "./groundunitdatabase";
|
||||
@@ -12,11 +12,12 @@ import { citiesDatabase } from "./citiesdatabase";
|
||||
|
||||
export class UnitsManager {
|
||||
#units: { [ID: number]: Unit };
|
||||
#copiedUnits: Unit[];
|
||||
#copiedUnits: any[];
|
||||
#selectionEventDisabled: boolean = false;
|
||||
#pasteDisabled: boolean = false;
|
||||
#hiddenTypes: string[] = [];
|
||||
#commandMode: string = HIDE_ALL;
|
||||
#requestDetectionUpdate: boolean = false;
|
||||
|
||||
constructor() {
|
||||
this.#units = {};
|
||||
@@ -31,6 +32,7 @@ export class UnitsManager {
|
||||
document.addEventListener('keyup', (event) => this.#onKeyUp(event));
|
||||
document.addEventListener('exportToFile', () => this.exportToFile());
|
||||
document.addEventListener('importFromFile', () => this.importFromFile());
|
||||
document.addEventListener('contactsUpdated', (e: CustomEvent) => {this.#requestDetectionUpdate = true});
|
||||
}
|
||||
|
||||
getSelectableAircraft() {
|
||||
@@ -91,17 +93,21 @@ export class UnitsManager {
|
||||
this.#units[ID]?.setData(dataExtractor);
|
||||
}
|
||||
|
||||
for (let ID in this.#units) {
|
||||
var unit = this.#units[ID];
|
||||
if (!unit.belongsToCommandedCoalition())
|
||||
unit.setDetectionMethods(this.getUnitDetectedMethods(unit));
|
||||
if (this.#requestDetectionUpdate) {
|
||||
for (let ID in this.#units) {
|
||||
var unit = this.#units[ID];
|
||||
if (!unit.belongsToCommandedCoalition())
|
||||
unit.setDetectionMethods(this.getUnitDetectedMethods(unit));
|
||||
}
|
||||
this.#requestDetectionUpdate = false;
|
||||
}
|
||||
|
||||
setLastUpdateTime(updateTime);
|
||||
|
||||
for (let ID in this.#units) {
|
||||
this.#units[ID].drawLines();
|
||||
if (this.#units[ID].getSelected())
|
||||
this.#units[ID].drawLines();
|
||||
};
|
||||
|
||||
return updateTime;
|
||||
}
|
||||
|
||||
setHiddenType(key: string, value: boolean) {
|
||||
@@ -188,36 +194,59 @@ export class UnitsManager {
|
||||
}
|
||||
|
||||
getSelectedUnitsTypes() {
|
||||
if (this.getSelectedUnits().length == 0)
|
||||
const selectedUnits = this.getSelectedUnits();
|
||||
if (selectedUnits.length == 0)
|
||||
return [];
|
||||
return this.getSelectedUnits().map((unit: Unit) => {
|
||||
return unit.constructor.name
|
||||
return selectedUnits.map((unit: Unit) => {
|
||||
return unit.getCategory();
|
||||
})?.filter((value: any, index: any, array: string[]) => {
|
||||
return array.indexOf(value) === index;
|
||||
});
|
||||
};
|
||||
|
||||
/* Gets the value of a variable from the selected units. If all the units have the same value, returns the value, else returns undefined */
|
||||
getSelectedUnitsVariable(variableGetter: CallableFunction) {
|
||||
if (this.getSelectedUnits().length == 0)
|
||||
const selectedUnits = this.getSelectedUnits();
|
||||
if (selectedUnits.length == 0)
|
||||
return undefined;
|
||||
return this.getSelectedUnits().map((unit: Unit) => {
|
||||
return selectedUnits.map((unit: Unit) => {
|
||||
return variableGetter(unit);
|
||||
})?.reduce((a: any, b: any) => {
|
||||
return a == b ? a : undefined
|
||||
return a === b ? a : undefined
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
getSelectedUnitsCoalition() {
|
||||
if (this.getSelectedUnits().length == 0)
|
||||
const selectedUnits = this.getSelectedUnits();
|
||||
if (selectedUnits.length == 0)
|
||||
return undefined;
|
||||
return this.getSelectedUnits().map((unit: Unit) => {
|
||||
return selectedUnits.map((unit: Unit) => {
|
||||
return unit.getCoalition()
|
||||
})?.reduce((a: any, b: any) => {
|
||||
return a == b ? a : undefined
|
||||
});
|
||||
};
|
||||
|
||||
getByType(type: string) {
|
||||
Object.values(this.getUnits()).filter((unit: Unit) => {
|
||||
return unit.getType() === type;
|
||||
})
|
||||
}
|
||||
|
||||
getUnitDetectedMethods(unit: Unit) {
|
||||
var detectionMethods: number[] = [];
|
||||
for (let idx in this.#units) {
|
||||
if (this.#units[idx].getAlive() && this.#units[idx].getIsLeader() && this.#units[idx].getCoalition() !== "neutral" && this.#units[idx].getCoalition() != unit.getCoalition())
|
||||
{
|
||||
this.#units[idx].getContacts().forEach((contact: Contact) => {
|
||||
if (contact.ID == unit.ID && !detectionMethods.includes(contact.detectionMethod))
|
||||
detectionMethods.push(contact.detectionMethod);
|
||||
});
|
||||
}
|
||||
}
|
||||
return detectionMethods;
|
||||
}
|
||||
|
||||
/*********************** Actions on selected units ************************/
|
||||
selectedUnitsAddDestination(latlng: L.LatLng, mantainRelativePosition: boolean, rotation: number) {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
@@ -227,7 +256,7 @@ export class UnitsManager {
|
||||
if (mantainRelativePosition)
|
||||
unitDestinations = this.selectedUnitsComputeGroupDestination(latlng, rotation);
|
||||
else
|
||||
selectedUnits.forEach((unit: Unit) => { unitDestinations[unit.ID] = latlng });
|
||||
selectedUnits.forEach((unit: Unit) => { unitDestinations[unit.ID] = latlng; });
|
||||
|
||||
for (let idx in selectedUnits) {
|
||||
const unit = selectedUnits[idx];
|
||||
@@ -515,36 +544,66 @@ export class UnitsManager {
|
||||
this.#showActionMessage(selectedUnits, `unit bombing point`);
|
||||
}
|
||||
|
||||
getUnitDetectedMethods(unit: Unit) {
|
||||
var detectionMethods: number[] = [];
|
||||
for (let idx in this.#units) {
|
||||
if (this.#units[idx].getCoalition() !== "neutral" && this.#units[idx].getCoalition() != unit.getCoalition())
|
||||
{
|
||||
this.#units[idx].getContacts().forEach((contact: Contact) => {
|
||||
if (this.#units[idx].getAlive() && contact.ID == unit.ID && !detectionMethods.includes(contact.detectionMethod))
|
||||
detectionMethods.push(contact.detectionMethod);
|
||||
});
|
||||
}
|
||||
// TODO add undo group
|
||||
selectedUnitsCreateGroup() {
|
||||
var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: false });
|
||||
var units = [];
|
||||
var coalition = "neutral";
|
||||
for (let idx in selectedUnits) {
|
||||
var unit = selectedUnits[idx];
|
||||
coalition = unit.getCoalition();
|
||||
deleteUnit(unit.ID, false, true);
|
||||
units.push({unitType: unit.getName(), location: unit.getPosition()});
|
||||
}
|
||||
return detectionMethods;
|
||||
const category = this.getSelectedUnitsTypes()[0];
|
||||
this.spawnUnit(category, units, coalition, true);
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
copyUnits() {
|
||||
this.#copiedUnits = this.getSelectedUnits(); /* Can be applied to humans too */
|
||||
this.#showActionMessage(this.#copiedUnits, `copied`);
|
||||
this.#copiedUnits = JSON.parse(JSON.stringify(this.getSelectedUnits().map((unit: Unit) => {return unit.getData()}))); /* Can be applied to humans too */
|
||||
getInfoPopup().setText(`${this.#copiedUnits.length} units copied`);
|
||||
}
|
||||
|
||||
pasteUnits() {
|
||||
if (!this.#pasteDisabled) {
|
||||
/* Compute the position of the center of the copied units */
|
||||
var nUnits = this.#copiedUnits.length;
|
||||
var avgLat = 0;
|
||||
var avgLng = 0;
|
||||
for (let idx in this.#copiedUnits) {
|
||||
var unit = this.#copiedUnits[idx];
|
||||
//getMap().addTemporaryMarker(getMap().getMouseCoordinates());
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
this.#showActionMessage(this.#copiedUnits, `pasted`);
|
||||
avgLat += unit.position.lat / nUnits;
|
||||
avgLng += unit.position.lng / nUnits;
|
||||
}
|
||||
this.#pasteDisabled = true;
|
||||
window.setTimeout(() => this.#pasteDisabled = false, 250);
|
||||
|
||||
/* Organize the copied units in groups */
|
||||
var groups: {[key: string]: any} = {};
|
||||
this.#copiedUnits.forEach((unit: any) => {
|
||||
if (!(unit.groupName in groups))
|
||||
groups[unit.groupName] = [];
|
||||
groups[unit.groupName].push(unit);
|
||||
});
|
||||
|
||||
for (let groupName in groups) {
|
||||
/* Paste the units as groups. Only for ground and navy units because of loadouts, TODO: find a better solution so it works for them too*/
|
||||
if (!["Aircraft", "Helicopter"].includes(groups[groupName][0].category)) {
|
||||
var units = groups[groupName].map((unit: any) => {
|
||||
var position = new LatLng(getMap().getMouseCoordinates().lat + unit.position.lat - avgLat, getMap().getMouseCoordinates().lng + unit.position.lng - avgLng);
|
||||
getMap().addTemporaryMarker(position, unit.name, unit.coalition);
|
||||
return {unitType: unit.name, location: position};
|
||||
});
|
||||
this.spawnUnit(groups[groupName][0].category, units, groups[groupName][0].coalition, true);
|
||||
}
|
||||
else {
|
||||
groups[groupName].forEach((unit: any) => {
|
||||
var position = new LatLng(getMap().getMouseCoordinates().lat + unit.position.lat - avgLat, getMap().getMouseCoordinates().lng + unit.position.lng - avgLng);
|
||||
getMap().addTemporaryMarker(position, unit.name, unit.coalition);
|
||||
cloneUnit(unit.ID, position);
|
||||
});
|
||||
}
|
||||
}
|
||||
getInfoPopup().setText(`${this.#copiedUnits.length - 1} units pasted`);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,7 +640,6 @@ export class UnitsManager {
|
||||
var unit = this.#units[ID];
|
||||
if (!["Aircraft", "Helicopter"].includes(unit.getCategory())) {
|
||||
var data: any = unit.getData();
|
||||
data.category = unit.getCategory();
|
||||
if (unit.getGroupName() in unitsToExport)
|
||||
unitsToExport[unit.getGroupName()].push(data);
|
||||
else
|
||||
@@ -609,7 +667,7 @@ export class UnitsManager {
|
||||
var groups = JSON.parse(contents);
|
||||
for (let groupName in groups) {
|
||||
if (groupName !== "" && groups[groupName].length > 0 && groups[groupName].every((unit: any) => {return unit.category == "GroundUnit";})) {
|
||||
var units = groups[groupName].map((unit: any) => {return {unitType: unit.name, location: unit.position}});
|
||||
var units = groups[groupName].filter((unit: any) => {return unit.alive}).map((unit: any) => {return {unitType: unit.name, location: unit.position}});
|
||||
spawnGroundUnits(units, groups[groupName][0].coalition, true);
|
||||
}
|
||||
}
|
||||
@@ -629,8 +687,11 @@ export class UnitsManager {
|
||||
|
||||
/***********************************************/
|
||||
#onKeyUp(event: KeyboardEvent) {
|
||||
if (!keyEventWasInInput(event) && event.key === "Delete" ) {
|
||||
this.selectedUnitsDelete();
|
||||
if (!keyEventWasInInput(event)) {
|
||||
if (event.key === "Delete")
|
||||
this.selectedUnitsDelete();
|
||||
else if (event.key === "a" && event.ctrlKey)
|
||||
Object.values(this.getUnits()).filter((unit: Unit) => {return !unit.getHidden()}).forEach((unit: Unit) => unit.setSelected(true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,7 +722,7 @@ export class UnitsManager {
|
||||
document.dispatchEvent(new CustomEvent("unitsDeselection", { detail: this.getSelectedUnits() }));
|
||||
}
|
||||
|
||||
#showActionMessage(units: Unit[], message: string) {
|
||||
#showActionMessage(units: any[], message: string) {
|
||||
if (units.length == 1)
|
||||
getInfoPopup().setText(`${units[0].getUnitName()} ${message}`);
|
||||
else if (units.length > 1)
|
||||
|
||||
@@ -15,10 +15,10 @@
|
||||
</div>
|
||||
<div id="more-options-button-bar" class="upper-bar ol-panel hide">
|
||||
<div id="coalition-switch" class="ol-switch ol-coalition-switch"></div>
|
||||
<!--
|
||||
|
||||
<button data-coalition="blue" id="navyunit-spawn-button" title="Spawn navy unit" data-on-click="mapContextMenuShow"
|
||||
data-on-click-params='{ "type": "navyunit" }' class="ol-contexmenu-button"><img src="/resources/theme/images/buttons/spawn/navyunit.svg" inject-svg></button>
|
||||
-->
|
||||
|
||||
<button data-coalition="blue" id="smoke-spawn-button" title="Spawn smoke" data-on-click="mapContextMenuShow"
|
||||
data-on-click-params='{ "type": "smoke" }' class="ol-contexmenu-button"><img src="/resources/theme/images/buttons/spawn/smoke.svg" inject-svg></button>
|
||||
<button data-coalition="blue" id="explosion-spawn-button" title="Explosion" data-on-click="mapContextMenuShow"
|
||||
|
||||
Reference in New Issue
Block a user