mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added better temporary markers and more map functions
This commit is contained in:
parent
635c487c2b
commit
61d6d9f16c
@ -311,4 +311,8 @@
|
||||
|
||||
[data-object|="unit-aircraft"][data-is-dead] .unit-summary .unit-callsign {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.ol-temporary-marker {
|
||||
opacity: 0.5;
|
||||
}
|
||||
@ -350,7 +350,7 @@
|
||||
height: fit-content;
|
||||
position: absolute;
|
||||
row-gap: 5px;
|
||||
width: 225px;
|
||||
width: 250px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
@ -370,6 +370,11 @@
|
||||
background-size: 48px;
|
||||
}
|
||||
|
||||
#coalitionarea-back-button {
|
||||
background-image: url("/resources/theme/images/buttons/other/back.svg");
|
||||
background-size: 48px;
|
||||
}
|
||||
|
||||
#coalitionarea-delete-button {
|
||||
background-image: url("/resources/theme/images/buttons/other/delete.svg");
|
||||
background-size: 48px;
|
||||
|
||||
41
client/public/themes/olympus/images/buttons/other/back.svg
Normal file
41
client/public/themes/olympus/images/buttons/other/back.svg
Normal file
@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="back.svg"
|
||||
width="32"
|
||||
height="32"
|
||||
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="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showgrid="false"
|
||||
inkscape:zoom="26.15625"
|
||||
inkscape:cx="20.587814"
|
||||
inkscape:cy="20.109916"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path
|
||||
d="M 24.337929,21.064066 H 7.766909 c -0.572865,0 -1.035689,0.462823 -1.035689,1.035689 0,0.572864 0.462824,1.035688 1.035689,1.035688 h 16.57102 c 0.572865,0 1.035689,-0.462824 1.035689,-1.035688 0,-0.572866 -0.462824,-1.035689 -1.035689,-1.035689 z M 20.024324,15.15093 c -0.404566,-0.404566 -1.061581,-0.404566 -1.466147,0 l -1.336685,1.339923 V 9.6714892 c 0,-0.572865 -0.462823,-1.035688 -1.035689,-1.035688 -0.572866,0 -1.035688,0.462823 -1.035688,1.035688 V 16.490853 L 13.810192,15.15093 c -0.404566,-0.404566 -1.061581,-0.404566 -1.466147,0 -0.404565,0.404566 -0.404565,1.061581 0,1.466147 l 3.107066,3.107066 c 0.404565,0.404566 1.061582,0.404566 1.466147,0 l 3.107066,-3.107066 c 0.404567,-0.404566 0.404567,-1.061581 0,-1.466147 z"
|
||||
id="path2"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke-width:0.0323653"
|
||||
sodipodi:nodetypes="ssssssssccssscssccccs" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M362.7 19.3L314.3 67.7 444.3 197.7l48.4-48.4c25-25 25-65.5 0-90.5L453.3 19.3c-25-25-65.5-25-90.5 0zm-71 71L58.6 323.5c-10.4 10.4-18 23.3-22.2 37.4L1 481.2C-1.5 489.7 .8 498.8 7 505s15.3 8.5 23.7 6.1l120.3-35.4c14.1-4.2 27-11.8 37.4-22.2L421.7 220.3 291.7 90.3z"/></svg>
|
||||
|
After Width: | Height: | Size: 508 B |
@ -99,4 +99,15 @@ export const layers = {
|
||||
maxZoom: 20,
|
||||
attribution: '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Map constants */
|
||||
export const IDLE = "Idle";
|
||||
export const MOVE_UNIT = "Move unit";
|
||||
export const BOMBING = "Bombing";
|
||||
export const CARPET_BOMBING = "Carpet bombing";
|
||||
export const FIRE_AT_AREA = "Fire at area";
|
||||
export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area";
|
||||
export const COALITIONAREA_INTERACT = "Interact with Coalition Areas"
|
||||
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"];
|
||||
|
||||
@ -11,7 +11,7 @@ import { ftToM } from "../other/utils";
|
||||
|
||||
export interface SpawnOptions {
|
||||
role: string;
|
||||
type: string;
|
||||
name: string;
|
||||
latlng: LatLng;
|
||||
coalition: string;
|
||||
loadout?: string | null;
|
||||
@ -28,7 +28,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
#aircrafSpawnAltitudeSlider: Slider;
|
||||
#groundUnitRoleDropdown: Dropdown;
|
||||
#groundUnitTypeDropdown: Dropdown;
|
||||
#spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: ftToM(20000) };
|
||||
#spawnOptions: SpawnOptions = { role: "", name: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null, altitude: ftToM(20000) };
|
||||
|
||||
constructor(id: string) {
|
||||
super(id);
|
||||
@ -57,7 +57,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.hide();
|
||||
this.#spawnOptions.coalition = getActiveCoalition();
|
||||
if (this.#spawnOptions) {
|
||||
getMap().addTemporaryMarker(this.#spawnOptions.latlng);
|
||||
getMap().addTemporaryMarker(this.#spawnOptions);
|
||||
spawnAircraft(this.#spawnOptions);
|
||||
}
|
||||
});
|
||||
@ -66,7 +66,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.hide();
|
||||
this.#spawnOptions.coalition = getActiveCoalition();
|
||||
if (this.#spawnOptions) {
|
||||
getMap().addTemporaryMarker(this.#spawnOptions.latlng);
|
||||
getMap().addTemporaryMarker(this.#spawnOptions);
|
||||
spawnGroundUnit(this.#spawnOptions);
|
||||
}
|
||||
});
|
||||
@ -179,7 +179,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.#resetAircraftType();
|
||||
var type = aircraftDatabase.getByLabel(label)?.name || null;
|
||||
if (type != null) {
|
||||
this.#spawnOptions.type = type;
|
||||
this.#spawnOptions.name = type;
|
||||
this.#aircraftLoadoutDropdown.setOptions(aircraftDatabase.getLoadoutNamesByRole(type, this.#spawnOptions.role));
|
||||
this.#aircraftLoadoutDropdown.selectValue(0);
|
||||
var image = (<HTMLImageElement>this.getContainer()?.querySelector("#unit-image"));
|
||||
@ -198,7 +198,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
}
|
||||
|
||||
#setAircraftLoadout(loadoutName: string) {
|
||||
var loadout = aircraftDatabase.getLoadoutByName(this.#spawnOptions.type, loadoutName);
|
||||
var loadout = aircraftDatabase.getLoadoutByName(this.#spawnOptions.name, loadoutName);
|
||||
if (loadout) {
|
||||
this.#spawnOptions.loadout = loadout.code;
|
||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = false;
|
||||
@ -241,7 +241,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.#resetGroundUnitType();
|
||||
var type = groundUnitsDatabase.getByLabel(label)?.name || null;
|
||||
if (type != null) {
|
||||
this.#spawnOptions.type = type;
|
||||
this.#spawnOptions.name = type;
|
||||
(<HTMLButtonElement>this.getContainer()?.querySelector("#ground-unit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = false;
|
||||
}
|
||||
this.clip();
|
||||
|
||||
@ -46,7 +46,7 @@ export var BoxSelect = Handler.extend({
|
||||
|
||||
_onMouseDown: function (e: any) {
|
||||
if ((e.which == 1 && e.button == 0 && e.shiftKey)) {
|
||||
|
||||
this._map.fire('selectionstart');
|
||||
// Clear the deferred resetState if it hasn't executed yet, otherwise it
|
||||
// will interrupt the interaction and orphan a box element in the container.
|
||||
this._clearDeferredResetState();
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions } from "leaflet";
|
||||
import { DomUtil, LatLng, LatLngExpression, Map, Point, Polygon, PolylineOptions } from "leaflet";
|
||||
import { getMap } from "..";
|
||||
import { CoalitionAreaHandle } from "./coalitionareahandle";
|
||||
import { CoalitionAreaMiddleHandle } from "./coalitionareamiddlehandle";
|
||||
@ -19,6 +19,7 @@ export class CoalitionArea extends Polygon {
|
||||
super(latlngs, options);
|
||||
this.#setColors();
|
||||
this.#registerCallbacks();
|
||||
|
||||
}
|
||||
|
||||
setCoalition(coalition: string) {
|
||||
@ -61,6 +62,17 @@ export class CoalitionArea extends Polygon {
|
||||
return this.#editing;
|
||||
}
|
||||
|
||||
setInteractive(interactive: boolean) {
|
||||
this.setOpacity(interactive? 1: 0.5);
|
||||
this.options.interactive = interactive;
|
||||
|
||||
if (interactive) {
|
||||
DomUtil.addClass(this.getElement() as HTMLElement, 'leaflet-interactive');
|
||||
} else {
|
||||
DomUtil.removeClass(this.getElement() as HTMLElement, 'leaflet-interactive');
|
||||
}
|
||||
}
|
||||
|
||||
addTemporaryLatLng(latlng: LatLng) {
|
||||
this.#activeIndex++;
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
@ -69,13 +81,17 @@ export class CoalitionArea extends Polygon {
|
||||
this.#setHandles();
|
||||
}
|
||||
|
||||
moveTemporaryLatLng(latlng: LatLng) {
|
||||
moveActiveVertex(latlng: LatLng) {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs[this.#activeIndex] = latlng;
|
||||
this.setLatLngs(latlngs);
|
||||
this.#setHandles();
|
||||
}
|
||||
|
||||
setOpacity(opacity: number) {
|
||||
this.setStyle({opacity: opacity, fillOpacity: opacity * 0.25});
|
||||
}
|
||||
|
||||
#setColors() {
|
||||
const coalitionColor = this.getCoalition() === "blue" ? "#247be2" : "#ff5858";
|
||||
this.setStyle({ color: this.getSelected() ? "white" : coalitionColor, fillColor: coalitionColor });
|
||||
@ -138,8 +154,11 @@ export class CoalitionArea extends Polygon {
|
||||
});
|
||||
|
||||
this.on("contextmenu", (e: any) => {
|
||||
if (this.getSelected() && !this.getEditing())
|
||||
if (!this.getEditing()) {
|
||||
getMap().deselectAllCoalitionAreas();
|
||||
this.setSelected(true);
|
||||
getMap().showCoalitionAreaContextMenu(e, this);
|
||||
}
|
||||
else
|
||||
this.setEditing(false);
|
||||
});
|
||||
|
||||
@ -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 } from "../constants/constants";
|
||||
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTootlips, FIRE_AT_AREA, MOVE_UNIT, CARPET_BOMBING, BOMBING, COALITIONAREA_INTERACT } from "../constants/constants";
|
||||
import { TargetMarker } from "./targetmarker";
|
||||
import { CoalitionArea } from "./coalitionarea";
|
||||
import { CoalitionAreaContextMenu } from "../controls/coalitionareacontextmenu";
|
||||
@ -24,16 +24,6 @@ L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
|
||||
require("../../public/javascripts/leaflet.nauticscale.js")
|
||||
require("../../public/javascripts/L.Path.Drag.js")
|
||||
|
||||
/* Map constants */
|
||||
export const IDLE = "Idle";
|
||||
export const MOVE_UNIT = "Move unit";
|
||||
export const BOMBING = "Bombing";
|
||||
export const CARPET_BOMBING = "Carpet bombing";
|
||||
export const FIRE_AT_AREA = "Fire at area";
|
||||
export const DRAW_COALITIONAREA_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 class Map extends L.Map {
|
||||
#ID: string;
|
||||
#state: string;
|
||||
@ -51,16 +41,17 @@ export class Map extends L.Map {
|
||||
#miniMap: ClickableMiniMap | null = null;
|
||||
#miniMapLayerGroup: L.LayerGroup;
|
||||
#temporaryMarkers: TemporaryUnitMarker[] = [];
|
||||
|
||||
#selecting: boolean = false;
|
||||
|
||||
#destinationGroupRotation: number = 0;
|
||||
#computeDestinationRotation: boolean = false;
|
||||
#destinationRotationCenter: L.LatLng | null = null;
|
||||
#coalitionAreas: CoalitionArea[] = [];
|
||||
|
||||
#targetCursor: TargetMarker = new TargetMarker(new L.LatLng(0, 0), {interactive: false});
|
||||
#targetCursor: TargetMarker = new TargetMarker(new L.LatLng(0, 0), { interactive: false });
|
||||
#destinationPreviewCursors: DestinationPreviewMarker[] = [];
|
||||
#drawingCursor: DrawingCursor = new DrawingCursor();
|
||||
|
||||
|
||||
#mapContextMenu: MapContextMenu = new MapContextMenu("map-contextmenu");
|
||||
#unitContextMenu: UnitContextMenu = new UnitContextMenu("unit-contextmenu");
|
||||
#airbaseContextMenu: AirbaseContextMenu = new AirbaseContextMenu("airbase-contextmenu");
|
||||
@ -71,8 +62,7 @@ export class Map extends L.Map {
|
||||
|
||||
constructor(ID: string) {
|
||||
/* Init the leaflet map */
|
||||
|
||||
//@ts-ignore
|
||||
//@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 });
|
||||
this.setView([37.23, -115.8], 10);
|
||||
|
||||
@ -102,6 +92,7 @@ export class Map extends L.Map {
|
||||
this.on("zoomstart", (e: any) => this.#onZoom(e));
|
||||
this.on("drag", (e: any) => this.centerOnUnit(null));
|
||||
this.on("contextmenu", (e: any) => this.#onContextMenu(e));
|
||||
this.on('selectionstart', (e: any) => this.#onSelectionStart(e));
|
||||
this.on('selectionend', (e: any) => this.#onSelectionEnd(e));
|
||||
this.on('mousedown', (e: any) => this.#onMouseDown(e));
|
||||
this.on('mouseup', (e: any) => this.#onMouseUp(e));
|
||||
@ -113,7 +104,7 @@ export class Map extends L.Map {
|
||||
document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => {
|
||||
const el = ev.detail._element;
|
||||
el?.classList.toggle("off");
|
||||
getUnitsManager().setHiddenType(ev.detail.coalition, (el?.currentTarget as HTMLElement)?.classList.contains("off"));
|
||||
getUnitsManager().setHiddenType(ev.detail.coalition, !el?.classList.contains("off"));
|
||||
Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility());
|
||||
});
|
||||
|
||||
@ -124,16 +115,28 @@ export class Map extends L.Map {
|
||||
Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility());
|
||||
});
|
||||
|
||||
document.addEventListener("toggleCoalitionAreaInteraction", (ev: CustomEventInit) => {
|
||||
const el = ev.detail._element;
|
||||
/* Add listener to set the button to off if the state changes */
|
||||
document.addEventListener("mapStateChanged", () => el?.classList.toggle("off", !(this.getState() === COALITIONAREA_INTERACT)));
|
||||
if (this.getState() !== COALITIONAREA_INTERACT)
|
||||
this.setState(COALITIONAREA_INTERACT);
|
||||
else
|
||||
this.setState(IDLE);
|
||||
});
|
||||
|
||||
document.addEventListener("toggleCoalitionAreaDraw", (ev: CustomEventInit) => {
|
||||
const el = ev.detail._element;
|
||||
document.addEventListener("mapStateChanged", () => el?.classList.toggle("off", !(this.getState() === DRAW_COALITIONAREA_POLYGON)));
|
||||
/* Add listener to set the button to off if the state changes */
|
||||
document.addEventListener("mapStateChanged", () => el?.classList.toggle("off", !(this.getState() === COALITIONAREA_DRAW_POLYGON)));
|
||||
this.deselectAllCoalitionAreas();
|
||||
if (ev.detail?.type == "polygon") {
|
||||
if (this.getState() !== DRAW_COALITIONAREA_POLYGON)
|
||||
this.setState(DRAW_COALITIONAREA_POLYGON);
|
||||
else
|
||||
if (this.getState() !== COALITIONAREA_DRAW_POLYGON)
|
||||
this.setState(COALITIONAREA_DRAW_POLYGON);
|
||||
else
|
||||
this.setState(IDLE);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
document.addEventListener("unitUpdated", (ev: CustomEvent) => {
|
||||
if (this.#centerUnit != null && ev.detail == this.#centerUnit)
|
||||
@ -143,7 +146,7 @@ export class Map extends L.Map {
|
||||
/* Pan interval */
|
||||
this.#panInterval = window.setInterval(() => {
|
||||
if (this.#panLeft || this.#panDown || this.#panRight || this.#panLeft)
|
||||
this.panBy(new L.Point(((this.#panLeft? -1 : 0) + (this.#panRight ? 1 : 0)) * this.#deafultPanDelta,
|
||||
this.panBy(new L.Point(((this.#panLeft ? -1 : 0) + (this.#panRight ? 1 : 0)) * this.#deafultPanDelta,
|
||||
((this.#panUp ? -1 : 0) + (this.#panDown ? 1 : 0)) * this.#deafultPanDelta));
|
||||
}, 20);
|
||||
|
||||
@ -155,10 +158,10 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
setLayer(layerName: string) {
|
||||
if (this.#layer != null)
|
||||
if (this.#layer != null)
|
||||
this.removeLayer(this.#layer)
|
||||
|
||||
if (layerName in mapLayers){
|
||||
|
||||
if (layerName in mapLayers) {
|
||||
const layerData = mapLayers[layerName as keyof typeof mapLayers];
|
||||
var options: L.TileLayerOptions = {
|
||||
attribution: layerData.attribution,
|
||||
@ -178,17 +181,25 @@ export class Map extends L.Map {
|
||||
/* State machine */
|
||||
setState(state: string) {
|
||||
this.#state = state;
|
||||
this.#showCursor();
|
||||
if (this.#state === IDLE) {
|
||||
this.#updateCursor();
|
||||
|
||||
/* Operations to perform if you are NOT in a state */
|
||||
if (this.#state !== COALITIONAREA_INTERACT) {
|
||||
this.#coalitionAreas.forEach((coalitionArea: CoalitionArea) => {
|
||||
coalitionArea.setInteractive(false);
|
||||
});
|
||||
}
|
||||
if (this.#state !== COALITIONAREA_DRAW_POLYGON) {
|
||||
this.#deselectCoalitionAreas();
|
||||
}
|
||||
else if (this.#state === MOVE_UNIT) {
|
||||
this.#deselectCoalitionAreas();
|
||||
|
||||
/* Operations to perform if you ARE in a state */
|
||||
if (this.#state === COALITIONAREA_INTERACT) {
|
||||
this.#coalitionAreas.forEach((coalitionArea: CoalitionArea) => {
|
||||
coalitionArea.setInteractive(true);
|
||||
});
|
||||
}
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) {
|
||||
this.#deselectCoalitionAreas();
|
||||
}
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
this.#coalitionAreas.push(new CoalitionArea([]));
|
||||
this.#coalitionAreas[this.#coalitionAreas.length - 1].addTo(this);
|
||||
}
|
||||
@ -377,13 +388,14 @@ export class Map extends L.Map {
|
||||
}
|
||||
}
|
||||
|
||||
addTemporaryMarker(latlng: L.LatLng) {
|
||||
var marker = new TemporaryUnitMarker(latlng);
|
||||
addTemporaryMarker(spawnOptions: SpawnOptions) {
|
||||
var marker = new TemporaryUnitMarker(spawnOptions);
|
||||
marker.addTo(this);
|
||||
this.#temporaryMarkers.push(marker);
|
||||
}
|
||||
|
||||
removeTemporaryMarker(latlng: L.LatLng) {
|
||||
// TODO something more refined than this
|
||||
var d: number | null = null;
|
||||
var closest: L.Marker | null = null;
|
||||
var i: number = 0;
|
||||
@ -402,7 +414,7 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
getSelectedCoalitionArea() {
|
||||
return this.#coalitionAreas.find((area: CoalitionArea) => {return area.getSelected()});
|
||||
return this.#coalitionAreas.find((area: CoalitionArea) => { return area.getSelected() });
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
@ -412,7 +424,7 @@ export class Map extends L.Map {
|
||||
if (this.#state === IDLE) {
|
||||
this.deselectAllCoalitionAreas();
|
||||
}
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing()) {
|
||||
this.getSelectedCoalitionArea()?.addTemporaryLatLng(e.latlng);
|
||||
}
|
||||
@ -443,41 +455,48 @@ export class Map extends L.Map {
|
||||
getUnitsManager().selectedUnitsClearDestinations();
|
||||
}
|
||||
getUnitsManager().selectedUnitsAddDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : e.latlng, e.originalEvent.shiftKey, this.#destinationGroupRotation)
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationRotationCenter = null;
|
||||
this.#computeDestinationRotation = false;
|
||||
}
|
||||
else if (this.#state === BOMBING) {
|
||||
getUnitsManager().getSelectedUnits().length > 0? this.setState(MOVE_UNIT): this.setState(IDLE);
|
||||
getUnitsManager().selectedUnitsBombPoint(this.getMouseCoordinates());
|
||||
getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getUnitsManager().selectedUnitsBombPoint(this.getMouseCoordinates());
|
||||
}
|
||||
else if (this.#state === CARPET_BOMBING) {
|
||||
getUnitsManager().getSelectedUnits().length > 0? this.setState(MOVE_UNIT): this.setState(IDLE);
|
||||
getUnitsManager().selectedUnitsCarpetBomb(this.getMouseCoordinates());
|
||||
getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getUnitsManager().selectedUnitsCarpetBomb(this.getMouseCoordinates());
|
||||
}
|
||||
else if (this.#state === FIRE_AT_AREA) {
|
||||
getUnitsManager().getSelectedUnits().length > 0? this.setState(MOVE_UNIT): this.setState(IDLE);
|
||||
getUnitsManager().selectedUnitsFireAtArea(this.getMouseCoordinates());
|
||||
getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getUnitsManager().selectedUnitsFireAtArea(this.getMouseCoordinates());
|
||||
}
|
||||
else {
|
||||
this.setState(IDLE);
|
||||
}
|
||||
}
|
||||
|
||||
#onSelectionStart(e: any) {
|
||||
this.#selecting = true;
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
#onSelectionEnd(e: any) {
|
||||
this.#selecting = false;
|
||||
clearTimeout(this.#leftClickTimer);
|
||||
this.#preventLeftClick = true;
|
||||
this.#leftClickTimer = window.setTimeout(() => {
|
||||
this.#preventLeftClick = false;
|
||||
}, 200);
|
||||
getUnitsManager().selectFromBounds(e.selectionBounds);
|
||||
this.#updateCursor();
|
||||
}
|
||||
|
||||
#onMouseDown(e: any) {
|
||||
this.hideAllContextMenus();
|
||||
|
||||
if (this.#state == MOVE_UNIT) {
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationRotationCenter = null;
|
||||
this.#computeDestinationRotation = false;
|
||||
if (e.originalEvent.button == 2) {
|
||||
@ -494,32 +513,32 @@ export class Map extends L.Map {
|
||||
this.#lastMousePosition.x = e.originalEvent.x;
|
||||
this.#lastMousePosition.y = e.originalEvent.y;
|
||||
|
||||
this.#showCursor(e);
|
||||
this.#updateCursor(e);
|
||||
|
||||
if (this.#state === MOVE_UNIT){
|
||||
if (this.#state === MOVE_UNIT) {
|
||||
/* Update the position of the destination cursors depeding on mouse rotation */
|
||||
if (this.#computeDestinationRotation && this.#destinationRotationCenter != null)
|
||||
this.#destinationGroupRotation = -bearing(this.#destinationRotationCenter.lat, this.#destinationRotationCenter.lng, this.getMouseCoordinates().lat, this.getMouseCoordinates().lng);
|
||||
this.#updateDestinationPreview(e);
|
||||
this.#updateDestinationCursors(e);
|
||||
}
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) {
|
||||
this.#targetCursor.setLatLng(this.getMouseCoordinates());
|
||||
}
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing() && !e.originalEvent.ctrlKey){
|
||||
this.#drawingCursor.setLatLng(e.latlng);
|
||||
this.getSelectedCoalitionArea()?.moveTemporaryLatLng(e.latlng);
|
||||
}
|
||||
else if (this.#state === COALITIONAREA_DRAW_POLYGON) {
|
||||
this.#drawingCursor.setLatLng(e.latlng);
|
||||
/* Update the polygon being drawn with the current position of the mouse cursor */
|
||||
this.getSelectedCoalitionArea()?.moveActiveVertex(e.latlng);
|
||||
}
|
||||
}
|
||||
|
||||
#onKeyDown(e: any) {
|
||||
this.#updateDestinationPreview(e);
|
||||
this.#showCursor(e);
|
||||
this.#updateDestinationCursors(e);
|
||||
this.#updateCursor(e);
|
||||
}
|
||||
|
||||
#onKeyUp(e: any) {
|
||||
this.#updateDestinationPreview(e);
|
||||
this.#showCursor(e);
|
||||
this.#updateDestinationCursors(e);
|
||||
this.#updateCursor(e);
|
||||
}
|
||||
|
||||
#onZoom(e: any) {
|
||||
@ -537,13 +556,6 @@ export class Map extends L.Map {
|
||||
return minimapBoundaries;
|
||||
}
|
||||
|
||||
#updateDestinationPreview(e: any) {
|
||||
Object.values(getUnitsManager().selectedUnitsComputeGroupDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : this.getMouseCoordinates(), this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => {
|
||||
if (idx < this.#destinationPreviewCursors.length)
|
||||
this.#destinationPreviewCursors[idx].setLatLng(e.originalEvent.shiftKey ? latlng : this.getMouseCoordinates());
|
||||
})
|
||||
}
|
||||
|
||||
#createOptionButton(value: string, url: string, title: string, callback: string, argument: string) {
|
||||
var button = document.createElement("button");
|
||||
const img = document.createElement("img");
|
||||
@ -557,32 +569,58 @@ export class Map extends L.Map {
|
||||
return button;
|
||||
}
|
||||
|
||||
#showDestinationCursors() {
|
||||
this.#hideDestinationCursors();
|
||||
#deselectCoalitionAreas() {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
}
|
||||
|
||||
if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length > 0) {
|
||||
/* Create the unit destination preview markers */
|
||||
this.#destinationPreviewCursors = getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).map((unit: Unit) => {
|
||||
var marker = new DestinationPreviewMarker(this.getMouseCoordinates(), {interactive: false});
|
||||
marker.addTo(this);
|
||||
return marker;
|
||||
})
|
||||
/* Cursors */
|
||||
#showDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.remove("hidden-cursor");
|
||||
}
|
||||
|
||||
#hideDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.add("hidden-cursor");
|
||||
}
|
||||
|
||||
#showDestinationCursors() {
|
||||
/* Don't create the cursors if there already are the correct number of them available */
|
||||
if (getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).length != this.#destinationPreviewCursors.length) {
|
||||
/* Reset the cursors to start from a clean condition */
|
||||
this.#hideDestinationCursors();
|
||||
|
||||
if (getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).length > 0) {
|
||||
/* Create the cursors. If a group is selected only one cursor is shown for it, because you can't control single units in a group */
|
||||
this.#destinationPreviewCursors = getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).map((unit: Unit) => {
|
||||
var marker = new DestinationPreviewMarker(this.getMouseCoordinates(), { interactive: false });
|
||||
marker.addTo(this);
|
||||
return marker;
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#updateDestinationCursors(e: any) {
|
||||
const groupLatLng = this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : this.getMouseCoordinates();
|
||||
Object.values(getUnitsManager().selectedUnitsComputeGroupDestination(groupLatLng, this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => {
|
||||
if (idx < this.#destinationPreviewCursors.length)
|
||||
this.#destinationPreviewCursors[idx].setLatLng(e.originalEvent.shiftKey ? latlng : this.getMouseCoordinates());
|
||||
})
|
||||
}
|
||||
|
||||
#hideDestinationCursors() {
|
||||
/* Remove all the destination preview markers */
|
||||
/* Remove all the destination cursors */
|
||||
this.#destinationPreviewCursors.forEach((marker: L.Marker) => {
|
||||
this.removeLayer(marker);
|
||||
})
|
||||
this.#destinationPreviewCursors = [];
|
||||
|
||||
/* Reset the variables used to compute the rotation of the group cursors */
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#computeDestinationRotation = false;
|
||||
this.#destinationRotationCenter = null;
|
||||
}
|
||||
|
||||
#showTargetCursor(){
|
||||
#showTargetCursor() {
|
||||
this.#hideTargetCursor();
|
||||
this.#targetCursor.addTo(this);
|
||||
}
|
||||
@ -592,18 +630,6 @@ export class Map extends L.Map {
|
||||
this.removeLayer(this.#targetCursor);
|
||||
}
|
||||
|
||||
#deselectCoalitionAreas() {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
}
|
||||
|
||||
#showDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.remove("hidden-cursor");
|
||||
}
|
||||
|
||||
#hideDefaultCursor() {
|
||||
document.getElementById(this.#ID)?.classList.add("hidden-cursor");
|
||||
}
|
||||
|
||||
#showDrawingCursor() {
|
||||
this.#hideDefaultCursor();
|
||||
if (!this.hasLayer(this.#drawingCursor))
|
||||
@ -611,38 +637,33 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#hideDrawingCursor() {
|
||||
this.#drawingCursor.setLatLng(new L.LatLng(0, 0));
|
||||
if (this.hasLayer(this.#drawingCursor))
|
||||
this.#drawingCursor.removeFrom(this);
|
||||
}
|
||||
|
||||
#showCursor(e?: any) {
|
||||
if (e?.originalEvent.ctrlKey) {
|
||||
this.#hideDefaultCursor();
|
||||
#updateCursor(e?: any) {
|
||||
/* If the ctrl key is being pressed or we are performing an area selection, show the default cursor */
|
||||
if (e?.originalEvent.ctrlKey || this.#selecting) {
|
||||
/* Hide all non default cursors */
|
||||
this.#hideDestinationCursors();
|
||||
this.#hideTargetCursor();
|
||||
this.#hideDrawingCursor();
|
||||
|
||||
this.#showDefaultCursor();
|
||||
} else {
|
||||
if (this.#state !== IDLE) this.#hideDefaultCursor();
|
||||
/* Hide all the unnecessary cursors depending on the active state */
|
||||
if (this.#state !== IDLE && this.#state !== COALITIONAREA_INTERACT) this.#hideDefaultCursor();
|
||||
if (this.#state !== MOVE_UNIT) this.#hideDestinationCursors();
|
||||
if (![BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) this.#hideTargetCursor();
|
||||
if (this.#state !== DRAW_COALITIONAREA_POLYGON) this.#hideDrawingCursor();
|
||||
if (this.#state !== COALITIONAREA_DRAW_POLYGON) this.#hideDrawingCursor();
|
||||
|
||||
if (this.#state === IDLE) this.#showDefaultCursor();
|
||||
/* Show the active cursor depending on the active state */
|
||||
if (this.#state === IDLE || this.#state === COALITIONAREA_INTERACT) this.#showDefaultCursor();
|
||||
else if (this.#state === MOVE_UNIT) this.#showDestinationCursors();
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) this.#showTargetCursor();
|
||||
else if (this.#state === DRAW_COALITIONAREA_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing())
|
||||
{
|
||||
this.#hideDefaultCursor();
|
||||
this.#showDrawingCursor();
|
||||
}
|
||||
else {
|
||||
this.#hideDrawingCursor();
|
||||
this.#showDefaultCursor();
|
||||
}
|
||||
}
|
||||
else if (this.#state === COALITIONAREA_DRAW_POLYGON) this.#showDrawingCursor();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,13 +1,52 @@
|
||||
import { Icon } from "leaflet";
|
||||
import { CustomMarker } from "./custommarker";
|
||||
import { SpawnOptions } from "../controls/mapcontextmenu";
|
||||
import { DivIcon } from "leaflet";
|
||||
import { SVGInjector } from "@tanem/svg-injector";
|
||||
import { getMarkerCategoryByName, getUnitDatabaseByCategory } from "../other/utils";
|
||||
|
||||
export class TemporaryUnitMarker extends CustomMarker {
|
||||
#spawnOptions: SpawnOptions;
|
||||
|
||||
constructor(spawnOptions: SpawnOptions) {
|
||||
super(spawnOptions.latlng, {interactive: false});
|
||||
this.#spawnOptions = spawnOptions;
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
var icon = new Icon({
|
||||
iconUrl: '/resources/theme/images/markers/temporary-icon.png',
|
||||
iconSize: [52, 52],
|
||||
iconAnchor: [26, 26]
|
||||
const category = getMarkerCategoryByName(this.#spawnOptions.name);
|
||||
|
||||
/* Set the icon */
|
||||
var icon = new DivIcon({
|
||||
className: 'leaflet-unit-icon',
|
||||
iconAnchor: [25, 25],
|
||||
iconSize: [50, 50],
|
||||
});
|
||||
this.setIcon(icon);
|
||||
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("unit");
|
||||
el.setAttribute("data-object", `unit-${category}`);
|
||||
el.setAttribute("data-coalition", this.#spawnOptions.coalition);
|
||||
|
||||
// Main icon
|
||||
var unitIcon = document.createElement("div");
|
||||
unitIcon.classList.add("unit-icon");
|
||||
var img = document.createElement("img");
|
||||
img.src = `/resources/theme/images/units/${category}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
unitIcon.toggleAttribute("data-rotate-to-heading", false);
|
||||
el.append(unitIcon);
|
||||
|
||||
// Short label
|
||||
if (category == "aircraft" || category == "helicopter") {
|
||||
var shortLabel = document.createElement("div");
|
||||
shortLabel.classList.add("unit-short-label");
|
||||
shortLabel.innerText = getUnitDatabaseByCategory(category)?.getByName(this.#spawnOptions.name)?.shortLabel || "";
|
||||
el.append(shortLabel);
|
||||
}
|
||||
|
||||
this.getElement()?.appendChild(el);
|
||||
this.getElement()?.classList.add("ol-temporary-marker");
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,9 @@
|
||||
import { LatLng, Point, Polygon } from "leaflet";
|
||||
import * as turf from "@turf/turf";
|
||||
import { UnitDatabase } from "../units/unitdatabase";
|
||||
import { aircraftDatabase } from "../units/aircraftdatabase";
|
||||
import { helicopterDatabase } from "../units/helicopterdatabase";
|
||||
import { groundUnitsDatabase } from "../units/groundunitsdatabase";
|
||||
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
@ -219,4 +222,29 @@ export function randomUnitBlueprintByRole(unitDatabse: UnitDatabase, role: strin
|
||||
const unitBlueprints = unitDatabse.getByRole(role);
|
||||
var index = Math.floor(Math.random() * unitBlueprints.length);
|
||||
return unitBlueprints[index];
|
||||
}
|
||||
|
||||
export function getMarkerCategoryByName(name: string) {
|
||||
if (aircraftDatabase.getByName(name) != null)
|
||||
return "aircraft";
|
||||
else if (helicopterDatabase.getByName(name) != null)
|
||||
return "helicopter";
|
||||
else if (groundUnitsDatabase.getByName(name) != null){
|
||||
// TODO this is very messy
|
||||
var role = groundUnitsDatabase.getByName(name)?.loadouts[0].roles[0];
|
||||
return (role?.includes("SAM")) ? "groundunit-sam" : "groundunit-other";
|
||||
}
|
||||
else
|
||||
return ""; // TODO add other unit types
|
||||
}
|
||||
|
||||
export function getUnitDatabaseByCategory(category: string) {
|
||||
if (category == "aircraft")
|
||||
return aircraftDatabase;
|
||||
else if (category == "helicopter")
|
||||
return helicopterDatabase;
|
||||
else if (category.includes("groundunit"))
|
||||
return groundUnitsDatabase;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
@ -134,13 +134,13 @@ export function spawnExplosion(intensity: number, latlng: LatLng) {
|
||||
}
|
||||
|
||||
export function spawnGroundUnit(spawnOptions: SpawnOptions) {
|
||||
var command = { "type": spawnOptions.type, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "immediate": spawnOptions.immediate? true: false };
|
||||
var command = { "type": spawnOptions.name, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "immediate": spawnOptions.immediate? true: false };
|
||||
var data = { "spawnGround": command }
|
||||
POST(data, () => { });
|
||||
}
|
||||
|
||||
export function spawnAircraft(spawnOptions: SpawnOptions) {
|
||||
var command = { "type": spawnOptions.type, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "altitude": spawnOptions.altitude, "payloadName": spawnOptions.loadout != null ? spawnOptions.loadout : "", "airbaseName": spawnOptions.airbaseName != null ? spawnOptions.airbaseName : "", "immediate": spawnOptions.immediate? true: false };
|
||||
var command = { "type": spawnOptions.name, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "altitude": spawnOptions.altitude, "payloadName": spawnOptions.loadout != null ? spawnOptions.loadout : "", "airbaseName": spawnOptions.airbaseName != null ? spawnOptions.airbaseName : "", "immediate": spawnOptions.immediate? true: false };
|
||||
var data = { "spawnAir": command }
|
||||
POST(data, () => { });
|
||||
}
|
||||
|
||||
@ -1,14 +1,12 @@
|
||||
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map } from 'leaflet';
|
||||
import { getMap, getUnitsManager } from '..';
|
||||
import { mToFt, msToKnots, rad2deg } from '../other/utils';
|
||||
import { getMarkerCategoryByName, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg } from '../other/utils';
|
||||
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads, bombPoint, carpetBomb, bombBuilding, fireAtArea } from '../server/server';
|
||||
import { aircraftDatabase } from './aircraftdatabase';
|
||||
import { groundUnitsDatabase } from './groundunitsdatabase';
|
||||
import { CustomMarker } from '../map/custommarker';
|
||||
import { SVGInjector } from '@tanem/svg-injector';
|
||||
import { UnitDatabase } from './unitdatabase';
|
||||
import { BOMBING, CARPET_BOMBING, FIRE_AT_AREA, IDLE, MOVE_UNIT } from '../map/map';
|
||||
import { TargetMarker } from '../map/targetmarker';
|
||||
import { BOMBING, CARPET_BOMBING, FIRE_AT_AREA, IDLE, MOVE_UNIT } from '../constants/constants';
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: '/resources/theme/images/markers/marker-icon.png',
|
||||
@ -133,12 +131,12 @@ export class Unit extends CustomMarker {
|
||||
|
||||
getMarkerCategory() {
|
||||
// Overloaded by child classes
|
||||
// TODO convert to use getMarkerCategoryByName
|
||||
return "";
|
||||
}
|
||||
|
||||
getDatabase(): UnitDatabase | null {
|
||||
// Overloaded by child classes
|
||||
return null;
|
||||
return getUnitDatabaseByCategory(this.getMarkerCategory());
|
||||
}
|
||||
|
||||
getIconOptions(): UnitIconOptions {
|
||||
@ -344,7 +342,7 @@ export class Unit extends CustomMarker {
|
||||
if (this.getIconOptions().showShortLabel) {
|
||||
var shortLabel = document.createElement("div");
|
||||
shortLabel.classList.add("unit-short-label");
|
||||
shortLabel.innerText = this.getDatabase()?.getByName(this.getBaseData().name)?.shortLabel || "";
|
||||
shortLabel.innerText = getUnitDatabaseByCategory(this.getMarkerCategory())?.getByName(this.getBaseData().name)?.shortLabel || "";
|
||||
el.append(shortLabel);
|
||||
}
|
||||
|
||||
@ -424,7 +422,7 @@ export class Unit extends CustomMarker {
|
||||
return getUnitsManager().getUnitByID(this.getFormationData().leaderID);
|
||||
}
|
||||
|
||||
canRole(roles: string | string[]) {
|
||||
canFulfillRole(roles: string | string[]) {
|
||||
if (typeof(roles) === "string")
|
||||
roles = [roles];
|
||||
|
||||
@ -565,7 +563,9 @@ export class Unit extends CustomMarker {
|
||||
/***********************************************/
|
||||
onAdd(map: Map): this {
|
||||
super.onAdd(map);
|
||||
getMap().removeTemporaryMarker(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude));
|
||||
/* If this is the first time adding this unit to the map, remove the temporary marker */
|
||||
if (getUnitsManager().getUnitByID(this.ID) == null)
|
||||
getMap().removeTemporaryMarker(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude));
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -609,14 +609,14 @@ export class Unit extends CustomMarker {
|
||||
|
||||
if ((selectedUnits.length === 0 && this.getBaseData().category == "Aircraft") || (selectedUnitTypes.length === 1 && ["Aircraft"].includes(selectedUnitTypes[0])))
|
||||
{
|
||||
if (selectedUnits.concat([this]).every((unit: Unit) => {return unit.canRole(["CAS", "Strike"])})) {
|
||||
if (selectedUnits.concat([this]).every((unit: Unit) => {return unit.canFulfillRole(["CAS", "Strike"])})) {
|
||||
options["bomb"] = {text: "Precision bombing", tooltip: "Precision bombing of a specific point"};
|
||||
options["carpet-bomb"] = {text: "Carpet bombing", tooltip: "Carpet bombing close to a point"};
|
||||
}
|
||||
}
|
||||
|
||||
if ((selectedUnits.length === 0 && this.getBaseData().category == "GroundUnit") || selectedUnitTypes.length === 1 && ["GroundUnit"].includes(selectedUnitTypes[0])) {
|
||||
if (selectedUnits.concat([this]).every((unit: Unit) => {return unit.canRole(["Gun Artillery", "Rocket Artillery", "Infantry", "IFV", "Tank"])}))
|
||||
if (selectedUnits.concat([this]).every((unit: Unit) => {return unit.canFulfillRole(["Gun Artillery", "Rocket Artillery", "Infantry", "IFV", "Tank"])}))
|
||||
options["fire-at-area"] = {text: "Fire at area", tooltip: "Fire at a large area"};
|
||||
}
|
||||
|
||||
@ -915,21 +915,17 @@ export class AirUnit extends Unit {
|
||||
}
|
||||
|
||||
export class Aircraft extends AirUnit {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
getMarkerCategory() {
|
||||
return "aircraft";
|
||||
}
|
||||
|
||||
getDatabase(): UnitDatabase | null {
|
||||
return aircraftDatabase;
|
||||
}
|
||||
}
|
||||
|
||||
export class Helicopter extends AirUnit {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
@ -939,7 +935,7 @@ export class Helicopter extends AirUnit {
|
||||
}
|
||||
|
||||
export class GroundUnit extends Unit {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
@ -958,19 +954,12 @@ export class GroundUnit extends Unit {
|
||||
}
|
||||
|
||||
getMarkerCategory() {
|
||||
// TODO this is very messy
|
||||
var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0];
|
||||
var markerCategory = (role === "SAM") ? "groundunit-sam" : "groundunit-other";
|
||||
return markerCategory;
|
||||
}
|
||||
|
||||
getDatabase(): UnitDatabase | null {
|
||||
return groundUnitsDatabase;
|
||||
return getMarkerCategoryByName(this.getBaseData().name);
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnit extends Unit {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
@ -994,7 +983,7 @@ export class NavyUnit extends Unit {
|
||||
}
|
||||
|
||||
export class Weapon extends Unit {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
this.setSelectable(false);
|
||||
}
|
||||
@ -1015,7 +1004,7 @@ export class Weapon extends Unit {
|
||||
}
|
||||
|
||||
export class Missile extends Weapon {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
@ -1025,7 +1014,7 @@ export class Missile extends Weapon {
|
||||
}
|
||||
|
||||
export class Bomb extends Weapon {
|
||||
constructor(ID: number, data: UnitData) {
|
||||
constructor(ID: number, data: UpdateData) {
|
||||
super(ID, data);
|
||||
}
|
||||
|
||||
|
||||
@ -3,10 +3,10 @@ import { getHotgroupPanel, getInfoPopup, getMap, getMissionHandler, getUnitDataT
|
||||
import { Unit } from "./unit";
|
||||
import { cloneUnit, spawnGroundUnit } from "../server/server";
|
||||
import { deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polygonArea, randomPointInPoly, randomUnitBlueprintByRole } from "../other/utils";
|
||||
import { IDLE, MOVE_UNIT } from "../map/map";
|
||||
import { CoalitionArea } from "../map/coalitionarea";
|
||||
import { Airbase } from "../missionhandler/airbase";
|
||||
import { groundUnitsDatabase } from "./groundunitsdatabase";
|
||||
import { IDLE, MOVE_UNIT } from "../constants/constants";
|
||||
|
||||
export class UnitsManager {
|
||||
#units: { [ID: number]: Unit };
|
||||
@ -493,7 +493,7 @@ export class UnitsManager {
|
||||
if (!this.#pasteDisabled) {
|
||||
for (let idx in this.#copiedUnits) {
|
||||
var unit = this.#copiedUnits[idx];
|
||||
getMap().addTemporaryMarker(getMap().getMouseCoordinates());
|
||||
//getMap().addTemporaryMarker(getMap().getMouseCoordinates());
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
this.#showActionMessage(this.#copiedUnits, `pasted`);
|
||||
}
|
||||
@ -520,14 +520,9 @@ export class UnitsManager {
|
||||
if (Math.random() < probability){
|
||||
const role = activeRoles[Math.floor(Math.random() * activeRoles.length)];
|
||||
const unitBlueprint = randomUnitBlueprintByRole(groundUnitsDatabase, role);
|
||||
spawnGroundUnit({
|
||||
role: role,
|
||||
latlng: latlng,
|
||||
type: unitBlueprint.name,
|
||||
coalition: coalitionArea.getCoalition(),
|
||||
immediate: true
|
||||
});
|
||||
getMap().addTemporaryMarker(latlng);
|
||||
const spawnOptions = {role: role, latlng: latlng, name: unitBlueprint.name, coalition: coalitionArea.getCoalition(), immediate: true};
|
||||
spawnGroundUnit(spawnOptions);
|
||||
getMap().addTemporaryMarker(spawnOptions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -116,6 +116,8 @@
|
||||
data-on-click-params='{ "type": "iads" }' class="ol-contexmenu-button"></button>
|
||||
<button data-coalition="blue" id="cap-button" title="Create Combat Air Patrols" data-on-click="coalitionAreaContextMenuShow"
|
||||
data-on-click-params='{ "type": "cap" }' class="ol-contexmenu-button"></button>
|
||||
<button data-coalition="blue" id="coalitionarea-back-button" title="Bring area to back" data-on-click="coalitionAreaBringToBack"
|
||||
class="ol-contexmenu-button"></button>
|
||||
<button data-coalition="blue" id="coalitionarea-delete-button" title="Delete area" data-on-click="coalitionAreaDelete"
|
||||
class="ol-contexmenu-button"></button>
|
||||
</div>
|
||||
|
||||
@ -61,6 +61,9 @@
|
||||
|
||||
<div id="map-tools" class="ol-group-container ol-navbar-buttons-group">
|
||||
<div class="ol-group">
|
||||
<button title="Enable area interaction" data-on-click="toggleCoalitionAreaInteraction" class="off">
|
||||
<img src="resources/theme/images/buttons/tools/pen-solid.svg" inject-svg>
|
||||
</button>
|
||||
<button title="Draw Coalition Areas on the map" data-on-click="toggleCoalitionAreaDraw" data-on-click-params='{"type": "polygon"}' class="off">
|
||||
<img src="resources/theme/images/buttons/tools/draw-polygon-solid.svg" inject-svg>
|
||||
</button>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user