From 3009a73a665556d6e6eac754d76a2ea692856fe2 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Wed, 24 May 2023 11:07:41 +0200 Subject: [PATCH] Completed transition to injected svgs --- client/package-lock.json | 35 ---- client/public/stylesheets/markers/units.css | 26 +-- .../public/stylesheets/other/contextmenus.css | 7 +- .../public/stylesheets/panels/mouseinfo.css | 2 +- .../formations/icons_form_abreast_dark.svg | 5 - .../formations/icons_form_abreast_light.svg | 5 - .../formations/icons_form_admin_dark.svg | 4 - .../formations/icons_form_admin_light.svg | 4 - .../formations/icons_form_echelon_dark.svg | 5 - .../formations/icons_form_echelon_light.svg | 5 - .../formations/icons_form_trail_dark.svg | 5 - .../formations/icons_form_trail_light.svg | 5 - .../themes/olympus/images/icons/diamond.svg | 73 +++++++ client/src/@types/unit.d.ts | 12 ++ client/src/controls/dropdown.ts | 5 +- client/src/controls/slider.ts | 2 +- client/src/controls/unitcontextmenu.ts | 13 +- client/src/index.ts | 35 +--- client/src/map/custommarker.ts | 3 +- client/src/map/map.ts | 24 ++- client/src/panels/hotgrouppanel.ts | 20 +- client/src/panels/unitcontrolpanel.ts | 6 +- client/src/units/unit.ts | 189 +++++++++++------- client/src/units/unitdatabase.ts | 53 ++--- client/src/units/unitsmanager.ts | 83 ++++---- scripts/OlympusCommand.lua | 10 +- 26 files changed, 333 insertions(+), 303 deletions(-) delete mode 100644 client/public/themes/olympus/images/formations/icons_form_abreast_dark.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_abreast_light.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_admin_dark.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_admin_light.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_echelon_dark.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_echelon_light.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_trail_dark.svg delete mode 100644 client/public/themes/olympus/images/formations/icons_form_trail_light.svg create mode 100644 client/public/themes/olympus/images/icons/diamond.svg diff --git a/client/package-lock.json b/client/package-lock.json index 44990dba..05df666f 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -14,17 +14,14 @@ "debug": "~2.6.9", "ejs": "^3.1.8", "express": "~4.16.1", - "geomag": "^1.0.0", "leaflet": "^1.9.3", "leaflet-control-mini-map": "^0.4.0", "leaflet.nauticscale": "^1.1.0", - "milsymbol": "^2.0.0", "morgan": "~1.9.1", "save": "^2.9.0" }, "devDependencies": { "@babel/preset-env": "^7.21.4", - "@iconfu/svg-inject": "^1.2.3", "@tanem/svg-injector": "^10.1.55", "@types/gtag.js": "^0.0.12", "@types/node": "^18.16.1", @@ -1772,12 +1769,6 @@ "node": ">=6.9.0" } }, - "node_modules/@iconfu/svg-inject": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@iconfu/svg-inject/-/svg-inject-1.2.3.tgz", - "integrity": "sha512-3v1MUAJqmJS4jmhHoCkSxt+EdJrjPHlLXrWocCT25kCxnxJto8028Z6CC406EL11KA53SDZgI/QQA5GEJAoiRw==", - "dev": true - }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -3454,11 +3445,6 @@ "node": ">=6.9.0" } }, - "node_modules/geomag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/geomag/-/geomag-1.0.0.tgz", - "integrity": "sha512-mEblE1vO7HojL7nk2R2s670s1nc/u0jtQaP/8EvZxPZ7XlfkwEJ+TWpjgkNy2402Yj2/VaxaefGQgIzbUzUwHg==" - }, "node_modules/get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -4161,11 +4147,6 @@ "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==", "dev": true }, - "node_modules/milsymbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/milsymbol/-/milsymbol-2.0.0.tgz", - "integrity": "sha512-GcBFrcIUr8jScaZqZb0SI2W6AbnUrPCTHu2kqHxduQjN2DIN8q5pY6ksSWfnJ4HlcIAWQhyotbdPIr1bBxFbwQ==" - }, "node_modules/mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", @@ -6919,12 +6900,6 @@ "to-fast-properties": "^2.0.0" } }, - "@iconfu/svg-inject": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/@iconfu/svg-inject/-/svg-inject-1.2.3.tgz", - "integrity": "sha512-3v1MUAJqmJS4jmhHoCkSxt+EdJrjPHlLXrWocCT25kCxnxJto8028Z6CC406EL11KA53SDZgI/QQA5GEJAoiRw==", - "dev": true - }, "@jridgewell/gen-mapping": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", @@ -8320,11 +8295,6 @@ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true }, - "geomag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/geomag/-/geomag-1.0.0.tgz", - "integrity": "sha512-mEblE1vO7HojL7nk2R2s670s1nc/u0jtQaP/8EvZxPZ7XlfkwEJ+TWpjgkNy2402Yj2/VaxaefGQgIzbUzUwHg==" - }, "get-assigned-identifiers": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-assigned-identifiers/-/get-assigned-identifiers-1.2.0.tgz", @@ -8856,11 +8826,6 @@ } } }, - "milsymbol": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/milsymbol/-/milsymbol-2.0.0.tgz", - "integrity": "sha512-GcBFrcIUr8jScaZqZb0SI2W6AbnUrPCTHu2kqHxduQjN2DIN8q5pY6ksSWfnJ4HlcIAWQhyotbdPIr1bBxFbwQ==" - }, "mime": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", diff --git a/client/public/stylesheets/markers/units.css b/client/public/stylesheets/markers/units.css index 056a92d3..43bc53a0 100644 --- a/client/public/stylesheets/markers/units.css +++ b/client/public/stylesheets/markers/units.css @@ -205,10 +205,10 @@ display: flex; } -[data-object|="unit"][data-has-fox-1] .unit-ammo-fox-1, -[data-object|="unit"][data-has-fox-2] .unit-ammo-fox-2, -[data-object|="unit"][data-has-fox-3] .unit-ammo-fox-3, -[data-object|="unit"][data-has-other-ammo] .unit-ammo-other { +[data-object|="unit"][data-has-fox-1] .unit-ammo>div:nth-child(1), +[data-object|="unit"][data-has-fox-2] .unit-ammo>div:nth-child(2), +[data-object|="unit"][data-has-fox-3] .unit-ammo>div:nth-child(3), +[data-object|="unit"][data-has-other-ammo] .unit-ammo>div:nth-child(4) { background-color: var(--secondary-gunmetal-grey); } @@ -217,10 +217,10 @@ } [data-object|="unit"][data-coalition="blue"] .unit-fuel-level, -[data-object|="unit"][data-coalition="blue"][data-has-fox-1] .unit-ammo-fox-1, -[data-object|="unit"][data-coalition="blue"][data-has-fox-2] .unit-ammo-fox-2, -[data-object|="unit"][data-coalition="blue"][data-has-fox-3] .unit-ammo-fox-3, -[data-object|="unit"][data-coalition="blue"][data-has-other-ammo] .unit-ammo-other { +[data-object|="unit"][data-coalition="blue"][data-has-fox-1] .unit-ammo>div:nth-child(1), +[data-object|="unit"][data-coalition="blue"][data-has-fox-2] .unit-ammo>div:nth-child(2), +[data-object|="unit"][data-coalition="blue"][data-has-fox-3] .unit-ammo>div:nth-child(3), +[data-object|="unit"][data-coalition="blue"][data-has-other-ammo] .unit-ammo>div:nth-child(4) { background-color: var(--primary-blue); } @@ -233,10 +233,10 @@ } [data-object|="unit"][data-coalition="red"] .unit-fuel-level, -[data-object|="unit"][data-coalition="red"][data-has-fox-1] .unit-ammo-fox-1, -[data-object|="unit"][data-coalition="red"][data-has-fox-2] .unit-ammo-fox-2, -[data-object|="unit"][data-coalition="red"][data-has-fox-3] .unit-ammo-fox-3, -[data-object|="unit"][data-coalition="red"][data-has-other-ammo] .unit-ammo-other { +[data-object|="unit"][data-coalition="red"][data-has-fox-1] .unit-ammo>div:nth-child(1), +[data-object|="unit"][data-coalition="red"][data-has-fox-2] .unit-ammo>div:nth-child(2), +[data-object|="unit"][data-coalition="red"][data-has-fox-3] .unit-ammo>div:nth-child(3), +[data-object|="unit"][data-coalition="red"][data-has-other-ammo] .unit-ammo>div:nth-child(4) { background-color: var(--primary-red); } @@ -250,6 +250,8 @@ height: 20px; position: absolute; width: 20px; + left: 0px; + top: 0px; } [data-object|="unit"][data-state="rtb"] .unit-state { diff --git a/client/public/stylesheets/other/contextmenus.css b/client/public/stylesheets/other/contextmenus.css index 361a6a0b..9e325678 100644 --- a/client/public/stylesheets/other/contextmenus.css +++ b/client/public/stylesheets/other/contextmenus.css @@ -307,7 +307,8 @@ content: url("/resources/theme/images/icons/echelon-rh.svg"); } -#line-abreast::before { +#line-abreast-rh::before, +#line-abreast-lh::before { content: url("/resources/theme/images/icons/line-abreast.svg"); } @@ -315,6 +316,10 @@ content: url("/resources/theme/images/icons/front.svg"); } +#diamond::before { + content: url("/resources/theme/images/icons/diamond.svg"); +} + #custom::before { content: url("/resources/theme/images/icons/custom.svg"); } diff --git a/client/public/stylesheets/panels/mouseinfo.css b/client/public/stylesheets/panels/mouseinfo.css index cfbb70c6..1c3d5e2e 100644 --- a/client/public/stylesheets/panels/mouseinfo.css +++ b/client/public/stylesheets/panels/mouseinfo.css @@ -39,7 +39,7 @@ } #mouse-info-panel dt#ref-measure-position::after { - background-image: url("/resources/theme/images/pin.png"); + background-image: url("/resources/theme/images/icons/pin.png"); background-position: 50% 50%; background-repeat: no-repeat; background-size: 16px 16px; diff --git a/client/public/themes/olympus/images/formations/icons_form_abreast_dark.svg b/client/public/themes/olympus/images/formations/icons_form_abreast_dark.svg deleted file mode 100644 index 513d6b25..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_abreast_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_abreast_light.svg b/client/public/themes/olympus/images/formations/icons_form_abreast_light.svg deleted file mode 100644 index 0b302a04..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_abreast_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_admin_dark.svg b/client/public/themes/olympus/images/formations/icons_form_admin_dark.svg deleted file mode 100644 index 44e42f62..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_admin_dark.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_admin_light.svg b/client/public/themes/olympus/images/formations/icons_form_admin_light.svg deleted file mode 100644 index 532c523f..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_admin_light.svg +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_echelon_dark.svg b/client/public/themes/olympus/images/formations/icons_form_echelon_dark.svg deleted file mode 100644 index dc4b4b60..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_echelon_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_echelon_light.svg b/client/public/themes/olympus/images/formations/icons_form_echelon_light.svg deleted file mode 100644 index a788953d..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_echelon_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_trail_dark.svg b/client/public/themes/olympus/images/formations/icons_form_trail_dark.svg deleted file mode 100644 index 555ea0dd..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_trail_dark.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/formations/icons_form_trail_light.svg b/client/public/themes/olympus/images/formations/icons_form_trail_light.svg deleted file mode 100644 index 0ac432f7..00000000 --- a/client/public/themes/olympus/images/formations/icons_form_trail_light.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/client/public/themes/olympus/images/icons/diamond.svg b/client/public/themes/olympus/images/icons/diamond.svg new file mode 100644 index 00000000..eef3c6f2 --- /dev/null +++ b/client/public/themes/olympus/images/icons/diamond.svg @@ -0,0 +1,73 @@ + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/client/src/@types/unit.d.ts b/client/src/@types/unit.d.ts index f3741e27..e6b1b345 100644 --- a/client/src/@types/unit.d.ts +++ b/client/src/@types/unit.d.ts @@ -79,4 +79,16 @@ interface GeneralSettings { prohibitAG: boolean; prohibitAfterburner: boolean; prohibitAirWpn: boolean; +} + +interface UnitIconOptions { + showState: boolean, + showVvi: boolean, + showHotgroup: boolean, + showUnitIcon: boolean, + showShortLabel: boolean, + showFuel: boolean, + showAmmo: boolean, + showSummary: boolean, + rotateToHeading: boolean } \ No newline at end of file diff --git a/client/src/controls/dropdown.ts b/client/src/controls/dropdown.ts index 641c405f..01aae36e 100644 --- a/client/src/controls/dropdown.ts +++ b/client/src/controls/dropdown.ts @@ -67,7 +67,10 @@ export class Dropdown { selectValue(idx: number) { if (idx < this.#optionsList.length) { var option = this.#optionsList[idx]; - this.#value.innerHTML = `
${option}
`; + var el = document.createElement("div"); + el.classList.add("ol-ellipsed"); + el.innerText = option; + this.#value.appendChild(el); this.#index = idx; this.#close(); this.#callback(option); diff --git a/client/src/controls/slider.ts b/client/src/controls/slider.ts index 7fab7782..e8070d2e 100644 --- a/client/src/controls/slider.ts +++ b/client/src/controls/slider.ts @@ -88,7 +88,7 @@ export class Slider { #onValue() { if (this.#valueText != null && this.#slider != null) - this.#valueText.innerHTML = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit + this.#valueText.innerText = this.#minValue + Math.round(parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue)) + this.#unit this.setActive(true); } diff --git a/client/src/controls/unitcontextmenu.ts b/client/src/controls/unitcontextmenu.ts index 86250e6d..4acbaf3e 100644 --- a/client/src/controls/unitcontextmenu.ts +++ b/client/src/controls/unitcontextmenu.ts @@ -40,11 +40,16 @@ export class UnitContextMenu extends ContextMenu { this.#customFormationCallback = callback; } - setOptions(options: { [key: string]: string }, callback: CallableFunction) { - this.getContainer()?.replaceChildren(...Object.keys(options).map((option: string, idx: number) => { + setOptions(options: { [key: string]: {text: string, tooltip: string }}, callback: CallableFunction) { + this.getContainer()?.replaceChildren(...Object.keys(options).map((key: string, idx: number) => { + const option = options[key]; var button = document.createElement("button"); - button.innerHTML = options[option]; - button.addEventListener("click", () => callback(option)); + var el = document.createElement("div"); + el.title = option.tooltip; + el.innerText = option.text; + el.id = key; + button.addEventListener("click", () => callback(key)); + button.appendChild(el); return (button); })); } diff --git a/client/src/index.ts b/client/src/index.ts index 16d9a8b2..c2f8a1b6 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -140,28 +140,14 @@ function setupEvents() { case "Space": setPaused(!getPaused()); break; - case "KeyW": - case "KeyA": - case "KeyS": - case "KeyD": - case "ArrowLeft": - case "ArrowRight": - case "ArrowUp": - case "ArrowDown": + case "KeyW": case "KeyA": case "KeyS": case "KeyD": + case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown": getMap().handleMapPanning(ev); break; - case "Digit1": - case "Digit2": - case "Digit3": - case "Digit4": - case "Digit5": - case "Digit6": - case "Digit7": - case "Digit8": - case "Digit9": + case "Digit1": case "Digit2": case "Digit3": case "Digit4": case "Digit5": case "Digit6": case "Digit7": case "Digit8": case "Digit9": // Using the substring because the key will be invalid when pressing the Shift key if (ev.ctrlKey && ev.shiftKey) - getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5))); + getUnitsManager().selectedUnitsAddToHotgroup(parseInt(ev.code.substring(5))); else if (ev.ctrlKey && !ev.shiftKey) getUnitsManager().selectedUnitsSetHotgroup(parseInt(ev.code.substring(5))); else @@ -176,14 +162,7 @@ function setupEvents() { return; } switch (ev.code) { - case "KeyW": - case "KeyA": - case "KeyS": - case "KeyD": - case "ArrowLeft": - case "ArrowRight": - case "ArrowUp": - case "ArrowDown": + case "KeyW": case "KeyA": case "KeyS": case "KeyD": case "ArrowLeft": case "ArrowRight": case "ArrowUp": case "ArrowDown": getMap().handleMapPanning(ev); break; } @@ -201,8 +180,8 @@ function setupEvents() { document.addEventListener("tryConnection", () => { const form = document.querySelector("#splash-content")?.querySelector("#authentication-form"); - const username = ( (form?.querySelector("#username"))).value; - const password = ( (form?.querySelector("#password"))).value; + const username = ((form?.querySelector("#username"))).value; + const password = ((form?.querySelector("#password"))).value; setCredentials(username, btoa("admin" + ":" + password)); /* Start periodically requesting updates */ diff --git a/client/src/map/custommarker.ts b/client/src/map/custommarker.ts index 41d79c14..a6ca5998 100644 --- a/client/src/map/custommarker.ts +++ b/client/src/map/custommarker.ts @@ -1,4 +1,4 @@ -import { Map, Marker } from "leaflet"; +import { DivIcon, Map, Marker } from "leaflet"; import { MarkerOptions } from "leaflet"; import { LatLngExpression } from "leaflet"; @@ -8,6 +8,7 @@ export class CustomMarker extends Marker { } onAdd(map: Map): this { + this.setIcon(new DivIcon()); // Default empty icon super.onAdd(map); this.createIcon(); return this; diff --git a/client/src/map/map.ts b/client/src/map/map.ts index a36ae834..477b8640 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -22,6 +22,7 @@ require("../../public/javascripts/leaflet.nauticscale.js") export const IDLE = "IDLE"; export const MOVE_UNIT = "MOVE_UNIT"; export const visibilityControls: string[] = ["human", "dcs", "aircraft", "groundunit-sam", "groundunit-other", "navyunit", "airbase"]; +export const visibilityControlsTootlips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"]; export class Map extends L.Map { #state: string; @@ -116,7 +117,7 @@ export class Map extends L.Map { /* Option buttons */ this.#optionButtons["visibility"] = visibilityControls.map((option: string, index: number) => { - return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, "", "toggleUnitVisibility", `{"type": "${option}"}`); + return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"type": "${option}"}`); }); document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]); } @@ -194,7 +195,7 @@ export class Map extends L.Map { }) this.#destinationPreviewMarkers = []; - if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) { + if (getUnitsManager().getSelectedUnits({ excludeHumans: true }).length > 1 && getUnitsManager().getSelectedUnits({ excludeHumans: true }).length < 20) { /* Create the unit destination preview markers */ this.#destinationPreviewMarkers = getUnitsManager().getSelectedUnits({ excludeHumans: true }).map((unit: Unit) => { var marker = new DestinationPreviewMarker(this.getMouseCoordinates()); @@ -425,6 +426,9 @@ export class Map extends L.Map { getUnitsManager().selectedUnitsClearDestinations(); } getUnitsManager().selectedUnitsAddDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : e.latlng, !e.originalEvent.shiftKey, this.#destinationGroupRotation) + this.#destinationGroupRotation = 0; + this.#destinationRotationCenter = null; + this.#computeDestinationRotation = false; } } @@ -440,18 +444,18 @@ export class Map extends L.Map { #onMouseDown(e: any) { this.hideAllContextMenus(); - if (this.#state == MOVE_UNIT && e.originalEvent.button == 2) { - this.#computeDestinationRotation = true; - this.#destinationRotationCenter = this.getMouseCoordinates(); + if (this.#state == MOVE_UNIT) { + this.#destinationGroupRotation = 0; + this.#destinationRotationCenter = null; + this.#computeDestinationRotation = false; + if (e.originalEvent.button == 2) { + this.#computeDestinationRotation = true; + this.#destinationRotationCenter = this.getMouseCoordinates(); + } } } #onMouseUp(e: any) { - if (this.#state == MOVE_UNIT) { - this.#computeDestinationRotation = false; - this.#destinationRotationCenter = null; - this.#destinationGroupRotation = 0; - } } #onMouseMove(e: any) { diff --git a/client/src/panels/hotgrouppanel.ts b/client/src/panels/hotgrouppanel.ts index 8431c2ab..f0abdb85 100644 --- a/client/src/panels/hotgrouppanel.ts +++ b/client/src/panels/hotgrouppanel.ts @@ -18,14 +18,24 @@ export class HotgroupPanel extends Panel { } addHotgroup(hotgroup: number) { - const hotgroupHtml = `
-
${hotgroup}
-
- x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}` + // Hotgroup number + var hotgroupDiv = document.createElement("div"); + hotgroupDiv.classList.add("unit-hotgroup"); + var idDiv = document.createElement("div"); + idDiv.classList.add("unit-hotgroup-id"); + idDiv.innerText = String(hotgroup); + hotgroupDiv.appendChild(idDiv); + + // Hotgroup unit count + var countDiv = document.createElement("div"); + countDiv.innerText = `x${getUnitsManager().getUnitsByHotgroup(hotgroup).length}`; + var el = document.createElement("div"); + el.appendChild(hotgroupDiv); + el.appendChild(countDiv); el.classList.add("hotgroup-selector"); - el.innerHTML = hotgroupHtml; el.toggleAttribute(`data-hotgroup-${hotgroup}`, true) + this.getElement().appendChild(el); el.addEventListener("click", () => { diff --git a/client/src/panels/unitcontrolpanel.ts b/client/src/panels/unitcontrolpanel.ts index 7b1967d4..ea90161d 100644 --- a/client/src/panels/unitcontrolpanel.ts +++ b/client/src/panels/unitcontrolpanel.ts @@ -1,3 +1,4 @@ +import { SVGInjector } from "@tanem/svg-injector"; import { getUnitsManager } from ".."; import { Dropdown } from "../controls/dropdown"; import { Slider } from "../controls/slider"; @@ -346,7 +347,10 @@ export class UnitControlPanel extends Panel { var button = document.createElement("button"); button.title = title; button.value = value; - button.innerHTML = `` + var img = document.createElement("img"); + img.src = `/resources/theme/images/buttons/${url}`; + img.onload = () => SVGInjector(img); + button.appendChild(img); button.addEventListener("click", callback); return button; } diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index 3338c095..d54034a7 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -6,6 +6,7 @@ import { aircraftDatabase } from './aircraftdatabase'; import { groundUnitsDatabase } from './groundunitsdatabase'; import { CustomMarker } from '../map/custommarker'; import { SVGInjector } from '@tanem/svg-injector'; +import { UnitDatabase } from './unitdatabase'; var pathIcon = new Icon({ iconUrl: '/resources/theme/images/markers/marker-icon.png', @@ -124,17 +125,23 @@ export class Unit extends CustomMarker { return ""; } - getActiveMarkerElements() { - // Default values + getDatabase(): UnitDatabase | null { + // Overloaded by child classes + return null; + } + + getIconOptions(): UnitIconOptions { + // Default values, overloaded by child classes if needed return { - state: false, - vvi: false, - hotgroup: false, - unitIcon: true, - shortLabel: false, - fuel: false, - ammo: false, - summary: false + showState: false, + showVvi: false, + showHotgroup: false, + showUnitIcon: true, + showShortLabel: false, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: false } } @@ -165,6 +172,7 @@ export class Unit extends CustomMarker { setHotgroup(hotgroup: number | null) { this.#hotgroup = hotgroup; + this.#updateMarker(); } getHotgroup() { @@ -172,7 +180,7 @@ export class Unit extends CustomMarker { } setHighlighted(highlighted: boolean) { - if (this.#highlighted != highlighted) { + if (this.getSelectable() && this.#highlighted != highlighted) { this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted); this.#highlighted = highlighted; this.getGroupMembers().forEach((unit: Unit) => unit.setHighlighted(highlighted)); @@ -297,19 +305,13 @@ export class Unit extends CustomMarker { this.setIcon(icon); var el = document.createElement("div"); + el.classList.add("unit"); el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`); el.setAttribute("data-coalition", this.getMissionData().coalition); - // Generate and append elements depending on active options - // State icon - if (this.getActiveMarkerElements().state){ - var state = document.createElement("div"); - state.classList.add("unit-state"); - el.appendChild(state); - } - + // Generate and append elements depending on active options // Velocity vector - if (this.getActiveMarkerElements().vvi) { + if (this.getIconOptions().showVvi) { var vvi = document.createElement("div"); vvi.classList.add("unit-vvi"); vvi.toggleAttribute("data-rotate-to-heading"); @@ -317,7 +319,7 @@ export class Unit extends CustomMarker { } // Hotgroup indicator - if (this.getActiveMarkerElements().hotgroup) { + if (this.getIconOptions().showHotgroup) { var hotgroup = document.createElement("div"); hotgroup.classList.add("unit-hotgroup"); var hotgroupId = document.createElement("div"); @@ -327,26 +329,34 @@ export class Unit extends CustomMarker { } // Main icon - if (this.getActiveMarkerElements().unitIcon) { + if (this.getIconOptions().showUnitIcon) { var unitIcon = document.createElement("div"); unitIcon.classList.add("unit-icon"); var img = document.createElement("img"); img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`; img.onload = () => SVGInjector(img); unitIcon.appendChild(img); + unitIcon.toggleAttribute("data-rotate-to-heading", this.getIconOptions().rotateToHeading); el.append(unitIcon); } + // State icon + if (this.getIconOptions().showState){ + var state = document.createElement("div"); + state.classList.add("unit-state"); + el.appendChild(state); + } + // Short label - if (this.getActiveMarkerElements().shortLabel) { + if (this.getIconOptions().showShortLabel) { var shortLabel = document.createElement("div"); shortLabel.classList.add("unit-short-label"); - shortLabel.innerText = aircraftDatabase.getByName(this.getBaseData().name)?.shortLabel || ""; //TODO: fix, use correct database + shortLabel.innerText = this.getDatabase()?.getByName(this.getBaseData().name)?.shortLabel || ""; el.append(shortLabel); } // Fuel indicator - if (this.getActiveMarkerElements().fuel) { + if (this.getIconOptions().showFuel) { var fuelIndicator = document.createElement("div"); fuelIndicator.classList.add("unit-fuel"); var fuelLevel = document.createElement("div"); @@ -356,7 +366,7 @@ export class Unit extends CustomMarker { } // Ammo indicator - if (this.getActiveMarkerElements().ammo){ + if (this.getIconOptions().showAmmo){ var ammoIndicator = document.createElement("div"); ammoIndicator.classList.add("unit-ammo"); for (let i = 0; i <= 3; i++) @@ -365,7 +375,7 @@ export class Unit extends CustomMarker { } // Unit summary - if (this.getActiveMarkerElements().summary) { + if (this.getIconOptions().showSummary) { var summary = document.createElement("div"); summary.classList.add("unit-summary"); var callsign = document.createElement("div"); @@ -544,18 +554,18 @@ export class Unit extends CustomMarker { } #onContextMenu(e: any) { - var options: { [key: string]: string } = {}; + var options: {[key: string]: {text: string, tooltip: string}} = {}; - options["Center"] = `
Center map
`; + options["center-map"] = {text: "Center map", tooltip: "Center the map on the unit and follow it"}; if (getUnitsManager().getSelectedUnits().length > 0 && !(getUnitsManager().getSelectedUnits().length == 1 && (getUnitsManager().getSelectedUnits().includes(this)))) { - options['Attack'] = `
Attack
`; + options["attack"] = {text: "Attack", tooltip: "Attack the unit using A/A or A/G weapons"}; if (getUnitsManager().getSelectedUnitsType() === "Aircraft") - options['Follow'] = `
Follow
`; + options["follow"] = {text: "Follow", tooltip: "Follow the unit at a user defined distance and position"};; } else if ((getUnitsManager().getSelectedUnits().length > 0 && (getUnitsManager().getSelectedUnits().includes(this))) || getUnitsManager().getSelectedUnits().length == 0) { if (this.getBaseData().category == "Aircraft") { - options["Refuel"] = `
Refuel
`; // TODO Add some way of knowing which aircraft can AAR + options["refuel"] = {text: "AAR Refuel", tooltip: "Refuel unit at the nearest AAR Tanker. If no tanker is available the unit will RTB."}; // TODO Add some way of knowing which aircraft can AAR } } @@ -569,28 +579,28 @@ export class Unit extends CustomMarker { } #executeAction(e: any, action: string) { - if (action === "Center") + if (action === "center-map") getMap().centerOnUnit(this.ID); - if (action === "Attack") + if (action === "attack") getUnitsManager().selectedUnitsAttackUnit(this.ID); - else if (action === "Refuel") + else if (action === "refuel") getUnitsManager().selectedUnitsRefuel(); - else if (action === "Follow") + else if (action === "follow") this.#showFollowOptions(e); } #showFollowOptions(e: any) { - var options: { [key: string]: string } = {}; + var options: {[key: string]: {text: string, tooltip: string}} = {}; options = { - 'Trail': `
Trail
`, - 'Echelon (LH)': `
Echelon (left)
`, - 'Echelon (RH)': `
Echelon (right)
`, - 'Line abreast (LH)': `
Line abreast (left)
`, - 'Line abreast (RH)': `
Line abreast (right)
`, - 'Front': `
In front
`, - 'Diamond': `
Diamond
`, - 'Custom': `
Custom
` + 'trail': {text: "Trail", tooltip: "Follow unit in trail formation"}, + 'echelon-lh': {text: "Echelon (LH)", tooltip: "Follow unit in echelon left formation"}, + 'echelon-rh': {text: "Echelon (RH)", tooltip: "Follow unit in echelon right formation"}, + 'line-abreast-lh': {text: "Line abreast (LH)", tooltip: "Follow unit in line abreast left formation"}, + 'line-abreast-rh': {text: "Line abreast (RH)", tooltip: "Follow unit in line abreast right formation"}, + 'front': {text: "Front", tooltip: "Fly in front of unit"}, + 'diamond': {text: "Diamond", tooltip: "Follow unit in diamond formation"}, + 'custom': {text: "Custom", tooltip: "Set a custom formation position"}, } getMap().getUnitContextMenu().setOptions(options, (option: string) => { @@ -601,7 +611,7 @@ export class Unit extends CustomMarker { } #applyFollowOptions(action: string) { - if (action === "Custom") { + if (action === "custom") { document.getElementById("custom-formation-dialog")?.classList.remove("hide"); getMap().getUnitContextMenu().setCustomFormationCallback((offset: { x: number, y: number, z: number }) => { getUnitsManager().selectedUnitsFollowUnit(this.ID, offset); @@ -657,18 +667,18 @@ export class Unit extends CustomMarker { element.querySelector(".unit")?.toggleAttribute("data-is-dead", !this.getBaseData().alive); /* Set current unit state */ - if (this.getMissionData().flags.Human) // Unit is human + if (this.getMissionData().flags.Human) // Unit is human element.querySelector(".unit")?.setAttribute("data-state", "human"); - else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus) + else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus) element.querySelector(".unit")?.setAttribute("data-state", "dcs"); - else // Unit is under Olympus control + else // Unit is under Olympus control element.querySelector(".unit")?.setAttribute("data-state", this.getTaskData().currentState.toLowerCase()); /* Set altitude and speed */ if (element.querySelector(".unit-altitude")) (element.querySelector(".unit-altitude")).innerText = "FL" + String(Math.floor(this.getFlightData().altitude / 0.3048 / 100)); if (element.querySelector(".unit-speed")) - (element.querySelector(".unit-speed")).innerHTML = String(Math.floor(this.getFlightData().speed * 1.94384)); + (element.querySelector(".unit-speed")).innerText = String(Math.floor(this.getFlightData().speed * 1.94384)); /* Rotate elements according to heading */ element.querySelectorAll("[data-rotate-to-heading]").forEach(el => { @@ -791,16 +801,17 @@ export class Unit extends CustomMarker { } export class AirUnit extends Unit { - getActiveMarkerElements() { + getIconOptions() { return { - state: true, - vvi: true, - hotgroup: true, - unitIcon: true, - shortLabel: true, - fuel: true, - ammo: true, - summary: true + showState: true, + showVvi: true, + showHotgroup: true, + showUnitIcon: true, + showShortLabel: true, + showFuel: true, + showAmmo: true, + showSummary: true, + rotateToHeading: false }; } } @@ -813,6 +824,10 @@ export class Aircraft extends AirUnit { getMarkerCategory() { return "aircraft"; } + + getDatabase(): UnitDatabase | null { + return aircraftDatabase; + } } export class Helicopter extends AirUnit { @@ -830,16 +845,17 @@ export class GroundUnit extends Unit { super(ID, data); } - getActiveMarkerElements() { + getIconOptions() { return { - state: true, - vvi: false, - hotgroup: true, - unitIcon: true, - shortLabel: true, - fuel: false, - ammo: false, - summary: false + showState: true, + showVvi: false, + showHotgroup: true, + showUnitIcon: true, + showShortLabel: true, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: false }; } @@ -849,6 +865,10 @@ export class GroundUnit extends Unit { var markerCategory = (role === "SAM") ? "groundunit-sam" : "groundunit-other"; return markerCategory; } + + getDatabase(): UnitDatabase | null { + return groundUnitsDatabase; + } } export class NavyUnit extends Unit { @@ -856,16 +876,17 @@ export class NavyUnit extends Unit { super(ID, data); } - getActiveMarkerElements() { + getIconOptions() { return { - state: true, - vvi: false, - hotgroup: true, - unitIcon: true, - shortLabel: true, - fuel: false, - ammo: false, - summary: false + showState: true, + showVvi: false, + showHotgroup: true, + showUnitIcon: true, + showShortLabel: true, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: false }; } @@ -879,6 +900,20 @@ export class Weapon extends Unit { super(ID, data); this.setSelectable(false); } + + getIconOptions() { + return { + showState: false, + showVvi: false, + showHotgroup: false, + showUnitIcon: true, + showShortLabel: false, + showFuel: false, + showAmmo: false, + showSummary: false, + rotateToHeading: true + }; + } } export class Missile extends Weapon { diff --git a/client/src/units/unitdatabase.ts b/client/src/units/unitdatabase.ts index 9bfd0095..90d87863 100644 --- a/client/src/units/unitdatabase.ts +++ b/client/src/units/unitdatabase.ts @@ -1,21 +1,16 @@ export class UnitDatabase { - blueprints: {[key: string]: UnitBlueprint} = {}; + blueprints: { [key: string]: UnitBlueprint } = {}; - constructor() - { + constructor() { } /* Returns a list of all possible roles in a database */ - getRoles() - { + getRoles() { var roles: string[] = []; - for (let unit in this.blueprints) - { - for (let loadout of this.blueprints[unit].loadouts) - { - for (let role of loadout.roles) - { + for (let unit in this.blueprints) { + for (let loadout of this.blueprints[unit].loadouts) { + for (let role of loadout.roles) { if (role !== "" && !roles.includes(role)) roles.push(role); } @@ -25,18 +20,15 @@ export class UnitDatabase { } /* Gets a specific blueprint by name */ - getByName(name: string) - { + getByName(name: string) { if (name in this.blueprints) return this.blueprints[name]; return null; } /* Gets a specific blueprint by label */ - getByLabel(label: string) - { - for (let unit in this.blueprints) - { + getByLabel(label: string) { + for (let unit in this.blueprints) { if (this.blueprints[unit].label === label) return this.blueprints[unit]; } @@ -44,15 +36,11 @@ export class UnitDatabase { } /* Get all blueprints by role */ - getByRole(role: string) - { + getByRole(role: string) { var units = []; - for (let unit in this.blueprints) - { - for (let loadout of this.blueprints[unit].loadouts) - { - if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) - { + for (let unit in this.blueprints) { + for (let loadout of this.blueprints[unit].loadouts) { + if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) { units.push(this.blueprints[unit]) break; } @@ -62,13 +50,10 @@ export class UnitDatabase { } /* Get the names of all the loadouts for a specific unit and for a specific role */ - getLoadoutNamesByRole(name: string, role: string) - { + getLoadoutNamesByRole(name: string, role: string) { var loadouts = []; - for (let loadout of this.blueprints[name].loadouts) - { - if (loadout.roles.includes(role) || loadout.roles.includes("")) - { + for (let loadout of this.blueprints[name].loadouts) { + if (loadout.roles.includes(role) || loadout.roles.includes("")) { loadouts.push(loadout.name) } } @@ -76,10 +61,8 @@ export class UnitDatabase { } /* Get the loadout content from the unit name and loadout name */ - getLoadoutByName(name: string, loadoutName: string) - { - for (let loadout of this.blueprints[name].loadouts) - { + getLoadoutByName(name: string, loadoutName: string) { + for (let loadout of this.blueprints[name].loadouts) { if (loadout.name === loadoutName) return loadout; } diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index 07964d7a..07f5ac9c 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -47,7 +47,7 @@ export class UnitsManager { } getUnitsByHotgroup(hotgroup: number) { - return Object.values(this.#units).filter((unit: Unit) => {return unit.getBaseData().alive && unit.getHotgroup() == hotgroup}); + return Object.values(this.#units).filter((unit: Unit) => { return unit.getBaseData().alive && unit.getHotgroup() == hotgroup }); } addUnit(ID: number, data: UnitData) { @@ -88,10 +88,8 @@ export class UnitsManager { }); } - setHiddenType(key: string, value: boolean) - { - if (value) - { + setHiddenType(key: string, value: boolean) { + if (value) { if (this.#hiddenTypes.includes(key)) delete this.#hiddenTypes[this.#hiddenTypes.indexOf(key)]; } @@ -100,8 +98,7 @@ export class UnitsManager { Object.values(this.getUnits()).forEach((unit: Unit) => unit.updateVisibility()); } - getHiddenTypes() - { + getHiddenTypes() { return this.#hiddenTypes; } @@ -123,7 +120,7 @@ export class UnitsManager { } } - getSelectedUnits(options?: {excludeHumans?: boolean}) { + getSelectedUnits(options?: { excludeHumans?: boolean }) { var selectedUnits = []; for (let ID in this.#units) { if (this.#units[ID].getSelected()) { @@ -132,7 +129,7 @@ export class UnitsManager { } if (options) { if (options.excludeHumans) - selectedUnits = selectedUnits.filter((unit: Unit) => {return !unit.getMissionData().flags.Human}); + selectedUnits = selectedUnits.filter((unit: Unit) => { return !unit.getMissionData().flags.Human }); } return selectedUnits; } @@ -190,14 +187,14 @@ export class UnitsManager { /*********************** Actions on selected units ************************/ selectedUnitsAddDestination(latlng: L.LatLng, mantainRelativePosition: boolean, rotation: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); /* Compute the destination for each unit. If mantainRelativePosition is true, compute the destination so to hold the relative distances */ - var unitDestinations: {[key: number]: LatLng} = {}; + var unitDestinations: { [key: number]: LatLng } = {}; if (mantainRelativePosition) unitDestinations = this.selectedUnitsComputeGroupDestination(latlng, rotation); else - selectedUnits.forEach((unit: Unit) => {unitDestinations[unit.ID] = latlng}); + selectedUnits.forEach((unit: Unit) => { unitDestinations[unit.ID] = latlng }); for (let idx in selectedUnits) { const unit = selectedUnits[idx]; @@ -206,7 +203,7 @@ export class UnitsManager { const leader = this.getUnitByID(unit.getFormationData().leaderID) if (leader && leader.getSelected()) leader.addDestination(latlng); - else + else unit.addDestination(latlng); } else { @@ -219,7 +216,7 @@ export class UnitsManager { } selectedUnitsClearDestinations() { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { const unit = selectedUnits[idx]; if (unit.getTaskData().currentState === "Follow") { @@ -235,7 +232,7 @@ export class UnitsManager { } selectedUnitsLandAt(latlng: LatLng) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].landAt(latlng); } @@ -243,21 +240,21 @@ export class UnitsManager { } selectedUnitsChangeSpeed(speedChange: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].changeSpeed(speedChange); } } selectedUnitsChangeAltitude(altitudeChange: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].changeAltitude(altitudeChange); } } selectedUnitsSetSpeed(speed: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setSpeed(speed); } @@ -265,7 +262,7 @@ export class UnitsManager { } selectedUnitsSetAltitude(altitude: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setAltitude(altitude); } @@ -273,7 +270,7 @@ export class UnitsManager { } selectedUnitsSetROE(ROE: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setROE(ROE); } @@ -281,7 +278,7 @@ export class UnitsManager { } selectedUnitsSetReactionToThreat(reactionToThreat: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setReactionToThreat(reactionToThreat); } @@ -289,7 +286,7 @@ export class UnitsManager { } selectedUnitsSetEmissionsCountermeasures(emissionCountermeasure: string) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].setEmissionsCountermeasures(emissionCountermeasure); } @@ -298,7 +295,7 @@ export class UnitsManager { selectedUnitsAttackUnit(ID: number) { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].attackUnit(ID); } @@ -314,7 +311,7 @@ export class UnitsManager { } selectedUnitsRefuel() { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); for (let idx in selectedUnits) { selectedUnits[idx].refuel(); } @@ -328,15 +325,15 @@ export class UnitsManager { // Y: top-bottom, positive top // Z: left-right, positive right offset = { "x": 0, "y": 0, "z": 0 }; - if (formation === "Trail") { offset.x = -50; offset.y = -30; offset.z = 0; } - else if (formation === "Echelon (LH)") { offset.x = -50; offset.y = -10; offset.z = -50; } - else if (formation === "Echelon (RH)") { offset.x = -50; offset.y = -10; offset.z = 50; } - else if (formation === "Line abreast (RH)") { offset.x = 0; offset.y = 0; offset.z = 50; } - else if (formation === "Line abreast (LH)") { offset.x = 0; offset.y = 0; offset.z = -50; } - else if (formation === "Front") { offset.x = 100; offset.y = 0; offset.z = 0; } + if (formation === "trail") { offset.x = -50; offset.y = -30; offset.z = 0; } + else if (formation === "echelon-lh") { offset.x = -50; offset.y = -10; offset.z = -50; } + else if (formation === "echelon-rh") { offset.x = -50; offset.y = -10; offset.z = 50; } + else if (formation === "line-abreast-rh") { offset.x = 0; offset.y = 0; offset.z = 50; } + else if (formation === "line-abreast-lh") { offset.x = 0; offset.y = 0; offset.z = -50; } + else if (formation === "front") { offset.x = 100; offset.y = 0; offset.z = 0; } else offset = undefined; } - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); var count = 1; var xr = 0; var yr = 1; var zr = -1; var layer = 1; @@ -347,7 +344,7 @@ export class UnitsManager { unit.followUnit(ID, { "x": offset.x * count, "y": offset.y * count, "z": offset.z * count }); else { /* More complex formations with variable offsets */ - if (formation === "Diamond") { + if (formation === "diamond") { var xl = xr * Math.cos(Math.PI / 4) - yr * Math.sin(Math.PI / 4); var yl = xr * Math.sin(Math.PI / 4) + yr * Math.cos(Math.PI / 4); unit.followUnit(ID, { "x": -yl * 50, "y": zr * 10, "z": xl * 50 }); @@ -364,14 +361,12 @@ export class UnitsManager { this.#showActionMessage(selectedUnits, `following unit ${this.getUnitByID(ID)?.getBaseData().unitName}`); } - selectedUnitsSetHotgroup(hotgroup: number) - { + selectedUnitsSetHotgroup(hotgroup: number) { this.getUnitsByHotgroup(hotgroup).forEach((unit: Unit) => unit.setHotgroup(null)); this.selectedUnitsAddToHotgroup(hotgroup); } - selectedUnitsAddToHotgroup(hotgroup: number) - { + selectedUnitsAddToHotgroup(hotgroup: number) { var selectedUnits = this.getSelectedUnits(); for (let idx in selectedUnits) { selectedUnits[idx].setHotgroup(hotgroup); @@ -380,11 +375,10 @@ export class UnitsManager { getHotgroupPanel().refreshHotgroups(); } - selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number) - { - var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + selectedUnitsComputeGroupDestination(latlng: LatLng, rotation: number) { + var selectedUnits = this.getSelectedUnits({ excludeHumans: true }); /* Compute the center of the group */ - var center = {x: 0, y: 0}; + var center = { x: 0, y: 0 }; selectedUnits.forEach((unit: Unit) => { var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude); center.x += mercator.x / selectedUnits.length; @@ -392,20 +386,19 @@ export class UnitsManager { }); /* Compute the distances from the center of the group */ - - var unitDestinations: {[key: number]: LatLng} = {}; + var unitDestinations: { [key: number]: LatLng } = {}; selectedUnits.forEach((unit: Unit) => { var mercator = latLngToMercator(unit.getFlightData().latitude, unit.getFlightData().longitude); - var distancesFromCenter = {dx: mercator.x - center.x, dy: mercator.y - center.y}; + var distancesFromCenter = { dx: mercator.x - center.x, dy: mercator.y - center.y }; /* Rotate the distance according to the group rotation */ - var rotatedDistancesFromCenter: {dx: number, dy: number} = {dx: 0, dy: 0}; + var rotatedDistancesFromCenter: { dx: number, dy: number } = { dx: 0, dy: 0 }; rotatedDistancesFromCenter.dx = distancesFromCenter.dx * Math.cos(deg2rad(rotation)) - distancesFromCenter.dy * Math.sin(deg2rad(rotation)); rotatedDistancesFromCenter.dy = distancesFromCenter.dx * Math.sin(deg2rad(rotation)) + distancesFromCenter.dy * Math.cos(deg2rad(rotation)); /* Compute the final position of the unit */ var destMercator = latLngToMercator(latlng.lat, latlng.lng); // Convert destination point to mercator - var unitMercator = {x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy}; // Compute final position of this unit in mercator coordinates + var unitMercator = { x: destMercator.x + rotatedDistancesFromCenter.dx, y: destMercator.y + rotatedDistancesFromCenter.dy }; // Compute final position of this unit in mercator coordinates var unitLatLng = mercatorToLatLng(unitMercator.x, unitMercator.y); unitDestinations[unit.ID] = new LatLng(unitLatLng.lat, unitLatLng.lng); }); diff --git a/scripts/OlympusCommand.lua b/scripts/OlympusCommand.lua index 68adfc0f..bd61f8d2 100644 --- a/scripts/OlympusCommand.lua +++ b/scripts/OlympusCommand.lua @@ -524,6 +524,7 @@ function Olympus.setMissionData(arg, time) bullseyes[i] = {} bullseyes[i]["latitude"] = bullseyeLatitude bullseyes[i]["longitude"] = bullseyeLongitude + bullseyes[i]["coalition"] = Olympus.getCoalitionByCoalitionID(i) end -- Units tactical data @@ -589,14 +590,7 @@ function Olympus.setMissionData(arg, time) local info = {} local latitude, longitude, altitude = coord.LOtoLL(Airbase.getPoint(base[i])) info["callsign"] = Airbase.getCallsign(base[i]) - local coalitionID = Airbase.getCoalition(base[i]) - if coalitionID == 0 then - info["coalition"] = "neutral" - elseif coalitionID == 1 then - info["coalition"] = "red" - else - info["coalition"] = "blue" - end + info["coalition"] = Olympus.getCoalitionByCoalitionID(Airbase.getCoalition(base[i])) info["latitude"] = latitude info["longitude"] = longitude if Airbase.getUnit(base[i]) then