diff --git a/client/public/uikit.html b/client/public/uikit.html index 04fe1ca3..49b900d1 100644 --- a/client/public/uikit.html +++ b/client/public/uikit.html @@ -2,6 +2,9 @@ Olympus UI Kit + + + diff --git a/client/src/@types/server.d.ts b/client/src/@types/server.d.ts new file mode 100644 index 00000000..4eb5c8ba --- /dev/null +++ b/client/src/@types/server.d.ts @@ -0,0 +1,6 @@ +interface ServerData { + units: {[key: string]: UnitData}, + bullseye: any, //TODO + airbases: any, //TODO + logs: any //TODO +} \ No newline at end of file diff --git a/client/src/@types/unit.d.ts b/client/src/@types/unit.d.ts new file mode 100644 index 00000000..0f7e9be7 --- /dev/null +++ b/client/src/@types/unit.d.ts @@ -0,0 +1,52 @@ +interface FlightData { + latitude: number; + longitude: number; + altitude: number; + heading: number; + speed: number; +} + +interface MissionData { + fuel: number; + flags: any; + ammo: any; + targets: any; + hasTask: boolean; + coalition: string; +} + +interface FormationData { + formation: string; + isLeader: boolean; + isWingman: boolean; + leaderID: number; + wingmen: Unit[]; + wingmenIDs: number[]; +} + +interface TaskData { + currentTask: string; + activePath: any; + targetSpeed: number; + targetAltitude: number; +} + +interface OptionsData { + ROE: string; + reactionToThreat: string; +} + +interface UnitData { + AI: boolean; + name: string; + unitName: string; + groupName: string; + alive: boolean; + category: string; + + flightData: FlightData; + missionData: MissionData; + formationData: FormationData; + taskData: TaskData; + optionsData: OptionsData; +} diff --git a/client/src/dcs/dcs.ts b/client/src/dcs/dcs.ts deleted file mode 100644 index 23688cf5..00000000 --- a/client/src/dcs/dcs.ts +++ /dev/null @@ -1,260 +0,0 @@ -import * as L from 'leaflet' -import { getUnitsManager, setConnected } from '..'; -import { ConvertDDToDMS } from '../other/utils'; - -/* Edit here to change server address */ -var RESTaddress = "http://localhost:30000/restdemo"; - -export function getDataFromDCS(callback: CallableFunction) { - /* Request the updated unit data from the server */ - var xmlHttp = new XMLHttpRequest(); - xmlHttp.open("GET", RESTaddress, true); - - xmlHttp.onload = function (e) { - var data = JSON.parse(xmlHttp.responseText); - callback(data); - setConnected(true); - }; - - xmlHttp.onerror = function () { - console.error("An error occurred during the XMLHttpRequest"); - setConnected(false); - }; - xmlHttp.send(null); -} - -export function addDestination(ID: number, path: any) { - var xhr = new XMLHttpRequest(); - xhr.open("PUT", RESTaddress); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.onreadystatechange = () => { }; - - var command = { "ID": ID, "path": path } - var data = { "setPath": command } - - xhr.send(JSON.stringify(data)); -} - -export function spawnSmoke(color: string, latlng: L.LatLng) { - var xhr = new XMLHttpRequest(); - xhr.open("PUT", RESTaddress); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.onreadystatechange = () => { - if (xhr.readyState === 4) { - //console.log("Added " + color + " smoke at " + ConvertDDToDMS(latlng.lat, false) + " " + ConvertDDToDMS(latlng.lng, true)); - } - }; - - 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) { - var xhr = new XMLHttpRequest(); - xhr.open("PUT", RESTaddress); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.onreadystatechange = () => { - if (xhr.readyState === 4) { - //console.log("Added " + coalition + " " + type + " at " + ConvertDDToDMS(latlng.lat, false) + " " + ConvertDDToDMS(latlng.lng, true)); - } - }; - - 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: string | null = null, airbaseName: string | null = null) { - var xhr = new XMLHttpRequest(); - xhr.open("PUT", RESTaddress); - xhr.setRequestHeader("Content-Type", "application/json"); - xhr.onreadystatechange = () => { - if (xhr.readyState === 4) { - //console.log("Added " + coalition + " " + type + " at " + ConvertDDToDMS(latlng.lat, false) + " " + ConvertDDToDMS(latlng.lng, true)); - } - }; - - 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) { - 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); - } - }; - - var command = { "ID": ID, "targetID": targetID }; - var data = { "attackUnit": command } - - xhr.send(JSON.stringify(data)); -} - -export function cloneUnit(ID: number, latlng: L.LatLng) { - 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"); - } - }; - - var command = { "ID": ID, "location": latlng }; - var data = { "cloneUnit": command } - - xhr.send(JSON.stringify(data)); -} - -export function deleteUnit(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"); - } - }; - - var command = { "ID": ID}; - var data = { "deleteUnit": command } - - xhr.send(JSON.stringify(data)); -} - -export function landAt(ID: number, latlng: L.LatLng) { - 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"); - } - }; - - var command = { "ID": ID, "location": latlng }; - var data = { "landAt": 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 setSpeed(ID: number, speed: number) { - 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, "speed": speed} - var data = {"setSpeed": 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)); -} - -export function setAltitude(ID: number, altitude: number) { - 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, "altitude": altitude} - var data = {"setAltitude": command} - - xhr.send(JSON.stringify(data)); -} - -export function createFormation(ID: number, isLeader: boolean, wingmenIDs: number[]) { - 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 + " created formation with: " + wingmenIDs); - } - }; - - var command = {"ID": ID, "wingmenIDs": wingmenIDs, "isLeader": isLeader} - var data = {"setLeader": command} - - xhr.send(JSON.stringify(data)); -} - -export function setROE(ID: number, ROE: 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, "ROE": ROE} - var data = {"setROE": command} - - xhr.send(JSON.stringify(data)); -} - -export function setReactionToThreat(ID: number, reactionToThreat: 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, "reactionToThreat": reactionToThreat} - var data = {"setReactionToThreat": command} - - xhr.send(JSON.stringify(data)); -} \ No newline at end of file diff --git a/client/src/index.ts b/client/src/index.ts index 2cee5f36..f78464c7 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -1,5 +1,5 @@ import { Map } from "./map/map" -import { getDataFromDCS } from "./dcs/dcs" +import { getDataFromDCS } from "./server/server" import { UnitsManager } from "./units/unitsmanager"; import { UnitInfoPanel } from "./panels/unitinfopanel"; import { ContextMenu } from "./controls/contextmenu"; @@ -39,9 +39,6 @@ var aicHelpButton: Button; var atc: ATC; var atcToggleButton: Button; -var altitudeSlider: Slider; -var airspeedSlider: Slider; - var connected: boolean; var activeCoalition: string; @@ -132,7 +129,7 @@ function requestUpdate() { connectionStatusPanel.update(getConnected()); } -export function update(data: JSON) { +export function update(data: ServerData) { unitsManager.update(data); missionData.update(data); logPanel.update(data); @@ -182,9 +179,4 @@ export function getConnected() { return connected; } -export function getUnitControlSliders() { - return {altitude: altitudeSlider, airspeed: airspeedSlider} -} - - window.onload = setup; \ No newline at end of file diff --git a/client/src/map/map.ts b/client/src/map/map.ts index 710123c9..966e6404 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -1,9 +1,9 @@ import * as L from "leaflet" import { getContextMenu, getUnitsManager, getActiveCoalition, getMouseInfoPanel } from ".."; -import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../dcs/dcs"; +import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../server/server"; import { bearing, distance, zeroAppend } from "../other/utils"; -import { getAircraftLabelsByRole, getLoadoutsByName, getLoadoutNamesByRole, getAircraftNameByLabel } from "../units/aircraftdatabase"; -import { unitTypes } from "../units/unitTypes"; +import { aircraftDatabase } from "../units/aircraftdatabase"; +import { unitTypes } from "../units/unittypes"; import { BoxSelect } from "./boxselect"; L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect); @@ -238,7 +238,7 @@ export class Map extends L.Map { var selectedUnits = getUnitsManager().getSelectedUnits(); if (selectedUnits && selectedUnits.length == 1) { - selectedUnitPosition = new L.LatLng(selectedUnits[0].latitude, selectedUnits[0].longitude); + selectedUnitPosition = new L.LatLng(selectedUnits[0].getFlightData().latitude, selectedUnits[0].getFlightData().longitude); } getMouseInfoPanel().update(e.latlng, this.#measurePoint, selectedUnitPosition); @@ -309,10 +309,10 @@ export class Map extends L.Map { /* Show unit selection for air units */ #selectAircraft(e: SpawnEvent, role: string) { this.hideContextMenu(); - var options = getAircraftLabelsByRole(role); + var options = aircraftDatabase.getLabelsByRole(role); this.showContextMenu(e, "Select aircraft", options, (label: string) => { this.hideContextMenu(); - var name = getAircraftNameByLabel(label); + var name = aircraftDatabase.getNameByLabel(label); if (name != null) this.#unitSelectPayload(e, name, role); }, true); @@ -321,14 +321,14 @@ export class Map extends L.Map { /* Show weapon selection for air units */ #unitSelectPayload(e: SpawnEvent, unitType: string, role: string) { this.hideContextMenu(); - var options = getLoadoutNamesByRole(unitType, role); + var options = aircraftDatabase.getLoadoutNamesByRole(unitType, role); //options = payloadNames[unitType] if (options != undefined && options.length > 0) { options.sort(); this.showContextMenu({x: e.x, y: e.y, latlng: e.latlng}, "Select loadout", options, (loadoutName: string) => { this.hideContextMenu(); - var loadout = getLoadoutsByName(unitType, loadoutName); - spawnAircraft(unitType, e.latlng, getActiveCoalition(), loadout.code, e.airbaseName); + var loadout = aircraftDatabase.getLoadoutsByName(unitType, loadoutName); + spawnAircraft(unitType, e.latlng, getActiveCoalition(), loadout != null? loadout.code: "", e.airbaseName); }, true); } else { diff --git a/client/src/missiondata/missiondata.ts b/client/src/missiondata/missiondata.ts index aedb2a76..c1a018a3 100644 --- a/client/src/missiondata/missiondata.ts +++ b/client/src/missiondata/missiondata.ts @@ -27,7 +27,7 @@ export class MissionData this.#airbasesMarkers = {}; } - update(data: any) + update(data: ServerData) { this.#bullseyes = data.bullseye; this.#airbases = data.airbases; diff --git a/client/src/panels/unitcontrolpanel.ts b/client/src/panels/unitcontrolpanel.ts index 9ffe60bc..4c7e2b07 100644 --- a/client/src/panels/unitcontrolpanel.ts +++ b/client/src/panels/unitcontrolpanel.ts @@ -147,7 +147,7 @@ export class UnitControlPanel extends Panel { for (let unit of units) { this.#addUnitButton(unit, this.#selectedUnitsContainer); - if (unit.isLeader) + if (unit.getFormationData().isLeader) for (let wingman of unit.getWingmen()) this.#addUnitButton(wingman, this.#selectedUnitsContainer); } @@ -160,16 +160,16 @@ export class UnitControlPanel extends Panel { /* Unit name (actually type, but DCS calls it name for some reason) */ var nameDiv = document.createElement("div"); nameDiv.classList.add("ol-rounded-container-small"); - if (unit.name.length >= 7) - nameDiv.innerHTML = `${unit.name.substring(0, 4)} ...`; + if (unit.getData().name.length >= 7) + nameDiv.innerHTML = `${unit.getData().name.substring(0, 4)} ...`; else - nameDiv.innerHTML = `${unit.name}`; + nameDiv.innerHTML = `${unit.getData().name}`; /* Unit icon */ var icon = document.createElement("img"); - if (unit.isLeader) + if (unit.getFormationData().isLeader) icon.src = "images/icons/formation.png" - else if (unit.isWingman) + else if (unit.getFormationData().isWingman) { var wingmen = unit.getLeader()?.getWingmen(); if (wingmen && wingmen.lastIndexOf(unit) == wingmen.length - 1) @@ -181,7 +181,7 @@ export class UnitControlPanel extends Panel { else icon.src = "images/icons/singleton.png" - el.innerHTML = unit.unitName; + el.innerHTML = unit.getData().unitName; el.prepend(nameDiv); @@ -195,12 +195,12 @@ export class UnitControlPanel extends Panel { el.classList.add("not-selected") /* Set background color */ - el.classList.toggle("red", unit.coalitionID == 1); - icon.classList.toggle("red", unit.coalitionID == 1); - el.classList.toggle("blue", unit.coalitionID == 2); - icon.classList.toggle("blue", unit.coalitionID == 2); - el.classList.toggle("neutral", unit.coalitionID == 0); - icon.classList.toggle("neutral", unit.coalitionID == 0); + el.classList.toggle("red", unit.getMissionData().coalition === "red"); + icon.classList.toggle("red", unit.getMissionData().coalition === "red"); + el.classList.toggle("blue", unit.getMissionData().coalition === "blue"); + icon.classList.toggle("blue", unit.getMissionData().coalition === "blue"); + el.classList.toggle("neutral", unit.getMissionData().coalition === "neutral"); + icon.classList.toggle("neutral", unit.getMissionData().coalition === "neutral"); el.addEventListener("click", () => getUnitsManager().selectUnit(unit.ID)); container.appendChild(el); @@ -275,14 +275,14 @@ export class UnitControlPanel extends Panel { var leaderFound = false; for (let unit of units) { - if (unit.isLeader) + if (unit.getFormationData().isLeader) { if (leaderFound) return false else leaderFound = true; } - if (!unit.isLeader) + if (!unit.getFormationData().isLeader) return false } return true @@ -291,7 +291,7 @@ export class UnitControlPanel extends Panel { #checkUnitsAlreadyInFormation(units: Unit[]) { for (let unit of units) - if (unit.isLeader) + if (unit.getFormationData().isLeader) return true return false } @@ -301,10 +301,10 @@ export class UnitControlPanel extends Panel { var airspeed = null; for (let unit of units) { - if (unit.targetSpeed != airspeed && airspeed != null) + if (unit.getTaskData().targetSpeed != airspeed && airspeed != null) return null else - airspeed = unit.targetSpeed; + airspeed = unit.getTaskData().targetSpeed; } return airspeed; } @@ -314,10 +314,10 @@ export class UnitControlPanel extends Panel { var altitude = null; for (let unit of units) { - if (unit.targetAltitude != altitude && altitude != null) + if (unit.getTaskData().targetAltitude != altitude && altitude != null) return null else - altitude = unit.targetAltitude; + altitude = unit.getTaskData().targetAltitude; } return altitude; } @@ -327,10 +327,10 @@ export class UnitControlPanel extends Panel { var ROE = null; for (let unit of units) { - if (unit.ROE !== ROE && ROE != null) + if (unit.getOptionsData().ROE !== ROE && ROE != null) return null else - ROE = unit.ROE; + ROE = unit.getOptionsData().ROE; } return ROE; } @@ -340,10 +340,10 @@ export class UnitControlPanel extends Panel { var reactionToThreat = null; for (let unit of units) { - if (unit.reactionToThreat !== reactionToThreat && reactionToThreat != null) + if (unit.getOptionsData().reactionToThreat !== reactionToThreat && reactionToThreat != null) return null else - reactionToThreat = unit.reactionToThreat; + reactionToThreat = unit.getOptionsData().reactionToThreat; } return reactionToThreat; } diff --git a/client/src/panels/unitinfopanel.ts b/client/src/panels/unitinfopanel.ts index 2e31759a..80c2d2fc 100644 --- a/client/src/panels/unitinfopanel.ts +++ b/client/src/panels/unitinfopanel.ts @@ -36,35 +36,35 @@ export class UnitInfoPanel extends Panel { update(unit: Unit) { if (this.getElement() != null) { /* Set the unit info */ - this.#unitName.innerHTML = unit.unitName; - this.#groupName.innerHTML = unit.groupName; - this.#name.innerHTML = unit.name; - this.#heading.innerHTML = String(Math.floor(rad2deg(unit.heading)) + " °"); - this.#altitude.innerHTML = String(Math.floor(unit.altitude / 0.3048) + " ft"); - this.#groundSpeed.innerHTML = String(Math.floor(unit.speed * 1.94384) + " kts"); - this.#fuel.innerHTML = String(unit.fuel + "%"); - this.#latitude.innerHTML = ConvertDDToDMS(unit.latitude, false); - this.#longitude.innerHTML = ConvertDDToDMS(unit.longitude, true); - this.#task.innerHTML = unit.currentTask !== ""? unit.currentTask: "No task"; + this.#unitName.innerHTML = unit.getData().unitName; + this.#groupName.innerHTML = unit.getData().groupName; + this.#name.innerHTML = unit.getData().name; + this.#heading.innerHTML = String(Math.floor(rad2deg(unit.getFlightData().heading)) + " °"); + this.#altitude.innerHTML = String(Math.floor(unit.getFlightData().altitude / 0.3048) + " ft"); + this.#groundSpeed.innerHTML = String(Math.floor(unit.getFlightData().speed * 1.94384) + " kts"); + this.#fuel.innerHTML = String(unit.getMissionData().fuel + "%"); + this.#latitude.innerHTML = ConvertDDToDMS(unit.getFlightData().latitude, false); + this.#longitude.innerHTML = ConvertDDToDMS(unit.getFlightData().longitude, true); + this.#task.innerHTML = unit.getTaskData().currentTask !== ""? unit.getTaskData().currentTask: "No task"; /* Set the class of the task container */ - this.#task.classList.toggle("red", unit.coalitionID == 1); - this.#task.classList.toggle("blue", unit.coalitionID == 2); - this.#task.classList.toggle("neutral", unit.coalitionID == 0); + this.#task.classList.toggle("red", unit.getMissionData().coalition === "red"); + this.#task.classList.toggle("blue", unit.getMissionData().coalition === "blue"); + this.#task.classList.toggle("neutral", unit.getMissionData().coalition === "neutral"); /* Add the loadout elements */ var els = this.getElement().getElementsByClassName("js-loadout-element"); while (els.length > 0) this.#loadoutContainer.removeChild(els[0]); - for (let index in unit.ammo) + for (let index in unit.getMissionData().ammo) this.#addLoadoutElement(unit, index); } } #addLoadoutElement(unit: Unit, index: string) { - var ammo = unit.ammo[index]; + var ammo = unit.getMissionData().ammo[index]; var displayName = ammo.desc.displayName; var amount = ammo.count; var el = document.createElement("div") diff --git a/client/src/panels/visibilitycontrolpanel.ts b/client/src/panels/visibilitycontrolpanel.ts index 46788bb0..8f12ed15 100644 --- a/client/src/panels/visibilitycontrolpanel.ts +++ b/client/src/panels/visibilitycontrolpanel.ts @@ -49,29 +49,29 @@ export class VisibilityControlPanel { var uncontrolledVisibilityCheckbox = this.#element.querySelector("#uncontrolled-visibility"); var uncontrolledVisibility = !uncontrolledVisibilityCheckbox.checked; - var airVisibilityCheckbox = this.#element.querySelector("#air-visibility"); - if (airVisibilityCheckbox.checked) - AirUnit.setVisibility({human: "full", ai: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); - else - AirUnit.setVisibility({human: "hidden", ai: "hidden", uncontrolled: "hidden", dead: "hidden"}); - - var groundVisibilityCheckbox = this.#element.querySelector("#ground-visibility"); - if (groundVisibilityCheckbox.checked) - GroundUnit.setVisibility({human: activeVisibility, ai: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); - else - GroundUnit.setVisibility({human: "hidden", ai: "hidden", uncontrolled: "hidden", dead: "hidden"}); - - var navyVisibilityCheckbox = this.#element.querySelector("#navy-visibility"); - if (navyVisibilityCheckbox.checked) - NavyUnit.setVisibility({human: activeVisibility, ai: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); - else - NavyUnit.setVisibility({human: "hidden", ai: "hidden", uncontrolled: "hidden", dead: "hidden"}); - - var weaponVisibilityCheckbox = this.#element.querySelector("#weapon-visibility"); - if (weaponVisibilityCheckbox.checked) - Weapon.setVisibility({human: activeVisibility, ai: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); - else - Weapon.setVisibility({human: "hidden", ai: "hidden", uncontrolled: "hidden", dead: "hidden"}); + //var airVisibilityCheckbox = this.#element.querySelector("#air-visibility"); + //if (airVisibilityCheckbox.checked) + // AirUnit.setVisibility({human: "full", AI: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); + //else + // AirUnit.setVisibility({human: "hidden", AI: "hidden", uncontrolled: "hidden", dead: "hidden"}); +// + //var groundVisibilityCheckbox = this.#element.querySelector("#ground-visibility"); + //if (groundVisibilityCheckbox.checked) + // GroundUnit.setVisibility({human: activeVisibility, AI: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); + //else + // GroundUnit.setVisibility({human: "hidden", AI: "hidden", uncontrolled: "hidden", dead: "hidden"}); +// + //var navyVisibilityCheckbox = this.#element.querySelector("#navy-visibility"); + //if (navyVisibilityCheckbox.checked) + // NavyUnit.setVisibility({human: activeVisibility, AI: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); + //else + // NavyUnit.setVisibility({human: "hidden", AI: "hidden", uncontrolled: "hidden", dead: "hidden"}); +// + //var weaponVisibilityCheckbox = this.#element.querySelector("#weapon-visibility"); + //if (weaponVisibilityCheckbox.checked) + // Weapon.setVisibility({human: activeVisibility, AI: activeVisibility, uncontrolled: uncontrolledVisibility? activeVisibility: "hidden", dead: "hidden"}); + //else + // Weapon.setVisibility({human: "hidden", AI: "hidden", uncontrolled: "hidden", dead: "hidden"}); } } diff --git a/client/src/units/aircraftDatabase.ts b/client/src/units/aircraftDatabase.ts index 89f5e3d0..f4e46bcf 100644 --- a/client/src/units/aircraftDatabase.ts +++ b/client/src/units/aircraftDatabase.ts @@ -1,1417 +1,1239 @@ -export function getAircraftLabelsByRole(role: string) -{ - var aircrafts = []; - for (let aircraft in aircraftDatabase) - { - //@ts-ignore - for (let loadout of aircraftDatabase[aircraft]["loadouts"]) - { - if (loadout["roles"].includes(role)) - { - //@ts-ignore - aircrafts.push(aircraftDatabase[aircraft]["label"]) - break; - } +import { UnitDatabase } from "./unitdatabase" + +export class AircraftDatabase extends UnitDatabase { + constructor() { + super(); + this.units = { + "A-10C": { + name: "A-10C", + label: "A-10CII", + shortLabel: "10", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Mk-84", + quantity: 2 + }, + { + name: "ECM", + quantity: 1 + }, + { + name: "AIM-9M", + quantity: 2 + }, + { + name: "Mk-82", + quantity: 6 + } + ], + roles: ["cas"], + code: "Mk-82*6,Mk-84*2,AIM-9*2,ECM", + name: "Heavy / Mk-84 / Short Range", + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "F-5E": { + name: "F-5E", + label: "F-5E", + shortLabel: "5", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Fuel 275", + quantity: 3 + }, + { + name: "AIM-9P5", + quantity: 2 + } + ], + roles: ["cap"], + code: "AIM-9P5*2, Fuel 275*3", + name: "Light / Fox 2 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "A-50": { + name: "A-50", + label: "A-50", + shortLabel: "50", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["awacs"], + code: "", + name: "Default AWACS" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "An-26B": { + name: "An-26B", + label: "An-26B", + shortLabel: "26", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["transport"], + code: "", + name: "Default Transport" + }, + ] + }, + + "An-30M": { + name: "An-30M", + label: "An-30M", + shortLabel: "30", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["reconnaissance"], + code: "", + name: "Default Reconnaissance" + }, + ] + }, + + "B-1B": { + name: "B-1B", + label: "B-1B", + shortLabel: "1", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Mk-84", + quantity: 24 + } + ], + roles: ["strike"], + code: "Mk-84*24", + name: "Heavy / Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "B-52H": { + name: "B-52H", + label: "B-52H", + shortLabel: "52", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Mk-84", + quantity: 18 + } + ], + roles: ["strike"], + code: "Mk-84*18", + name: "Heavy / Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "C-130": { + name: "C-130", + label: "C-130", + shortLabel: "130", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["transport"], + code: "C-130", + name: "Default Transport" + }, + ] + }, + + "C-17A": { + name: "C-17A", + label: "C-17A", + shortLabel: "C17", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["transport"], + code: "", + name: "Default Transport" + }, + ] + }, + + "E-3A": { + name: "E-3A", + label: "E-3A", + shortLabel: "3", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["awacs"], + code: "", + name: "Default AWACS" + }, + ] + }, + + "F-117A": { + name: "F-117A", + label: "F-117A", + shortLabel: "117", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "GBU-10", + quantity: 2 + } + ], + roles: ["strike"], + code: "GBU-10*2", + name: "Heavy / GBU-10 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "F-14A": { + name: "F-14A", + label: "F-14A", + shortLabel: "14", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 2 + }, + { + name: "AIM-24C", + quantity: 4 + }, + { + name: "AIM-7", + quantity: 4 + }, + { + name: "AIM-9M", + quantity: 2 + } + ], + roles: ["cap"], + code: "AIM-54C*4,AIM-9*2,AIM-7*2", + name: "Heavy / Fox 3 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "F-15C": { + name: "F-15C", + label: "F-15C", + shortLabel: "15", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 3 + }, + { + name: "AIM-120B", + quantity: 6 + }, + { + name: "AIM-9M", + quantity: 2 + } + ], + roles: ["cap"], + code: "AIM-9*2,AIM-120*6,Fuel*3", + name: "Heavy / Fox 3 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "F-15E": { + name: "F-15E", + label: "F-15E", + shortLabel: "15", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 2 + }, + { + name: "AIM-120B", + quantity: 2 + }, + { + name: "AIM-9M", + quantity: 2 + }, + { + name: "Mk-84", + quantity: 8 + } + ], + roles: ["cas"], + code: "AIM-120B*2,AIM-9M*2,FUEL*3,Mk-84*8", + name: "Heavy / Fox 3, Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "F-16C bl.52d": { + name: "F-16C bl.52d", + label: "F-16C bl.52d", + shortLabel: "16", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 2 + }, + { + name: "AIM-120C", + quantity: 4 + }, + { + name: "AIM-9M", + quantity: 2 + }, + { + name: "ECM", + quantity: 1 + } + ], + roles: ["cap"], + code: "AIM-120C*4,AIM-9M*2,ECM,Fuel*2", + name: "Heavy / Fox 3 / Long Range" + }, + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 2 + }, + { + name: "AIM-120C", + quantity: 2 + }, + { + name: "ECM", + quantity: 1 + }, + { + name: "LIGHTNING", + quantity: 1 + }, + { + name: "Mk-84", + quantity: 2 + } + ], + roles: ["strike"], + code: "Mk-84*2,AIM-120*2,ECM,Fuel*2,LIGHTNING", + name: "Heavy / Fox 3, Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "F-4E": { + name: "F-4E", + label: "F-4E", + shortLabel: "4", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 2 + }, + { + name: "AIM-7M", + quantity: 4 + }, + { + name: "AIM-9M", + quantity: 4 + }, + ], + roles: ["cap"], + code: "AIM-9*4,AIM-7*4,Fuel*2", + name: "Heavy / Fox 1 / Long Range" + }, + { + fuel: 1, + items: [ + { + name: "ECM", + quantity: 1 + }, + { + name: "AIM-7", + quantity: 2 + }, + { + name: "Mk-82", + quantity: 18 + } + ], + roles: ["cas"], + code: "Mk-82*18,AIM-7*2,ECM", + name: "Heavy / Fox 1, Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "FA-18C_hornet": { + name: "FA-18C_hornet", + label: "F/A-18C", + shortLabel: "18", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 3 + }, + { + name: "AIM-120C", + quantity: 4 + }, + { + name: "AIM-9M", + quantity: 2 + }, + ], + roles: ["cap"], + code: "AIM-120*4,AIM-9*2,Fuel*3", + name: "Heavy / Fox 3 / Long Range" + }, + { + fuel: 1, + items: [ + { + name: "fuel", + quantity: 3 + }, + { + name: "GBU-10", + quantity: 2 + }, + { + name: "AIM-9M", + quantity: 2 + }, + { + name: "FLIR Pod", + quantity: 1 + }, + { + name: "AIM-7", + quantity: 1 + } + ], + roles: ["strike"], + code: "GBU-10*2,AIM-9*2,AIM-7,FLIR Pod,Fuel*3", + name: "Heavy / Fox 1, Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "IL-76MD": { + name: "IL-76MD", + label: "IL-76MD", + shortLabel: "76", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["transport"], + code: "", + name: "Default Transport" + }, + ] + }, + + "IL-78M": { + name: "IL-78M", + label: "IL-78M", + shortLabel: "78", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["tanker"], + code: "", + name: "Default Tanker" + } + ] + }, + + "KC-135": { + name: "KC-135", + label: "KC-135", + shortLabel: "135", + loadouts: [ + { + fuel: 1, + items: [], + roles: ["tanker"], + code: "", + name: "Default Tanker" + } + ] + }, + + "MiG-23MLD": { + name: "MiG-23MLD", + label: "MiG-23MLD", + shortLabel: "23", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Fuel-800", + quantity: 1 + }, + { + name: "R-60M", + quantity: 4 + }, + { + name: "R-24R", + quantity: 2 + }, + ], + roles: ["cap"], + code: "R-24R*2,R-60M*4,Fuel-800", + name: "Heavy / Fox 1 / Long Range" + }, + { + fuel: 1, + items: [ + { + name: "Fuel-800", + quantity: 1 + }, + { + name: "FAB-500", + quantity: 2 + }, + { + name: "R-60M", + quantity: 2 + }, + ], + roles: ["strike"], + code: "FAB-500*2,R-60M*2,Fuel-800", + name: "Heavy / FAB-500 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "MiG-25RBT": { + name: "MiG-25RBT", + label: "MiG-25RBT", + shortLabel: "25", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-60M", + quantity: 2 + }, + ], + roles: ["cap"], + code: "R-60M*2", + name: "Heavy / Fox 2 / Long Range" + }, + { + fuel: 1, + items: [ + { + name: "FAB-500", + quantity: 2 + }, + { + name: "R-60M", + quantity: 2 + }, + ], + roles: ["strike"], + code: "FAB-500x2_60x2", + name: "Heavy / FAB-500 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "MiG-27K": { + name: "MiG-27K", + label: "MiG-27K", + shortLabel: "27", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "B-8", + quantity: 4 + }, + ], + roles: ["cas"], + code: "B-8*4", + name: "Heavy / B-8 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "MiG-29S": { + name: "MiG-29S", + label: "MiG-29S", + shortLabel: "29", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-73M", + quantity: 2 + }, + { + name: "R-77", + quantity: 4 + }, + { + name: "Fuel-1500", + quantity: 1 + }, + ], + roles: ["cap"], + code: "R-73*2,R-60M*2,R-27R*2", + name: "Heavy / Fox 3 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "MiG-31": { + name: "MiG-31", + label: "MiG-31", + shortLabel: "31", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-33", + quantity: 4 + }, + { + name: "R-40T", + quantity: 2 + } + ], + roles: ["cap"], + code: "R-40T*2,R-33*4", + name: "Heavy / Fox 3 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Mirage 2000-5": { + name: "Mirage 2000-5", + label: "Mirage 2000-5", + shortLabel: "M2", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R 550", + quantity: 2 + }, + { + name: "SUPER 530F", + quantity: 2 + }, + { + name: "fuel", + quantity: 1 + } + ], + roles: ["cap"], + code: "R 550*2,SUPER 530F*2,Fuel", + name: "Heavy / Fox 1 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "MQ-9 Reaper": { + name: "MQ-9 Reaper", + label: "MQ-9 Reaper", + shortLabel: "9", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "AGM-114K", + quantity: 12 + } + ], + roles: ["drone"], + code: "AGM-114K*12", + name: "Default Drone" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-17M4": { + name: "Su-17M4", + label: "Su-17M4", + shortLabel: "17", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-60M", + quantity: 2 + }, + { + name: "B-8", + quantity: 4 + }, + { + name: "fuel", + quantity: 2 + } + ], + roles: ["cas"], + code: "B-8*4,R-60M*2,Fuel*2", + name: "Heavy / B-8 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-24M": { + name: "Su-24M", + label: "Su-24M", + shortLabel: "24", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-60M", + quantity: 2 + }, + { + name: "FAB-1500", + quantity: 2 + }, + ], + roles: ["strike"], + code: "FAB-1500*2,R-60M*2", + name: "Heavy / FAB-500 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-25": { + name: "Su-25", + label: "Su-25", + shortLabel: "S25", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-60M", + quantity: 2 + }, + { + name: "UB-13", + quantity: 6 + }, + { + name: "fuel", + quantity: 2 + }, + ], + roles: ["cas"], + code: "UB-13*6,R-60M*2,Fuel*2", + name: "Heavy / Rockets / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-27": { + name: "Su-27", + label: "Su-27", + shortLabel: "27", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-73", + quantity: 4 + }, + { + name: "R-27ER", + quantity: 6 + } + ], + roles: ["cap"], + code: "R-73*4,R-27ER*6", + name: "Heavy / Fox 3 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-30": { + name: "Su-30", + label: "Su-30", + shortLabel: "30", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-73", + quantity: 2 + }, + { + name: "R-77", + quantity: 4 + }, + { + name: "R-27ER", + quantity: 2 + } + ], + roles: ["cap"], + code: "R-40T*2,R-33*4", + name: "Heavy / Fox 3 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-33": { + name: "Su-33", + label: "Su-33", + shortLabel: "33", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-73", + quantity: 4 + }, + { + name: "R-27ER", + quantity: 6 + }, + { + name: "R-27R", + quantity: 2 + } + ], + roles: ["cap"], + code: "R-73*4,R-27R*2,R-27ER*6", + name: "Heavy / Fox 3 / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Su-34": { + name: "Su-34", + label: "Su-34", + shortLabel: "34", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "R-73", + quantity: 2 + }, + { + name: "FAB-250", + quantity: 4 + }, + { + name: "UB-13", + quantity: 4 + }, + { + name: "ECM", + quantity: 1 + }, + ], + roles: ["cas"], + code: "UB-13*4,FAB-250*4,R-73*2,ECM", + name: "Heavy / Mixed Ground Ordinance / Short Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Tornado IDS": { + name: "Tornado IDS", + label: "Tornado IDS", + shortLabel: "IDS", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "AIM-9M", + quantity: 2 + }, + { + name: "fuel", + quantity: 2 + }, + { + name: "Mk-82", + quantity: 4 + } + ], + roles: ["cas"], + code: "Mk-82*4,AIM-9*2,Fuel*2", + name: "Heavy / Mk-84 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Tu-142": { + name: "Tu-142", + label: "Tu-142", + shortLabel: "142", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Kh-35", + quantity: 6 + } + ], + roles: ["strike"], + code: "Kh-35*6", + name: "Heavy / Kh-35 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Tu-160": { + name: "Tu-160", + label: "Tu-160", + shortLabel: "160", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Kh-65", + quantity: 12 + } + ], + roles: ["strike"], + code: "Kh-65*12", + name: "Heavy / Kh-65 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Tu-22M3": { + name: "Tu-22M3", + label: "Tu-22M3", + shortLabel: "T22", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Kh-22n", + quantity: 2 + }, + ], + roles: ["strike"], + code: "Kh-22N*2", + name: "Heavy / Kh-22n / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout", + }, + ] + }, + + "Tu-95MS": { + name: "Tu-95MS", + label: "Tu-95MS", + shortLabel: "95", + loadouts: [ + { + fuel: 1, + items: [ + { + name: "Kh-65", + quantity: 6 + }, + ], + roles: ["strike"], + code: "Kh-65*6", + name: "Heavy / Kh-65 / Long Range" + }, + { + fuel: 1, + items: [], + roles: [""], + code: "", + name: "Empty Loadout" + } + ] + }, } } - return aircrafts; } -export function getLoadoutNamesByRole(aircraft: string, role: string) -{ - var loadouts = []; - //@ts-ignore - for (let loadout of aircraftDatabase[aircraft]["loadouts"]) - { - if (loadout["roles"].includes(role) || loadout["roles"].includes("")) - { - loadouts.push(loadout["name"]) - } - } - return loadouts; -} +export var aircraftDatabase = new AircraftDatabase(); -export function getLoadoutsByName(aircraft: string, loadoutName: string) -{ - //@ts-ignore TODO - for (let loadout of aircraftDatabase[aircraft]["loadouts"]) - { - if (loadout["name"] === loadoutName) - { - return loadout; - } - } - return null; -} - -export function getAircraftNameByLabel(label: string) -{ - for (let name in aircraftDatabase) - { - //@ts-ignore TODO - if (aircraftDatabase[name]["label"] === label) - { - return name; - } - } - return null; -} - - -export function getAircraftLabelByName(name: string) -{ - //@ts-ignore TODO - return aircraftDatabase[name] === undefined? name: aircraftDatabase[name].label; -} - -export var aircraftDatabase = { - "A-10C": { - "name": "A-10C", - "label": "A-10CII", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Mk-84", - "quantity": 2 - }, - { - "name": "ECM", - "quantity": 1 - }, - { - "name": "AIM-9M", - "quantity": 2 - }, - { - "name": "Mk-82", - "quantity": 6 - } - ], - "roles": ["cas"], - "code": "Mk-82*6,Mk-84*2,AIM-9*2,ECM", - "name": "Heavy / Mk-84 / Short Range", - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "F-5E": { - "name": "F-5E", - "label": "F-5E", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel 275", - "quantity": 3 - }, - { - "name": "AIM-9P5", - "quantity": 2 - } - ], - "roles": ["cap"], - "code": "AIM-9P5*2, Fuel 275*3", - "name": "Light / Fox 2 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "A-50": { - "name": "A-50", - "label": "A-50", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["awacs"], - "code": "", - "name": "Default AWACS" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "An-26B": { - "name": "An-26B", - "label": "An-26B", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["transport"], - "code": "", - "name": "Default Transport" - }, - ] - }, - - "An-30M": { - "name": "An-30M", - "label": "An-30M", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["reconnaissance"], - "code": "", - "name": "Default Reconnaissance" - }, - ] - }, - - "B-1B": { - "name": "B-1B", - "label": "B-1B", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Mk-84", - "quantity": 24 - } - ], - "roles": ["strike"], - "code": "Mk-84*24", - "name": "Heavy / Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "B-52H": { - "name": "B-52H", - "label": "B-52H", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Mk-84", - "quantity": 18 - } - ], - "roles": ["strike"], - "code": "Mk-84*18", - "name": "Heavy / Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "C-130": { - "name": "C-130", - "label": "C-130", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["transport"], - "code": "C-130", - "name": "Default Transport" - }, - ] - }, - - "C-17A": { - "name": "C-17A", - "label": "C-17A", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["transport"], - "code": "", - "name": "Default Transport" - }, - ] - }, - - "E-3A": { - "name": "E-3A", - "label": "E-3A", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["awacs"], - "code": "", - "name": "Default AWACS" - }, - ] - }, - - "F-117A": { - "name": "F-117A", - "label": "F-117A", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "GBU-10", - "quantity": 2 - } - ], - "roles": ["strike"], - "code": "GBU-10*2", - "name": "Heavy / GBU-10 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "F-14A": { - "name": "F-14A", - "label": "F-14A", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 2 - }, - { - "name": "AIM-24C", - "quantity": 4 - }, - { - "name": "AIM-7", - "quantity": 4 - }, - { - "name": "AIM-9M", - "quantity": 2 - } - ], - "roles": ["cap"], - "code": "AIM-54C*4,AIM-9*2,AIM-7*2", - "name": "Heavy / Fox 3 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "F-15C": { - "name": "F-15C", - "label": "F-15C", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 3 - }, - { - "name": "AIM-120B", - "quantity": 6 - }, - { - "name": "AIM-9M", - "quantity": 2 - } - ], - "roles": ["cap"], - "code": "AIM-9*2,AIM-120*6,Fuel*3", - "name": "Heavy / Fox 3 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "F-15E": { - "name": "F-15E", - "label": "F-15E", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 2 - }, - { - "name": "AIM-120B", - "quantity": 2 - }, - { - "name": "AIM-9M", - "quantity": 2 - }, - { - "name": "Mk-84", - "quantity": 8 - } - ], - "roles": ["cas"], - "code": "AIM-120B*2,AIM-9M*2,FUEL*3,Mk-84*8", - "name": "Heavy / Fox 3, Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "F-16C bl.52d": { - "name": "F-16C bl.52d", - "label": "F-16C bl.52d", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 2 - }, - { - "name": "AIM-120C", - "quantity": 4 - }, - { - "name": "AIM-9M", - "quantity": 2 - }, - { - "name": "ECM", - "quantity": 1 - } - ], - "roles": ["cap"], - "code": "AIM-120C*4,AIM-9M*2,ECM,Fuel*2", - "name": "Heavy / Fox 3 / Long Range" - }, - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 2 - }, - { - "name": "AIM-120C", - "quantity": 2 - }, - { - "name": "ECM", - "quantity": 1 - }, - { - "name": "LIGHTNING", - "quantity": 1 - }, - { - "name": "Mk-84", - "quantity": 2 - } - ], - "roles": ["strike"], - "code": "Mk-84*2,AIM-120*2,ECM,Fuel*2,LIGHTNING", - "name": "Heavy / Fox 3, Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "F-4E": { - "name": "F-4E", - "label": "F-4E", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 2 - }, - { - "name": "AIM-7M", - "quantity": 4 - }, - { - "name": "AIM-9M", - "quantity": 4 - }, - ], - "roles": ["cap"], - "code": "AIM-9*4,AIM-7*4,Fuel*2", - "name": "Heavy / Fox 1 / Long Range" - }, - { - "fuel": 1, - "items": [ - { - "name": "ECM", - "quantity": 1 - }, - { - "name": "AIM-7", - "quantity": 2 - }, - { - "name": "Mk-82", - "quantity": 18 - } - ], - "roles": ["cas"], - "code": "Mk-82*18,AIM-7*2,ECM", - "name": "Heavy / Fox 1, Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "FA-18C_hornet": { - "name": "FA-18C_hornet", - "label": "F/A-18C", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 3 - }, - { - "name": "AIM-120C", - "quantity": 4 - }, - { - "name": "AIM-9M", - "quantity": 2 - }, - ], - "roles": ["cap"], - "code": "AIM-120*4,AIM-9*2,Fuel*3", - "name": "Heavy / Fox 3 / Long Range" - }, - { - "fuel": 1, - "items": [ - { - "name": "Fuel", - "quantity": 3 - }, - { - "name": "GBU-10", - "quantity": 2 - }, - { - "name": "AIM-9M", - "quantity": 2 - }, - { - "name": "FLIR Pod", - "quantity": 1 - }, - { - "name": "AIM-7", - "quantity": 1 - } - ], - "roles": ["strike"], - "code": "GBU-10*2,AIM-9*2,AIM-7,FLIR Pod,Fuel*3", - "name": "Heavy / Fox 1, Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "IL-76MD": { - "name": "IL-76MD", - "label": "IL-76MD", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["transport"], - "code": "", - "name": "Default Transport" - }, - ] - }, - - "IL-78M": { - "name": "IL-78M", - "label": "IL-78M", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["tanker"], - "code": "", - "name": "Default Tanker" - } - ] - }, - - "KC-135": { - "name": "KC-135", - "label": "KC-135", - "loadouts": [ - { - "fuel": 1, - "items": [], - "roles": ["tanker"], - "code": "", - "name": "Default Tanker" - } - ] - }, - - "MiG-23MLD": { - "name": "MiG-23MLD", - "label": "MiG-23MLD", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Fuel-800", - "quantity": 1 - }, - { - "name": "R-60M", - "quantity": 4 - }, - { - "name": "R-24R", - "quantity": 2 - }, - ], - "roles": ["cap"], - "code": "R-24R*2,R-60M*4,Fuel-800", - "name": "Heavy / Fox 1 / Long Range" - }, - { - "fuel": 1, - "items": [ - { - "name": "Fuel-800", - "quantity": 1 - }, - { - "name": "FAB-500", - "quantity": 2 - }, - { - "name": "R-60M", - "quantity": 2 - }, - ], - "roles": ["strike"], - "code": "FAB-500*2,R-60M*2,Fuel-800", - "name": "Heavy / FAB-500 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "MiG-25RBT": { - "name": "MiG-25RBT", - "label": "MiG-25RBT", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-60M", - "quantity": 2 - }, - ], - "roles": ["cap"], - "code": "R-60M*2", - "name": "Heavy / Fox 2 / Long Range" - }, - { - "fuel": 1, - "items": [ - { - "name": "FAB-500", - "quantity": 2 - }, - { - "name": "R-60M", - "quantity": 2 - }, - ], - "roles": ["strike"], - "code": "FAB-500x2_60x2", - "name": "Heavy / FAB-500 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "MiG-27K": { - "name": "MiG-27K", - "label": "MiG-27K", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "B-8", - "quantity": 4 - }, - ], - "roles": ["cas"], - "code": "B-8*4", - "name": "Heavy / B-8 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "MiG-29S": { - "name": "MiG-29S", - "label": "MiG-29S", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-73M", - "quantity": 2 - }, - { - "name": "R-77", - "quantity": 4 - }, - { - "name": "Fuel-1500", - "quantity": 1 - }, - ], - "roles": ["cap"], - "code": "R-73*2,R-60M*2,R-27R*2", - "name": "Heavy / Fox 3 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "MiG-31": { - "name": "MiG-31", - "label": "MiG-31", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-33", - "quantity": 4 - }, - { - "name": "R-40T", - "quantity": 2 - } - ], - "roles": ["cap"], - "code": "R-40T*2,R-33*4", - "name": "Heavy / Fox 3 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Mirage 2000-5": { - "name": "Mirage 2000-5", - "label": "Mirage 2000-5", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R 550", - "quantity": 2 - }, - { - "name": "SUPER 530F", - "quantity": 2 - }, - { - "name": "Fuel", - "quantity": 1 - } - ], - "roles": ["cap"], - "code": "R 550*2,SUPER 530F*2,Fuel", - "name": "Heavy / Fox 1 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "MQ-9 Reaper": { - "name": "MQ-9 Reaper", - "label": "MQ-9 Reaper", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "AGM-114K", - "quantity": 12 - } - ], - "roles": ["drone"], - "code": "AGM-114K*12", - "name": "Default Drone" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-17M4": { - "name": "Su-17M4", - "label": "Su-17M4", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-60M", - "quantity": 2 - }, - { - "name": "B-8", - "quantity": 4 - }, - { - "name": "Fuel", - "quantity": 2 - } - ], - "roles": ["cas"], - "code": "B-8*4,R-60M*2,Fuel*2", - "name": "Heavy / B-8 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-24M": { - "name": "Su-24M", - "label": "Su-24M", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-60M", - "quantity": 2 - }, - { - "name": "FAB-1500", - "quantity": 2 - }, - ], - "roles": ["strike"], - "code": "FAB-1500*2,R-60M*2", - "name": "Heavy / FAB-500 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-25": { - "name": "Su-25", - "label": "Su-25", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-60M", - "quantity": 2 - }, - { - "name": "UB-13", - "quantity": 6 - }, - { - "name": "Fuel", - "quantity": 2 - }, - ], - "roles": ["cas"], - "code": "UB-13*6,R-60M*2,Fuel*2", - "name": "Heavy / Rockets / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-27": { - "name": "Su-27", - "label": "Su-27", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-73", - "quantity": 4 - }, - { - "name": "R-27ER", - "quantity": 6 - } - ], - "roles": ["cap"], - "code": "R-73*4,R-27ER*6", - "name": "Heavy / Fox 3 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-30": { - "name": "Su-30", - "label": "Su-30", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-73", - "quantity": 2 - }, - { - "name": "R-77", - "quantity": 4 - }, - { - "name": "R-27ER", - "quantity": 2 - } - ], - "roles": ["cap"], - "code": "R-40T*2,R-33*4", - "name": "Heavy / Fox 3 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-33": { - "name": "Su-33", - "label": "Su-33", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-73", - "quantity": 4 - }, - { - "name": "R-27ER", - "quantity": 6 - }, - { - "name": "R-27R", - "quantity": 2 - } - ], - "roles": ["cap"], - "code": "R-73*4,R-27R*2,R-27ER*6", - "name": "Heavy / Fox 3 / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Su-34": { - "name": "Su-34", - "label": "Su-34", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "R-73", - "quantity": 2 - }, - { - "name": "FAB-250", - "quantity": 4 - }, - { - "name": "UB-13", - "quantity": 4 - }, - { - "name": "ECM", - "quantity": 1 - }, - ], - "roles": ["cas"], - "code": "UB-13*4,FAB-250*4,R-73*2,ECM", - "name": "Heavy / Mixed Ground Ordinance / Short Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Tornado IDS": { - "name": "Tornado IDS", - "label": "Tornado IDS", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "AIM-9M", - "quantity": 2 - }, - { - "name": "Fuel", - "quantity": 2 - }, - { - "name": "Mk-82", - "quantity": 4 - } - ], - "roles": ["cas"], - "code": "Mk-82*4,AIM-9*2,Fuel*2", - "name": "Heavy / Mk-84 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Tu-142": { - "name": "Tu-142", - "label": "Tu-142", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Kh-35", - "quantity": 6 - } - ], - "roles": ["strike"], - "code": "Kh-35*6", - "name": "Heavy / Kh-35 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Tu-160": { - "name": "Tu-160", - "label": "Tu-160", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Kh-65", - "quantity": 12 - } - ], - "roles": ["strike"], - "code": "Kh-65*12", - "name": "Heavy / Kh-65 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Tu-22M3": { - "name": "Tu-22M3", - "label": "Tu-22M3", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Kh-22n", - "quantity": 2 - }, - ], - "roles": ["strike"], - "code": "Kh-22N*2", - "name": "Heavy / Kh-22n / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout", - }, - ] - }, - - "Tu-95MS": { - "name": "Tu-95MS", - "label": "Tu-95MS", - "loadouts": [ - { - "fuel": 1, - "items": [ - { - "name": "Kh-65", - "quantity": 6 - }, - ], - "roles": ["strike"], - "code": "Kh-65*6", - "name": "Heavy / Kh-65 / Long Range" - }, - { - "fuel": 1, - "items": [], - "roles": [""], - "code": "", - "name": "Empty Loadout" - } - ] - }, -} - -export function getAircrafImage(name: string) -{ - var results = [] - for (let imageName of imageNames) { - var score = similarity(imageName, name); - results.push({score: score, imageName: imageName}); - } - - var bestResult = null; - for (let result of results) - { - if (bestResult == null) - bestResult = result; - else { - if (result.score > bestResult.score) - bestResult = result; - } - } - return bestResult?.imageName + ".png"; -} - -function similarity(s1: string, s2: string) { - var longer = s1; - var shorter = s2; - if (s1.length < s2.length) { - longer = s2; - shorter = s1; - } - var longerLength = longer.length; - if (longerLength == 0) { - return 1.0; - } - return (longerLength - editDistance(longer, shorter)) / longerLength; - } - -function editDistance(s1: string, s2: string) { - s1 = s1.toLowerCase(); - s2 = s2.toLowerCase(); - - var costs = new Array(); - for (var i = 0; i <= s1.length; i++) { - var lastValue = i; - for (var j = 0; j <= s2.length; j++) { - if (i == 0) - costs[j] = j; - else { - if (j > 0) { - var newValue = costs[j - 1]; - if (s1.charAt(i - 1) != s2.charAt(j - 1)) - newValue = Math.min(Math.min(newValue, lastValue), - costs[j]) + 1; - costs[j - 1] = lastValue; - lastValue = newValue; - } - } - } - if (i > 0) - costs[s2.length] = lastValue; - } - return costs[s2.length]; - } - -var imageNames = [ - 'a-10', - 'a-20', - 'a-29', - 'a-4', - 'a-400', - 'a-50', - 'a-6', - 'ah-1', - 'ah-64', - 'an-26', - 'av8bna', - 'b-1', - 'b-17', - 'b-2', - 'b-52', - 'b707', - 'bf109', - 'bomb', - 'c-101', - 'c-130', - 'c-17', - 'c-5', - 'ch-47', - 'ch-53', - 'christeneagleii', - 'e-2', - 'e-3', - 'eurofighter', - 'f-111', - 'f-117', - 'f-14', - 'f-15', - 'f-16', - 'f-18', - 'f-22', - 'f-35', - 'f-4', - 'f-5', - 'f-86', - 'fw190', - 'general1', - 'gripen', - 'h-6', - 'hawk', - 'helicopter1', - 'i-16', - 'il-76', - 'j-10', - 'j-20', - 'j-7', - 'jf-17', - 'ju-88', - 'ka-27', - 'ka-50', - 'kc-10', - 'kc-135', - 'l-159', - 'l-39', - 'm2000', - 'mi-24', - 'mi-26', - 'mi-28', - 'mi-8', - 'mig-15', - 'mig-19', - 'mig-21', - 'mig-23', - 'mig-25', - 'mig-29', - 'mosquito', - 'multiengine', - 'oh-58', - 'p-47', - 'p-51', - 'rafale', - 'rq-1', - 'rq-4', - 's-3', - 'sa-342', - 'spitfire', - 'su-17', - 'su-24', - 'su-25', - 'su-27', - 'su-34', - 'su-57', - 'tornado', - 'tu-160', - 'tu-22', - 'tu-95', - 'u-28', - 'uh-1', - 'uh-60', - 'viggen', - 'yak-40', - 'yak-52' -] \ No newline at end of file diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index a9f0300d..98f49dde 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -1,14 +1,8 @@ import { Marker, LatLng, Polyline, Icon } from 'leaflet'; -import { getMap, getUnitsManager} from '..'; +import { getMap, getUnitsManager } from '..'; import { UnitMarker, MarkerOptions, AircraftMarker, HelicopterMarker, GroundUnitMarker, NavyUnitMarker, WeaponMarker, MissileMarker, BombMarker } from './unitmarker'; -import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, landAt, setAltitude, setReactionToThreat, setROE, setSpeed } from '../dcs/dcs'; - -interface VisibilityOptions { - dead: string; - ai: string; - uncontrolled: string; - human: string; -} +import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, landAt, setAltitude, setReactionToThreat, setROE, setSpeed } from '../server/server'; +import { aircraftDatabase } from './aircraftdatabase'; var pathIcon = new Icon({ iconUrl: 'images/marker-icon.png', @@ -17,60 +11,37 @@ var pathIcon = new Icon({ }); export class Unit { - ID: number = -1; - AI: boolean = false; - 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; - hasTask: boolean = false; - isLeader: boolean = false; - isWingman: boolean = false; - leaderID: number = 0; - wingmen: Unit[] = []; - wingmenIDs: number[] = []; - targetSpeed: number = 0; - targetAltitude: number = 0; - ROE: string = ""; - reactionToThreat: string = ""; - + ID: number; + + #data: UnitData; + #marker: UnitMarker; + #selectable: boolean; #selected: boolean = false; + #preventClick: boolean = false; + #pathMarkers: Marker[] = []; #pathPolyline: Polyline; #targetsPolylines: Polyline[]; - #marker: UnitMarker; + #timer: number = 0; #forceUpdate: boolean = false; - static getConstructor(name: string) { - if (name === "GroundUnit") return GroundUnit; - if (name === "Aircraft") return Aircraft; - if (name === "Helicopter") return Helicopter; - if (name === "Missile") return Missile; - if (name === "Bomb") return Bomb; - if (name === "NavyUnit") return NavyUnit; + static getConstructor(type: string) { + if (type === "GroundUnit") return GroundUnit; + if (type === "Aircraft") return Aircraft; + if (type === "Helicopter") return Helicopter; + if (type === "Missile") return Missile; + if (type === "Bomb") return Bomb; + if (type === "NavyUnit") return NavyUnit; } - constructor(ID: number, marker: UnitMarker) { + constructor(ID: number, marker: UnitMarker, data: UnitData) { this.ID = ID; this.#selectable = true; + this.#data = data; /* The marker is set by the inherited class */ this.#marker = marker; @@ -83,42 +54,34 @@ export class Unit { this.#targetsPolylines = []; } - update(response: any) { + update(response: UnitData) { var updateMarker = false; - if (this.latitude != response['latitude'] || this.longitude != response['longitude'] || this.alive != response['alive'] || this.#forceUpdate) + if (this.#data.flightData.latitude != response.flightData.latitude || this.#data.flightData.longitude != response.flightData.longitude || this.#data.alive != response.alive || this.#forceUpdate) updateMarker = true; - for (let entry in response) { - // @ts-ignore TODO handle better - this[entry] = response[entry]; - } - - // TODO handle better - if (response['activePath'] == undefined) - this.activePath = null + this.#data = response; /* Dead units can't be selected */ - this.setSelected(this.getSelected() && this.alive) + this.setSelected(this.getSelected() && this.#data.alive) if (updateMarker) this.#updateMarker(); this.#clearTargets(); - if (this.getSelected() && this.activePath != null) - { + if (this.getSelected()) { this.#drawPath(); this.#drawTargets(); } else - this.#clearPath(); + this.#clearPath(); } 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.#data.alive || !selected) && this.#selectable && this.#selected != selected) { this.#selected = selected; this.#marker.setSelected(selected); - document.dispatchEvent(new CustomEvent("unitSelection", {detail: this})); + document.dispatchEvent(new CustomEvent("unitSelection", { detail: this })); } } @@ -136,8 +99,8 @@ export class Unit { addDestination(latlng: L.LatLng) { var path: any = {}; - if (this.activePath != null) { - path = this.activePath; + if (this.#data.taskData.activePath != null) { + path = this.#data.taskData.activePath; path[(Object.keys(path).length + 1).toString()] = latlng; } else { @@ -147,7 +110,7 @@ export class Unit { } clearDestinations() { - this.activePath = null; + this.#data.taskData.activePath = null; } getHidden() { @@ -155,7 +118,7 @@ export class Unit { } getLeader() { - return getUnitsManager().getUnitByID(this.leaderID); + return getUnitsManager().getUnitByID(this.#data.formationData.leaderID); } getFormation() { @@ -164,10 +127,8 @@ export class Unit { getWingmen() { var wingmen: Unit[] = []; - if (this.wingmenIDs != null) - { - for (let ID of this.wingmenIDs) - { + if (this.#data.formationData.wingmenIDs != null) { + for (let ID of this.#data.formationData.wingmenIDs) { var unit = getUnitsManager().getUnitByID(ID) if (unit) wingmen.push(unit); @@ -176,11 +137,86 @@ export class Unit { return wingmen; } - forceUpdate() - { + forceUpdate() { this.#forceUpdate = true; } + getData() { + return this.#data; + } + + getFlightData() { + return this.#data.flightData; + } + + getTaskData() { + return this.#data.taskData; + } + + getMissionData() { + return this.#data.missionData; + } + + getFormationData() { + return this.#data.formationData; + } + + getOptionsData() { + return this.#data.optionsData; + } + + attackUnit(targetID: number) { + /* Call DCS attackUnit function */ + if (this.ID != targetID) { + attackUnit(this.ID, targetID); + } + else { + // TODO: show a message + } + } + + landAt(latlng: LatLng) { + landAt(this.ID, latlng); + } + + changeSpeed(speedChange: string) { + changeSpeed(this.ID, speedChange); + } + + changeAltitude(altitudeChange: string) { + changeAltitude(this.ID, altitudeChange); + } + + setSpeed(speed: number) { + setSpeed(this.ID, speed); + } + + setAltitude(altitude: number) { + setAltitude(this.ID, altitude); + } + + setROE(ROE: string) { + setROE(this.ID, ROE); + } + + setReactionToThreat(reactionToThreat: string) { + setReactionToThreat(this.ID, reactionToThreat); + } + + delete() { + deleteUnit(this.ID); + } + + /* + setformation(formation) + { + } + */ + + setLeader(isLeader: boolean, wingmenIDs: number[] = []) { + setLeader(this.ID, isLeader, wingmenIDs); + } + #onClick(e: any) { this.#timer = setTimeout(() => { if (!this.#preventClick) { @@ -206,7 +242,7 @@ export class Unit { 'Follow' ] - getMap().showContextMenu(e.originalEvent, "Action: " + this.unitName, options, (action: string) => this.#executeAction(action)); + getMap().showContextMenu(e.originalEvent, "Action: " + this.#data.unitName, options, (action: string) => this.#executeAction(action)); } #executeAction(action: string) { @@ -225,14 +261,13 @@ export class Unit { if (getMap().hasLayer(this.#marker) && this.getHidden()) { getMap().removeLayer(this.#marker); } - else - { - this.#marker.setLatLng(new LatLng(this.latitude, this.longitude)); + else { + this.#marker.setLatLng(new LatLng(this.#data.flightData.latitude, this.#data.flightData.longitude)); this.#marker.draw({ - heading: this.heading, - speed: this.speed, - altitude: this.altitude, - alive: this.alive + heading: this.#data.flightData.heading, + speed: this.#data.flightData.speed, + altitude: this.#data.flightData.altitude, + alive: this.#data.alive }); } @@ -240,25 +275,25 @@ export class Unit { } #drawPath() { - if (this.activePath != null) { + if (this.#data.taskData.activePath != null) { var points = []; - points.push(new LatLng(this.latitude, this.longitude)); + points.push(new LatLng(this.#data.flightData.latitude, this.#data.flightData.longitude)); /* Add markers if missing */ - while (this.#pathMarkers.length < Object.keys(this.activePath).length) { + while (this.#pathMarkers.length < Object.keys(this.#data.taskData.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.#data.taskData.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) { - var destination = this.activePath[WP]; + for (let WP in this.#data.taskData.activePath) { + var destination = this.#data.taskData.activePath[WP]; this.#pathMarkers[parseInt(WP) - 1].setLatLng([destination.lat, destination.lng]); points.push(new LatLng(destination.lat, destination.lng)); this.#pathPolyline.setLatLngs(points); @@ -274,36 +309,25 @@ export class Unit { this.#pathPolyline.setLatLngs([]); } - #drawTargets() - { - for (let typeIndex in this.targets) - { - for (let index in this.targets[typeIndex]) - { - var targetData = this.targets[typeIndex][index]; + #drawTargets() { + for (let typeIndex in this.getMissionData().targets) { + for (let index in this.getMissionData().targets[typeIndex]) { + var targetData = this.getMissionData().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) - + if (target != null) { + var startLatLng = new LatLng(this.#data.flightData.latitude, this.#data.flightData.longitude) + var endLatLng = new LatLng(target.getFlightData().latitude, target.getFlightData().longitude) + var color; if (typeIndex === "radar") - { color = "#FFFF00"; - } else if (typeIndex === "visual") - { color = "#FF00FF"; - } else if (typeIndex === "rwr") - { color = "#00FF00"; - } else - { color = "#FFFFFF"; - } - var targetPolyline = new Polyline([startLatLng, endLatLng], {color: color, weight: 3, opacity: 1, smoothFactor: 1}); + var targetPolyline = new Polyline([startLatLng, endLatLng], { color: color, weight: 3, opacity: 1, smoothFactor: 1 }); targetPolyline.addTo(getMap()); this.#targetsPolylines.push(targetPolyline) } @@ -311,242 +335,102 @@ export class Unit { } } - #clearTargets() - { - for (let index in this.#targetsPolylines) - { + #clearTargets() { + for (let index in this.#targetsPolylines) { getMap().removeLayer(this.#targetsPolylines[index]) } } - - attackUnit(targetID: number) { - /* Call DCS attackUnit function */ - if (this.ID != targetID) { - attackUnit(this.ID, targetID); - } - else { - // TODO: show a message - } - } - - landAt(latlng: LatLng) - { - landAt(this.ID, latlng); - } - - changeSpeed(speedChange: string) - { - changeSpeed(this.ID, speedChange); - } - - changeAltitude(altitudeChange: string) - { - changeAltitude(this.ID, altitudeChange); - } - - setSpeed(speed: number) - { - setSpeed(this.ID, speed); - } - - setAltitude(altitude: number) - { - setAltitude(this.ID, altitude); - } - - setROE(ROE: string) - { - setROE(this.ID, ROE); - } - - setReactionToThreat(reactionToThreat: string) - { - setReactionToThreat(this.ID, reactionToThreat); - } - - delete() - { - deleteUnit(this.ID); - } - - /* - setformation(formation) - { - // 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 + " formation change: " + formation); - } - }; - - var command = {"ID": this.ID, "formation": formation} - var data = {"setFormation": command} - - xhr.send(JSON.stringify(data)); - } - */ - - setLeader(isLeader: boolean, wingmenIDs: number[] = []) - { - setLeader(this.ID, isLeader, wingmenIDs); - } - } export class AirUnit extends Unit { - static visibility: VisibilityOptions = {dead: "hidden", ai: "partial", uncontrolled: "partial", human: "full"} - static setVisibility(visibility: VisibilityOptions) - { - getUnitsManager().forceUpdate(); - AirUnit.visibility = visibility; - } - - static getVisibility() - { - return AirUnit.visibility; - } - getHidden() { - if (this.alive) - { - if (this.flags.user) - return AirUnit.getVisibility().human === "hidden" - - if (this.AI) - return AirUnit.getVisibility().ai === "hidden" - else - return AirUnit.getVisibility().uncontrolled === "hidden" - } - else - { - return AirUnit.getVisibility().dead === "hidden" - } + return false; } } export class Aircraft extends AirUnit { - constructor(ID: number, options: MarkerOptions) { - var marker = new AircraftMarker(options); - super(ID, marker); + constructor(ID: number, data: UnitData) { + var marker = new AircraftMarker({ + AI: data.AI, + unitName: data.unitName, + name: aircraftDatabase.getShortLabelByName(data.name), + human: data.missionData.flags.human, + coalition: data.missionData.coalition}); + super(ID, marker, data); } } export class Helicopter extends AirUnit { - constructor(ID: number, options: MarkerOptions) { - var marker = new HelicopterMarker(options); - super(ID, marker); + constructor(ID: number, data: UnitData) { + var marker = new HelicopterMarker({ + AI: data.AI, + unitName: data.unitName, + name: "H", + human: data.missionData.flags.human, + coalition: data.missionData.coalition}); + super(ID, marker, data); } } export class GroundUnit extends Unit { - static visibility: VisibilityOptions = {dead: "hidden", ai: "partial", uncontrolled: "partial", human: "partial"} - static setVisibility(visibility: VisibilityOptions) - { - getUnitsManager().forceUpdate(); - GroundUnit.visibility = visibility; - } - - static getVisibility() - { - return GroundUnit.visibility; - } - - constructor(ID: number, options: MarkerOptions) { - var marker = new GroundUnitMarker(options); - super(ID, marker); + constructor(ID: number, data: UnitData) { + var marker = new GroundUnitMarker({ + AI: data.AI, + unitName: data.unitName, + name: "G", + human: data.missionData.flags.human, + coalition: data.missionData.coalition}); + super(ID, marker, data); } getHidden() { - if (this.alive) - { - if (this.flags.user) - return GroundUnit.getVisibility().human === "hidden" - - if (this.AI) - return GroundUnit.getVisibility().ai === "hidden" - else - return GroundUnit.getVisibility().uncontrolled === "hidden" - } - else - { - return GroundUnit.getVisibility().dead === "hidden" - } + return false; } } export class NavyUnit extends Unit { - static visibility: VisibilityOptions = {dead: "hidden", ai: "partial", uncontrolled: "partial", human: "partial"} - static setVisibility(visibility: VisibilityOptions) - { - getUnitsManager().forceUpdate(); - NavyUnit.visibility = visibility; - } - - static getVisibility() - { - return NavyUnit.visibility; - } - - constructor(ID: number, options: MarkerOptions) { - var marker = new NavyUnitMarker(options); - super(ID, marker); + constructor(ID: number, data: UnitData) { + var marker = new NavyUnitMarker({ + AI: data.AI, + unitName: data.unitName, + name: "N", + human: data.missionData.flags.human, + coalition: data.missionData.coalition}); + super(ID, marker, data); } getHidden() { - if (this.alive) - { - if (this.AI) - return NavyUnit.getVisibility().ai === "hidden" - else - return NavyUnit.getVisibility().uncontrolled === "hidden" - } - else - { - return NavyUnit.getVisibility().dead === "hidden" - } + return false; } } export class Weapon extends Unit { - static visibility: VisibilityOptions = {dead: "hidden", ai: "partial", uncontrolled: "partial", human: "partial"} - static setVisibility(visibility: VisibilityOptions) - { - getUnitsManager().forceUpdate(); - Weapon.visibility = visibility; - } - - static getVisibility() - { - return Weapon.visibility; - } - - constructor(ID: number, marker: UnitMarker) - { - super(ID, marker); + constructor(ID: number, marker: UnitMarker, data: UnitData) { + super(ID, marker, data); this.setSelectable(false); } - - getHidden() { - if (this.alive) - return Weapon.getVisibility().uncontrolled === "hidden" - else - return true; - } } export class Missile extends Weapon { - constructor(ID: number, options: MarkerOptions) { - var marker = new MissileMarker(options); - super(ID, marker); + constructor(ID: number, data: UnitData) { + var marker = new MissileMarker({ + AI: data.AI, + unitName: data.unitName, + name: "M", + human: data.missionData.flags.human, + coalition: data.missionData.coalition}); + super(ID, marker, data); } } export class Bomb extends Weapon { - constructor(ID: number, options: MarkerOptions) { - var marker = new BombMarker(options); - super(ID, marker); + constructor(ID: number, data: UnitData) { + var marker = new BombMarker({ + AI: data.AI, + unitName: data.unitName, + name: "B", + human: data.missionData.flags.human, + coalition: data.missionData.coalition}); + super(ID, marker, data); } } diff --git a/client/src/units/unitdatabase.ts b/client/src/units/unitdatabase.ts new file mode 100644 index 00000000..6f606cf9 --- /dev/null +++ b/client/src/units/unitdatabase.ts @@ -0,0 +1,92 @@ +export interface LoadoutItemBlueprint { + name: string; + quantity: number; +} + +export interface LoadoutBlueprint { + fuel: number; + items: LoadoutItemBlueprint[]; + roles: string[]; + code: string; + name: string; +} + +export interface UnitBlueprint { + name: string; + label: string; + shortLabel: string; + loadouts: LoadoutBlueprint[]; +} + +export class UnitDatabase { + units: {[key: string]: UnitBlueprint} = {}; + + constructor() + { + + } + + getLabelsByRole(role: string) + { + var units = []; + for (let unit in this.units) + { + for (let loadout of this.units[unit].loadouts) + { + if (loadout.roles.includes(role)) + { + units.push(this.units[unit].label) + break; + } + } + } + return units; + } + + getLoadoutNamesByRole(unit: string, role: string) + { + var loadouts = []; + for (let loadout of this.units[unit].loadouts) + { + if (loadout.roles.includes(role) || loadout.roles.includes("")) + { + loadouts.push(loadout.name) + } + } + return loadouts; + } + + getLoadoutsByName(unit: string, loadoutName: string) + { + for (let loadout of this.units[unit].loadouts) + { + if (loadout.name === loadoutName) + { + return loadout; + } + } + return null; + } + + getNameByLabel(label: string) + { + for (let name in this.units) + { + if (this.units[name].label === label) + { + return name; + } + } + return null; + } + + getLabelByName(name: string) + { + return this.units[name] === undefined? name: this.units[name].label; + } + + getShortLabelByName(name: string) + { + return this.units[name] === undefined? name: this.units[name].shortLabel; + } +} \ No newline at end of file diff --git a/client/src/units/unitmarker.ts b/client/src/units/unitmarker.ts index 0405b935..be78bf1b 100644 --- a/client/src/units/unitmarker.ts +++ b/client/src/units/unitmarker.ts @@ -1,58 +1,43 @@ import * as L from 'leaflet' import { getMap } from '..' import { rad2deg } from '../other/utils' -import { getAircrafImage, getAircraftLabelByName } from './aircraftdatabase' -import { AirUnit, GroundUnit, NavyUnit, Weapon } from './unit' export interface MarkerOptions { - unitName: string - name: string - human: boolean - coalitionID: number - type: any + unitName: string, + name: string, + human: boolean, + coalition: string, AI: boolean } export interface MarkerData { - heading: number - speed: number - altitude: number + heading: number, + speed: number, + altitude: number, alive: boolean } export class UnitMarker extends L.Marker { - #unitName: string - #name: string - #human: boolean - #AI: boolean - #alive: boolean = true + #options: MarkerOptions; + #data: MarkerData; #selected: boolean = false constructor(options: MarkerOptions) { super(new L.LatLng(0, 0), { riseOnHover: true }); - this.#unitName = options.unitName; - this.#name = getAircraftLabelByName(options.name); - this.#human = options.human; - this.#AI = options.AI; - var coalition = ""; - if (options.coalitionID == 1) - coalition = "red" - else if (options.coalitionID == 2) - coalition = "blue" - else - coalition = "neutral" + this.#options = options; + this.#data = {heading: 0, speed: 0, altitude: 0, alive: true}; var icon = new L.DivIcon({ html: `
+ data-coalition=${this.#options.coalition} + data-pilot=${this.#options.human? "human": "ai"}>
-
${this.#name}
+
${this.#options.name}
@@ -68,7 +53,7 @@ export class UnitMarker extends L.Marker {
-
${this.#unitName}
+
${this.#options.unitName}
@@ -87,14 +72,14 @@ export class UnitMarker extends L.Marker { } draw(data: MarkerData) { - this.#alive = data.alive; + this.#data; var element = this.getElement(); - if (element != null) { - element.querySelector(".unit")?.setAttribute("data-is-selected", String(this.getSelected())); - element.querySelector(".unit-vvi-heading")?.setAttribute("style",`transform: rotate(${rad2deg(data.heading)}deg); width: ${data.speed / 5}px`); + element.querySelector(".unit-vvi-heading")?.setAttribute("style",`transform: rotate(${rad2deg(data.heading)}deg); width: ${15 + data.speed / 5}px`); + element.querySelector(".unit")?.setAttribute("data-fuel-level", "20"); + element.querySelector(".unit")?.setAttribute("data-has-fox-1", "true"); var unitHeadingDiv = element.querySelector(".unit-heading"); if (unitHeadingDiv != null) @@ -102,7 +87,7 @@ export class UnitMarker extends L.Marker { var unitAltitudeDiv = element.querySelector(".unit-altitude"); if (unitAltitudeDiv != null) - unitAltitudeDiv.innerHTML = String(Math.floor(data.altitude / 1000)); + unitAltitudeDiv.innerHTML = String(Math.floor(data.altitude / 0.3048 / 1000)); } var pos = getMap().latLngToLayerPoint(this.getLatLng()).round(); this.setZIndexOffset(Math.floor(data.altitude) - pos.y); @@ -110,9 +95,7 @@ export class UnitMarker extends L.Marker { setSelected(selected: boolean) { this.#selected = selected; - this.getElement()?.querySelector("#icon")?.classList.remove("ol-unit-marker-hovered"); - this.getElement()?.querySelector("#ring")?.classList.toggle("ol-unit-marker-selected", selected); - this.getElement()?.querySelector("#background")?.classList.toggle("ol-unit-marker-selected", selected); + this.getElement()?.querySelector(".unit")?.setAttribute("data-is-selected", String(this.getSelected())); } getSelected() { @@ -120,141 +103,46 @@ export class UnitMarker extends L.Marker { } setHovered(hovered: boolean) { - this.getElement()?.querySelector("#icon")?.classList.toggle("ol-unit-marker-hovered", hovered && this.#alive); + this.getElement()?.querySelector("#icon")?.classList.toggle("ol-unit-marker-hovered", hovered && this.#data.alive); } - getName() { - return this.#name; + getData() { + return this.#data; } - getHuman() { - return this.#human; - } - - getAI() { - return this.#AI; - } - - getAlive() { - return this.#alive; - } - - getVisibility() { - return "full"; - } - - getUnitImage() { - return new Image().src = "images/units/unit.png" + getOptions() { + return this.#options; } } export class AirUnitMarker extends UnitMarker { - getVisibility() { - if (this.getAlive()) - { - if (this.getSelected()) - return "full"; - else if (this.getHuman()) - return AirUnit.getVisibility().human; - else if (this.getAI()) - return AirUnit.getVisibility().ai; - else - return AirUnit.getVisibility().uncontrolled; - } - else - return "minimal"; - } + } export class AircraftMarker extends AirUnitMarker { - getUnitImage() - { - return new Image().src = "images/units/" + getAircrafImage(this.getName()); - } + } export class HelicopterMarker extends AirUnitMarker { - getUnitImage() - { - return new Image().src = "images/units/airUnit.png" - } + } export class GroundUnitMarker extends UnitMarker { - /* Are user driven units recognized as human? */ - getVisibility() { - if (this.getAlive()) - { - if (this.getSelected()) - return "full"; - else if (this.getHuman()) - return GroundUnit.getVisibility().human; - else if (this.getAI()) - return GroundUnit.getVisibility().ai; - else - return GroundUnit.getVisibility().uncontrolled; - } - else - return "minimal"; - } - - getUnitImage() - { - return new Image().src = "images/units/groundUnit.png" - } + } export class NavyUnitMarker extends UnitMarker { - getVisibility() { - if (this.getAlive()) - { - if (this.getSelected()) - return "full"; - else if (this.getHuman()) - return NavyUnit.getVisibility().human; - else if (this.getAI()) - return NavyUnit.getVisibility().ai; - else - return NavyUnit.getVisibility().uncontrolled; - } - else - return "minimal"; - } - - getUnitImage() - { - return new Image().src = "images/units/navyUnit.png" - } + } export class WeaponMarker extends UnitMarker { - getVisibility() { - if (this.getAlive()) - { - if (this.getSelected()) - return "full"; - else if (this.getHuman()) - return Weapon.getVisibility().human; - else if (this.getAI()) - return Weapon.getVisibility().ai; - else - return Weapon.getVisibility().uncontrolled; - } - else - return "minimal"; - } + } export class BombMarker extends WeaponMarker { - getUnitImage() - { - return new Image().src = "images/units/bomb.png" - } + } export class MissileMarker extends WeaponMarker { - getUnitImage() - { - return new Image().src = "images/units/missile.png" - } + } \ No newline at end of file diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index 4e8ca445..524d44d3 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -1,7 +1,7 @@ import { LatLng, LatLngBounds } from "leaflet"; import { getMap, getUnitControlPanel, getUnitInfoPanel } from ".."; import { Unit, GroundUnit } from "./unit"; -import { cloneUnit } from "../dcs/dcs"; +import { cloneUnit } from "../server/server"; export class UnitsManager { #units: { [ID: number]: Unit }; @@ -40,19 +40,11 @@ export class UnitsManager { return this.#units; } - addUnit(ID: number, data: any) { + addUnit(ID: number, data: UnitData) { /* The name of the unit category is exactly the same as the constructor name */ var constructor = Unit.getConstructor(data.category); if (constructor != undefined) { - var options = { - unitName: data.unitName, - name: data.name, - human: data.flags.Human, - coalitionID: data.coalitionID, - type: data.type, - AI: data.AI - } - this.#units[ID] = new constructor(ID, options); + this.#units[ID] = new constructor(ID, data); } } @@ -80,13 +72,13 @@ export class UnitsManager { this.#units[ID]?.setSelected(true); } - update(data: any) { - for (let ID in data["units"]) { + update(data: ServerData) { + 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)) { - this.addUnit(parseInt(ID), data["units"][ID]); + this.addUnit(parseInt(ID), data.units[ID]); } - this.#units[parseInt(ID)].update(data["units"][ID]); + this.#units[parseInt(ID)].update(data.units[ID]); } /* Update the unit info panel */ @@ -124,7 +116,7 @@ export class UnitsManager { { if (this.#units[ID].getHidden() == false) { - var latlng = new LatLng(this.#units[ID].latitude, this.#units[ID].longitude); + var latlng = new LatLng(this.#units[ID].getFlightData().latitude, this.#units[ID].getFlightData().longitude); if (bounds.contains(latlng)) { this.#units[ID].setSelected(true); @@ -148,9 +140,9 @@ export class UnitsManager { for (let idx in this.getSelectedUnits()) { var unit = this.getSelectedUnits()[idx]; - if (unit.isLeader) + if (unit.getFormationData().isLeader) leaders.push(unit); - else if (unit.isWingman) + else if (unit.getFormationData().isWingman) { var leader = unit.getLeader(); if (leader && !leaders.includes(leader)) @@ -165,7 +157,7 @@ export class UnitsManager { for (let idx in this.getSelectedUnits()) { var unit = this.getSelectedUnits()[idx]; - if (!unit.isLeader && !unit.isWingman) + if (!unit.getFormationData().isLeader && !unit.getFormationData().isWingman) singletons.push(unit); } return singletons; @@ -290,12 +282,12 @@ export class UnitsManager { var wingmenIDs = []; for (let idx in selectedUnits) { - if (selectedUnits[idx].isWingman) + if (selectedUnits[idx].getFormationData().isWingman) { //console.log(selectedUnits[idx].unitName + " is already in a formation."); return; } - else if (selectedUnits[idx].isLeader) + else if (selectedUnits[idx].getFormationData().isLeader) { //console.log(selectedUnits[idx].unitName + " is already in a formation."); return; diff --git a/client/views/unitcontrolpanel.ejs b/client/views/unitcontrolpanel.ejs index c9f5dd6e..369dae65 100644 --- a/client/views/unitcontrolpanel.ejs +++ b/client/views/unitcontrolpanel.ejs @@ -1,14 +1,14 @@
- + -