Completed transition to injected svgs

This commit is contained in:
Pax1601
2023-05-24 11:07:41 +02:00
parent e7ce9ac76d
commit 3009a73a66
26 changed files with 333 additions and 303 deletions

View File

@@ -79,4 +79,16 @@ interface GeneralSettings {
prohibitAG: boolean;
prohibitAfterburner: boolean;
prohibitAirWpn: boolean;
}
interface UnitIconOptions {
showState: boolean,
showVvi: boolean,
showHotgroup: boolean,
showUnitIcon: boolean,
showShortLabel: boolean,
showFuel: boolean,
showAmmo: boolean,
showSummary: boolean,
rotateToHeading: boolean
}

View File

@@ -67,7 +67,10 @@ export class Dropdown {
selectValue(idx: number) {
if (idx < this.#optionsList.length) {
var option = this.#optionsList[idx];
this.#value.innerHTML = `<div class = "ol-ellipsed"> ${option} </div>`;
var el = document.createElement("div");
el.classList.add("ol-ellipsed");
el.innerText = option;
this.#value.appendChild(el);
this.#index = idx;
this.#close();
this.#callback(option);

View File

@@ -88,7 +88,7 @@ export class Slider {
#onValue() {
if (this.#valueText != null && this.#slider != null)
this.#valueText.innerHTML = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit
this.#valueText.innerText = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit
this.setActive(true);
}

View File

@@ -40,11 +40,16 @@ export class UnitContextMenu extends ContextMenu {
this.#customFormationCallback = callback;
}
setOptions(options: { [key: string]: string }, callback: CallableFunction) {
this.getContainer()?.replaceChildren(...Object.keys(options).map((option: string, idx: number) => {
setOptions(options: { [key: string]: {text: string, tooltip: string }}, callback: CallableFunction) {
this.getContainer()?.replaceChildren(...Object.keys(options).map((key: string, idx: number) => {
const option = options[key];
var button = document.createElement("button");
button.innerHTML = options[option];
button.addEventListener("click", () => callback(option));
var el = document.createElement("div");
el.title = option.tooltip;
el.innerText = option.text;
el.id = key;
button.addEventListener("click", () => callback(key));
button.appendChild(el);
return (button);
}));
}

View File

@@ -140,28 +140,14 @@ function setupEvents() {
case "Space":
setPaused(!getPaused());
break;
case "KeyW":
case "KeyA":
case "KeyS":
case "KeyD":
case "ArrowLeft":
case "ArrowRight":
case "ArrowUp":
case "ArrowDown":
case "KeyW": case "KeyA": case "KeyS": case "KeyD":
case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown":
getMap().handleMapPanning(ev);
break;
case "Digit1":
case "Digit2":
case "Digit3":
case "Digit4":
case "Digit5":
case "Digit6":
case "Digit7":
case "Digit8":
case "Digit9":
case "Digit1": case "Digit2": case "Digit3": case "Digit4": case "Digit5": case "Digit6": case "Digit7": case "Digit8": case "Digit9":
// Using the substring because the key will be invalid when pressing the Shift key
if (ev.ctrlKey && ev.shiftKey)
getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5)));
getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5)));
else if (ev.ctrlKey && !ev.shiftKey)
getUnitsManager().selectedUnitsSetHotgroup(parseInt(ev.code.substring(5)));
else
@@ -176,14 +162,7 @@ function setupEvents() {
return;
}
switch (ev.code) {
case "KeyW":
case "KeyA":
case "KeyS":
case "KeyD":
case "ArrowLeft":
case "ArrowRight":
case "ArrowUp":
case "ArrowDown":
case "KeyW": case "KeyA": case "KeyS": case "KeyD": case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown":
getMap().handleMapPanning(ev);
break;
}
@@ -201,8 +180,8 @@ function setupEvents() {
document.addEventListener("tryConnection", () => {
const form = document.querySelector("#splash-content")?.querySelector("#authentication-form");
const username = (<HTMLInputElement> (form?.querySelector("#username"))).value;
const password = (<HTMLInputElement> (form?.querySelector("#password"))).value;
const username = (<HTMLInputElement>(form?.querySelector("#username"))).value;
const password = (<HTMLInputElement>(form?.querySelector("#password"))).value;
setCredentials(username, btoa("admin" + ":" + password));
/* Start periodically requesting updates */

View File

@@ -1,4 +1,4 @@
import { Map, Marker } from "leaflet";
import { DivIcon, Map, Marker } from "leaflet";
import { MarkerOptions } from "leaflet";
import { LatLngExpression } from "leaflet";
@@ -8,6 +8,7 @@ export class CustomMarker extends Marker {
}
onAdd(map: Map): this {
this.setIcon(new DivIcon()); // Default empty icon
super.onAdd(map);
this.createIcon();
return this;

View File

@@ -22,6 +22,7 @@ require("../../public/javascripts/leaflet.nauticscale.js")
export const IDLE = "IDLE";
export const MOVE_UNIT = "MOVE_UNIT";
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 {
#state: string;
@@ -116,7 +117,7 @@ export class Map extends L.Map {
/* Option buttons */
this.#optionButtons["visibility"] = visibilityControls.map((option: string, index: number) => {
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, "", "toggleUnitVisibility", `{"type": "${option}"}`);
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"type": "${option}"}`);
});
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
}
@@ -194,7 +195,7 @@ export class Map extends L.Map {
})
this.#destinationPreviewMarkers = [];
if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) {
if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length > 1 && getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) {
/* Create the unit destination preview markers */
this.#destinationPreviewMarkers = getUnitsManager().getSelectedUnits({ excludeHumans: true }).map((unit: Unit) => {
var marker = new DestinationPreviewMarker(this.getMouseCoordinates());
@@ -425,6 +426,9 @@ 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.#destinationRotationCenter = null;
this.#computeDestinationRotation = false;
}
}
@@ -440,18 +444,18 @@ export class Map extends L.Map {
#onMouseDown(e: any) {
this.hideAllContextMenus();
if (this.#state == MOVE_UNIT && e.originalEvent.button == 2) {
this.#computeDestinationRotation = true;
this.#destinationRotationCenter = this.getMouseCoordinates();
if (this.#state == MOVE_UNIT) {
this.#destinationGroupRotation = 0;
this.#destinationRotationCenter = null;
this.#computeDestinationRotation = false;
if (e.originalEvent.button == 2) {
this.#computeDestinationRotation = true;
this.#destinationRotationCenter = this.getMouseCoordinates();
}
}
}
#onMouseUp(e: any) {
if (this.#state == MOVE_UNIT) {
this.#computeDestinationRotation = false;
this.#destinationRotationCenter = null;
this.#destinationGroupRotation = 0;
}
}
#onMouseMove(e: any) {

View File

@@ -18,14 +18,24 @@ export class HotgroupPanel extends Panel {
}
addHotgroup(hotgroup: number) {
const hotgroupHtml = `<div class="unit-hotgroup">
<div class="unit-hotgroup-id">${hotgroup}</div>
</div>
x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`
// Hotgroup number
var hotgroupDiv = document.createElement("div");
hotgroupDiv.classList.add("unit-hotgroup");
var idDiv = document.createElement("div");
idDiv.classList.add("unit-hotgroup-id");
idDiv.innerText = String(hotgroup);
hotgroupDiv.appendChild(idDiv);
// Hotgroup unit count
var countDiv = document.createElement("div");
countDiv.innerText = `x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`;
var el = document.createElement("div");
el.appendChild(hotgroupDiv);
el.appendChild(countDiv);
el.classList.add("hotgroup-selector");
el.innerHTML = hotgroupHtml;
el.toggleAttribute(`data-hotgroup-${hotgroup}`, true)
this.getElement().appendChild(el);
el.addEventListener("click", () => {

View File

@@ -1,3 +1,4 @@
import { SVGInjector } from "@tanem/svg-injector";
import { getUnitsManager } from "..";
import { Dropdown } from "../controls/dropdown";
import { Slider } from "../controls/slider";
@@ -346,7 +347,10 @@ export class UnitControlPanel extends Panel {
var button = document.createElement("button");
button.title = title;
button.value = value;
button.innerHTML = `<img src="/resources/theme/images/buttons/${url}" />`
var img = document.createElement("img");
img.src = `/resources/theme/images/buttons/${url}`;
img.onload = () => SVGInjector(img);
button.appendChild(img);
button.addEventListener("click", callback);
return button;
}

View File

@@ -6,6 +6,7 @@ import { aircraftDatabase } from './aircraftdatabase';
import { groundUnitsDatabase } from './groundunitsdatabase';
import { CustomMarker } from '../map/custommarker';
import { SVGInjector } from '@tanem/svg-injector';
import { UnitDatabase } from './unitdatabase';
var pathIcon = new Icon({
iconUrl: '/resources/theme/images/markers/marker-icon.png',
@@ -124,17 +125,23 @@ export class Unit extends CustomMarker {
return "";
}
getActiveMarkerElements() {
// Default values
getDatabase(): UnitDatabase | null {
// Overloaded by child classes
return null;
}
getIconOptions(): UnitIconOptions {
// Default values, overloaded by child classes if needed
return {
state: false,
vvi: false,
hotgroup: false,
unitIcon: true,
shortLabel: false,
fuel: false,
ammo: false,
summary: false
showState: false,
showVvi: false,
showHotgroup: false,
showUnitIcon: true,
showShortLabel: false,
showFuel: false,
showAmmo: false,
showSummary: false,
rotateToHeading: false
}
}
@@ -165,6 +172,7 @@ export class Unit extends CustomMarker {
setHotgroup(hotgroup: number | null) {
this.#hotgroup = hotgroup;
this.#updateMarker();
}
getHotgroup() {
@@ -172,7 +180,7 @@ export class Unit extends CustomMarker {
}
setHighlighted(highlighted: boolean) {
if (this.#highlighted != highlighted) {
if (this.getSelectable() && this.#highlighted != highlighted) {
this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted);
this.#highlighted = highlighted;
this.getGroupMembers().forEach((unit: Unit) => unit.setHighlighted(highlighted));
@@ -297,19 +305,13 @@ export class Unit extends CustomMarker {
this.setIcon(icon);
var el = document.createElement("div");
el.classList.add("unit");
el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`);
el.setAttribute("data-coalition", this.getMissionData().coalition);
// Generate and append elements depending on active options
// State icon
if (this.getActiveMarkerElements().state){
var state = document.createElement("div");
state.classList.add("unit-state");
el.appendChild(state);
}
// Generate and append elements depending on active options
// Velocity vector
if (this.getActiveMarkerElements().vvi) {
if (this.getIconOptions().showVvi) {
var vvi = document.createElement("div");
vvi.classList.add("unit-vvi");
vvi.toggleAttribute("data-rotate-to-heading");
@@ -317,7 +319,7 @@ export class Unit extends CustomMarker {
}
// Hotgroup indicator
if (this.getActiveMarkerElements().hotgroup) {
if (this.getIconOptions().showHotgroup) {
var hotgroup = document.createElement("div");
hotgroup.classList.add("unit-hotgroup");
var hotgroupId = document.createElement("div");
@@ -327,26 +329,34 @@ export class Unit extends CustomMarker {
}
// Main icon
if (this.getActiveMarkerElements().unitIcon) {
if (this.getIconOptions().showUnitIcon) {
var unitIcon = document.createElement("div");
unitIcon.classList.add("unit-icon");
var img = document.createElement("img");
img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`;
img.onload = () => SVGInjector(img);
unitIcon.appendChild(img);
unitIcon.toggleAttribute("data-rotate-to-heading", this.getIconOptions().rotateToHeading);
el.append(unitIcon);
}
// State icon
if (this.getIconOptions().showState){
var state = document.createElement("div");
state.classList.add("unit-state");
el.appendChild(state);
}
// Short label
if (this.getActiveMarkerElements().shortLabel) {
if (this.getIconOptions().showShortLabel) {
var shortLabel = document.createElement("div");
shortLabel.classList.add("unit-short-label");
shortLabel.innerText = aircraftDatabase.getByName(this.getBaseData().name)?.shortLabel || ""; //TODO: fix, use correct database
shortLabel.innerText = this.getDatabase()?.getByName(this.getBaseData().name)?.shortLabel || "";
el.append(shortLabel);
}
// Fuel indicator
if (this.getActiveMarkerElements().fuel) {
if (this.getIconOptions().showFuel) {
var fuelIndicator = document.createElement("div");
fuelIndicator.classList.add("unit-fuel");
var fuelLevel = document.createElement("div");
@@ -356,7 +366,7 @@ export class Unit extends CustomMarker {
}
// Ammo indicator
if (this.getActiveMarkerElements().ammo){
if (this.getIconOptions().showAmmo){
var ammoIndicator = document.createElement("div");
ammoIndicator.classList.add("unit-ammo");
for (let i = 0; i <= 3; i++)
@@ -365,7 +375,7 @@ export class Unit extends CustomMarker {
}
// Unit summary
if (this.getActiveMarkerElements().summary) {
if (this.getIconOptions().showSummary) {
var summary = document.createElement("div");
summary.classList.add("unit-summary");
var callsign = document.createElement("div");
@@ -544,18 +554,18 @@ export class Unit extends CustomMarker {
}
#onContextMenu(e: any) {
var options: { [key: string]: string } = {};
var options: {[key: string]: {text: string, tooltip: string}} = {};
options["Center"] = `<div id="center-map">Center map</div>`;
options["center-map"] = {text: "Center map", tooltip: "Center the map on the unit and follow it"};
if (getUnitsManager().getSelectedUnits().length > 0 && !(getUnitsManager().getSelectedUnits().length == 1 && (getUnitsManager().getSelectedUnits().includes(this)))) {
options['Attack'] = `<div id="attack">Attack</div>`;
options["attack"] = {text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons"};
if (getUnitsManager().getSelectedUnitsType() === "Aircraft")
options['Follow'] = `<div id="follow">Follow</div>`;
options["follow"] = {text: "Follow", tooltip: "Follow the unit at a user defined distance and position"};;
}
else if ((getUnitsManager().getSelectedUnits().length > 0 && (getUnitsManager().getSelectedUnits().includes(this))) || getUnitsManager().getSelectedUnits().length == 0) {
if (this.getBaseData().category == "Aircraft") {
options["Refuel"] = `<div id="refuel">Refuel</div>`; // TODO Add some way of knowing which aircraft can AAR
options["refuel"] = {text: "AAR Refuel", tooltip: "Refuel unit at the nearest AAR Tanker. If no tanker is available the unit will RTB."}; // TODO Add some way of knowing which aircraft can AAR
}
}
@@ -569,28 +579,28 @@ export class Unit extends CustomMarker {
}
#executeAction(e: any, action: string) {
if (action === "Center")
if (action === "center-map")
getMap().centerOnUnit(this.ID);
if (action === "Attack")
if (action === "attack")
getUnitsManager().selectedUnitsAttackUnit(this.ID);
else if (action === "Refuel")
else if (action === "refuel")
getUnitsManager().selectedUnitsRefuel();
else if (action === "Follow")
else if (action === "follow")
this.#showFollowOptions(e);
}
#showFollowOptions(e: any) {
var options: { [key: string]: string } = {};
var options: {[key: string]: {text: string, tooltip: string}} = {};
options = {
'Trail': `<div id="trail">Trail</div>`,
'Echelon (LH)': `<div id="echelon-lh">Echelon (left)</div>`,
'Echelon (RH)': `<div id="echelon-rh">Echelon (right)</div>`,
'Line abreast (LH)': `<div id="line-abreast">Line abreast (left)</div>`,
'Line abreast (RH)': `<div id="line-abreast">Line abreast (right)</div>`,
'Front': `<div id="front">In front</div>`,
'Diamond': `<div id="diamond">Diamond</div>`,
'Custom': `<div id="custom">Custom</div>`
'trail': {text: "Trail", tooltip: "Follow unit in trail formation"},
'echelon-lh': {text: "Echelon (LH)", tooltip: "Follow unit in echelon left formation"},
'echelon-rh': {text: "Echelon (RH)", tooltip: "Follow unit in echelon right formation"},
'line-abreast-lh': {text: "Line abreast (LH)", tooltip: "Follow unit in line abreast left formation"},
'line-abreast-rh': {text: "Line abreast (RH)", tooltip: "Follow unit in line abreast right formation"},
'front': {text: "Front", tooltip: "Fly in front of unit"},
'diamond': {text: "Diamond", tooltip: "Follow unit in diamond formation"},
'custom': {text: "Custom", tooltip: "Set a custom formation position"},
}
getMap().getUnitContextMenu().setOptions(options, (option: string) => {
@@ -601,7 +611,7 @@ export class Unit extends CustomMarker {
}
#applyFollowOptions(action: string) {
if (action === "Custom") {
if (action === "custom") {
document.getElementById("custom-formation-dialog")?.classList.remove("hide");
getMap().getUnitContextMenu().setCustomFormationCallback((offset: { x: number, y: number, z: number }) => {
getUnitsManager().selectedUnitsFollowUnit(this.ID, offset);
@@ -657,18 +667,18 @@ export class Unit extends CustomMarker {
element.querySelector(".unit")?.toggleAttribute("data-is-dead", !this.getBaseData().alive);
/* Set current unit state */
if (this.getMissionData().flags.Human) // Unit is human
if (this.getMissionData().flags.Human) // Unit is human
element.querySelector(".unit")?.setAttribute("data-state", "human");
else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus)
else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus)
element.querySelector(".unit")?.setAttribute("data-state", "dcs");
else // Unit is under Olympus control
else // Unit is under Olympus control
element.querySelector(".unit")?.setAttribute("data-state", this.getTaskData().currentState.toLowerCase());
/* Set altitude and speed */
if (element.querySelector(".unit-altitude"))
(<HTMLElement>element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 100));
if (element.querySelector(".unit-speed"))
(<HTMLElement>element.querySelector(".unit-speed")).innerHTML = String(Math.floor(this.getFlightData().speed * 1.94384));
(<HTMLElement>element.querySelector(".unit-speed")).innerText = String(Math.floor(this.getFlightData().speed * 1.94384));
/* Rotate elements according to heading */
element.querySelectorAll("[data-rotate-to-heading]").forEach(el => {
@@ -791,16 +801,17 @@ export class Unit extends CustomMarker {
}
export class AirUnit extends Unit {
getActiveMarkerElements() {
getIconOptions() {
return {
state: true,
vvi: true,
hotgroup: true,
unitIcon: true,
shortLabel: true,
fuel: true,
ammo: true,
summary: true
showState: true,
showVvi: true,
showHotgroup: true,
showUnitIcon: true,
showShortLabel: true,
showFuel: true,
showAmmo: true,
showSummary: true,
rotateToHeading: false
};
}
}
@@ -813,6 +824,10 @@ export class Aircraft extends AirUnit {
getMarkerCategory() {
return "aircraft";
}
getDatabase(): UnitDatabase | null {
return aircraftDatabase;
}
}
export class Helicopter extends AirUnit {
@@ -830,16 +845,17 @@ export class GroundUnit extends Unit {
super(ID, data);
}
getActiveMarkerElements() {
getIconOptions() {
return {
state: true,
vvi: false,
hotgroup: true,
unitIcon: true,
shortLabel: true,
fuel: false,
ammo: false,
summary: false
showState: true,
showVvi: false,
showHotgroup: true,
showUnitIcon: true,
showShortLabel: true,
showFuel: false,
showAmmo: false,
showSummary: false,
rotateToHeading: false
};
}
@@ -849,6 +865,10 @@ export class GroundUnit extends Unit {
var markerCategory = (role === "SAM") ? "groundunit-sam" : "groundunit-other";
return markerCategory;
}
getDatabase(): UnitDatabase | null {
return groundUnitsDatabase;
}
}
export class NavyUnit extends Unit {
@@ -856,16 +876,17 @@ export class NavyUnit extends Unit {
super(ID, data);
}
getActiveMarkerElements() {
getIconOptions() {
return {
state: true,
vvi: false,
hotgroup: true,
unitIcon: true,
shortLabel: true,
fuel: false,
ammo: false,
summary: false
showState: true,
showVvi: false,
showHotgroup: true,
showUnitIcon: true,
showShortLabel: true,
showFuel: false,
showAmmo: false,
showSummary: false,
rotateToHeading: false
};
}
@@ -879,6 +900,20 @@ export class Weapon extends Unit {
super(ID, data);
this.setSelectable(false);
}
getIconOptions() {
return {
showState: false,
showVvi: false,
showHotgroup: false,
showUnitIcon: true,
showShortLabel: false,
showFuel: false,
showAmmo: false,
showSummary: false,
rotateToHeading: true
};
}
}
export class Missile extends Weapon {

View File

@@ -1,21 +1,16 @@
export class UnitDatabase {
blueprints: {[key: string]: UnitBlueprint} = {};
blueprints: { [key: string]: UnitBlueprint } = {};
constructor()
{
constructor() {
}
/* Returns a list of all possible roles in a database */
getRoles()
{
getRoles() {
var roles: string[] = [];
for (let unit in this.blueprints)
{
for (let loadout of this.blueprints[unit].loadouts)
{
for (let role of loadout.roles)
{
for (let unit in this.blueprints) {
for (let loadout of this.blueprints[unit].loadouts) {
for (let role of loadout.roles) {
if (role !== "" && !roles.includes(role))
roles.push(role);
}
@@ -25,18 +20,15 @@ export class UnitDatabase {
}
/* Gets a specific blueprint by name */
getByName(name: string)
{
getByName(name: string) {
if (name in this.blueprints)
return this.blueprints[name];
return null;
}
/* Gets a specific blueprint by label */
getByLabel(label: string)
{
for (let unit in this.blueprints)
{
getByLabel(label: string) {
for (let unit in this.blueprints) {
if (this.blueprints[unit].label === label)
return this.blueprints[unit];
}
@@ -44,15 +36,11 @@ export class UnitDatabase {
}
/* Get all blueprints by role */
getByRole(role: string)
{
getByRole(role: string) {
var units = [];
for (let unit in this.blueprints)
{
for (let loadout of this.blueprints[unit].loadouts)
{
if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase()))
{
for (let unit in this.blueprints) {
for (let loadout of this.blueprints[unit].loadouts) {
if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) {
units.push(this.blueprints[unit])
break;
}
@@ -62,13 +50,10 @@ export class UnitDatabase {
}
/* Get the names of all the loadouts for a specific unit and for a specific role */
getLoadoutNamesByRole(name: string, role: string)
{
getLoadoutNamesByRole(name: string, role: string) {
var loadouts = [];
for (let loadout of this.blueprints[name].loadouts)
{
if (loadout.roles.includes(role) || loadout.roles.includes(""))
{
for (let loadout of this.blueprints[name].loadouts) {
if (loadout.roles.includes(role) || loadout.roles.includes("")) {
loadouts.push(loadout.name)
}
}
@@ -76,10 +61,8 @@ export class UnitDatabase {
}
/* Get the loadout content from the unit name and loadout name */
getLoadoutByName(name: string, loadoutName: string)
{
for (let loadout of this.blueprints[name].loadouts)
{
getLoadoutByName(name: string, loadoutName: string) {
for (let loadout of this.blueprints[name].loadouts) {
if (loadout.name === loadoutName)
return loadout;
}

View File

@@ -47,7 +47,7 @@ export class UnitsManager {
}
getUnitsByHotgroup(hotgroup: number) {
return Object.values(this.#units).filter((unit: Unit) => {return unit.getBaseData().alive && unit.getHotgroup() == hotgroup});
return Object.values(this.#units).filter((unit: Unit) => { return unit.getBaseData().alive && unit.getHotgroup() == hotgroup });
}
addUnit(ID: number, data: UnitData) {
@@ -88,10 +88,8 @@ export class UnitsManager {
});
}
setHiddenType(key: string, value: boolean)
{
if (value)
{
setHiddenType(key: string, value: boolean) {
if (value) {
if (this.#hiddenTypes.includes(key))
delete this.#hiddenTypes[this.#hiddenTypes.indexOf(key)];
}
@@ -100,8 +98,7 @@ export class UnitsManager {
Object.values(this.getUnits()).forEach((unit: Unit) => unit.updateVisibility());
}
getHiddenTypes()
{
getHiddenTypes() {
return this.#hiddenTypes;
}
@@ -123,7 +120,7 @@ export class UnitsManager {
}
}
getSelectedUnits(options?: {excludeHumans?: boolean}) {
getSelectedUnits(options?: { excludeHumans?: boolean }) {
var selectedUnits = [];
for (let ID in this.#units) {
if (this.#units[ID].getSelected()) {
@@ -132,7 +129,7 @@ export class UnitsManager {
}
if (options) {
if (options.excludeHumans)
selectedUnits = selectedUnits.filter((unit: Unit) => {return !unit.getMissionData().flags.Human});
selectedUnits = selectedUnits.filter((unit: Unit) => { return !unit.getMissionData().flags.Human });
}
return selectedUnits;
}
@@ -190,14 +187,14 @@ export class UnitsManager {
/*********************** Actions on selected units ************************/
selectedUnitsAddDestination(latlng: L.LatLng, mantainRelativePosition: boolean, rotation: number) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
/* Compute the destination for each unit. If mantainRelativePosition is true, compute the destination so to hold the relative distances */
var unitDestinations: {[key: number]: LatLng} = {};
var unitDestinations: { [key: number]: LatLng } = {};
if (mantainRelativePosition)
unitDestinations = this.selectedUnitsComputeGroupDestination(latlng, rotation);
else
selectedUnits.forEach((unit: Unit) => {unitDestinations[unit.ID] = latlng});
selectedUnits.forEach((unit: Unit) => { unitDestinations[unit.ID] = latlng });
for (let idx in selectedUnits) {
const unit = selectedUnits[idx];
@@ -206,7 +203,7 @@ export class UnitsManager {
const leader = this.getUnitByID(unit.getFormationData().leaderID)
if (leader && leader.getSelected())
leader.addDestination(latlng);
else
else
unit.addDestination(latlng);
}
else {
@@ -219,7 +216,7 @@ export class UnitsManager {
}
selectedUnitsClearDestinations() {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
const unit = selectedUnits[idx];
if (unit.getTaskData().currentState === "Follow") {
@@ -235,7 +232,7 @@ export class UnitsManager {
}
selectedUnitsLandAt(latlng: LatLng) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].landAt(latlng);
}
@@ -243,21 +240,21 @@ export class UnitsManager {
}
selectedUnitsChangeSpeed(speedChange: string) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].changeSpeed(speedChange);
}
}
selectedUnitsChangeAltitude(altitudeChange: string) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].changeAltitude(altitudeChange);
}
}
selectedUnitsSetSpeed(speed: number) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].setSpeed(speed);
}
@@ -265,7 +262,7 @@ export class UnitsManager {
}
selectedUnitsSetAltitude(altitude: number) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].setAltitude(altitude);
}
@@ -273,7 +270,7 @@ export class UnitsManager {
}
selectedUnitsSetROE(ROE: string) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].setROE(ROE);
}
@@ -281,7 +278,7 @@ export class UnitsManager {
}
selectedUnitsSetReactionToThreat(reactionToThreat: string) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].setReactionToThreat(reactionToThreat);
}
@@ -289,7 +286,7 @@ export class UnitsManager {
}
selectedUnitsSetEmissionsCountermeasures(emissionCountermeasure: string) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].setEmissionsCountermeasures(emissionCountermeasure);
}
@@ -298,7 +295,7 @@ export class UnitsManager {
selectedUnitsAttackUnit(ID: number) {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].attackUnit(ID);
}
@@ -314,7 +311,7 @@ export class UnitsManager {
}
selectedUnitsRefuel() {
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
for (let idx in selectedUnits) {
selectedUnits[idx].refuel();
}
@@ -328,15 +325,15 @@ export class UnitsManager {
// Y: top-bottom, positive top
// Z: left-right, positive right
offset = { "x": 0, "y": 0, "z": 0 };
if (formation === "Trail") { offset.x = -50; offset.y = -30; offset.z = 0; }
else if (formation === "Echelon (LH)") { offset.x = -50; offset.y = -10; offset.z = -50; }
else if (formation === "Echelon (RH)") { offset.x = -50; offset.y = -10; offset.z = 50; }
else if (formation === "Line abreast (RH)") { offset.x = 0; offset.y = 0; offset.z = 50; }
else if (formation === "Line abreast (LH)") { offset.x = 0; offset.y = 0; offset.z = -50; }
else if (formation === "Front") { offset.x = 100; offset.y = 0; offset.z = 0; }
if (formation === "trail") { offset.x = -50; offset.y = -30; offset.z = 0; }
else if (formation === "echelon-lh") { offset.x = -50; offset.y = -10; offset.z = -50; }
else if (formation === "echelon-rh") { offset.x = -50; offset.y = -10; offset.z = 50; }
else if (formation === "line-abreast-rh") { offset.x = 0; offset.y = 0; offset.z = 50; }
else if (formation === "line-abreast-lh") { offset.x = 0; offset.y = 0; offset.z = -50; }
else if (formation === "front") { offset.x = 100; offset.y = 0; offset.z = 0; }
else offset = undefined;
}
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
var count = 1;
var xr = 0; var yr = 1; var zr = -1;
var layer = 1;
@@ -347,7 +344,7 @@ export class UnitsManager {
unit.followUnit(ID, { "x": offset.x * count, "y": offset.y * count, "z": offset.z * count });
else {
/* More complex formations with variable offsets */
if (formation === "Diamond") {
if (formation === "diamond") {
var xl = xr * Math.cos(Math.PI / 4) - yr * Math.sin(Math.PI / 4);
var yl = xr * Math.sin(Math.PI / 4) + yr * Math.cos(Math.PI / 4);
unit.followUnit(ID, { "x": -yl * 50, "y": zr * 10, "z": xl * 50 });
@@ -364,14 +361,12 @@ export class UnitsManager {
this.#showActionMessage(selectedUnits, `following unit ${this.getUnitByID(ID)?.getBaseData().unitName}`);
}
selectedUnitsSetHotgroup(hotgroup: number)
{
selectedUnitsSetHotgroup(hotgroup: number) {
this.getUnitsByHotgroup(hotgroup).forEach((unit: Unit) => unit.setHotgroup(null));
this.selectedUnitsAddToHotgroup(hotgroup);
}
selectedUnitsAddToHotgroup(hotgroup: number)
{
selectedUnitsAddToHotgroup(hotgroup: number) {
var selectedUnits = this.getSelectedUnits();
for (let idx in selectedUnits) {
selectedUnits[idx].setHotgroup(hotgroup);
@@ -380,11 +375,10 @@ export class UnitsManager {
getHotgroupPanel().refreshHotgroups();
}
selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number)
{
var selectedUnits = this.getSelectedUnits({excludeHumans: true});
selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number) {
var selectedUnits = this.getSelectedUnits({ excludeHumans: true });
/* Compute the center of the group */
var center = {x: 0, y: 0};
var center = { x: 0, y: 0 };
selectedUnits.forEach((unit: Unit) => {
var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude);
center.x += mercator.x / selectedUnits.length;
@@ -392,20 +386,19 @@ export class UnitsManager {
});
/* Compute the distances from the center of the group */
var unitDestinations: {[key: number]: LatLng} = {};
var unitDestinations: { [key: number]: LatLng } = {};
selectedUnits.forEach((unit: Unit) => {
var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude);
var distancesFromCenter = {dx: mercator.x - center.x, dy: mercator.y - center.y};
var distancesFromCenter = { dx: mercator.x - center.x, dy: mercator.y - center.y };
/* Rotate the distance according to the group rotation */
var rotatedDistancesFromCenter: {dx: number, dy: number} = {dx: 0, dy: 0};
var rotatedDistancesFromCenter: { dx: number, dy: number } = { dx: 0, dy: 0 };
rotatedDistancesFromCenter.dx = distancesFromCenter.dx * Math.cos(deg2rad(rotation)) - distancesFromCenter.dy * Math.sin(deg2rad(rotation));
rotatedDistancesFromCenter.dy = distancesFromCenter.dx * Math.sin(deg2rad(rotation)) + distancesFromCenter.dy * Math.cos(deg2rad(rotation));
/* Compute the final position of the unit */
var destMercator = latLngToMercator(latlng.lat, latlng.lng); // Convert destination point to mercator
var unitMercator = {x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy}; // Compute final position of this unit in mercator coordinates
var unitMercator = { x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy }; // Compute final position of this unit in mercator coordinates
var unitLatLng = mercatorToLatLng(unitMercator.x, unitMercator.y);
unitDestinations[unit.ID] = new LatLng(unitLatLng.lat, unitLatLng.lng);
});