From aad0fd22ad0732cf6a0cd9ee63ab20dc2fe2f84b Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Sun, 5 Nov 2023 10:57:53 +0000 Subject: [PATCH 1/3] Air defence has its own spawn icon --- client/@types/olympus/index.d.ts | 2 +- client/plugins/databasemanager/index.js | 26 +++-------- .../databasemanager/src/loadouteditor.ts | 8 ++-- client/plugins/databasemanager/src/utils.ts | 2 +- client/src/contextmenus/mapcontextmenu.ts | 21 ++++++++- client/src/controls/unitspawnmenu.ts | 46 ++++++++++++++++++- client/src/unit/databases/unitdatabase.ts | 4 +- client/views/contextmenus/map.ejs | 9 +++- 8 files changed, 86 insertions(+), 32 deletions(-) diff --git a/client/@types/olympus/index.d.ts b/client/@types/olympus/index.d.ts index faa3f853..063b3ddf 100644 --- a/client/@types/olympus/index.d.ts +++ b/client/@types/olympus/index.d.ts @@ -869,7 +869,7 @@ declare module "contextmenus/mapcontextmenu" { * @param y Y screen coordinate of the top left corner of the context menu * @param latlng Leaflet latlng object of the mouse click */ - show(x: number, y: number, latlng: LatLng): void; + show(x: number, y: number, latlng: LatLng): false | undefined; /** If the user rightclicked on a CoalitionArea, it will be given the ability to edit it. * * @param coalitionArea The CoalitionArea the user can edit diff --git a/client/plugins/databasemanager/index.js b/client/plugins/databasemanager/index.js index 82738524..a43d566e 100644 --- a/client/plugins/databasemanager/index.js +++ b/client/plugins/databasemanager/index.js @@ -613,10 +613,10 @@ class LoadoutEditor { title.innerText = "Loadout properties"; __classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f").appendChild(title); if (__classPrivateFieldGet(this, _LoadoutEditor_loadout, "f")) { - var laodout = __classPrivateFieldGet(this, _LoadoutEditor_loadout, "f"); - (0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Name", laodout.name, "text", (value) => { laodout.name = value; __classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f").dispatchEvent(new Event("refresh")); }); - (0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Code", laodout.code, "text", (value) => { laodout.code = value; }); - (0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Roles", (0, utils_1.arrayToString)(laodout.roles), "text", (value) => { laodout.roles = (0, utils_1.stringToArray)(value); }); + var loadout = __classPrivateFieldGet(this, _LoadoutEditor_loadout, "f"); + (0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Name", loadout.name, "text", (value) => { loadout.name = value; __classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f").dispatchEvent(new Event("refresh")); }); + (0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Code", loadout.code, "text", (value) => { loadout.code = value; }); + (0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Roles", (0, utils_1.arrayToString)(loadout.roles), "text", (value) => { loadout.roles = (0, utils_1.stringToArray)(value); }); (0, utils_1.addLoadoutItemsEditor)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), __classPrivateFieldGet(this, _LoadoutEditor_loadout, "f")); } } @@ -1034,25 +1034,11 @@ exports.addLoadoutsScroll = addLoadoutsScroll; * @returns The string */ function arrayToString(array) { - var value = "["; - var firstRole = true; - array.forEach((role) => { - value += firstRole ? "" : ", "; - firstRole = false; - value += role; - }); - value += "]"; - return value; + return "[" + array.join(", ") + "]"; } exports.arrayToString = arrayToString; function stringToArray(input) { - input = input.replace("[", "").replace("]", ""); - var values = input.split(","); - var result = []; - values.forEach((value) => { - result.push(value.trim()); - }); - return result; + return input.match(/(\w)+/g) || []; } exports.stringToArray = stringToArray; diff --git a/client/plugins/databasemanager/src/loadouteditor.ts b/client/plugins/databasemanager/src/loadouteditor.ts index 73fe32e1..5f07c605 100644 --- a/client/plugins/databasemanager/src/loadouteditor.ts +++ b/client/plugins/databasemanager/src/loadouteditor.ts @@ -37,10 +37,10 @@ export class LoadoutEditor { this.#contentDiv.appendChild(title); if (this.#loadout) { - var laodout = this.#loadout; - addStringInput(this.#contentDiv, "Name", laodout.name, "text", (value: string) => {laodout.name = value; this.#contentDiv.dispatchEvent(new Event("refresh"));}); - addStringInput(this.#contentDiv, "Code", laodout.code, "text", (value: string) => {laodout.code = value; }); - addStringInput(this.#contentDiv, "Roles", arrayToString(laodout.roles), "text", (value: string) => {laodout.roles = stringToArray(value);}); + var loadout = this.#loadout; + addStringInput(this.#contentDiv, "Name", loadout.name, "text", (value: string) => {loadout.name = value; this.#contentDiv.dispatchEvent(new Event("refresh"));}); + addStringInput(this.#contentDiv, "Code", loadout.code, "text", (value: string) => {loadout.code = value; }); + addStringInput(this.#contentDiv, "Roles", arrayToString(loadout.roles), "text", (value: string) => {loadout.roles = stringToArray(value);}); addLoadoutItemsEditor(this.#contentDiv, this.#loadout); } } diff --git a/client/plugins/databasemanager/src/utils.ts b/client/plugins/databasemanager/src/utils.ts index 19cec041..59594c83 100644 --- a/client/plugins/databasemanager/src/utils.ts +++ b/client/plugins/databasemanager/src/utils.ts @@ -269,5 +269,5 @@ export function arrayToString(array: string[]) { export function stringToArray(input: string) { - return input.match( /(\w)+/g ); + return input.match( /(\w)+/g ) || []; } \ No newline at end of file diff --git a/client/src/contextmenus/mapcontextmenu.ts b/client/src/contextmenus/mapcontextmenu.ts index f7924fcd..30006313 100644 --- a/client/src/contextmenus/mapcontextmenu.ts +++ b/client/src/contextmenus/mapcontextmenu.ts @@ -4,7 +4,7 @@ import { ContextMenu } from "./contextmenu"; import { Switch } from "../controls/switch"; import { GAME_MASTER } from "../constants/constants"; import { CoalitionArea } from "../map/coalitionarea/coalitionarea"; -import { AircraftSpawnMenu, GroundUnitSpawnMenu, HelicopterSpawnMenu, NavyUnitSpawnMenu } from "../controls/unitspawnmenu"; +import { AirDefenceUnitSpawnMenu, AircraftSpawnMenu, GroundUnitSpawnMenu, HelicopterSpawnMenu, NavyUnitSpawnMenu } from "../controls/unitspawnmenu"; import { Airbase } from "../mission/airbase"; import { SmokeMarker } from "../map/markers/smokemarker"; @@ -15,6 +15,7 @@ export class MapContextMenu extends ContextMenu { #coalitionSwitch: Switch; #aircraftSpawnMenu: AircraftSpawnMenu; #helicopterSpawnMenu: HelicopterSpawnMenu; + #airDefenceUnitSpawnMenu: AirDefenceUnitSpawnMenu; #groundUnitSpawnMenu: GroundUnitSpawnMenu; #navyUnitSpawnMenu: NavyUnitSpawnMenu; #coalitionArea: CoalitionArea | null = null; @@ -35,6 +36,7 @@ export class MapContextMenu extends ContextMenu { /* Create the spawn menus for the different unit types */ this.#aircraftSpawnMenu = new AircraftSpawnMenu("aircraft-spawn-menu"); this.#helicopterSpawnMenu = new HelicopterSpawnMenu("helicopter-spawn-menu"); + this.#airDefenceUnitSpawnMenu = new AirDefenceUnitSpawnMenu("air-defence-spawn-menu"); this.#groundUnitSpawnMenu = new GroundUnitSpawnMenu("groundunit-spawn-menu"); this.#navyUnitSpawnMenu = new NavyUnitSpawnMenu("navyunit-spawn-menu"); @@ -73,21 +75,25 @@ export class MapContextMenu extends ContextMenu { this.#aircraftSpawnMenu.getContainer().addEventListener("resize", () => this.clip()); this.#helicopterSpawnMenu.getContainer().addEventListener("resize", () => this.clip()); + this.#airDefenceUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip()); this.#groundUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip()); this.#navyUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip()); this.#aircraftSpawnMenu.getContainer().addEventListener("hide", () => this.hide()); this.#helicopterSpawnMenu.getContainer().addEventListener("hide", () => this.hide()); + this.#airDefenceUnitSpawnMenu.getContainer().addEventListener("hide", () => this.hide()); this.#groundUnitSpawnMenu.getContainer().addEventListener("hide", () => this.hide()); this.#navyUnitSpawnMenu.getContainer().addEventListener("hide", () => this.hide()); this.getContainer()?.addEventListener("show", () => this.#aircraftSpawnMenu.showCirclesPreviews()); this.getContainer()?.addEventListener("show", () => this.#helicopterSpawnMenu.showCirclesPreviews()); + this.getContainer()?.addEventListener("show", () => this.#airDefenceUnitSpawnMenu.showCirclesPreviews()); this.getContainer()?.addEventListener("show", () => this.#groundUnitSpawnMenu.showCirclesPreviews()); this.getContainer()?.addEventListener("show", () => this.#navyUnitSpawnMenu.showCirclesPreviews()); this.getContainer()?.addEventListener("hide", () => this.#aircraftSpawnMenu.clearCirclesPreviews()); this.getContainer()?.addEventListener("hide", () => this.#helicopterSpawnMenu.clearCirclesPreviews()); + this.getContainer()?.addEventListener("hide", () => this.#airDefenceUnitSpawnMenu.clearCirclesPreviews()); this.getContainer()?.addEventListener("hide", () => this.#groundUnitSpawnMenu.clearCirclesPreviews()); this.getContainer()?.addEventListener("hide", () => this.#navyUnitSpawnMenu.clearCirclesPreviews()); } @@ -103,11 +109,13 @@ export class MapContextMenu extends ContextMenu { this.#aircraftSpawnMenu.setLatLng(latlng); this.#helicopterSpawnMenu.setLatLng(latlng); + this.#airDefenceUnitSpawnMenu.setLatLng(latlng); this.#groundUnitSpawnMenu.setLatLng(latlng); this.#navyUnitSpawnMenu.setLatLng(latlng); this.#aircraftSpawnMenu.setCountries(); this.#helicopterSpawnMenu.setCountries(); + this.#airDefenceUnitSpawnMenu.setCountries(); this.#groundUnitSpawnMenu.setCountries(); this.#navyUnitSpawnMenu.setCountries(); @@ -143,7 +151,7 @@ export class MapContextMenu extends ContextMenu { #showSubMenu(type: string) { if (type === "more") this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide"); - else if (["aircraft", "helicopter", "groundunit"].includes(type)) + else if (["aircraft", "helicopter", "air-defence", "groundunit"].includes(type)) this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide", true); this.getContainer()?.querySelector("#aircraft-spawn-menu")?.classList.toggle("hide", type !== "aircraft"); @@ -152,6 +160,8 @@ export class MapContextMenu extends ContextMenu { this.getContainer()?.querySelector("#helicopter-spawn-button")?.classList.toggle("is-open", type === "helicopter"); this.getContainer()?.querySelector("#groundunit-spawn-menu")?.classList.toggle("hide", type !== "groundunit"); this.getContainer()?.querySelector("#groundunit-spawn-button")?.classList.toggle("is-open", type === "groundunit"); + this.getContainer()?.querySelector("#air-defence-spawn-menu")?.classList.toggle("hide", type !== "air-defence"); + this.getContainer()?.querySelector("#air-defence-spawn-button")?.classList.toggle("is-open", type === "air-defence"); this.getContainer()?.querySelector("#navyunit-spawn-menu")?.classList.toggle("hide", type !== "navyunit"); this.getContainer()?.querySelector("#navyunit-spawn-button")?.classList.toggle("is-open", type === "navyunit"); this.getContainer()?.querySelector("#smoke-spawn-menu")?.classList.toggle("hide", type !== "smoke"); @@ -167,6 +177,9 @@ export class MapContextMenu extends ContextMenu { this.#helicopterSpawnMenu.reset(); this.#helicopterSpawnMenu.setCountries(); this.#helicopterSpawnMenu.clearCirclesPreviews(); + this.#airDefenceUnitSpawnMenu.reset(); + this.#airDefenceUnitSpawnMenu.setCountries(); + this.#airDefenceUnitSpawnMenu.clearCirclesPreviews(); this.#groundUnitSpawnMenu.reset(); this.#groundUnitSpawnMenu.setCountries(); this.#groundUnitSpawnMenu.clearCirclesPreviews(); @@ -200,11 +213,13 @@ export class MapContextMenu extends ContextMenu { this.#aircraftSpawnMenu.reset(); this.#helicopterSpawnMenu.reset(); + this.#airDefenceUnitSpawnMenu.reset(); this.#groundUnitSpawnMenu.reset(); this.#navyUnitSpawnMenu.reset(); this.#aircraftSpawnMenu.clearCirclesPreviews(); this.#helicopterSpawnMenu.clearCirclesPreviews(); + this.#airDefenceUnitSpawnMenu.clearCirclesPreviews(); this.#groundUnitSpawnMenu.clearCirclesPreviews(); this.#navyUnitSpawnMenu.clearCirclesPreviews(); @@ -221,6 +236,7 @@ export class MapContextMenu extends ContextMenu { this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getApp().getActiveCoalition()) }); this.#aircraftSpawnMenu.setCountries(); this.#helicopterSpawnMenu.setCountries(); + this.#airDefenceUnitSpawnMenu.setCountries(); this.#groundUnitSpawnMenu.setCountries(); this.#navyUnitSpawnMenu.setCountries(); } @@ -234,6 +250,7 @@ export class MapContextMenu extends ContextMenu { this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getApp().getActiveCoalition()) }); this.#aircraftSpawnMenu.setCountries(); this.#helicopterSpawnMenu.setCountries(); + this.#airDefenceUnitSpawnMenu.setCountries(); this.#groundUnitSpawnMenu.setCountries(); this.#navyUnitSpawnMenu.setCountries(); } diff --git a/client/src/controls/unitspawnmenu.ts b/client/src/controls/unitspawnmenu.ts index 0ed023d1..adfbd68e 100644 --- a/client/src/controls/unitspawnmenu.ts +++ b/client/src/controls/unitspawnmenu.ts @@ -31,6 +31,7 @@ export class UnitSpawnMenu { #unitDatabase: UnitDatabase; #countryCodes: any; #orderByRole: boolean; + protected unitTypeFilter = (unit:any) => { return true; }; /* Controls */ #unitRoleTypeDropdown: Dropdown; @@ -258,7 +259,7 @@ export class UnitSpawnMenu { if (this.#orderByRole) this.#unitRoleTypeDropdown.setOptions(this.#unitDatabase.getRoles()); else - this.#unitRoleTypeDropdown.setOptions(this.#unitDatabase.getTypes()); + this.#unitRoleTypeDropdown.setOptions(this.#unitDatabase.getTypes(this.unitTypeFilter)); this.#unitLoadoutListEl.replaceChildren(); this.#unitLoadoutDropdown.reset(); @@ -582,9 +583,52 @@ export class HelicopterSpawnMenu extends UnitSpawnMenu { } } +export class AirDefenceUnitSpawnMenu extends UnitSpawnMenu { + + protected showRangeCircles: boolean = true; + protected unitTypeFilter = (unit:any) => {return /\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type)}; + + /** + * + * @param ID - the ID of the HTML element which will contain the context menu + */ + constructor(ID: string){ + super(ID, groundUnitDatabase, false); + this.setMaxUnitCount(4); + this.getAltitudeSlider().hide(); + this.getLoadoutDropdown().hide(); + this.getLoadoutPreview().classList.add("hide"); + } + + deployUnits(spawnOptions: UnitSpawnOptions, unitsCount: number) { + spawnOptions.coalition = getApp().getActiveCoalition(); + if (spawnOptions) { + var unitTable: UnitSpawnTable = { + unitType: spawnOptions.name, + location: spawnOptions.latlng, + liveryID: spawnOptions.liveryID? spawnOptions.liveryID: "" + }; + + var units = []; + for (let i = 0; i < unitsCount; i++) { + units.push(JSON.parse(JSON.stringify(unitTable))); + unitTable.location.lat += i > 0? 0.0001: 0; + } + + getApp().getUnitsManager().spawnUnits("GroundUnit", units, getApp().getActiveCoalition(), false, spawnOptions.airbase ? spawnOptions.airbase.getName() : "", spawnOptions.country, (res: any) => { + if (res.commandHash !== undefined) + getApp().getMap().addTemporaryMarker(spawnOptions.latlng, spawnOptions.name, getApp().getActiveCoalition(), res.commandHash); + }); + + this.getContainer().dispatchEvent(new Event("hide")); + } + } +} + export class GroundUnitSpawnMenu extends UnitSpawnMenu { protected showRangeCircles: boolean = true; + protected unitTypeFilter = (unit:any) => {return !(/\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type))}; /** * diff --git a/client/src/unit/databases/unitdatabase.ts b/client/src/unit/databases/unitdatabase.ts index ba7c41cc..94c8acca 100644 --- a/client/src/unit/databases/unitdatabase.ts +++ b/client/src/unit/databases/unitdatabase.ts @@ -94,10 +94,12 @@ export class UnitDatabase { } /* Returns a list of all possible types in a database */ - getTypes() { + getTypes(unitFilter?:CallableFunction) { var filteredBlueprints = this.getBlueprints(); var types: string[] = []; for (let unit in filteredBlueprints) { + if ( typeof unitFilter === "function" && !unitFilter(filteredBlueprints[unit])) + continue; var type = filteredBlueprints[unit].type; if (type && type !== "" && !types.includes(type)) types.push(type); diff --git a/client/views/contextmenus/map.ejs b/client/views/contextmenus/map.ejs index 75533346..ae4de75d 100644 --- a/client/views/contextmenus/map.ejs +++ b/client/views/contextmenus/map.ejs @@ -6,6 +6,8 @@ data-on-click-params='{ "type": "aircraft" }' class="ol-contexmenu-button"> + From 5db90e589651c93852961642449096c1c4f793df Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Sun, 5 Nov 2023 19:24:23 +0000 Subject: [PATCH 2/3] Changed air defence form to extend ground units' form --- client/src/controls/unitspawnmenu.ts | 56 +++++++--------------------- 1 file changed, 14 insertions(+), 42 deletions(-) diff --git a/client/src/controls/unitspawnmenu.ts b/client/src/controls/unitspawnmenu.ts index adfbd68e..b0ee3fd4 100644 --- a/client/src/controls/unitspawnmenu.ts +++ b/client/src/controls/unitspawnmenu.ts @@ -583,48 +583,6 @@ export class HelicopterSpawnMenu extends UnitSpawnMenu { } } -export class AirDefenceUnitSpawnMenu extends UnitSpawnMenu { - - protected showRangeCircles: boolean = true; - protected unitTypeFilter = (unit:any) => {return /\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type)}; - - /** - * - * @param ID - the ID of the HTML element which will contain the context menu - */ - constructor(ID: string){ - super(ID, groundUnitDatabase, false); - this.setMaxUnitCount(4); - this.getAltitudeSlider().hide(); - this.getLoadoutDropdown().hide(); - this.getLoadoutPreview().classList.add("hide"); - } - - deployUnits(spawnOptions: UnitSpawnOptions, unitsCount: number) { - spawnOptions.coalition = getApp().getActiveCoalition(); - if (spawnOptions) { - var unitTable: UnitSpawnTable = { - unitType: spawnOptions.name, - location: spawnOptions.latlng, - liveryID: spawnOptions.liveryID? spawnOptions.liveryID: "" - }; - - var units = []; - for (let i = 0; i < unitsCount; i++) { - units.push(JSON.parse(JSON.stringify(unitTable))); - unitTable.location.lat += i > 0? 0.0001: 0; - } - - getApp().getUnitsManager().spawnUnits("GroundUnit", units, getApp().getActiveCoalition(), false, spawnOptions.airbase ? spawnOptions.airbase.getName() : "", spawnOptions.country, (res: any) => { - if (res.commandHash !== undefined) - getApp().getMap().addTemporaryMarker(spawnOptions.latlng, spawnOptions.name, getApp().getActiveCoalition(), res.commandHash); - }); - - this.getContainer().dispatchEvent(new Event("hide")); - } - } -} - export class GroundUnitSpawnMenu extends UnitSpawnMenu { protected showRangeCircles: boolean = true; @@ -667,6 +625,20 @@ export class GroundUnitSpawnMenu extends UnitSpawnMenu { } } +export class AirDefenceUnitSpawnMenu extends GroundUnitSpawnMenu { + + protected unitTypeFilter = (unit:any) => {return /\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type)}; + + /** + * + * @param ID - the ID of the HTML element which will contain the context menu + */ + constructor(ID: string){ + super(ID); + this.setMaxUnitCount(4); + } +} + export class NavyUnitSpawnMenu extends UnitSpawnMenu { /** * From e1f404c647543030dab10387034190f2730a8a63 Mon Sep 17 00:00:00 2001 From: PeekabooSteam Date: Mon, 6 Nov 2023 22:28:44 +0000 Subject: [PATCH 3/3] Added some doc comments --- client/@types/olympus/index.d.ts | 13 +++++- client/src/unit/unit.ts | 70 ++++++++++++++++++++++++++++++-- 2 files changed, 79 insertions(+), 4 deletions(-) diff --git a/client/@types/olympus/index.d.ts b/client/@types/olympus/index.d.ts index 95f77f6b..3cf448d8 100644 --- a/client/@types/olympus/index.d.ts +++ b/client/@types/olympus/index.d.ts @@ -659,7 +659,7 @@ declare module "unit/databases/unitdatabase" { [key: string]: UnitBlueprint; }; getRoles(): string[]; - getTypes(): string[]; + getTypes(unitFilter?: CallableFunction): string[]; getEras(): string[]; getByRange(range: string): UnitBlueprint[]; getByType(type: string): UnitBlueprint[]; @@ -810,6 +810,7 @@ declare module "controls/unitspawnmenu" { #private; protected showRangeCircles: boolean; protected spawnOptions: UnitSpawnOptions; + protected unitTypeFilter: (unit: any) => boolean; constructor(ID: string, unitDatabase: UnitDatabase, orderByRole: boolean); getContainer(): HTMLElement; getVisible(): boolean; @@ -849,6 +850,7 @@ declare module "controls/unitspawnmenu" { } export class GroundUnitSpawnMenu extends UnitSpawnMenu { protected showRangeCircles: boolean; + protected unitTypeFilter: (unit: any) => boolean; /** * * @param ID - the ID of the HTML element which will contain the context menu @@ -856,6 +858,14 @@ declare module "controls/unitspawnmenu" { constructor(ID: string); deployUnits(spawnOptions: UnitSpawnOptions, unitsCount: number): void; } + export class AirDefenceUnitSpawnMenu extends GroundUnitSpawnMenu { + protected unitTypeFilter: (unit: any) => boolean; + /** + * + * @param ID - the ID of the HTML element which will contain the context menu + */ + constructor(ID: string); + } export class NavyUnitSpawnMenu extends UnitSpawnMenu { /** * @@ -1510,6 +1520,7 @@ declare module "map/map" { [key: string]: boolean; }; unitIsProtected(unit: Unit): boolean; + getMapMarkerControls(): MapMarkerControl[]; } } declare module "mission/bullseye" { diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts index 22f6b214..a8a13198 100644 --- a/client/src/unit/unit.ts +++ b/client/src/unit/unit.ts @@ -18,6 +18,11 @@ var pathIcon = new Icon({ iconAnchor: [13, 41] }); +/** + * Unit class which controls unit behaviour + * + * Just about everything is a unit - even missiles! + */ export class Unit extends CustomMarker { ID: number; @@ -279,6 +284,10 @@ export class Unit extends CustomMarker { } } + /** Get unit data collated into an object + * + * @returns object populated by unit information which can also be retrieved using getters + */ getData(): UnitData { return { category: this.getCategory(), @@ -328,14 +337,27 @@ export class Unit extends CustomMarker { } } + /** + * + * @returns string containing the marker category + */ getMarkerCategory(): string { return getMarkerCategoryByName(this.getName()); } + /** Get a database of information also in this unit's category + * + * @returns UnitDatabase + */ getDatabase(): UnitDatabase | null { return getUnitDatabaseByCategory(this.getMarkerCategory()); } + /** Get the icon options + * Used to configure how the marker appears on the map + * + * @returns ObjectIconOptions + */ getIconOptions(): ObjectIconOptions { // Default values, overloaded by child classes if needed return { @@ -352,12 +374,20 @@ export class Unit extends CustomMarker { } } + /** Set the unit as alive or dead + * + * @param newAlive (boolean) true = alive, false = dead + */ setAlive(newAlive: boolean) { if (newAlive != this.#alive) document.dispatchEvent(new CustomEvent("unitDeath", { detail: this })); this.#alive = newAlive; } + /** Set the unit as user-selected + * + * @param selected (boolean) + */ setSelected(selected: boolean) { /* Only alive units can be selected. Some units are not selectable (weapons) */ if ((this.#alive || !selected) && this.getSelectable() && this.getSelected() != selected && this.belongsToCommandedCoalition()) { @@ -396,27 +426,51 @@ export class Unit extends CustomMarker { } } + /** Is this unit selected? + * + * @returns boolean + */ getSelected() { return this.#selected; } + /** Set whether this unit is selectable + * + * @param selectable (boolean) + */ setSelectable(selectable: boolean) { this.#selectable = selectable; } + /** Get whether this unit is selectable + * + * @returns boolean + */ getSelectable() { return this.#selectable; } + /** Set the number of the hotgroup to which the unit belongs + * + * @param hotgroup (number) + */ setHotgroup(hotgroup: number | null) { this.#hotgroup = hotgroup; this.#updateMarker(); } + /** Get the unit's hotgroup number + * + * @returns number + */ getHotgroup() { return this.#hotgroup; } + /** Set the unit as highlighted + * + * @param highlighted (boolean) + */ setHighlighted(highlighted: boolean) { if (this.getSelectable() && this.#highlighted != highlighted) { this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted); @@ -425,18 +479,28 @@ export class Unit extends CustomMarker { } } + /** Get whether the unit is highlighted or not + * + * @returns boolean + */ getHighlighted() { return this.#highlighted; } + /** Get the other members of the group which this unit is in + * + * @returns Unit[] + */ getGroupMembers() { return Object.values(getApp().getUnitsManager().getUnits()).filter((unit: Unit) => { return unit != this && unit.getGroupName() === this.getGroupName(); }); } + /** Returns whether the user is allowed to command this unit, based on coalition + * + * @returns boolean + */ belongsToCommandedCoalition() { - if (getApp().getMissionManager().getCommandModeOptions().commandMode !== GAME_MASTER && getApp().getMissionManager().getCommandedCoalition() !== this.#coalition) - return false; - return true; + return (getApp().getMissionManager().getCommandModeOptions().commandMode !== GAME_MASTER && getApp().getMissionManager().getCommandedCoalition() !== this.#coalition) ? false : true; } getType() {