Merge branch 'main' into 343-add-ability-to-select-unit-nation-and-livery

This commit is contained in:
Pax1601
2023-08-10 17:52:43 +02:00
33 changed files with 13188 additions and 12707 deletions

View File

@@ -13,7 +13,7 @@ export const RWR = 16;
export const DLINK = 32;
export const states: string[] = ["none", "idle", "reach-destination", "attack", "follow", "land", "refuel", "AWACS", "tanker", "bomb-point", "carpet-bomb", "bomb-building", "fire-at-area"];
export const ROEs: string[] = ["free", "designated", "return", "hold"];
export const ROEs: string[] = ["free", "designated", "", "return", "hold"];
export const reactionsToThreat: string[] = ["none", "manoeuvre", "passive", "evade"];
export const emissionsCountermeasures: string[] = ["silent", "attack", "defend", "free"];

View File

@@ -205,11 +205,13 @@ function setupEvents() {
document.querySelectorAll("[inject-svg]").forEach((el: Element) => {
var img = el as HTMLImageElement;
var isLoaded = img.complete && img.naturalHeight !== 0;
var isLoaded = img.complete;
if (isLoaded)
SVGInjector(img);
else
img.onload = () => SVGInjector(img);
img.addEventListener("load", () => {
SVGInjector(img);
});
})
}

View File

@@ -1,5 +1,5 @@
import * as L from "leaflet"
import { getUnitsManager } from "..";
import { getMissionHandler, getUnitsManager } from "..";
import { BoxSelect } from "./boxselect";
import { MapContextMenu } from "../controls/mapcontextmenu";
import { UnitContextMenu } from "../controls/unitcontextmenu";
@@ -117,11 +117,20 @@ export class Map extends L.Map {
Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility());
});
document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => {
document.addEventListener("toggleMarkerVisibility", (ev: CustomEventInit) => {
const el = ev.detail._element;
el?.classList.toggle("off");
ev.detail.types.forEach((type: string) => getUnitsManager().setHiddenType(type, !el?.classList.contains("off")));
Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility());
if (ev.detail.types.includes("airbase")) {
Object.values(getMissionHandler().getAirbases()).forEach((airbase: Airbase) => {
if (el?.classList.contains("off"))
airbase.removeFrom(this);
else
airbase.addTo(this);
})
}
});
@@ -150,7 +159,9 @@ 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`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"types": "${visibilityControlsTypes[index]}"}`);
var typesArrayString = `"${visibilityControlsTypes[index][0]}"`;
visibilityControlsTypes[index].forEach((type: string, idx: number) => {if (idx > 0) typesArrayString = `${typesArrayString}, "${type}"`});
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleMarkerVisibility", `{"types": [${typesArrayString}]}`);
});
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);

View File

@@ -38,6 +38,7 @@ export class Airbase extends CustomMarker
img.onload = () => SVGInjector(img);
el.appendChild(img);
this.getElement()?.appendChild(el);
el.dataset.coalition = this.#coalition;
}
setCoalition(coalition: string)

View File

@@ -1,3 +1,4 @@
import { getMouseInfoPanel } from "..";
import { Panel } from "./panel";
export class LogPanel extends Panel {
@@ -23,8 +24,21 @@ export class LogPanel extends Panel {
if (scrollEl) {
scrollEl.addEventListener("scroll", () => {
this.#scrolledDown = Math.abs(scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight) < 1
})
});
}
window.addEventListener("resize", () => {
this.#calculateHeight();
});
const mouseInfoPanel = getMouseInfoPanel();
new ResizeObserver(() => this.#calculateHeight()).observe(mouseInfoPanel.getElement())
}
show() {
super.show();
this.#calculateHeight();
}
appendLogs(logs: {[key: string]: string}) {
@@ -68,4 +82,9 @@ export class LogPanel extends Panel {
scrollEl.scrollTop = scrollEl.scrollHeight - scrollEl.clientHeight;
}
}
#calculateHeight() {
const mouseInfoPanel = getMouseInfoPanel();
this.getElement().style.height = `${mouseInfoPanel.getElement().offsetTop - this.getElement().offsetTop - 10}px`;
}
}

View File

@@ -39,7 +39,7 @@ export class UnitControlPanel extends Panel {
// Reversing the ROEs so that the least "aggressive" option is always on the left
this.#optionButtons["ROE"] = ROEs.slice(0).reverse().map((option: string, index: number) => {
return this.#createOptionButton(option, `roe/${option.toLowerCase()}.svg`, ROEDescriptions.slice(0).reverse()[index], () => { getUnitsManager().selectedUnitsSetROE(option); });
});
}).filter((button: HTMLButtonElement, index: number) => {return ROEs[index] !== "";});
this.#optionButtons["reactionToThreat"] = reactionsToThreat.map((option: string, index: number) => {
return this.#createOptionButton(option, `threat/${option.toLowerCase()}.svg`, reactionsToThreatDescriptions[index],() => { getUnitsManager().selectedUnitsSetReactionToThreat(option); });

View File

@@ -419,7 +419,7 @@ export function startUpdate() {
getWeapons((buffer: ArrayBuffer) => {
var time = getWeaponsManager()?.update(buffer);
return time;
}, false);
}, true);
}
}, 5000);
}

View File

@@ -1,5 +1,5 @@
import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map, Point } from 'leaflet';
import { getMap, getMissionHandler, getUnitsManager } from '..';
import { getMap, getMissionHandler, getUnitsManager, getWeaponsManager } from '..';
import { enumToCoalition, enumToEmissioNCountermeasure, getMarkerCategoryByName, enumToROE, enumToReactionToThreat, enumToState, getUnitDatabaseByCategory, mToFt, msToKnots, rad2deg, bearing, deg2rad } from '../other/utils';
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures, setSpeedType, setAltitudeType, setOnOff, setFollowRoads, bombPoint, carpetBomb, bombBuilding, fireAtArea } from '../server/server';
import { CustomMarker } from '../map/custommarker';
@@ -11,6 +11,7 @@ import { Ammo, Contact, GeneralSettings, Offset, Radio, TACAN, ObjectIconOptions
import { DataExtractor } from '../server/dataextractor';
import { groundUnitDatabase } from './groundunitdatabase';
import { navyUnitDatabase } from './navyunitdatabase';
import { Weapon } from '../weapon/weapon';
var pathIcon = new Icon({
iconUrl: '/resources/theme/images/markers/marker-icon.png',
@@ -153,7 +154,7 @@ export class Unit extends CustomMarker {
this.on('click', (e) => this.#onClick(e));
this.on('dblclick', (e) => this.#onDoubleClick(e));
this.on('contextmenu', (e) => this.#onContextMenu(e));
this.on('mouseover', () => { this.setHighlighted(true); })
this.on('mouseover', () => { if (this.belongsToCommandedCoalition()) this.setHighlighted(true); })
this.on('mouseout', () => { this.setHighlighted(false); })
getMap().on("zoomend", () => {this.#onZoom();})
@@ -540,7 +541,7 @@ export class Unit extends CustomMarker {
/* Force a redraw of the unit to reflect the new status of the detection methods */
this.setHidden(true);
this.#detectionMethods = newDetectionMethods;
this.updateVisibility();
this.#updateMarker();
}
}
}
@@ -986,19 +987,25 @@ export class Unit extends CustomMarker {
if (getMap().getVisibilityOptions()[SHOW_CONTACT_LINES]) {
for (let index in this.#contacts) {
var contactData = this.#contacts[index];
var contact = getUnitsManager().getUnitByID(contactData.ID);
var contact: Unit | Weapon | null;
if (contactData.ID in getUnitsManager().getUnits())
contact = getUnitsManager().getUnitByID(contactData.ID);
else
contact = getWeaponsManager().getWeaponByID(contactData.ID);
if (contact != null && contact.getAlive()) {
var startLatLng = new LatLng(this.#position.lat, this.#position.lng);
var endLatLng: LatLng;
if (contactData.detectionMethod === RWR) {
var bearingToContact = bearing(this.#position.lat, this.#position.lng, contact.#position.lat, contact.#position.lng);
var bearingToContact = bearing(this.#position.lat, this.#position.lng, contact.getPosition().lat, contact.getPosition().lng);
var startXY = getMap().latLngToContainerPoint(startLatLng);
var endX = startXY.x + 80 * Math.sin(deg2rad(bearingToContact));
var endY = startXY.y - 80 * Math.cos(deg2rad(bearingToContact));
endLatLng = getMap().containerPointToLatLng(new Point(endX, endY));
}
else
endLatLng = new LatLng(contact.#position.lat, contact.#position.lng);
endLatLng = new LatLng(contact.getPosition().lat, contact.getPosition().lng);
var color;
if (contactData.detectionMethod === VISUAL || contactData.detectionMethod === OPTIC)

View File

@@ -1,5 +1,5 @@
import { LatLng, LatLngBounds } from "leaflet";
import { getHotgroupPanel, getInfoPopup, getMap, getMissionHandler, getUnitsManager } from "..";
import { getHotgroupPanel, getInfoPopup, getMap, getMissionHandler, getUnitsManager, getWeaponsManager } from "..";
import { Unit } from "./unit";
import { cloneUnit, deleteUnit, refreshAll, spawnAircrafts, spawnGroundUnits, spawnHelicopters, spawnNavyUnits } from "../server/server";
import { bearingAndDistanceToLatLng, deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils";
@@ -36,6 +36,8 @@ export class UnitsManager {
document.addEventListener('importFromFile', () => this.importFromFile());
document.addEventListener('contactsUpdated', (e: CustomEvent) => {this.#requestDetectionUpdate = true});
document.addEventListener('commandModeOptionsChanged', () => {Object.values(this.#units).forEach((unit: Unit) => unit.updateVisibility())});
document.addEventListener('selectedUnitsChangeSpeed', (e: any) => {this.selectedUnitsChangeSpeed(e.detail.type)});
document.addEventListener('selectedUnitsChangeAltitude', (e: any) => {this.selectedUnitsChangeAltitude(e.detail.type)});
}
getSelectableAircraft() {
@@ -95,11 +97,11 @@ export class UnitsManager {
if (this.#requestDetectionUpdate && getMissionHandler().getCommandModeOptions().commandMode != GAME_MASTER) {
/* Create a dictionary of empty detection methods arrays */
var detectionMethods: {[key: string]: number[]} = {};
for (let ID in this.#units) {
const unit = this.#units[ID];
for (let ID in this.#units)
detectionMethods[ID] = [];
}
for (let ID in getWeaponsManager().getWeapons())
detectionMethods[ID] = [];
/* Fill the array with the detection methods */
for (let ID in this.#units) {
const unit = this.#units[ID];
@@ -107,7 +109,7 @@ export class UnitsManager {
const contacts = unit.getContacts();
contacts.forEach((contact: Contact) => {
const contactID = contact.ID;
if (!(detectionMethods[contactID].includes(contact.detectionMethod)))
if (contactID in detectionMethods && !(detectionMethods[contactID].includes(contact.detectionMethod)))
detectionMethods[contactID]?.push(contact.detectionMethod);
})
}
@@ -116,7 +118,11 @@ export class UnitsManager {
/* Set the detection methods for every unit */
for (let ID in this.#units) {
const unit = this.#units[ID];
unit.setDetectionMethods(detectionMethods[ID]);
unit?.setDetectionMethods(detectionMethods[ID]);
}
for (let ID in getWeaponsManager().getWeapons()) {
const weapon = getWeaponsManager().getWeaponByID(parseInt(ID));
weapon?.setDetectionMethods(detectionMethods[ID]);
}
this.#requestDetectionUpdate = false;

View File

@@ -202,7 +202,7 @@ export class Weapon extends CustomMarker {
/* Force a redraw of the unit to reflect the new status of the detection methods */
this.setHidden(true);
this.#detectionMethods = newDetectionMethods;
this.updateVisibility();
this.#updateMarker();
}
}
}

View File

@@ -6,13 +6,11 @@ import { Contact } from "../@types/unit";
export class WeaponsManager {
#weapons: { [ID: number]: Weapon };
#requestDetectionUpdate: boolean = false;
constructor() {
this.#weapons = {};
document.addEventListener("commandModeOptionsChanged", () => {Object.values(this.#weapons).forEach((weapon: Weapon) => weapon.updateVisibility())});
document.addEventListener('contactsUpdated', (e: CustomEvent) => {this.#requestDetectionUpdate = true});
}
getWeapons() {
@@ -54,16 +52,6 @@ export class WeaponsManager {
}
this.#weapons[ID]?.setData(dataExtractor);
}
if (this.#requestDetectionUpdate && getMissionHandler().getCommandModeOptions().commandMode != GAME_MASTER) {
for (let ID in this.#weapons) {
var weapon = this.#weapons[ID];
if (!weapon.belongsToCommandedCoalition())
weapon.setDetectionMethods(this.getWeaponDetectedMethods(weapon));
}
this.#requestDetectionUpdate = false;
}
return updateTime;
}