diff --git a/client/demo.js b/client/demo.js
index d7f970df..6530f21b 100644
--- a/client/demo.js
+++ b/client/demo.js
@@ -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\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
- contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}],
+ contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}, {ID: 5, 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",
diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css
index fabc3105..9c40b7f1 100644
--- a/client/public/stylesheets/olympus.css
+++ b/client/public/stylesheets/olympus.css
@@ -1031,13 +1031,41 @@ nav.ol-panel> :last-child {
}
.ol-target-icon {
- background-image: url("/resources/theme/images/markers/target.svg");
height: 52px;
pointer-events: none;
width: 52px;
z-index: 9999;
}
+.ol-smoke-icon {
+ background-image: url("/resources/theme/images/markers/smoke.svg");
+ height: 52px;
+ pointer-events: none;
+ width: 52px;
+ z-index: 9999;
+ opacity: 0.8;
+}
+
+.ol-smoke-icon[data-color="white"] {
+ fill: white;
+}
+
+.ol-smoke-icon[data-color="blue"] {
+ fill: blue;
+}
+
+.ol-smoke-icon[data-color="red"] {
+ fill: red;
+}
+
+.ol-smoke-icon[data-color="green"] {
+ fill: green;
+}
+
+.ol-smoke-icon[data-color="orange"] {
+ fill: orange;
+}
+
.ol-draw-icon {
background-image: url("/resources/theme/images/markers/draw.svg");
height: 24px;
diff --git a/client/public/themes/olympus/images/markers/smoke.svg b/client/public/themes/olympus/images/markers/smoke.svg
new file mode 100644
index 00000000..4c058371
--- /dev/null
+++ b/client/public/themes/olympus/images/markers/smoke.svg
@@ -0,0 +1,133 @@
+
+
+
+
diff --git a/client/public/themes/olympus/images/markers/target - Copy.svg b/client/public/themes/olympus/images/markers/target - Copy.svg
new file mode 100644
index 00000000..7afbf612
--- /dev/null
+++ b/client/public/themes/olympus/images/markers/target - Copy.svg
@@ -0,0 +1,101 @@
+
+
+
+
diff --git a/client/public/themes/olympus/images/markers/temporary-icon.png b/client/public/themes/olympus/images/markers/temporary-icon.png
deleted file mode 100644
index 712221a0..00000000
Binary files a/client/public/themes/olympus/images/markers/temporary-icon.png and /dev/null differ
diff --git a/client/src/@types/dom.d.ts b/client/src/@types/dom.d.ts
index a3712343..dc70c183 100644
--- a/client/src/@types/dom.d.ts
+++ b/client/src/@types/dom.d.ts
@@ -19,7 +19,7 @@ interface CustomEventMap {
"mapStateChanged": CustomEvent,
"mapContextMenu": CustomEvent<>,
"mapVisibilityOptionsChanged": CustomEvent<>,
- "commandModeOptionsChanged": CustomEvent<>,
+ "commandModeOptionsChanged": CustomEvent<>,
"contactsUpdated": CustomEvent,
}
diff --git a/client/src/constants/constants.ts b/client/src/constants/constants.ts
index f4216afb..1013f6e3 100644
--- a/client/src/constants/constants.ts
+++ b/client/src/constants/constants.ts
@@ -138,15 +138,16 @@ export const MOVE_UNIT = "Move unit";
export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area";
export const visibilityControls: string[] = ["human", "dcs", "aircraft", "groundunit-sam", "groundunit-other", "navyunit", "airbase"];
export const visibilityControlsTypes: string[][] = [["human"], ["dcs"], ["aircraft"], ["groundunit-sam", "groundunit-sam-radar", "groundunit-sam-launcher"], ["groundunit-other", "groundunit-ewr"], ["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 visibilityControlsTooltips: 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 Site", "Radar"];
export const IADSDensities: {[key: string]: number}= {"AAA": 0.8, "MANPADS": 0.3, "SAM Site": 0.1, "Radar": 0.05};
export const SHOW_CONTACT_LINES = "Show unit contact lines";
export const HIDE_GROUP_MEMBERS = "Hide group members when zoomed out";
-export const SHOW_UNIT_PATHS = "Show unit paths";
-export const SHOW_UNIT_TARGETS = "Show unit targets";
+export const SHOW_UNIT_LABELS = "Show unit labels";
+export const SHOW_UNIT_PATHS = "Show unit paths";
+export const SHOW_UNIT_TARGETS = "Show unit targets";
export enum DataIndexes {
startOfData = 0,
diff --git a/client/src/controls/mapcontextmenu.ts b/client/src/controls/mapcontextmenu.ts
index 1d51952c..1dd906ad 100644
--- a/client/src/controls/mapcontextmenu.ts
+++ b/client/src/controls/mapcontextmenu.ts
@@ -12,6 +12,7 @@ import { ftToM } from "../other/utils";
import { GAME_MASTER } from "../constants/constants";
import { navyUnitDatabase } from "../unit/navyunitdatabase";
import { CoalitionArea } from "../map/coalitionarea";
+import { SmokeMarker } from "../map/smokemarker";
export class MapContextMenu extends ContextMenu {
#coalitionSwitch: Switch;
@@ -158,6 +159,8 @@ export class MapContextMenu extends ContextMenu {
document.addEventListener("contextMenuDeploySmoke", (e: any) => {
this.hide();
spawnSmoke(e.detail.color, this.getLatLng());
+ var marker = new SmokeMarker(this.getLatLng(), e.detail.color);
+ marker.addTo(getMap());
});
document.addEventListener("contextMenuExplosion", (e: any) => {
diff --git a/client/src/index.ts b/client/src/index.ts
index 8a86d75e..e16f8562 100644
--- a/client/src/index.ts
+++ b/client/src/index.ts
@@ -137,9 +137,6 @@ function setupEvents() {
return;
}
switch (ev.code) {
- case "KeyL":
- document.body.toggleAttribute("data-hide-labels");
- break;
case "KeyT":
toggleDemoEnabled();
break;
diff --git a/client/src/map/map.ts b/client/src/map/map.ts
index 6dfd0222..f809a388 100644
--- a/client/src/map/map.ts
+++ b/client/src/map/map.ts
@@ -12,7 +12,7 @@ import { DestinationPreviewMarker } from "./destinationpreviewmarker";
import { TemporaryUnitMarker } from "./temporaryunitmarker";
import { ClickableMiniMap } from "./clickableminimap";
import { SVGInjector } from '@tanem/svg-injector'
-import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTootlips, MOVE_UNIT, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes } from "../constants/constants";
+import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTootlips, MOVE_UNIT, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS } from "../constants/constants";
import { TargetMarker } from "./targetmarker";
import { CoalitionArea } from "./coalitionarea";
import { CoalitionAreaContextMenu } from "../controls/coalitionareacontextmenu";
@@ -45,7 +45,7 @@ export class Map extends L.Map {
#temporaryMarkers: TemporaryUnitMarker[] = [];
#selecting: boolean = false;
#isZooming: boolean = false;
-
+
#destinationGroupRotation: number = 0;
#computeDestinationRotation: boolean = false;
#destinationRotationCenter: L.LatLng | null = null;
@@ -65,7 +65,7 @@ export class Map extends L.Map {
#mapSourceDropdown: Dropdown;
#mapVisibilityOptionsDropdown: Dropdown;
#optionButtons: { [key: string]: HTMLButtonElement[] } = {}
- #visibiityOptions: { [key: string]: boolean } = {}
+ #visibilityOptions: { [key: string]: boolean } = {}
constructor(ID: string) {
/* Init the leaflet map */
@@ -91,7 +91,7 @@ export class Map extends L.Map {
this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers());
/* Visibility options dropdown */
- this.#mapVisibilityOptionsDropdown = new Dropdown("map-visibility-options", () => {});
+ this.#mapVisibilityOptionsDropdown = new Dropdown("map-visibility-options", (value: string) => { });
/* Init the state machine */
this.#state = IDLE;
@@ -134,7 +134,7 @@ export class Map extends L.Map {
})
}
});
-
+
document.addEventListener("toggleCoalitionAreaDraw", (ev: CustomEventInit) => {
this.getMapContextMenu().hide();
this.deselectAllCoalitionAreas();
@@ -151,6 +151,10 @@ export class Map extends L.Map {
this.#panToUnit(this.#centerUnit);
});
+ document.addEventListener("mapVisibilityOptionsChanged", () => {
+ this.getContainer().toggleAttribute("data-hide-labels", !this.getVisibilityOptions()[SHOW_UNIT_LABELS]);
+ });
+
/* Pan interval */
this.#panInterval = window.setInterval(() => {
if (this.#panLeft || this.#panDown || this.#panRight || this.#panLeft)
@@ -161,19 +165,19 @@ export class Map extends L.Map {
/* Option buttons */
this.#optionButtons["visibility"] = visibilityControls.map((option: string, index: number) => {
var typesArrayString = `"${visibilityControlsTypes[index][0]}"`;
- visibilityControlsTypes[index].forEach((type: string, idx: number) => {if (idx > 0) typesArrayString = `${typesArrayString}, "${type}"`});
- return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleMarkerVisibility", `{"types": [${typesArrayString}]}`);
+ visibilityControlsTypes[index].forEach((type: string, idx: number) => { if (idx > 0) typesArrayString = `${typesArrayString}, "${type}"` });
+ return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTooltips[index], "toggleMarkerVisibility", `{"types": [${typesArrayString}]}`);
});
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
/* Create the checkboxes to select the advanced visibility options */
-
- this.#visibiityOptions[SHOW_CONTACT_LINES] = false;
- this.#visibiityOptions[HIDE_GROUP_MEMBERS] = true;
- this.#visibiityOptions[SHOW_UNIT_PATHS] = true;
- this.#visibiityOptions[SHOW_UNIT_TARGETS] = true;
- this.#mapVisibilityOptionsDropdown.setOptionsElements(Object.keys(this.#visibiityOptions).map((option: string) => {
- return createCheckboxOption(option, option, this.#visibiityOptions[option], (ev: any) => {
+ this.#visibilityOptions[SHOW_CONTACT_LINES] = false;
+ this.#visibilityOptions[HIDE_GROUP_MEMBERS] = true;
+ this.#visibilityOptions[SHOW_UNIT_PATHS] = true;
+ this.#visibilityOptions[SHOW_UNIT_TARGETS] = true;
+ this.#visibilityOptions[SHOW_UNIT_LABELS] = true;
+ this.#mapVisibilityOptionsDropdown.setOptionsElements(Object.keys(this.#visibilityOptions).map((option: string) => {
+ return createCheckboxOption(option, option, this.#visibilityOptions[option], (ev: any) => {
this.#setVisibilityOption(option, ev);
});
}));
@@ -436,7 +440,7 @@ export class Map extends L.Map {
}
getVisibilityOptions() {
- return this.#visibiityOptions;
+ return this.#visibilityOptions;
}
/* Event handlers */
@@ -482,7 +486,7 @@ export class Map extends L.Map {
/* Coalition areas are ordered in the #coalitionAreas array according to their zindex. Select the upper one */
for (let coalitionArea of this.#coalitionAreas) {
if (coalitionArea.getBounds().contains(e.latlng)) {
- if (coalitionArea.getSelected())
+ if (coalitionArea.getSelected())
clickedCoalitionArea = coalitionArea;
else
this.getMapContextMenu().setCoalitionArea(coalitionArea);
@@ -704,7 +708,7 @@ export class Map extends L.Map {
else {
Object.values(getUnitsManager().selectedUnitsComputeGroupDestination(groupLatLng, this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => {
if (idx < this.#destinationPreviewCursors.length)
- this.#destinationPreviewCursors[idx].setLatLng(this.#shiftKey? latlng : this.getMouseCoordinates());
+ this.#destinationPreviewCursors[idx].setLatLng(this.#shiftKey ? latlng : this.getMouseCoordinates());
})
};
}
@@ -769,7 +773,7 @@ export class Map extends L.Map {
}
#setVisibilityOption(option: string, ev: any) {
- this.#visibiityOptions[option] = ev.currentTarget.checked;
+ this.#visibilityOptions[option] = ev.currentTarget.checked;
document.dispatchEvent(new CustomEvent("mapVisibilityOptionsChanged"));
}
}
diff --git a/client/src/map/smokemarker.ts b/client/src/map/smokemarker.ts
new file mode 100644
index 00000000..678912c2
--- /dev/null
+++ b/client/src/map/smokemarker.ts
@@ -0,0 +1,31 @@
+import { DivIcon, LatLngExpression, MarkerOptions } from "leaflet";
+import { CustomMarker } from "./custommarker";
+import { SVGInjector } from "@tanem/svg-injector";
+import { getMap } from "..";
+
+export class SmokeMarker extends CustomMarker {
+ #color: string;
+
+ constructor(latlng: LatLngExpression, color: string, options?: MarkerOptions) {
+ super(latlng, options);
+ this.setZIndexOffset(9999);
+ this.#color = color;
+ window.setTimeout(() => { this.removeFrom(getMap()); }, 300000) /* Remove the smoke after 5 minutes */
+ }
+
+ createIcon() {
+ this.setIcon(new DivIcon({
+ iconSize: [52, 52],
+ iconAnchor: [26, 52],
+ className: "leaflet-smoke-marker",
+ }));
+ var el = document.createElement("div");
+ el.classList.add("ol-smoke-icon");
+ el.setAttribute("data-color", this.#color);
+ var img = document.createElement("img");
+ img.src = "/resources/theme/images/markers/smoke.svg";
+ img.onload = () => SVGInjector(img);
+ el.appendChild(img);
+ this.getElement()?.appendChild(el);
+ }
+}
diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts
index 59cc0035..4de688ce 100644
--- a/client/src/unit/unit.ts
+++ b/client/src/unit/unit.ts
@@ -76,7 +76,7 @@ export class Unit extends CustomMarker {
};
#ammo: Ammo[] = [];
#contacts: Contact[] = [];
- #activePath: LatLng[] = [];
+ #activePath: LatLng[] = [];
#isLeader: boolean = false;
#selectable: boolean;
@@ -94,43 +94,43 @@ export class Unit extends CustomMarker {
#hotgroup: number | null = null;
#detectionMethods: number[] = [];
- getAlive() {return this.#alive};
- getHuman() {return this.#human};
- getControlled() {return this.#controlled};
- getCoalition() {return this.#coalition};
- getCountry() {return this.#country};
- getName() {return this.#name};
- getUnitName() {return this.#unitName};
- getGroupName() {return this.#groupName};
- getState() {return this.#state};
- getTask() {return this.#task};
- getHasTask() {return this.#hasTask};
- getPosition() {return this.#position};
- getSpeed() {return this.#speed};
- getHeading() {return this.#heading};
- getIsTanker() {return this.#isTanker};
- getIsAWACS() {return this.#isAWACS};
- getOnOff() {return this.#onOff};
- getFollowRoads() {return this.#followRoads};
- getFuel() {return this.#fuel};
- getDesiredSpeed() {return this.#desiredSpeed};
- getDesiredSpeedType() {return this.#desiredSpeedType};
- getDesiredAltitude() {return this.#desiredAltitude};
- getDesiredAltitudeType() {return this.#desiredAltitudeType};
- getLeaderID() {return this.#leaderID};
- getFormationOffset() {return this.#formationOffset};
- getTargetID() {return this.#targetID};
- getTargetPosition() {return this.#targetPosition};
- getROE() {return this.#ROE};
- getReactionToThreat() {return this.#reactionToThreat};
- getEmissionsCountermeasures() {return this.#emissionsCountermeasures};
- getTACAN() {return this.#TACAN};
- getRadio() {return this.#radio};
- getGeneralSettings() {return this.#generalSettings};
- getAmmo() {return this.#ammo};
- getContacts() {return this.#contacts};
- getActivePath() {return this.#activePath};
- getIsLeader() {return this.#isLeader};
+ getAlive() { return this.#alive };
+ getHuman() { return this.#human };
+ getControlled() { return this.#controlled };
+ getCoalition() { return this.#coalition };
+ getCountry() { return this.#country };
+ getName() { return this.#name };
+ getUnitName() { return this.#unitName };
+ getGroupName() { return this.#groupName };
+ getState() { return this.#state };
+ getTask() { return this.#task };
+ getHasTask() { return this.#hasTask };
+ getPosition() { return this.#position };
+ getSpeed() { return this.#speed };
+ getHeading() { return this.#heading };
+ getIsTanker() { return this.#isTanker };
+ getIsAWACS() { return this.#isAWACS };
+ getOnOff() { return this.#onOff };
+ getFollowRoads() { return this.#followRoads };
+ getFuel() { return this.#fuel };
+ getDesiredSpeed() { return this.#desiredSpeed };
+ getDesiredSpeedType() { return this.#desiredSpeedType };
+ getDesiredAltitude() { return this.#desiredAltitude };
+ getDesiredAltitudeType() { return this.#desiredAltitudeType };
+ getLeaderID() { return this.#leaderID };
+ getFormationOffset() { return this.#formationOffset };
+ getTargetID() { return this.#targetID };
+ getTargetPosition() { return this.#targetPosition };
+ getROE() { return this.#ROE };
+ getReactionToThreat() { return this.#reactionToThreat };
+ getEmissionsCountermeasures() { return this.#emissionsCountermeasures };
+ getTACAN() { return this.#TACAN };
+ getRadio() { return this.#radio };
+ getGeneralSettings() { return this.#generalSettings };
+ 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;
@@ -156,7 +156,7 @@ export class Unit extends CustomMarker {
this.on('contextmenu', (e) => this.#onContextMenu(e));
this.on('mouseover', () => { if (this.belongsToCommandedCoalition()) this.setHighlighted(true); })
this.on('mouseout', () => { this.setHighlighted(false); })
- getMap().on("zoomend", () => {this.#onZoom();})
+ getMap().on("zoomend", () => { this.#onZoom(); })
/* Deselect units if they are hidden */
document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => {
@@ -165,13 +165,13 @@ export class Unit extends CustomMarker {
document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => {
window.setTimeout(() => { this.setSelected(this.getSelected() && !this.getHidden()) }, 300);
- });
-
+ });
+
document.addEventListener("mapVisibilityOptionsChanged", (ev: CustomEventInit) => {
this.#updateMarker();
if (this.getSelected())
this.drawLines();
- });
+ });
}
getCategory() {
@@ -222,12 +222,12 @@ 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(); document.dispatchEvent(new CustomEvent("contactsUpdated", {detail: this})); 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;
}
}
-
+
/* Dead units can't be selected */
this.setSelected(this.getSelected() && this.#alive && !this.getHidden())
@@ -314,7 +314,7 @@ export class Unit extends CustomMarker {
getLiveryID(): string {
const liveryID = this.getDatabase()?.getByName(this.getName())?.liveryID;
- return liveryID? liveryID: "";
+ return liveryID ? liveryID : "";
}
setAlive(newAlive: boolean) {
@@ -327,7 +327,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;
-
+
if (selected) {
document.dispatchEvent(new CustomEvent("unitSelection", { detail: this }));
this.#updateMarker();
@@ -346,7 +346,7 @@ export class Unit extends CustomMarker {
else
this.#updateMarker();
}
-
+
}
}
@@ -390,7 +390,7 @@ export class Unit extends CustomMarker {
belongsToCommandedCoalition() {
if (getMissionHandler().getCommandModeOptions().commandMode !== GAME_MASTER && getMissionHandler().getCommandedCoalition() !== this.#coalition)
return false;
- return true;
+ return true;
}
getType() {
@@ -438,7 +438,15 @@ export class Unit extends CustomMarker {
var unitIcon = document.createElement("div");
unitIcon.classList.add("unit-icon");
var img = document.createElement("img");
- img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`;
+ var imgSrc;
+
+ /* If a unit does not belong to the commanded coalition or it is not visually detected, show it with the generic aircraft square */
+ if (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)))
+ imgSrc = this.getMarkerCategory();
+ else
+ imgSrc = "aircraft";
+
+ img.src = `/resources/theme/images/units/${imgSrc}.svg`;
img.onload = () => SVGInjector(img);
unitIcon.appendChild(img);
unitIcon.toggleAttribute("data-rotate-to-heading", iconOptions.rotateToHeading);
@@ -503,12 +511,12 @@ export class Unit extends CustomMarker {
updateVisibility() {
const hiddenUnits = getUnitsManager().getHiddenTypes();
var hidden = ((this.#human && hiddenUnits.includes("human")) ||
- (this.#controlled == false && hiddenUnits.includes("dcs")) ||
- (hiddenUnits.includes(this.getMarkerCategory())) ||
- (hiddenUnits.includes(this.#coalition)) ||
- (!this.belongsToCommandedCoalition() && (this.#detectionMethods.length == 0 || (this.#detectionMethods.length == 1 && this.#detectionMethods[0] === RWR))) ||
- (getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13 && (this.belongsToCommandedCoalition() || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0)))) &&
- !(this.getSelected());
+ (this.#controlled == false && hiddenUnits.includes("dcs")) ||
+ (hiddenUnits.includes(this.getMarkerCategory())) ||
+ (hiddenUnits.includes(this.#coalition)) ||
+ (!this.belongsToCommandedCoalition() && (this.#detectionMethods.length == 0 || (this.#detectionMethods.length == 1 && this.#detectionMethods[0] === RWR))) ||
+ (getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13 && (this.belongsToCommandedCoalition() || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0)))) &&
+ !(this.getSelected());
this.setHidden(hidden || !this.#alive);
}
@@ -518,9 +526,9 @@ export class Unit extends CustomMarker {
/* Add the marker if not present */
if (!getMap().hasLayer(this) && !this.getHidden()) {
- if (getMap().isZooming())
- this.once("zoomend", () => {this.addTo(getMap())})
- else
+ if (getMap().isZooming())
+ this.once("zoomend", () => { this.addTo(getMap()) })
+ else
this.addTo(getMap());
}
@@ -563,10 +571,22 @@ export class Unit extends CustomMarker {
return loadouts.some((loadout: LoadoutBlueprint) => {
return (roles as string[]).some((role: string) => { return loadout.roles.includes(role) });
});
- } else
+ } else
return false;
}
+ isInViewport() {
+
+ const mapBounds = getMap().getBounds();
+ const unitPos = this.getPosition();
+
+ return (unitPos.lng > mapBounds.getWest()
+ && unitPos.lng < mapBounds.getEast()
+ && unitPos.lat > mapBounds.getSouth()
+ && unitPos.lat < mapBounds.getNorth());
+
+ }
+
/********************** Unit commands *************************/
addDestination(latlng: L.LatLng) {
if (!this.#human) {
@@ -708,24 +728,28 @@ export class Unit extends CustomMarker {
#onClick(e: any) {
if (!this.#preventClick) {
if (getMap().getState() === IDLE || getMap().getState() === MOVE_UNIT || e.originalEvent.ctrlKey) {
- if (!e.originalEvent.ctrlKey)
+ if (!e.originalEvent.ctrlKey)
getUnitsManager().deselectAllUnits();
-
- this.setSelected( !this.getSelected() );
- if ( this.getSelected() ) {
- document.dispatchEvent( new CustomEvent( "unitSelection", { "detail": this }));
- } else {
- document.dispatchEvent( new CustomEvent( "unitDeselection", { "detail": this }));
- }
+
+ this.setSelected(!this.getSelected());
+ const detail = { "detail": { "unit": this } };
+ if (this.getSelected())
+ document.dispatchEvent(new CustomEvent("unitSelected", detail));
+ else
+ document.dispatchEvent(new CustomEvent("unitDeselection", { "detail": this }));
}
}
- this.#timer = window.setTimeout(() => {
- this.#preventClick = false;
- }, 200);
+ this.#timer = window.setTimeout(() => { this.#preventClick = false; }, 200);
}
#onDoubleClick(e: any) {
+ const unitsManager = getUnitsManager();
+ Object.values(unitsManager.getUnits()).forEach((unit: Unit) => {
+ if (unit.getAlive() === true && unit.getName() === this.getName() && unit.isInViewport())
+ unitsManager.selectUnit(unit.ID, false);
+ });
+
clearTimeout(this.#timer);
this.#preventClick = true;
}
@@ -747,7 +771,7 @@ export class Unit extends CustomMarker {
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
}
}
-
+
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." };
@@ -791,7 +815,7 @@ export class Unit extends CustomMarker {
getMap().hideUnitContextMenu();
this.#applyFollowOptions(option);
});
-
+
getMap().showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
}
@@ -1050,16 +1074,17 @@ export class Unit extends CustomMarker {
export class AirUnit extends Unit {
getIconOptions() {
+ var belongsToCommandedCoalition = this.belongsToCommandedCoalition();
return {
- showState: this.belongsToCommandedCoalition(),
- showVvi: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
- showHotgroup: this.belongsToCommandedCoalition(),
- showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
- showShortLabel: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value))),
- showFuel: this.belongsToCommandedCoalition(),
- showAmmo: this.belongsToCommandedCoalition(),
- showSummary: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
- showCallsign: this.belongsToCommandedCoalition(),
+ showState: belongsToCommandedCoalition,
+ showVvi: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
+ showHotgroup: belongsToCommandedCoalition,
+ showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
+ showShortLabel: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value))),
+ showFuel: belongsToCommandedCoalition,
+ showAmmo: belongsToCommandedCoalition,
+ showSummary: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
+ showCallsign: belongsToCommandedCoalition,
rotateToHeading: false
};
}
@@ -1091,16 +1116,17 @@ export class GroundUnit extends Unit {
}
getIconOptions() {
+ var belongsToCommandedCoalition = this.belongsToCommandedCoalition();
return {
- showState: this.belongsToCommandedCoalition(),
+ showState: belongsToCommandedCoalition,
showVvi: false,
- showHotgroup: this.belongsToCommandedCoalition(),
- showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
+ showHotgroup: belongsToCommandedCoalition,
+ showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
showShortLabel: false,
showFuel: false,
showAmmo: false,
showSummary: false,
- showCallsign: this.belongsToCommandedCoalition(),
+ showCallsign: belongsToCommandedCoalition,
rotateToHeading: false
};
}
@@ -1111,7 +1137,7 @@ export class GroundUnit extends Unit {
getType() {
var blueprint = groundUnitDatabase.getByName(this.getName());
- return blueprint?.type? blueprint.type: "";
+ return blueprint?.type ? blueprint.type : "";
}
}
@@ -1121,16 +1147,17 @@ export class NavyUnit extends Unit {
}
getIconOptions() {
+ var belongsToCommandedCoalition = this.belongsToCommandedCoalition();
return {
- showState: this.belongsToCommandedCoalition(),
+ showState: belongsToCommandedCoalition,
showVvi: false,
showHotgroup: true,
- showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
+ showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
showShortLabel: false,
showFuel: false,
showAmmo: false,
showSummary: false,
- showCallsign: this.belongsToCommandedCoalition(),
+ showCallsign: belongsToCommandedCoalition,
rotateToHeading: false
};
}
@@ -1145,6 +1172,6 @@ export class NavyUnit extends Unit {
getType() {
var blueprint = navyUnitDatabase.getByName(this.getName());
- return blueprint?.type? blueprint.type: "";
+ return blueprint?.type ? blueprint.type : "";
}
}