mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Migration to node.js completed
This commit is contained in:
@@ -1,14 +1,38 @@
|
||||
export class Button
|
||||
{
|
||||
export class Button {
|
||||
#container: HTMLElement | null;
|
||||
constructor(ID: string, srcs: string[], callback: CallableFunction)
|
||||
{
|
||||
#srcs: string[];
|
||||
#callback: CallableFunction;
|
||||
#img: any;
|
||||
#state: number = 0;
|
||||
|
||||
constructor(ID: string, srcs: string[], callback: CallableFunction) {
|
||||
this.#container = document.getElementById(ID);
|
||||
if (this.#container != null)
|
||||
{
|
||||
var img = document.createElement("img");
|
||||
img.src = srcs[0];
|
||||
this.#container.appendChild(img);
|
||||
this.#srcs = srcs;
|
||||
this.#callback = callback;
|
||||
if (this.#container != null) {
|
||||
this.#img = document.createElement("img");
|
||||
this.#img.src = this.#srcs[this.#state];
|
||||
this.#container.appendChild(this.#img);
|
||||
this.#container.addEventListener("click", () => this.#onClick());
|
||||
}
|
||||
}
|
||||
|
||||
setState(state: number) {
|
||||
if (state < this.#srcs.length) {
|
||||
this.#state = state;
|
||||
this.#img.src = this.#srcs[this.#state];
|
||||
}
|
||||
}
|
||||
|
||||
getState() {
|
||||
return this.#state;
|
||||
}
|
||||
|
||||
#onClick() {
|
||||
if (this.#img != null) {
|
||||
this.setState(this.#state < this.#srcs.length - 1 ? this.#state + 1 : 0);
|
||||
if (this.#callback)
|
||||
this.#callback(this.#state);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,41 +1,36 @@
|
||||
export class Dropdown
|
||||
{
|
||||
export class Dropdown {
|
||||
#container: HTMLElement | null;
|
||||
#options: string[];
|
||||
#options: string[];
|
||||
#open?: boolean;
|
||||
#content?: HTMLElement;
|
||||
#callback?: CallableFunction;
|
||||
|
||||
constructor(ID: string, options: string[], callback: CallableFunction)
|
||||
{
|
||||
constructor(ID: string, options: string[], callback: CallableFunction) {
|
||||
this.#container = document.getElementById(ID);
|
||||
this.#options = options;
|
||||
this.#callback = callback;
|
||||
this.close()
|
||||
this.#container?.addEventListener("click", () => {
|
||||
this.#open ? this.close(): this.open();
|
||||
this.#open ? this.close() : this.open();
|
||||
})
|
||||
}
|
||||
|
||||
open()
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
open() {
|
||||
if (this.#container != null) {
|
||||
this.#open = true;
|
||||
this.#container.classList.add("olympus-dropdown-open");
|
||||
this.#container.classList.remove("olympus-dropdown-closed");
|
||||
this.#content = document.createElement("div");
|
||||
this.#content.classList.add("olympus-dropdown-content");
|
||||
this.#content.style.width = (this.#container.offsetWidth - this.#container.offsetHeight) + "px";
|
||||
|
||||
|
||||
this.#content.style.left = this.#container.offsetLeft + "px";
|
||||
this.#content.style.top = this.#container.offsetTop + this.#container.offsetHeight + "px";
|
||||
console.log(this.#container);
|
||||
document.body.appendChild(this.#content);
|
||||
|
||||
var height = 2;
|
||||
for (let optionID in this.#options)
|
||||
{
|
||||
for (let optionID in this.#options) {
|
||||
var node = document.createElement("div");
|
||||
node.classList.add("olympus-dropdown-element");
|
||||
node.appendChild(document.createTextNode(this.#options[optionID]));
|
||||
@@ -53,10 +48,8 @@ export class Dropdown
|
||||
}
|
||||
}
|
||||
|
||||
close()
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
close() {
|
||||
if (this.#container != null) {
|
||||
this.#open = false;
|
||||
this.#container?.classList.remove("olympus-dropdown-open");
|
||||
this.#container?.classList.add("olympus-dropdown-closed");
|
||||
|
||||
@@ -1,32 +1,28 @@
|
||||
export class SelectionScroll
|
||||
{
|
||||
#container : HTMLElement | null;
|
||||
import { LatLng } from "leaflet";
|
||||
|
||||
export class SelectionScroll {
|
||||
#container: HTMLElement | null;
|
||||
#display: string;
|
||||
|
||||
constructor(id: string, )
|
||||
{
|
||||
constructor(id: string,) {
|
||||
this.#container = document.getElementById(id);
|
||||
this.#display = '';
|
||||
if (this.#container != null)
|
||||
{
|
||||
if (this.#container != null) {
|
||||
this.#display = this.#container.style.display;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
show(x: number, y: number, options: any, callback: CallableFunction)
|
||||
{
|
||||
show(x: number, y: number, options: any, callback: CallableFunction) {
|
||||
/* Hide to remove buttons, if present */
|
||||
this.hide();
|
||||
|
||||
if (this.#container != null && options.length > 1)
|
||||
{
|
||||
if (this.#container != null && options.length > 1) {
|
||||
this.#container.style.display = this.#display;
|
||||
this.#container.style.left = x - 110 + "px";
|
||||
this.#container.style.top = y - 110 + "px";
|
||||
this.#container.style.top = y - 110 + "px";
|
||||
|
||||
for (let optionID in options)
|
||||
{
|
||||
for (let optionID in options) {
|
||||
var node = document.createElement("div");
|
||||
node.classList.add("olympus-selection-scroll-element");
|
||||
node.appendChild(document.createTextNode(options[optionID]));
|
||||
@@ -36,14 +32,11 @@ export class SelectionScroll
|
||||
}
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
hide() {
|
||||
if (this.#container != null) {
|
||||
this.#container.style.display = "none";
|
||||
var buttons = this.#container.querySelectorAll(".olympus-selection-scroll-element");
|
||||
for (let child of buttons)
|
||||
{
|
||||
for (let child of buttons) {
|
||||
this.#container.removeChild(child);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,40 +1,34 @@
|
||||
import { getActiveCoalition, setActiveCoalition } from "..";
|
||||
import { deg2rad } from "../other/utils";
|
||||
|
||||
export class SelectionWheel
|
||||
{
|
||||
export class SelectionWheel {
|
||||
#container: HTMLElement | null;
|
||||
#display: string;
|
||||
|
||||
constructor(id: string)
|
||||
{
|
||||
constructor(id: string) {
|
||||
this.#container = document.getElementById(id);
|
||||
this.#display = '';
|
||||
if (this.#container != null)
|
||||
{
|
||||
if (this.#container != null) {
|
||||
this.#container.querySelector("#coalition-switch")?.addEventListener('change', (e) => this.#onSwitch(e))
|
||||
this.#display = this.#container.style.display;
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
show(x: number, y: number, options: any, showCoalition: boolean)
|
||||
{
|
||||
|
||||
show(x: number, y: number, options: any, showCoalition: boolean) {
|
||||
/* Hide to remove buttons, if present */
|
||||
this.hide();
|
||||
|
||||
if (this.#container != null)
|
||||
{
|
||||
if (this.#container != null) {
|
||||
this.#container.style.display = this.#display;
|
||||
this.#container.style.left = x - 110 + "px";
|
||||
this.#container.style.top = y - 110 + "px";
|
||||
this.#container.style.top = y - 110 + "px";
|
||||
|
||||
var angularSize = 360 / options.length;
|
||||
var r = 80;
|
||||
|
||||
/* Create the buttons */
|
||||
for (let id in options)
|
||||
{
|
||||
for (let id in options) {
|
||||
var button = document.createElement("div");
|
||||
button.classList.add("selection-wheel-button");
|
||||
button.style.left = x - 25 + "px";
|
||||
@@ -50,8 +44,7 @@ export class SelectionWheel
|
||||
image.classList.add("selection-wheel-image");
|
||||
image.src = `images/buttons/${options[id].src}`
|
||||
image.title = options[id].tooltip;
|
||||
if ('tint' in options[id])
|
||||
{
|
||||
if ('tint' in options[id]) {
|
||||
button.style.setProperty('background-color', options[id].tint);
|
||||
image.style.opacity = "0";
|
||||
}
|
||||
@@ -59,14 +52,12 @@ export class SelectionWheel
|
||||
}
|
||||
|
||||
/* Hide the coalition switch if required */
|
||||
var switchContainer = <HTMLElement> this.#container.querySelector("#coalition-switch-container");
|
||||
if (showCoalition == false)
|
||||
{
|
||||
var switchContainer = <HTMLElement>this.#container.querySelector("#coalition-switch-container");
|
||||
if (showCoalition == false) {
|
||||
switchContainer.style.display = "none";
|
||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--neutral-coalition-color"));
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
switchContainer.style.display = "block";
|
||||
if (getActiveCoalition() == "blue")
|
||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--blue-coalition-color"));
|
||||
@@ -76,33 +67,26 @@ export class SelectionWheel
|
||||
}
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
hide() {
|
||||
if (this.#container != null) {
|
||||
this.#container.style.display = "none";
|
||||
var buttons = this.#container.querySelectorAll(".selection-wheel-button");
|
||||
for (let child of buttons)
|
||||
{
|
||||
for (let child of buttons) {
|
||||
this.#container.removeChild(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#onSwitch(e: any)
|
||||
{
|
||||
if (this.#container != null)
|
||||
{
|
||||
if (e.currentTarget.checked)
|
||||
{
|
||||
#onSwitch(e: any) {
|
||||
if (this.#container != null) {
|
||||
if (e.currentTarget.checked) {
|
||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--red-coalition-color"));
|
||||
setActiveCoalition("red");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
document.documentElement.style.setProperty('--active-coalition-color', getComputedStyle(this.#container).getPropertyValue("--blue-coalition-color"));
|
||||
setActiveCoalition("blue");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5,14 +5,12 @@ import { ConvertDDToDMS } from '../other/utils';
|
||||
/* Edit here to change server address */
|
||||
var RESTaddress = "http://localhost:30000/restdemo";
|
||||
|
||||
export function getDataFromDCS(callback: CallableFunction)
|
||||
{
|
||||
export function getDataFromDCS(callback: CallableFunction) {
|
||||
/* Request the updated unit data from the server */
|
||||
var xmlHttp = new XMLHttpRequest();
|
||||
xmlHttp.open( "GET", RESTaddress, true);
|
||||
xmlHttp.open("GET", RESTaddress, true);
|
||||
|
||||
xmlHttp.onload = function(e)
|
||||
{
|
||||
xmlHttp.onload = function (e) {
|
||||
var data = JSON.parse(xmlHttp.responseText);
|
||||
callback(data);
|
||||
setConnected(true);
|
||||
@@ -22,24 +20,22 @@ export function getDataFromDCS(callback: CallableFunction)
|
||||
console.error("An error occurred during the XMLHttpRequest");
|
||||
setConnected(false);
|
||||
};
|
||||
xmlHttp.send( null );
|
||||
xmlHttp.send(null);
|
||||
}
|
||||
|
||||
export function addDestination(ID: number, path: any)
|
||||
{
|
||||
export function addDestination(ID: number, path: any) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {};
|
||||
xhr.onreadystatechange = () => { };
|
||||
|
||||
var command = {"ID": ID, "path": path}
|
||||
var data = {"setPath": command}
|
||||
var command = { "ID": ID, "path": path }
|
||||
var data = { "setPath": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function spawnSmoke(color: string, latlng: L.LatLng)
|
||||
{
|
||||
export function spawnSmoke(color: string, latlng: L.LatLng) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
@@ -49,14 +45,13 @@ export function spawnSmoke(color: string, latlng: L.LatLng)
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"color": color, "location": latlng};
|
||||
var data = {"smoke": command}
|
||||
var command = { "color": color, "location": latlng };
|
||||
var data = { "smoke": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function spawnGroundUnit(type: string, latlng: L.LatLng, coalition: string)
|
||||
{
|
||||
export function spawnGroundUnit(type: string, latlng: L.LatLng, coalition: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
@@ -66,14 +61,13 @@ export function spawnGroundUnit(type: string, latlng: L.LatLng, coalition: strin
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"type": type, "location": latlng, "coalition": coalition};
|
||||
var data = {"spawnGround": command}
|
||||
var command = { "type": type, "location": latlng, "coalition": coalition };
|
||||
var data = { "spawnGround": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function spawnAircraft(type: string, latlng: L.LatLng, coalition: string, payloadName = "", airbaseName = "")
|
||||
{
|
||||
export function spawnAircraft(type: string, latlng: L.LatLng, coalition: string, payloadName: string | null = null, airbaseName: string | null = null) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
@@ -83,42 +77,72 @@ export function spawnAircraft(type: string, latlng: L.LatLng, coalition: string,
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"type": type, "location": latlng, "coalition": coalition, "payloadName": payloadName, "airbaseName": airbaseName};
|
||||
var data = {"spawnAir": command}
|
||||
var command = { "type": type, "location": latlng, "coalition": coalition, "payloadName": payloadName != null? payloadName: "", "airbaseName": airbaseName != null? airbaseName: ""};
|
||||
var data = { "spawnAir": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function attackUnit(ID: number, targetID: number)
|
||||
{
|
||||
export function attackUnit(ID: number, targetID: number) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Unit " + getUnitsManager().getUnitByID(ID).unitName + " attack " + getUnitsManager().getUnitByID(targetID).unitName );
|
||||
}
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Unit " + getUnitsManager().getUnitByID(ID).unitName + " attack " + getUnitsManager().getUnitByID(targetID).unitName);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "targetID": targetID};
|
||||
var data = {"attackUnit": command}
|
||||
var command = { "ID": ID, "targetID": targetID };
|
||||
var data = { "attackUnit": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function cloneUnit(ID: number)
|
||||
{
|
||||
export function cloneUnit(ID: number) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Unit " + getUnitsManager().getUnitByID(ID).unitName + " cloned");
|
||||
}
|
||||
if (xhr.readyState === 4) {
|
||||
console.log("Unit " + getUnitsManager().getUnitByID(ID).unitName + " cloned");
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID};
|
||||
var data = {"cloneUnit": command}
|
||||
var command = { "ID": ID };
|
||||
var data = { "cloneUnit": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function changeSpeed(ID: number, speedChange: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(getUnitsManager().getUnitByID(ID).unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "change": speedChange}
|
||||
var data = {"changeSpeed": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function changeAltitude(ID: number, altitudeChange: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(getUnitsManager().getUnitByID(ID).unitName + " altitude change request: " + altitudeChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "change": altitudeChange}
|
||||
var data = {"changeAltitude": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
@@ -7,6 +7,7 @@ import { SelectionScroll } from "./controls/selectionscroll";
|
||||
import { Dropdown } from "./controls/dropdown";
|
||||
import { ConnectionStatusPanel } from "./panels/connectionstatuspanel";
|
||||
import { Button } from "./controls/button";
|
||||
import { MissionData } from "./missiondata/missiondata";
|
||||
|
||||
/* TODO: should this be a class? */
|
||||
var map: Map;
|
||||
@@ -19,26 +20,44 @@ var scenarioDropdown: Dropdown;
|
||||
var mapSourceDropdown: Dropdown;
|
||||
var connected: boolean;
|
||||
var connectionStatusPanel: ConnectionStatusPanel;
|
||||
var missionData: MissionData;
|
||||
|
||||
var slowButton: Button;
|
||||
var fastButton: Button;
|
||||
var climbButton: Button;
|
||||
var descendButton: Button;
|
||||
var userVisibilityButton: Button;
|
||||
var aiVisibilityButton: Button;
|
||||
var weaponVisibilityButton: Button;
|
||||
var deadVisibilityButton: Button;
|
||||
|
||||
function setup()
|
||||
{
|
||||
function setup() {
|
||||
/* Initialize */
|
||||
map = new Map('map-container');
|
||||
selectionWheel = new SelectionWheel("selection-wheel");
|
||||
selectionScroll = new SelectionScroll("selection-scroll");
|
||||
unitsManager = new UnitsManager();
|
||||
unitInfoPanel = new UnitInfoPanel("unit-info-panel");
|
||||
scenarioDropdown = new Dropdown("scenario-dropdown", ["Caucasus", "Syria", "Nevada", "Marianas", "South Atlantic", "The channel"], () => {});
|
||||
scenarioDropdown = new Dropdown("scenario-dropdown", ["Caucasus", "Syria", "Nevada", "Marianas", "South Atlantic", "The channel"], () => { });
|
||||
mapSourceDropdown = new Dropdown("map-source-dropdown", map.getLayers(), (option: string) => map.setLayer(option));
|
||||
connectionStatusPanel = new ConnectionStatusPanel("connection-status-panel");
|
||||
slowButton = new Button("slow-button", ["images/buttons/slow.svg"], () => {});
|
||||
fastButton = new Button("fast-button", ["images/buttons/fast.svg"], () => {});
|
||||
climbButton = new Button("climb-button", ["images/buttons/climb.svg"], () => {});
|
||||
descendButton = new Button("descend-button", ["images/buttons/descend.svg"], () => {});
|
||||
missionData = new MissionData();
|
||||
|
||||
/* Unit control buttons */
|
||||
slowButton = new Button("slow-button", ["images/buttons/slow.svg"], () => { getUnitsManager().selectedUnitsChangeSpeed("slow"); });
|
||||
fastButton = new Button("fast-button", ["images/buttons/fast.svg"], () => { getUnitsManager().selectedUnitsChangeSpeed("fast"); });
|
||||
climbButton = new Button("climb-button", ["images/buttons/climb.svg"], () => { getUnitsManager().selectedUnitsChangeAltitude("climb"); });
|
||||
descendButton = new Button("descend-button", ["images/buttons/descend.svg"], () => { getUnitsManager().selectedUnitsChangeAltitude("descend"); });
|
||||
|
||||
/* Visibility buttons */
|
||||
userVisibilityButton = new Button("user-visibility-button", ["images/buttons/user-full.svg", "images/buttons/user-partial.svg", "images/buttons/user-none.svg", "images/buttons/user-hidden.svg"], () => { });
|
||||
aiVisibilityButton = new Button("ai-visibility-button", ["images/buttons/ai-full.svg", "images/buttons/ai-partial.svg", "images/buttons/ai-none.svg", "images/buttons/ai-hidden.svg"], () => { });
|
||||
weaponVisibilityButton = new Button("weapon-visibility-button", ["images/buttons/weapon-partial.svg", "images/buttons/weapon-none.svg", "images/buttons/weapon-hidden.svg"], () => { });
|
||||
deadVisibilityButton = new Button("dead-visibility-button", ["images/buttons/dead.svg", "images/buttons/dead-hidden.svg"], () => { });
|
||||
|
||||
aiVisibilityButton.setState(1);
|
||||
weaponVisibilityButton.setState(1);
|
||||
deadVisibilityButton.setState(1);
|
||||
|
||||
/* Default values */
|
||||
activeCoalition = "blue";
|
||||
@@ -47,62 +66,100 @@ function setup()
|
||||
requestUpdate();
|
||||
}
|
||||
|
||||
function requestUpdate()
|
||||
{
|
||||
function requestUpdate() {
|
||||
getDataFromDCS(update);
|
||||
/* Main update rate = 250ms is minimum time, equal to server update time. */
|
||||
setTimeout(() => requestUpdate(), getConnected() ? 250: 1000);
|
||||
connectionStatusPanel.update(getConnected() );
|
||||
setTimeout(() => requestUpdate(), getConnected() ? 250 : 1000);
|
||||
connectionStatusPanel.update(getConnected());
|
||||
}
|
||||
|
||||
export function update(data: JSON)
|
||||
{
|
||||
export function update(data: JSON) {
|
||||
unitsManager.update(data);
|
||||
missionData.update(data);
|
||||
}
|
||||
|
||||
export function getMap()
|
||||
{
|
||||
export function getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
export function getSelectionWheel()
|
||||
{
|
||||
export function getSelectionWheel() {
|
||||
return selectionWheel;
|
||||
}
|
||||
|
||||
export function getSelectionScroll()
|
||||
{
|
||||
export function getSelectionScroll() {
|
||||
return selectionScroll;
|
||||
}
|
||||
|
||||
export function getUnitsManager()
|
||||
{
|
||||
export function getUnitsManager() {
|
||||
return unitsManager;
|
||||
}
|
||||
|
||||
export function getUnitInfoPanel()
|
||||
{
|
||||
export function getUnitInfoPanel() {
|
||||
return unitInfoPanel;
|
||||
}
|
||||
|
||||
export function setActiveCoalition(newActiveCoalition: string)
|
||||
{
|
||||
export function setActiveCoalition(newActiveCoalition: string) {
|
||||
activeCoalition = newActiveCoalition;
|
||||
}
|
||||
|
||||
export function getActiveCoalition()
|
||||
{
|
||||
export function getActiveCoalition() {
|
||||
return activeCoalition;
|
||||
}
|
||||
|
||||
export function setConnected(newConnected: boolean)
|
||||
{
|
||||
export function setConnected(newConnected: boolean) {
|
||||
connected = newConnected
|
||||
}
|
||||
|
||||
export function getConnected()
|
||||
{
|
||||
export function getConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
export function getVisibilitySettings() {
|
||||
var visibility = {
|
||||
user: "",
|
||||
ai: "",
|
||||
weapon: "",
|
||||
dead: ""
|
||||
};
|
||||
|
||||
switch (userVisibilityButton.getState()) {
|
||||
case 0:
|
||||
visibility.user = "full"; break;
|
||||
case 1:
|
||||
visibility.user = "partial"; break;
|
||||
case 2:
|
||||
visibility.user = "none"; break;
|
||||
case 3:
|
||||
visibility.user = "hidden"; break;
|
||||
}
|
||||
|
||||
switch (aiVisibilityButton.getState()) {
|
||||
case 0:
|
||||
visibility.ai = "full"; break;
|
||||
case 1:
|
||||
visibility.ai = "partial"; break;
|
||||
case 2:
|
||||
visibility.ai = "none"; break;
|
||||
case 3:
|
||||
visibility.ai = "hidden"; break;
|
||||
}
|
||||
|
||||
switch (weaponVisibilityButton.getState()) {
|
||||
case 0:
|
||||
visibility.weapon = "partial"; break;
|
||||
case 1:
|
||||
visibility.weapon = "none"; break;
|
||||
case 2:
|
||||
visibility.weapon = "hidden"; break;
|
||||
}
|
||||
|
||||
switch (deadVisibilityButton.getState()) {
|
||||
case 0:
|
||||
visibility.dead = "none"; break;
|
||||
case 1:
|
||||
visibility.dead = "hidden"; break;
|
||||
}
|
||||
return visibility;
|
||||
}
|
||||
|
||||
window.onload = setup;
|
||||
133
client/src/map/boxselect.ts
Normal file
133
client/src/map/boxselect.ts
Normal file
@@ -0,0 +1,133 @@
|
||||
import { Map } from 'leaflet';
|
||||
import { Handler} from 'leaflet';
|
||||
import { Util } from 'leaflet';
|
||||
import { DomUtil } from 'leaflet';
|
||||
import { DomEvent } from 'leaflet';
|
||||
import { LatLngBounds } from 'leaflet';
|
||||
import { Bounds } from 'leaflet';
|
||||
|
||||
export var BoxSelect = Handler.extend({
|
||||
initialize: function (map: Map) {
|
||||
this._map = map;
|
||||
this._container = map.getContainer();
|
||||
this._pane = map.getPanes().overlayPane;
|
||||
this._resetStateTimeout = 0;
|
||||
map.on('unload', this._destroy, this);
|
||||
},
|
||||
|
||||
addHooks: function () {
|
||||
DomEvent.on(this._container, 'mousedown', this._onMouseDown, this);
|
||||
},
|
||||
|
||||
removeHooks: function () {
|
||||
DomEvent.off(this._container, 'mousedown', this._onMouseDown, this);
|
||||
},
|
||||
|
||||
moved: function () {
|
||||
return this._moved;
|
||||
},
|
||||
|
||||
_destroy: function () {
|
||||
DomUtil.remove(this._pane);
|
||||
delete this._pane;
|
||||
},
|
||||
|
||||
_resetState: function () {
|
||||
this._resetStateTimeout = 0;
|
||||
this._moved = false;
|
||||
},
|
||||
|
||||
_clearDeferredResetState: function () {
|
||||
if (this._resetStateTimeout !== 0) {
|
||||
clearTimeout(this._resetStateTimeout);
|
||||
this._resetStateTimeout = 0;
|
||||
}
|
||||
},
|
||||
|
||||
_onMouseDown: function (e: any) {
|
||||
if (((e.which !== 3) && (e.button !== 2))) { return false; }
|
||||
|
||||
// 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();
|
||||
this._resetState();
|
||||
|
||||
DomUtil.disableTextSelection();
|
||||
DomUtil.disableImageDrag();
|
||||
|
||||
this._startPoint = this._map.mouseEventToContainerPoint(e);
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.on(document, {
|
||||
contextmenu: DomEvent.stop,
|
||||
mousemove: this._onMouseMove,
|
||||
mouseup: this._onMouseUp,
|
||||
keydown: this._onKeyDown
|
||||
}, this);
|
||||
},
|
||||
|
||||
_onMouseMove: function (e: any) {
|
||||
if (!this._moved) {
|
||||
this._moved = true;
|
||||
|
||||
this._box = DomUtil.create('div', 'leaflet-zoom-box', this._container);
|
||||
DomUtil.addClass(this._container, 'leaflet-crosshair');
|
||||
|
||||
this._map.fire('boxzoomstart');
|
||||
}
|
||||
|
||||
this._point = this._map.mouseEventToContainerPoint(e);
|
||||
|
||||
var bounds = new Bounds(this._point, this._startPoint),
|
||||
size = bounds.getSize();
|
||||
|
||||
if (bounds.min != undefined)
|
||||
DomUtil.setPosition(this._box, bounds.min);
|
||||
|
||||
this._box.style.width = size.x + 'px';
|
||||
this._box.style.height = size.y + 'px';
|
||||
},
|
||||
|
||||
_finish: function () {
|
||||
if (this._moved) {
|
||||
DomUtil.remove(this._box);
|
||||
DomUtil.removeClass(this._container, 'leaflet-crosshair');
|
||||
}
|
||||
|
||||
DomUtil.enableTextSelection();
|
||||
DomUtil.enableImageDrag();
|
||||
|
||||
//@ts-ignore
|
||||
DomEvent.off(document, {
|
||||
contextmenu: DomEvent.stop,
|
||||
mousemove: this._onMouseMove,
|
||||
mouseup: this._onMouseUp,
|
||||
keydown: this._onKeyDown
|
||||
}, this);
|
||||
},
|
||||
|
||||
_onMouseUp: function (e: any) {
|
||||
if ((e.which !== 3) && (e.button !== 2)) { return; }
|
||||
|
||||
this._finish();
|
||||
|
||||
if (!this._moved) { return; }
|
||||
// Postpone to next JS tick so internal click event handling
|
||||
// still see it as "moved".
|
||||
setTimeout(Util.bind(this._resetState, this), 0);
|
||||
var bounds = new LatLngBounds(
|
||||
this._map.containerPointToLatLng(this._startPoint),
|
||||
this._map.containerPointToLatLng(this._point));
|
||||
|
||||
this._map.fire('selectionend', {selectionBounds: bounds});
|
||||
},
|
||||
|
||||
_onKeyDown: function (e: any) {
|
||||
if (e.keyCode === 27) {
|
||||
this._finish();
|
||||
this._clearDeferredResetState();
|
||||
this._resetState();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,75 +1,83 @@
|
||||
import * as L from "leaflet"
|
||||
import { getSelectionWheel, getSelectionScroll, getUnitsManager, getActiveCoalition } from "..";
|
||||
import { spawnAircraft } from "../dcs/dcs";
|
||||
import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../dcs/dcs";
|
||||
import { payloadNames } from "../units/payloadNames";
|
||||
import { unitTypes } from "../units/unitTypes";
|
||||
import { BoxSelect } from "./boxselect";
|
||||
|
||||
export class Map extends L.Map
|
||||
{
|
||||
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
|
||||
|
||||
export interface ClickEvent {
|
||||
x: number;
|
||||
y: number;
|
||||
latlng: L.LatLng;
|
||||
}
|
||||
|
||||
export interface SpawnEvent extends ClickEvent{
|
||||
airbaseName: string | null;
|
||||
coalitionID: number | null;
|
||||
}
|
||||
|
||||
export class Map extends L.Map {
|
||||
#state: string;
|
||||
#layer?: L.TileLayer;
|
||||
#preventRightClick: boolean = false;
|
||||
#rightClickTimer: number = 0;
|
||||
|
||||
constructor(ID: string)
|
||||
{
|
||||
constructor(ID: string) {
|
||||
/* Init the leaflet map */
|
||||
super(ID, {doubleClickZoom: false, zoomControl: false});
|
||||
//@ts-ignore
|
||||
super(ID, { doubleClickZoom: false, zoomControl: false, boxZoom: false, boxSelect: true });
|
||||
this.setView([37.23, -115.8], 12);
|
||||
|
||||
|
||||
this.setLayer("ArcGIS Satellite");
|
||||
|
||||
/* Init the state machine */
|
||||
this.#state = "IDLE";
|
||||
|
||||
/* Register event handles */
|
||||
this.on("contextmenu", (e) => this.#onContextMenu(e));
|
||||
this.on("click", (e) => this.#onClick(e));
|
||||
this.on("dblclick", (e) => this.#onDoubleClick(e));
|
||||
this.on("click", (e: any) => this.#onClick(e));
|
||||
this.on("dblclick", (e: any) => this.#onDoubleClick(e));
|
||||
this.on("contextmenu", (e: any) => this.#onContextMenu(e));
|
||||
this.on('selectionend', (e: any) => this.#onSelectionEnd(e));
|
||||
}
|
||||
|
||||
setLayer(layerName: string)
|
||||
{
|
||||
if (this.#layer != null)
|
||||
{
|
||||
setLayer(layerName: string) {
|
||||
if (this.#layer != null) {
|
||||
this.removeLayer(this.#layer)
|
||||
}
|
||||
|
||||
if (layerName == "ArcGIS Satellite")
|
||||
{
|
||||
|
||||
if (layerName == "ArcGIS Satellite") {
|
||||
this.#layer = L.tileLayer("https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}", {
|
||||
attribution: "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
|
||||
});
|
||||
}
|
||||
else if (layerName == "USGS Topo")
|
||||
{
|
||||
else if (layerName == "USGS Topo") {
|
||||
this.#layer = L.tileLayer('https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}', {
|
||||
maxZoom: 20,
|
||||
attribution: 'Tiles courtesy of the <a href="https://usgs.gov/">U.S. Geological Survey</a>'
|
||||
});
|
||||
}
|
||||
else if (layerName == "OpenStreetMap Mapnik")
|
||||
{
|
||||
else if (layerName == "OpenStreetMap Mapnik") {
|
||||
this.#layer = L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
|
||||
maxZoom: 19,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
});
|
||||
}
|
||||
else if (layerName == "OPENVKarte")
|
||||
{
|
||||
else if (layerName == "OPENVKarte") {
|
||||
this.#layer = L.tileLayer('https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png', {
|
||||
maxZoom: 18,
|
||||
attribution: 'Map <a href="https://memomaps.de/">memomaps.de</a> <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
});
|
||||
}
|
||||
else if (layerName == "Esri.DeLorme")
|
||||
{
|
||||
else if (layerName == "Esri.DeLorme") {
|
||||
this.#layer = L.tileLayer('https://server.arcgisonline.com/ArcGIS/rest/services/Specialty/DeLorme_World_Base_Map/MapServer/tile/{z}/{y}/{x}', {
|
||||
attribution: 'Tiles © Esri — Copyright: ©2012 DeLorme',
|
||||
minZoom: 1,
|
||||
maxZoom: 11
|
||||
});
|
||||
}
|
||||
else if (layerName == "CyclOSM")
|
||||
{
|
||||
else if (layerName == "CyclOSM") {
|
||||
this.#layer = L.tileLayer('https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png', {
|
||||
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'
|
||||
@@ -78,169 +86,194 @@ export class Map extends L.Map
|
||||
this.#layer?.addTo(this);
|
||||
}
|
||||
|
||||
getLayers()
|
||||
{
|
||||
getLayers() {
|
||||
return ["ArcGIS Satellite", "USGS Topo", "OpenStreetMap Mapnik", "OPENVKarte", "Esri.DeLorme", "CyclOSM"]
|
||||
}
|
||||
|
||||
/* State machine */
|
||||
setState(state: string)
|
||||
{
|
||||
setState(state: string) {
|
||||
this.#state = state;
|
||||
|
||||
if (this.#state === "IDLE")
|
||||
{
|
||||
|
||||
|
||||
if (this.#state === "IDLE") {
|
||||
|
||||
}
|
||||
else if (this.#state === "MOVE_UNIT")
|
||||
{
|
||||
|
||||
else if (this.#state === "MOVE_UNIT") {
|
||||
|
||||
}
|
||||
else if (this.#state === "ATTACK")
|
||||
{
|
||||
|
||||
else if (this.#state === "ATTACK") {
|
||||
|
||||
}
|
||||
else if (this.#state === "FORMATION")
|
||||
{
|
||||
|
||||
else if (this.#state === "FORMATION") {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
getState()
|
||||
{
|
||||
getState() {
|
||||
return this.#state;
|
||||
}
|
||||
|
||||
/* Selection wheel */
|
||||
showSelectionWheel(e: PointerEvent, options: any, showCoalition: boolean)
|
||||
{
|
||||
showSelectionWheel(e: ClickEvent | SpawnEvent, options: any, showCoalition: boolean) {
|
||||
var x = e.x;
|
||||
var y = e.y;
|
||||
getSelectionWheel().show(x, y, options, showCoalition);
|
||||
}
|
||||
|
||||
hideSelectionWheel()
|
||||
{
|
||||
hideSelectionWheel() {
|
||||
getSelectionWheel().hide();
|
||||
}
|
||||
|
||||
/* Selection scroll */
|
||||
showSelectionScroll(e: PointerEvent, options: any, callback: CallableFunction)
|
||||
{
|
||||
showSelectionScroll(e: ClickEvent | SpawnEvent, options: any, callback: CallableFunction) {
|
||||
var x = e.x;
|
||||
var y = e.y;
|
||||
getSelectionScroll().show(x, y, options, callback);
|
||||
}
|
||||
|
||||
hideSelectionScroll()
|
||||
{
|
||||
hideSelectionScroll() {
|
||||
getSelectionScroll().hide();
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
#onContextMenu(e: any)
|
||||
{
|
||||
this.setState("IDLE");
|
||||
getUnitsManager().deselectAllUnits();
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
}
|
||||
|
||||
#onClick(e: any)
|
||||
{
|
||||
/* Event handlers */
|
||||
#onClick(e: any) {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
if (this.#state === "IDLE")
|
||||
{
|
||||
|
||||
if (this.#state === "IDLE") {
|
||||
|
||||
}
|
||||
else if (this.#state === "MOVE_UNIT")
|
||||
{
|
||||
if (!e.originalEvent.ctrlKey)
|
||||
{
|
||||
else if (this.#state === "MOVE_UNIT") {
|
||||
if (!e.originalEvent.ctrlKey) {
|
||||
getUnitsManager().clearDestinations();
|
||||
}
|
||||
getUnitsManager().addDestination(e.latlng)
|
||||
}
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any)
|
||||
{
|
||||
if (this.#state == "IDLE")
|
||||
{
|
||||
#onDoubleClick(e: any) {
|
||||
var spawnEvent: SpawnEvent = {x: e.originalEvent.x, y: e.originalEvent.y, latlng: e.latlng, airbaseName: null, coalitionID: null};
|
||||
if (this.#state == "IDLE") {
|
||||
var options = [
|
||||
{"tooltip": "Air unit", "src": "spawnAir.png", "callback": () => this.#aircraftSpawnMenu(e)},
|
||||
{"tooltip": "Ground unit", "src": "spawnGround.png", "callback": () => this.#groundUnitSpawnMenu(e)},
|
||||
{"tooltip": "Smoke", "src": "spawnSmoke.png", "callback": () => this.#smokeSpawnMenu(e)},
|
||||
{"tooltip": "Explosion", "src": "spawnExplosion.png", "callback": () => this.#explosionSpawnMenu(e)}
|
||||
{ "tooltip": "Spawn air unit", "src": "spawnAir.png", "callback": () => this.#aircraftSpawnMenu(spawnEvent) },
|
||||
{ "tooltip": "Spawn ground unit", "src": "spawnGround.png", "callback": () => this.#groundUnitSpawnMenu(spawnEvent) },
|
||||
{ "tooltip": "Smoke", "src": "spawnSmoke.png", "callback": () => this.#smokeSpawnMenu(spawnEvent) },
|
||||
//{ "tooltip": "Explosion", "src": "spawnExplosion.png", "callback": () => this.#explosionSpawnMenu(e) }
|
||||
]
|
||||
this.showSelectionWheel(e.originalEvent, options, true);
|
||||
this.showSelectionWheel(spawnEvent, options, true);
|
||||
}
|
||||
}
|
||||
|
||||
/* Spawning menus */
|
||||
#groundUnitSpawnMenu(e: any)
|
||||
{
|
||||
|
||||
#onContextMenu(e: any) {
|
||||
this.#rightClickTimer = setTimeout(() => {
|
||||
if (!this.#preventRightClick) {
|
||||
this.setState("IDLE");
|
||||
getUnitsManager().deselectAllUnits();
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
}
|
||||
this.#preventRightClick = false;
|
||||
}, 200);
|
||||
}
|
||||
|
||||
#smokeSpawnMenu(e: any)
|
||||
#onSelectionEnd(e: any)
|
||||
{
|
||||
|
||||
clearTimeout(this.#rightClickTimer);
|
||||
this.#preventRightClick = true;
|
||||
getUnitsManager().selectFromBounds(e.selectionBounds);
|
||||
}
|
||||
|
||||
#explosionSpawnMenu(e: any)
|
||||
/* Spawn from air base */
|
||||
spawnFromAirbase(e: SpawnEvent)
|
||||
{
|
||||
|
||||
this.#aircraftSpawnMenu(e);
|
||||
}
|
||||
|
||||
#aircraftSpawnMenu(e: any)
|
||||
{
|
||||
/* Spawning menus */
|
||||
#groundUnitSpawnMenu(e: SpawnEvent) {
|
||||
var options = [
|
||||
{'coalition': true, 'tooltip': 'CAP', 'src': 'spawnCAP.png', 'callback': () => this.#selectAircraft(e, "CAP")},
|
||||
{'coalition': true, 'tooltip': 'CAS', 'src': 'spawnCAS.png', 'callback': () => this.#selectAircraft(e, "CAS")},
|
||||
{'coalition': true, 'tooltip': 'Tanker', 'src': 'spawnTanker.png', 'callback': () => this.#selectAircraft(e, "tanker")},
|
||||
{'coalition': true, 'tooltip': 'AWACS', 'src': 'spawnAWACS.png', 'callback': () => this.#selectAircraft(e, "awacs")},
|
||||
{'coalition': true, 'tooltip': 'Strike', 'src': 'spawnStrike.png', 'callback': () => this.#selectAircraft(e, "strike")},
|
||||
{'coalition': true, 'tooltip': 'Drone', 'src': 'spawnDrone.png', 'callback': () => this.#selectAircraft(e, "drone")},
|
||||
{'coalition': true, 'tooltip': 'Transport', 'src': 'spawnTransport.png','callback': () => this.#selectAircraft(e, "transport")},
|
||||
{'coalition': true, 'tooltip': 'Howitzer', 'src': 'spawnHowitzer.png', 'callback': () => this.#selectGroundUnit(e, "Howitzers")},
|
||||
{'coalition': true, 'tooltip': 'SAM', 'src': 'spawnSAM.png', 'callback': () => this.#selectGroundUnit(e, "SAM")},
|
||||
{'coalition': true, 'tooltip': 'IFV', 'src': 'spawnIFV.png', 'callback': () => this.#selectGroundUnit(e, "IFV")},
|
||||
{'coalition': true, 'tooltip': 'Tank', 'src': 'spawnTank.png', 'callback': () => this.#selectGroundUnit(e, "Tanks")},
|
||||
{'coalition': true, 'tooltip': 'MLRS', 'src': 'spawnMLRS.png', 'callback': () => this.#selectGroundUnit(e, "MLRS")},
|
||||
{'coalition': true, 'tooltip': 'Radar', 'src': 'spawnRadar.png', 'callback': () => this.#selectGroundUnit(e, "Radar")},
|
||||
{'coalition': true, 'tooltip': 'Unarmed', 'src': 'spawnUnarmed.png', 'callback': () => this.#selectGroundUnit(e, "Unarmed")}
|
||||
]
|
||||
this.showSelectionWheel(e.originalEvent, options, true);
|
||||
this.showSelectionWheel(e, options, true);
|
||||
}
|
||||
|
||||
#smokeSpawnMenu(e: SpawnEvent) {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
var options = [
|
||||
{'tooltip': 'Red smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('red', e.latlng)}, 'tint': 'red'},
|
||||
{'tooltip': 'White smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('white', e.latlng)}, 'tint': 'white'},
|
||||
{'tooltip': 'Blue smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('blue', e.latlng)}, 'tint': 'blue'},
|
||||
{'tooltip': 'Green smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('green', e.latlng)}, 'tint': 'green'},
|
||||
{'tooltip': 'Orange smoke', 'src': 'spawnSmoke.png', 'callback': () => {this.hideSelectionWheel(); this.hideSelectionScroll(); spawnSmoke('orange', e.latlng)}, 'tint': 'orange'},
|
||||
]
|
||||
this.showSelectionWheel(e, options, true);
|
||||
}
|
||||
|
||||
#explosionSpawnMenu(e: SpawnEvent) {
|
||||
|
||||
}
|
||||
|
||||
#aircraftSpawnMenu(e: SpawnEvent) {
|
||||
var options = [
|
||||
{ 'coalition': true, 'tooltip': 'CAP', 'src': 'spawnCAP.png', 'callback': () => this.#selectAircraft(e, "CAP") },
|
||||
{ 'coalition': true, 'tooltip': 'CAS', 'src': 'spawnCAS.png', 'callback': () => this.#selectAircraft(e, "CAS") },
|
||||
{ 'coalition': true, 'tooltip': 'Tanker', 'src': 'spawnTanker.png', 'callback': () => this.#selectAircraft(e, "tanker") },
|
||||
{ 'coalition': true, 'tooltip': 'AWACS', 'src': 'spawnAWACS.png', 'callback': () => this.#selectAircraft(e, "awacs") },
|
||||
{ 'coalition': true, 'tooltip': 'Strike', 'src': 'spawnStrike.png', 'callback': () => this.#selectAircraft(e, "strike") },
|
||||
{ 'coalition': true, 'tooltip': 'Drone', 'src': 'spawnDrone.png', 'callback': () => this.#selectAircraft(e, "drone") },
|
||||
{ 'coalition': true, 'tooltip': 'Transport', 'src': 'spawnTransport.png', 'callback': () => this.#selectAircraft(e, "transport") },
|
||||
]
|
||||
this.showSelectionWheel(e, options, true);
|
||||
}
|
||||
|
||||
/* Show unit selection for air units */
|
||||
#selectAircraft(e: any, group: string)
|
||||
{
|
||||
#selectAircraft(e: SpawnEvent, group: string) {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
var options = unitTypes.air[group];
|
||||
options.sort();
|
||||
this.showSelectionScroll(e.originalEvent, options, (unitType: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
this.showSelectionScroll(e, options, (unitType: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
this.#unitSelectPayload(e, unitType);
|
||||
});
|
||||
}
|
||||
|
||||
/* Show weapon selection for air units */
|
||||
#unitSelectPayload(e: any, unitType: string)
|
||||
{
|
||||
#unitSelectPayload(e: SpawnEvent, unitType: string) {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
var options = [];
|
||||
options = payloadNames[unitType]
|
||||
if (options != undefined && options.length > 0)
|
||||
{
|
||||
if (options != undefined && options.length > 0) {
|
||||
options.sort();
|
||||
this.showSelectionScroll(e.originalEvent, options, (payloadName: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
this.showSelectionScroll({x: e.x, y: e.y, latlng: e.latlng}, options, (payloadName: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
spawnAircraft(unitType, e.latlng, getActiveCoalition(), payloadName, e.airbaseName);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else {
|
||||
spawnAircraft(unitType, e.latlng, getActiveCoalition());
|
||||
}
|
||||
}
|
||||
|
||||
/* Show unit selection for ground units */
|
||||
#selectGroundUnit(e: any, group: string)
|
||||
{
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
var options = unitTypes.vehicles[group];
|
||||
options.sort();
|
||||
this.showSelectionScroll(e, options, (unitType: string) => {
|
||||
this.hideSelectionWheel();
|
||||
this.hideSelectionScroll();
|
||||
spawnGroundUnit(unitType, e.latlng, getActiveCoalition());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
66
client/src/missiondata/airbasemarker.ts
Normal file
66
client/src/missiondata/airbasemarker.ts
Normal file
@@ -0,0 +1,66 @@
|
||||
import * as L from 'leaflet'
|
||||
|
||||
export interface AirbaseOptions
|
||||
{
|
||||
name: string,
|
||||
position: L.LatLng,
|
||||
src: string
|
||||
}
|
||||
|
||||
export class AirbaseMarker extends L.Marker
|
||||
{
|
||||
#name: string = "";
|
||||
#coalitionID: number = -1;
|
||||
|
||||
constructor(options: AirbaseOptions)
|
||||
{
|
||||
super(options.position, { riseOnHover: true });
|
||||
|
||||
this.#name = options.name;
|
||||
|
||||
var icon = new L.DivIcon({
|
||||
html: `<table class="airbasemarker-container" id="container">
|
||||
<tr>
|
||||
<td>
|
||||
<img class="airbasemarker-icon" id="icon" src="${options.src}">
|
||||
<div class="airbasemarker-name" id="name">${options.name}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>`,
|
||||
className: 'airbase-marker'}); // Set the marker, className must be set to avoid white square
|
||||
this.setIcon(icon);
|
||||
}
|
||||
|
||||
setCoalitionID(coalitionID: number)
|
||||
{
|
||||
this.#coalitionID = coalitionID;
|
||||
var element = this.getElement();
|
||||
if (element != null)
|
||||
{
|
||||
var img = element.querySelector("#icon");
|
||||
if (img != null)
|
||||
{
|
||||
img.classList.remove("airbasemarker-icon-blue");
|
||||
img.classList.remove("airbasemarker-icon-red");
|
||||
if (this.#coalitionID == 2)
|
||||
{
|
||||
img.classList.add("airbasemarker-icon-blue");
|
||||
}
|
||||
else if (this.#coalitionID == 1)
|
||||
{
|
||||
img.classList.add("airbasemarker-icon-red");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getName()
|
||||
{
|
||||
return this.#name;
|
||||
}
|
||||
|
||||
getCoalitionID()
|
||||
{
|
||||
return this.#coalitionID;
|
||||
}
|
||||
}
|
||||
65
client/src/missiondata/missiondata.ts
Normal file
65
client/src/missiondata/missiondata.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { Marker, LatLng } from "leaflet";
|
||||
import { getMap } from "..";
|
||||
import { SpawnEvent } from "../map/map";
|
||||
import { AirbaseMarker } from "./airbasemarker";
|
||||
|
||||
export class MissionData
|
||||
{
|
||||
//#bullseye : any; //TODO declare interface
|
||||
//#bullseyeMarker : Marker;
|
||||
#airbases : any; //TODO declare interface
|
||||
#airbasesMarkers: {[name: string]: AirbaseMarker};
|
||||
|
||||
constructor()
|
||||
{
|
||||
//this.#bullseye = undefined;
|
||||
//this.#bullseyeMarker = undefined;
|
||||
this.#airbasesMarkers = {};
|
||||
}
|
||||
|
||||
update(data: any)
|
||||
{
|
||||
//this.#bullseye = data.missionData.bullseye;
|
||||
this.#airbases = data.airbases;
|
||||
//this.#drawBullseye();
|
||||
this.#drawAirbases();
|
||||
}
|
||||
|
||||
//#drawBullseye()
|
||||
//{
|
||||
// if (this.#bullseyeMarker === undefined)
|
||||
// {
|
||||
// this.#bullseyeMarker = new Marker([this.#bullseye.lat, this.#bullseye.lng]).addTo(map.getMap());
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// this.#bullseyeMarker.setLatLng(new LatLng(this.#bullseye.lat, this.#bullseye.lng));
|
||||
// }
|
||||
//}
|
||||
|
||||
#drawAirbases()
|
||||
{
|
||||
for (let idx in this.#airbases)
|
||||
{
|
||||
var airbase = this.#airbases[idx]
|
||||
if (this.#airbasesMarkers[idx] === undefined)
|
||||
{
|
||||
this.#airbasesMarkers[idx] = new AirbaseMarker({
|
||||
position: new LatLng(airbase.lat, airbase.lng),
|
||||
name: airbase.callsign,
|
||||
src: "images/airbase.png"}).addTo(getMap());
|
||||
this.#airbasesMarkers[idx].on('click', (e) => this.#onAirbaseClick(e));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.#airbasesMarkers[idx].setCoalitionID(airbase.coalition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#onAirbaseClick(e: any)
|
||||
{
|
||||
var spawnEvent: SpawnEvent = {x: e.originalEvent.x, y: e.originalEvent.y, latlng: e.latlng, airbaseName: e.sourceTarget.getName(), coalitionID: e.sourceTarget.getCoalitionID()};
|
||||
getMap().spawnFromAirbase(spawnEvent);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,40 @@
|
||||
export function distance(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
{
|
||||
export function distance(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const R = 6371e3; // metres
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
const Δφ = deg2rad(lat2-lat1);
|
||||
const Δλ = deg2rad(lon2-lon1);
|
||||
const Δφ = deg2rad(lat2 - lat1);
|
||||
const Δλ = deg2rad(lon2 - lon1);
|
||||
|
||||
const a = Math.sin(Δφ/2) * Math.sin(Δφ/2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ/2) * Math.sin(Δλ/2);
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));
|
||||
const a = Math.sin(Δφ / 2) * Math.sin(Δφ / 2) + Math.cos(φ1) * Math.cos(φ2) * Math.sin(Δλ / 2) * Math.sin(Δλ / 2);
|
||||
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
||||
|
||||
const d = R * c; // in metres
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number)
|
||||
{
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
const λ1 = deg2rad(lon1); // φ, λ in radians
|
||||
const λ2 = deg2rad(lon2);
|
||||
const y = Math.sin(λ2-λ1) * Math.cos(φ2);
|
||||
const x = Math.cos(φ1)*Math.sin(φ2) - Math.sin(φ1)*Math.cos(φ2)*Math.cos(λ2-λ1);
|
||||
const y = Math.sin(λ2 - λ1) * Math.cos(φ2);
|
||||
const x = Math.cos(φ1) * Math.sin(φ2) - Math.sin(φ1) * Math.cos(φ2) * Math.cos(λ2 - λ1);
|
||||
const θ = Math.atan2(y, x);
|
||||
const brng = (rad2deg(θ) + 360) % 360; // in degrees
|
||||
|
||||
return brng;
|
||||
}
|
||||
|
||||
const zeroPad = function(num: number, places: number)
|
||||
{
|
||||
const zeroPad = function (num: number, places: number) {
|
||||
var string = String(num);
|
||||
while (string.length < places)
|
||||
{
|
||||
while (string.length < places) {
|
||||
string += "0";
|
||||
}
|
||||
return string;
|
||||
}
|
||||
}
|
||||
|
||||
export function ConvertDDToDMS(D: number, lng: boolean)
|
||||
{
|
||||
export function ConvertDDToDMS(D: number, lng: boolean) {
|
||||
var dir = D < 0 ? (lng ? "W" : "S") : lng ? "E" : "N";
|
||||
var deg = 0 | (D < 0 ? (D = -D) : D);
|
||||
var min = 0 | (((D += 1e-9) % 1) * 60);
|
||||
@@ -52,14 +47,12 @@ export function ConvertDDToDMS(D: number, lng: boolean)
|
||||
return dir + zeroPad(deg, 2) + "°" + zeroPad(min, 2) + "'" + zeroPad(sec, 2) + "." + zeroPad(dec, 2) + "\"";
|
||||
}
|
||||
|
||||
export function deg2rad(deg: number)
|
||||
{
|
||||
export function deg2rad(deg: number) {
|
||||
var pi = Math.PI;
|
||||
return deg * (pi/180);
|
||||
return deg * (pi / 180);
|
||||
}
|
||||
|
||||
export function rad2deg(rad: number)
|
||||
{
|
||||
export function rad2deg(rad: number) {
|
||||
var pi = Math.PI;
|
||||
return rad / (pi/180);
|
||||
return rad / (pi / 180);
|
||||
}
|
||||
@@ -1,27 +1,20 @@
|
||||
export class ConnectionStatusPanel
|
||||
{
|
||||
export class ConnectionStatusPanel {
|
||||
#element: HTMLElement
|
||||
|
||||
constructor(ID: string)
|
||||
{
|
||||
constructor(ID: string) {
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
}
|
||||
|
||||
update(connected: boolean)
|
||||
{
|
||||
if (this.#element != null)
|
||||
{
|
||||
update(connected: boolean) {
|
||||
if (this.#element != null) {
|
||||
var div = this.#element.querySelector("#status-string");
|
||||
if (div != null)
|
||||
{
|
||||
if (connected)
|
||||
{
|
||||
if (div != null) {
|
||||
if (connected) {
|
||||
div.innerHTML = "Connected";
|
||||
div.classList.add("olympus-status-connected");
|
||||
div.classList.remove("olympus-status-disconnected");
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
div.innerHTML = "Disconnected";
|
||||
div.classList.add("olympus-status-disconnected");
|
||||
div.classList.remove("olympus-status-connected");
|
||||
|
||||
@@ -1,43 +1,49 @@
|
||||
import { ConvertDDToDMS, rad2deg } from "../other/utils";
|
||||
import { Unit } from "../units/unit";
|
||||
|
||||
export class UnitInfoPanel
|
||||
{
|
||||
export class UnitInfoPanel {
|
||||
#element: HTMLElement
|
||||
#display: string;
|
||||
|
||||
constructor(ID: string)
|
||||
{
|
||||
constructor(ID: string) {
|
||||
this.#element = <HTMLElement>document.getElementById(ID);
|
||||
this.#display = '';
|
||||
if (this.#element != null)
|
||||
{
|
||||
if (this.#element != null) {
|
||||
this.#display = this.#element.style.display;
|
||||
this.show();
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
|
||||
show()
|
||||
{
|
||||
show() {
|
||||
this.#element.style.display = this.#display;
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
hide() {
|
||||
this.#element.style.display = "none";
|
||||
}
|
||||
|
||||
update(unit: Unit)
|
||||
{
|
||||
if (this.#element != null)
|
||||
{
|
||||
this.#element.querySelector("#unit-name")!.innerHTML = unit.unitName;
|
||||
update(unit: Unit) {
|
||||
var loadout = "";
|
||||
for (let index in unit.ammo) {
|
||||
var ammo = unit.ammo[index];
|
||||
var displayName = ammo.desc.displayName;
|
||||
var amount = ammo.count;
|
||||
loadout += amount + "x" + displayName;
|
||||
if (parseInt(index) < Object.keys(unit.ammo).length)
|
||||
loadout += ", ";
|
||||
}
|
||||
|
||||
if (this.#element != null) {
|
||||
this.#element.querySelector("#unit-name")!.innerHTML = unit.unitName;
|
||||
this.#element.querySelector("#group-name")!.innerHTML = unit.groupName;
|
||||
this.#element.querySelector("#heading")!.innerHTML = String(Math.floor(rad2deg(unit.heading)) + "°");
|
||||
this.#element.querySelector("#altitude")!.innerHTML = String(Math.floor(unit.altitude / 0.3048) + "ft");
|
||||
this.#element.querySelector("#groundspeed")!.innerHTML = String(Math.floor(unit.speed * 1.94384) + "kts");
|
||||
//this.#element.querySelector("#altitude")!.innerHTML = String(Math.floor(unit.missionData.fuel * 100) + "%");
|
||||
this.#element.querySelector("#fuel")!.innerHTML = String(unit.fuel + "%");
|
||||
this.#element.querySelector("#position")!.innerHTML = ConvertDDToDMS(unit.latitude, false) + " " + ConvertDDToDMS(unit.longitude, true);
|
||||
}
|
||||
|
||||
this.#element.querySelector("#task")!.innerHTML = unit.currentTask;
|
||||
this.#element.querySelector("#loadout")!.innerHTML = loadout;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,43 +1,49 @@
|
||||
import { Marker, LatLng, Polyline } from 'leaflet';
|
||||
import { Marker, LatLng, Polyline, Icon } from 'leaflet';
|
||||
import { ConvertDDToDMS } from '../other/utils';
|
||||
import { getMap, getUnitsManager } from '..';
|
||||
import { UnitMarker, MarkerOptions } from './unitmarker';
|
||||
import { addDestination, attackUnit } from '../dcs/dcs';
|
||||
import { getMap, getUnitsManager, getVisibilitySettings } from '..';
|
||||
import { UnitMarker, MarkerOptions, AircraftMarker, HelicopterMarker, GroundUnitMarker, NavyUnitMarker, WeaponMarker } from './unitmarker';
|
||||
import { addDestination, attackUnit, changeAltitude, changeSpeed } from '../dcs/dcs';
|
||||
|
||||
export class Unit
|
||||
{
|
||||
ID : number;
|
||||
leader : boolean;
|
||||
wingman : boolean;
|
||||
wingmen : Unit[];
|
||||
formation : string;
|
||||
name : string;
|
||||
unitName : string;
|
||||
groupName : string;
|
||||
latitude : number;
|
||||
longitude : number;
|
||||
altitude : number;
|
||||
heading : number;
|
||||
coalitionID : number;
|
||||
alive : boolean;
|
||||
speed : number;
|
||||
currentTask : string;
|
||||
type : Object | null;
|
||||
flags : Object | null;
|
||||
activePath : any | null; // TODO: declare inteface
|
||||
missionData : Object | null;
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: 'images/marker-icon.png',
|
||||
shadowUrl: 'images/marker-shadow.png',
|
||||
iconAnchor: [13, 41]
|
||||
});
|
||||
|
||||
#selectable : boolean;
|
||||
#selected : boolean;
|
||||
#preventClick : boolean;
|
||||
#pathMarkers : Marker[];
|
||||
#pathPolyline : Polyline;
|
||||
#targetsPolylines : Polyline[];
|
||||
#marker : UnitMarker;
|
||||
#timer : number;
|
||||
export class Unit {
|
||||
ID: number = -1;
|
||||
leader: boolean = false;
|
||||
wingman: boolean = false;
|
||||
wingmen: Unit[] = [];
|
||||
formation: string = "";
|
||||
name: string = "";
|
||||
unitName: string = "";
|
||||
groupName: string = "";
|
||||
latitude: number = 0;
|
||||
longitude: number = 0;
|
||||
altitude: number = 0;
|
||||
heading: number = 0;
|
||||
speed: number = 0;
|
||||
coalitionID: number = -1;
|
||||
alive: boolean = true;
|
||||
currentTask: string = "";
|
||||
fuel: number = 0;
|
||||
type: any = null;
|
||||
flags: any = null;
|
||||
activePath: any = null;
|
||||
ammo: any = null;
|
||||
targets: any = null;
|
||||
|
||||
static getConstructor(name: string)
|
||||
{
|
||||
#selectable: boolean;
|
||||
#selected: boolean = false;
|
||||
#preventClick: boolean = false;
|
||||
#pathMarkers: Marker[] = [];
|
||||
#pathPolyline: Polyline;
|
||||
#targetsPolylines: Polyline[];
|
||||
#marker: UnitMarker;
|
||||
#timer: number = 0;
|
||||
|
||||
static getConstructor(name: string) {
|
||||
if (name === "GroundUnit") return GroundUnit;
|
||||
if (name === "Aircraft") return Aircraft;
|
||||
if (name === "Helicopter") return Helicopter;
|
||||
@@ -46,73 +52,41 @@ export class Unit
|
||||
if (name === "NavyUnit") return NavyUnit;
|
||||
}
|
||||
|
||||
constructor(ID: number, marker: UnitMarker)
|
||||
{
|
||||
constructor(ID: number, marker: UnitMarker) {
|
||||
this.ID = ID;
|
||||
|
||||
/* Names */
|
||||
this.name = "";
|
||||
this.unitName = "";
|
||||
this.groupName = "";
|
||||
|
||||
/* Position and speed */
|
||||
this.latitude = 0;
|
||||
this.longitude = 0;
|
||||
this.altitude = 0;
|
||||
this.heading = 0;
|
||||
this.speed = 0;
|
||||
|
||||
/* Tasking */
|
||||
this.coalitionID = 0;
|
||||
this.alive = true;
|
||||
this.currentTask = "";
|
||||
|
||||
/* Formation */
|
||||
this.leader = false;
|
||||
this.wingman = false;
|
||||
this.wingmen = [];
|
||||
this.formation = "";
|
||||
|
||||
/* Structures */
|
||||
this.type = null;
|
||||
this.flags = null;
|
||||
this.activePath = null;
|
||||
this.missionData = null;
|
||||
|
||||
this.#selectable = true;
|
||||
this.#timer = 0;
|
||||
|
||||
/* The marker is set by the inherited class */
|
||||
this.#marker = marker;
|
||||
this.#marker.on('click', (e) => this.#onClick(e));
|
||||
this.#marker.on('dblclick', (e) => this.#onDoubleClick(e));
|
||||
|
||||
this.#selected = false;
|
||||
this.#preventClick = false;
|
||||
this.#pathMarkers = [];
|
||||
this.#pathPolyline = new Polyline([], {color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1});
|
||||
|
||||
this.#pathPolyline = new Polyline([], { color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1 });
|
||||
this.#pathPolyline.addTo(getMap());
|
||||
this.#targetsPolylines = [];
|
||||
}
|
||||
|
||||
update(response: JSON)
|
||||
{
|
||||
for (let entry in response)
|
||||
{
|
||||
update(response: JSON) {
|
||||
for (let entry in response) {
|
||||
// @ts-ignore
|
||||
this[entry] = response[entry];
|
||||
}
|
||||
|
||||
this.#updateMarker();
|
||||
|
||||
this.#clearTargets();
|
||||
if (this.getSelected())
|
||||
{
|
||||
this.#drawPath();
|
||||
this.#drawTargets();
|
||||
}
|
||||
else
|
||||
this.#clearPath();
|
||||
|
||||
|
||||
/*
|
||||
this.wingmen = [];
|
||||
if (response["wingmenIDs"] != undefined)
|
||||
if (response["wingmenIDs"] != null)
|
||||
{
|
||||
for (let ID of response["wingmenIDs"])
|
||||
{
|
||||
@@ -124,134 +98,114 @@ export class Unit
|
||||
this.missionData = missionData.getUnitData(this.ID)
|
||||
|
||||
this.setSelected(this.getSelected() && this.alive)
|
||||
|
||||
|
||||
|
||||
this.clearTargets();
|
||||
this.missionData = missionData.getUnitData(this.ID);
|
||||
if (this.missionData != undefined)
|
||||
{
|
||||
if (this.getSelected())
|
||||
{
|
||||
this.drawTargets();
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
setSelected(selected: boolean)
|
||||
{
|
||||
setSelected(selected: boolean) {
|
||||
/* Only alive units can be selected. Some units are not selectable (weapons) */
|
||||
if ((this.alive || !selected) && this.#selectable && this.#selected != selected)
|
||||
{
|
||||
if ((this.alive || !selected) && this.#selectable && this.#selected != selected) {
|
||||
this.#selected = selected;
|
||||
this.#marker.setSelected(selected);
|
||||
getUnitsManager().onUnitSelection();
|
||||
}
|
||||
}
|
||||
|
||||
getSelected()
|
||||
{
|
||||
getSelected() {
|
||||
return this.#selected;
|
||||
}
|
||||
|
||||
addDestination(latlng: L.LatLng)
|
||||
{
|
||||
addDestination(latlng: L.LatLng) {
|
||||
var path: any = {};
|
||||
if (this.activePath != undefined)
|
||||
{
|
||||
if (this.activePath != null) {
|
||||
path = this.activePath;
|
||||
path[(Object.keys(path).length + 1).toString()] = latlng;
|
||||
}
|
||||
else
|
||||
{
|
||||
path = {"1": latlng};
|
||||
else {
|
||||
path = { "1": latlng };
|
||||
}
|
||||
addDestination(this.ID, path);
|
||||
}
|
||||
|
||||
clearDestinations()
|
||||
{
|
||||
this.activePath = undefined;
|
||||
clearDestinations() {
|
||||
this.activePath = null;
|
||||
}
|
||||
|
||||
#onClick(e: any)
|
||||
{
|
||||
getHidden() {
|
||||
return false;
|
||||
}
|
||||
|
||||
#onClick(e: any) {
|
||||
this.#timer = setTimeout(() => {
|
||||
if (!this.#preventClick) {
|
||||
if (getMap().getState() === 'IDLE' || getMap().getState() === 'MOVE_UNIT' || e.originalEvent.ctrlKey)
|
||||
{
|
||||
if (!e.originalEvent.ctrlKey)
|
||||
{
|
||||
if (getMap().getState() === 'IDLE' || getMap().getState() === 'MOVE_UNIT' || e.originalEvent.ctrlKey) {
|
||||
if (!e.originalEvent.ctrlKey) {
|
||||
getUnitsManager().deselectAllUnits();
|
||||
}
|
||||
this.setSelected(true);
|
||||
}
|
||||
}
|
||||
this.#preventClick = false;
|
||||
}, 200);
|
||||
}, 200);
|
||||
}
|
||||
|
||||
#onDoubleClick(e: any)
|
||||
{
|
||||
#onDoubleClick(e: any) {
|
||||
clearTimeout(this.#timer);
|
||||
this.#preventClick = true;
|
||||
|
||||
var options = [
|
||||
{'tooltip': 'Attack', 'src': 'attack.png', 'callback': () => {getMap().hideSelectionWheel(); getUnitsManager().attackUnit(this.ID);}},
|
||||
{'tooltip': 'Go to tanker', 'src': 'tanker.png', 'callback': () => {getMap().hideSelectionWheel(); /*showMessage("Function not implemented yet");*/}},
|
||||
{'tooltip': 'RTB', 'src': 'rtb.png', 'callback': () => {getMap().hideSelectionWheel(); /*showMessage("Function not implemented yet");*/}}
|
||||
{ 'tooltip': 'Attack', 'src': 'attack.png', 'callback': () => { getMap().hideSelectionWheel(); getUnitsManager().attackUnit(this.ID); } },
|
||||
{ 'tooltip': 'Go to tanker', 'src': 'tanker.png', 'callback': () => { getMap().hideSelectionWheel(); /*showMessage("Function not implemented yet");*/ } },
|
||||
{ 'tooltip': 'RTB', 'src': 'rtb.png', 'callback': () => { getMap().hideSelectionWheel(); /*showMessage("Function not implemented yet");*/ } }
|
||||
]
|
||||
|
||||
if (!this.leader && !this.wingman)
|
||||
{
|
||||
options.push({'tooltip': 'Create formation', 'src': 'formation.png', 'callback': () => {getMap().hideSelectionWheel(); /*unitsManager.createFormation(this.ID);*/}});
|
||||
if (!this.leader && !this.wingman) {
|
||||
options.push({ 'tooltip': 'Create formation', 'src': 'formation.png', 'callback': () => { getMap().hideSelectionWheel(); /*unitsManager.createFormation(this.ID);*/ } });
|
||||
}
|
||||
|
||||
getMap().showSelectionWheel(e.originalEvent, options, false);
|
||||
}
|
||||
|
||||
#updateMarker()
|
||||
{
|
||||
#updateMarker() {
|
||||
/* Add the marker if not present */
|
||||
if (!getMap().hasLayer(this.#marker))
|
||||
{
|
||||
if (!getMap().hasLayer(this.#marker) && !this.getHidden()) {
|
||||
this.#marker.addTo(getMap());
|
||||
}
|
||||
|
||||
this.#marker.setLatLng(new LatLng(this.latitude, this.longitude));
|
||||
this.#marker.draw({
|
||||
heading: this.heading,
|
||||
speed: this.speed,
|
||||
altitude: this.altitude,
|
||||
alive: this.alive
|
||||
});
|
||||
/* Hide the marker if necessary*/
|
||||
if (getMap().hasLayer(this.#marker) && this.getHidden()) {
|
||||
getMap().removeLayer(this.#marker);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.#marker.setLatLng(new LatLng(this.latitude, this.longitude));
|
||||
this.#marker.draw({
|
||||
heading: this.heading,
|
||||
speed: this.speed,
|
||||
altitude: this.altitude,
|
||||
alive: this.alive
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#drawPath()
|
||||
{
|
||||
if (this.activePath != null)
|
||||
{
|
||||
#drawPath() {
|
||||
if (this.activePath != null) {
|
||||
var _points = [];
|
||||
_points.push(new LatLng(this.latitude, this.longitude));
|
||||
|
||||
/* Add markers if missing */
|
||||
while (this.#pathMarkers.length < Object.keys(this.activePath).length)
|
||||
{
|
||||
var marker = new Marker([0, 0]).addTo(getMap());
|
||||
while (this.#pathMarkers.length < Object.keys(this.activePath).length) {
|
||||
var marker = new Marker([0, 0], { icon: pathIcon }).addTo(getMap());
|
||||
this.#pathMarkers.push(marker);
|
||||
}
|
||||
|
||||
/* Remove markers if too many */
|
||||
while (this.#pathMarkers.length > Object.keys(this.activePath).length)
|
||||
{
|
||||
while (this.#pathMarkers.length > Object.keys(this.activePath).length) {
|
||||
getMap().removeLayer(this.#pathMarkers[this.#pathMarkers.length - 1]);
|
||||
this.#pathMarkers.splice(this.#pathMarkers.length - 1, 1)
|
||||
}
|
||||
|
||||
/* Update the position of the existing markers (to avoid creating markers uselessly) */
|
||||
for (let WP in this.activePath)
|
||||
{
|
||||
for (let WP in this.activePath) {
|
||||
var destination = this.activePath[WP];
|
||||
this.#pathMarkers[parseInt(WP) - 1].setLatLng([destination.lat, destination.lng]);
|
||||
_points.push(new LatLng(destination.lat, destination.lng));
|
||||
@@ -260,26 +214,24 @@ export class Unit
|
||||
}
|
||||
}
|
||||
|
||||
#clearPath()
|
||||
{
|
||||
for (let WP in this.#pathMarkers)
|
||||
{
|
||||
#clearPath() {
|
||||
for (let WP in this.#pathMarkers) {
|
||||
getMap().removeLayer(this.#pathMarkers[WP]);
|
||||
}
|
||||
this.#pathMarkers = [];
|
||||
this.#pathPolyline.setLatLngs([]);
|
||||
}
|
||||
|
||||
/*
|
||||
drawTargets()
|
||||
|
||||
#drawTargets()
|
||||
{
|
||||
for (let typeIndex in this.missionData['targets'])
|
||||
for (let typeIndex in this.targets)
|
||||
{
|
||||
for (let index in this.missionData['targets'][typeIndex])
|
||||
for (let index in this.targets[typeIndex])
|
||||
{
|
||||
var targetData = this.missionData['targets'][typeIndex][index];
|
||||
var target = unitsManager.getUnitByID(targetData.object["id_"])
|
||||
if (target != undefined){
|
||||
var targetData = this.targets[typeIndex][index];
|
||||
var target = getUnitsManager().getUnitByID(targetData.object["id_"])
|
||||
if (target != null){
|
||||
var startLatLng = new LatLng(this.latitude, this.longitude)
|
||||
var endLatLng = new LatLng(target.latitude, target.longitude)
|
||||
|
||||
@@ -301,72 +253,44 @@ export class Unit
|
||||
color = "#FFFFFF";
|
||||
}
|
||||
var targetPolyline = new Polyline([startLatLng, endLatLng], {color: color, weight: 3, opacity: 1, smoothFactor: 1});
|
||||
targetPolyline.addTo(map.getMap());
|
||||
targetPolyline.addTo(getMap());
|
||||
this.#targetsPolylines.push(targetPolyline)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clearTargets()
|
||||
#clearTargets()
|
||||
{
|
||||
for (let index in this.#targetsPolylines)
|
||||
{
|
||||
map.getMap().removeLayer(this.#targetsPolylines[index])
|
||||
getMap().removeLayer(this.#targetsPolylines[index])
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
attackUnit(targetID: number)
|
||||
{
|
||||
// Call DCS attackUnit function
|
||||
if (this.ID != targetID)
|
||||
{
|
||||
attackUnit(targetID: number) {
|
||||
/* Call DCS attackUnit function */
|
||||
if (this.ID != targetID) {
|
||||
attackUnit(this.ID, targetID);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
// TODO: show a message
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
changeSpeed(speedChange: string)
|
||||
{
|
||||
changeSpeed(this.ID, speedChange);
|
||||
}
|
||||
|
||||
changeAltitude(altitudeChange: string)
|
||||
{
|
||||
changeAltitude(this.ID, altitudeChange);
|
||||
}
|
||||
|
||||
/*
|
||||
changeSpeed(speedChange)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(this.unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": this.ID, "change": speedChange}
|
||||
var data = {"changeSpeed": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
changeAltitude(altitudeChange)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
console.log(this.unitName + " altitude change request: " + altitudeChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": this.ID, "change": altitudeChange}
|
||||
var data = {"changeAltitude": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
setformation(formation)
|
||||
{
|
||||
// TODO move in dedicated file
|
||||
@@ -405,66 +329,98 @@ export class Unit
|
||||
*/
|
||||
}
|
||||
|
||||
export class AirUnit extends Unit
|
||||
{
|
||||
|
||||
export class AirUnit extends Unit {
|
||||
getHidden() {
|
||||
if (this.alive)
|
||||
{
|
||||
if (this.flags.user && getVisibilitySettings().user === "hidden")
|
||||
return true
|
||||
else if (!this.flags.user && getVisibilitySettings().ai === "hidden")
|
||||
return true
|
||||
}
|
||||
else
|
||||
return getVisibilitySettings().dead === "hidden"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class Aircraft extends AirUnit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
export class Aircraft extends AirUnit {
|
||||
constructor(ID: number, options: MarkerOptions) {
|
||||
var marker = new AircraftMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class Helicopter extends AirUnit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
export class Helicopter extends AirUnit {
|
||||
constructor(ID: number, options: MarkerOptions) {
|
||||
var marker = new HelicopterMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class GroundUnit extends Unit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
export class GroundUnit extends Unit {
|
||||
constructor(ID: number, options: MarkerOptions) {
|
||||
var marker = new GroundUnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
|
||||
getHidden() {
|
||||
if (this.alive)
|
||||
{
|
||||
if (this.flags.user && getVisibilitySettings().user === "hidden")
|
||||
return true
|
||||
else if (!this.flags.user && getVisibilitySettings().ai === "hidden")
|
||||
return true
|
||||
}
|
||||
else
|
||||
return getVisibilitySettings().dead === "hidden"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnit extends Unit {
|
||||
constructor(ID: number, options: MarkerOptions) {
|
||||
var marker = new NavyUnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
|
||||
getHidden() {
|
||||
if (this.alive)
|
||||
{
|
||||
if (this.flags.user && getVisibilitySettings().user === "hidden")
|
||||
return true
|
||||
else if (!this.flags.user && getVisibilitySettings().ai === "hidden")
|
||||
return true
|
||||
}
|
||||
else
|
||||
return getVisibilitySettings().dead === "hidden"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class Weapon extends Unit {
|
||||
getHidden() {
|
||||
if (this.alive)
|
||||
{
|
||||
if (!this.flags.user && getVisibilitySettings().weapon === "hidden")
|
||||
return true
|
||||
}
|
||||
else
|
||||
return getVisibilitySettings().dead === "hidden"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export class Missile extends Weapon {
|
||||
constructor(ID: number, options: MarkerOptions) {
|
||||
var marker = new WeaponMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnit extends Unit
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class Weapon extends Unit
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
export class Missile extends Weapon
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
export class Bomb extends Weapon
|
||||
{
|
||||
constructor(ID: number, options: MarkerOptions)
|
||||
{
|
||||
var marker = new UnitMarker(options);
|
||||
export class Bomb extends Weapon {
|
||||
constructor(ID: number, options: MarkerOptions) {
|
||||
var marker = new WeaponMarker(options);
|
||||
super(ID, marker);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,43 +1,37 @@
|
||||
import * as L from 'leaflet'
|
||||
import { Symbol } from 'milsymbol'
|
||||
import { getVisibilitySettings } from '..'
|
||||
|
||||
export interface MarkerOptions
|
||||
{
|
||||
unitName: string
|
||||
name: string
|
||||
human: boolean
|
||||
coalitionID: number
|
||||
type: any
|
||||
export interface MarkerOptions {
|
||||
unitName: string
|
||||
name: string
|
||||
human: boolean
|
||||
coalitionID: number
|
||||
type: any
|
||||
}
|
||||
|
||||
export interface MarkerData
|
||||
{
|
||||
heading: number
|
||||
speed: number
|
||||
altitude: number
|
||||
alive: boolean
|
||||
export interface MarkerData {
|
||||
heading: number
|
||||
speed: number
|
||||
altitude: number
|
||||
alive: boolean
|
||||
}
|
||||
|
||||
export class UnitMarker extends L.Marker
|
||||
{
|
||||
#unitName: string
|
||||
#name: string
|
||||
#human: boolean
|
||||
#coalitionID: number
|
||||
#alive: boolean
|
||||
export class UnitMarker extends L.Marker {
|
||||
#unitName: string
|
||||
#name: string
|
||||
#human: boolean
|
||||
#alive: boolean = true
|
||||
#selected: boolean = false
|
||||
|
||||
constructor(options: MarkerOptions)
|
||||
{
|
||||
super(new L.LatLng(0, 0), {riseOnHover: true});
|
||||
this.#unitName = options.unitName
|
||||
this.#name = options.name
|
||||
this.#human = options.human
|
||||
this.#coalitionID = options.coalitionID
|
||||
|
||||
this.#alive = true;
|
||||
constructor(options: MarkerOptions) {
|
||||
super(new L.LatLng(0, 0), { riseOnHover: true });
|
||||
this.#unitName = options.unitName;
|
||||
this.#name = options.name;
|
||||
this.#human = options.human;
|
||||
|
||||
var symbol = new Symbol(this.#computeMarkerCode(options), {size: 100});
|
||||
var img = symbol.asCanvas().toDataURL('image/png');
|
||||
var symbol = new Symbol(this.#computeMarkerCode(options), { size: 25 });
|
||||
var img = symbol.asCanvas().toDataURL('image/png');
|
||||
|
||||
var icon = new L.DivIcon({
|
||||
html: `<table class="unit-marker-container" id="container">
|
||||
@@ -50,25 +44,23 @@ export class UnitMarker extends L.Marker
|
||||
<div class="unit-marker-name" id="name">${this.#name}</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>`,
|
||||
className: 'unit-marker'});
|
||||
this.setIcon(icon);
|
||||
</table>`,
|
||||
className: 'unit-marker'
|
||||
});
|
||||
this.setIcon(icon);
|
||||
}
|
||||
|
||||
onAdd(map: L.Map): this
|
||||
{
|
||||
onAdd(map: L.Map): this {
|
||||
super.onAdd(map);
|
||||
var element = <HTMLElement>this.getElement();
|
||||
this.addEventListener('mouseover', function(e: any) { e.target?.setHovered(true);});
|
||||
this.addEventListener('mouseout', function(e: any) { e.target?.setHovered(false);});
|
||||
this.addEventListener('mouseover', function (e: any) { e.target?.setHovered(true); });
|
||||
this.addEventListener('mouseout', function (e: any) { e.target?.setHovered(false); });
|
||||
return this
|
||||
}
|
||||
|
||||
draw(data: MarkerData)
|
||||
{
|
||||
draw(data: MarkerData) {
|
||||
this.#alive = data.alive;
|
||||
var element = this.getElement();
|
||||
if (element != null)
|
||||
{
|
||||
if (element != null) {
|
||||
var nameDiv = <HTMLElement>element.querySelector("#name");
|
||||
var unitNameDiv = <HTMLElement>element.querySelector("#unitName");
|
||||
var container = <HTMLElement>element.querySelector("#container");
|
||||
@@ -76,33 +68,70 @@ export class UnitMarker extends L.Marker
|
||||
var altitudeDiv = <HTMLElement>element.querySelector("#altitude");
|
||||
var speedDiv = <HTMLElement>element.querySelector("#speed");
|
||||
|
||||
/* If visibility is full show all labels */
|
||||
nameDiv.style.display = '';
|
||||
unitNameDiv.style.display = '';
|
||||
altitudeDiv.style.display = '';
|
||||
speedDiv.style.display = '';
|
||||
|
||||
/* If visibility is partial shown only icon and unit name. If none, shown only icon. */
|
||||
if (this.getVisibility() === "partial" || this.getVisibility() === "none")
|
||||
{
|
||||
unitNameDiv.style.display = 'none';
|
||||
altitudeDiv.style.display = 'none';
|
||||
speedDiv.style.display = 'none';
|
||||
}
|
||||
if (this.getVisibility() === "none")
|
||||
nameDiv.style.display = 'none';
|
||||
|
||||
nameDiv.style.left = (-(nameDiv.offsetWidth - container.offsetWidth) / 2) + "px";
|
||||
unitNameDiv.style.left = (-(unitNameDiv.offsetWidth - container.offsetWidth) / 2) + "px";
|
||||
|
||||
|
||||
icon.style.transform = "rotate(" + data.heading + "rad)";
|
||||
altitudeDiv.innerHTML = String(Math.round(data.altitude / 0.3048 / 100) / 10);
|
||||
speedDiv.innerHTML = String(Math.round(data.speed * 1.94384));
|
||||
|
||||
if (!this.#alive)
|
||||
{
|
||||
this.getElement()?.querySelector("#icon")?.classList.add("unit-marker-dead");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setSelected(selected: boolean)
|
||||
{
|
||||
setSelected(selected: boolean) {
|
||||
this.#selected = selected;
|
||||
this.getElement()?.querySelector("#icon")?.classList.remove("unit-marker-hovered");
|
||||
this.getElement()?.querySelector("#icon")?.classList.toggle("unit-marker-selected", selected);
|
||||
}
|
||||
|
||||
setHovered(hovered: boolean)
|
||||
{
|
||||
getSelected() {
|
||||
return this.#selected;
|
||||
}
|
||||
|
||||
setHovered(hovered: boolean) {
|
||||
this.getElement()?.querySelector("#icon")?.classList.toggle("unit-marker-hovered", hovered && this.#alive);
|
||||
}
|
||||
|
||||
#computeMarkerCode(options: MarkerOptions)
|
||||
{
|
||||
getHuman() {
|
||||
return this.#human;
|
||||
}
|
||||
|
||||
getAlive() {
|
||||
return this.#alive;
|
||||
}
|
||||
|
||||
getVisibility() {
|
||||
return "full";
|
||||
}
|
||||
|
||||
#computeMarkerCode(options: MarkerOptions) {
|
||||
var identity = "00";
|
||||
var set = "00";
|
||||
var entity = "00";
|
||||
var entityType = "00";
|
||||
var entitySubtype = "00";
|
||||
var sectorOneModifier = "00";
|
||||
var sectorTwoModifier = "00";
|
||||
|
||||
/* Identity */
|
||||
if (options.coalitionID == 1)
|
||||
@@ -112,8 +141,8 @@ export class UnitMarker extends L.Marker
|
||||
else
|
||||
identity = "04" /* Neutral */
|
||||
|
||||
if (options.type.level1 == 1)
|
||||
{
|
||||
/* Air */
|
||||
if (options.type.level1 == 1) {
|
||||
set = "01"
|
||||
entity = "11"
|
||||
if (options.type.level2 == 1)
|
||||
@@ -134,14 +163,103 @@ export class UnitMarker extends L.Marker
|
||||
else if (options.type.level3 == 6)
|
||||
entitySubtype = "00";
|
||||
}
|
||||
|
||||
/* Ground */
|
||||
else if (options.type.level1 == 2)
|
||||
{
|
||||
set = "10"
|
||||
entity = "12"
|
||||
entityType = "05"
|
||||
}
|
||||
/* Navy */
|
||||
else if (options.type.level1 == 3)
|
||||
set = "30"
|
||||
else if (options.type.level1 == 2)
|
||||
/* Weapon */
|
||||
else if (options.type.level1 == 4)
|
||||
{
|
||||
set = "02"
|
||||
|
||||
|
||||
return `10${identity}${set}0000${entity}${entityType}${entitySubtype}0000`
|
||||
entity = "11"
|
||||
if (options.type.level3 == 7)
|
||||
{
|
||||
sectorOneModifier = "01"
|
||||
sectorTwoModifier = "01"
|
||||
}
|
||||
else if (options.type.level3 == 8)
|
||||
{
|
||||
sectorOneModifier = "01"
|
||||
sectorTwoModifier = "02"
|
||||
}
|
||||
else if (options.type.level3 == 34)
|
||||
{
|
||||
sectorOneModifier = "02"
|
||||
sectorTwoModifier = "01"
|
||||
}
|
||||
else if (options.type.level3 == 11)
|
||||
{
|
||||
sectorOneModifier = "02"
|
||||
sectorTwoModifier = "02"
|
||||
}
|
||||
}
|
||||
|
||||
return `10${identity}${set}0000${entity}${entityType}${entitySubtype}${sectorOneModifier}${sectorTwoModifier}`
|
||||
}
|
||||
}
|
||||
|
||||
export class AirUnitMarker extends UnitMarker {
|
||||
getVisibility() {
|
||||
if (this.getSelected())
|
||||
return "full";
|
||||
|
||||
if (this.getHuman())
|
||||
return getVisibilitySettings().user;
|
||||
else if (!this.getAlive())
|
||||
return "none";
|
||||
else
|
||||
return getVisibilitySettings().ai;
|
||||
}
|
||||
}
|
||||
|
||||
export class AircraftMarker extends AirUnitMarker {
|
||||
}
|
||||
|
||||
export class HelicopterMarker extends AirUnitMarker {
|
||||
}
|
||||
|
||||
export class GroundUnitMarker extends UnitMarker {
|
||||
/* Are user driven units recognized as human? */
|
||||
getVisibility() {
|
||||
if (this.getSelected())
|
||||
return "full";
|
||||
|
||||
if (this.getHuman())
|
||||
return getVisibilitySettings().user;
|
||||
else if (!this.getAlive())
|
||||
return "none";
|
||||
else
|
||||
return getVisibilitySettings().ai;
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnitMarker extends UnitMarker {
|
||||
getVisibility() {
|
||||
if (this.getSelected())
|
||||
return "full";
|
||||
|
||||
if (!this.getAlive())
|
||||
return "none";
|
||||
else
|
||||
return getVisibilitySettings().ai;
|
||||
}
|
||||
}
|
||||
|
||||
export class WeaponMarker extends UnitMarker {
|
||||
getVisibility() {
|
||||
if (this.getSelected())
|
||||
return "full";
|
||||
|
||||
if (!this.getAlive())
|
||||
return "none";
|
||||
else
|
||||
return getVisibilitySettings().weapon;
|
||||
}
|
||||
}
|
||||
@@ -1,23 +1,20 @@
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { getMap, getUnitInfoPanel } from "..";
|
||||
import { Unit, GroundUnit } from "./unit";
|
||||
|
||||
export class UnitsManager
|
||||
{
|
||||
#units: { [ID: number]: Unit};
|
||||
export class UnitsManager {
|
||||
#units: { [ID: number]: Unit };
|
||||
#copiedUnits: Unit[];
|
||||
|
||||
constructor()
|
||||
{
|
||||
constructor() {
|
||||
this.#units = {};
|
||||
this.#copiedUnits = [];
|
||||
}
|
||||
|
||||
addUnit(ID: number, data: any)
|
||||
{
|
||||
addUnit(ID: number, data: any) {
|
||||
/* The name of the unit category is exactly the same as the constructor name */
|
||||
var constructor = Unit.getConstructor(data.category);
|
||||
if (constructor != undefined)
|
||||
{
|
||||
var constructor = Unit.getConstructor(data.category);
|
||||
if (constructor != undefined) {
|
||||
var options = {
|
||||
unitName: data.unitName,
|
||||
name: data.name,
|
||||
@@ -29,92 +26,75 @@ export class UnitsManager
|
||||
}
|
||||
}
|
||||
|
||||
getUnitByID(ID: number)
|
||||
{
|
||||
getUnitByID(ID: number) {
|
||||
return this.#units[ID];
|
||||
}
|
||||
|
||||
removeUnit(ID: number)
|
||||
{
|
||||
removeUnit(ID: number) {
|
||||
|
||||
}
|
||||
|
||||
deselectAllUnits()
|
||||
{
|
||||
for (let ID in this.#units)
|
||||
{
|
||||
deselectAllUnits() {
|
||||
for (let ID in this.#units) {
|
||||
this.#units[ID].setSelected(false);
|
||||
}
|
||||
}
|
||||
|
||||
update(data: any)
|
||||
{
|
||||
for (let ID in data["units"])
|
||||
{
|
||||
update(data: any) {
|
||||
for (let ID in data["units"]) {
|
||||
/* Create the unit if missing from the local array, then update the data. Drawing is handled by leaflet. */
|
||||
if (!(ID in this.#units))
|
||||
{
|
||||
if (!(ID in this.#units)) {
|
||||
this.addUnit(parseInt(ID), data["units"][ID]);
|
||||
}
|
||||
this.#units[parseInt(ID)].update(data["units"][ID]);
|
||||
}
|
||||
|
||||
if (this.getSelectedUnits().length == 1)
|
||||
{
|
||||
if (this.getSelectedUnits().length == 1) {
|
||||
getUnitInfoPanel().show();
|
||||
getUnitInfoPanel().update(this.getSelectedUnits()[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
getUnitInfoPanel().hide();
|
||||
}
|
||||
}
|
||||
|
||||
onUnitSelection()
|
||||
{
|
||||
if (this.getSelectedUnits().length > 0)
|
||||
{
|
||||
|
||||
onUnitSelection() {
|
||||
if (this.getSelectedUnits().length > 0) {
|
||||
getMap().setState("MOVE_UNIT");
|
||||
//unitControlPanel.setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
else {
|
||||
getMap().setState("IDLE");
|
||||
//unitControlPanel.setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// selectFromBounds(bounds)
|
||||
// {
|
||||
// this.deselectAllUnits();
|
||||
// for (let ID in this.#units)
|
||||
// {
|
||||
// var latlng = new LatLng(this.#units[ID].latitude, this.#units[ID].longitude);
|
||||
// if (bounds.contains(latlng))
|
||||
// {
|
||||
// this.#units[ID].setSelected(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
getSelectedUnits()
|
||||
selectFromBounds(bounds: LatLngBounds)
|
||||
{
|
||||
var selectedUnits = [];
|
||||
this.deselectAllUnits();
|
||||
for (let ID in this.#units)
|
||||
{
|
||||
if (this.#units[ID].getSelected())
|
||||
var latlng = new LatLng(this.#units[ID].latitude, this.#units[ID].longitude);
|
||||
if (bounds.contains(latlng))
|
||||
{
|
||||
this.#units[ID].setSelected(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedUnits() {
|
||||
var selectedUnits = [];
|
||||
for (let ID in this.#units) {
|
||||
if (this.#units[ID].getSelected()) {
|
||||
selectedUnits.push(this.#units[ID]);
|
||||
}
|
||||
}
|
||||
return selectedUnits;
|
||||
}
|
||||
|
||||
addDestination(latlng: L.LatLng)
|
||||
{
|
||||
addDestination(latlng: L.LatLng) {
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
for (let idx in selectedUnits) {
|
||||
var commandedUnit = selectedUnits[idx];
|
||||
//if (selectedUnits[idx].wingman)
|
||||
//{
|
||||
@@ -124,11 +104,9 @@ export class UnitsManager
|
||||
}
|
||||
}
|
||||
|
||||
clearDestinations()
|
||||
{
|
||||
clearDestinations() {
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
for (let idx in selectedUnits) {
|
||||
var commandedUnit = selectedUnits[idx];
|
||||
//if (selectedUnits[idx].wingman)
|
||||
//{
|
||||
@@ -138,28 +116,23 @@ export class UnitsManager
|
||||
}
|
||||
}
|
||||
|
||||
// selectedUnitsMove()
|
||||
// {
|
||||
|
||||
// }
|
||||
selectedUnitsChangeSpeed(speedChange: string)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].changeSpeed(speedChange);
|
||||
}
|
||||
}
|
||||
|
||||
// selectedUnitsChangeSpeed(speedChange)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// selectedUnits[idx].changeSpeed(speedChange);
|
||||
// }
|
||||
// }
|
||||
|
||||
// selectedUnitsChangeAltitude(altitudeChange)
|
||||
// {
|
||||
// var selectedUnits = this.getSelectedUnits();
|
||||
// for (let idx in selectedUnits)
|
||||
// {
|
||||
// selectedUnits[idx].changeAltitude(altitudeChange);
|
||||
// }
|
||||
// }
|
||||
selectedUnitsChangeAltitude(altitudeChange: string)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].changeAltitude(altitudeChange);
|
||||
}
|
||||
}
|
||||
|
||||
// handleKeyEvent(e)
|
||||
// {
|
||||
@@ -187,11 +160,9 @@ export class UnitsManager
|
||||
// }
|
||||
// }
|
||||
|
||||
attackUnit(ID: number)
|
||||
{
|
||||
attackUnit(ID: number) {
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
for (let idx in selectedUnits) {
|
||||
/* If a unit is a wingman, send the command to its leader */
|
||||
var commandedUnit = selectedUnits[idx];
|
||||
//if (selectedUnits[idx].wingman)
|
||||
|
||||
Reference in New Issue
Block a user