From 71ef292763bddabb43d6f8c82196421be9529bb0 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 11 May 2023 17:24:56 +0200 Subject: [PATCH] Added frontend controls for emissions and countermeasures --- client/public/stylesheets/layout.css | 2 +- client/public/stylesheets/olympus.css | 70 +++++++++++++---- .../public/stylesheets/unitcontrolpanel.css | 25 +++++- client/src/index.ts | 2 +- client/src/panels/unitcontrolpanel.ts | 33 +++++--- client/src/server/server.ts | 6 ++ client/src/units/unit.ts | 7 +- client/src/units/unitsmanager.ts | 9 +++ client/views/dialogs.ejs | 77 ++++++++++--------- client/views/unitcontrolpanel.ejs | 7 ++ 10 files changed, 170 insertions(+), 68 deletions(-) diff --git a/client/public/stylesheets/layout.css b/client/public/stylesheets/layout.css index 5c60d1bb..a595382d 100644 --- a/client/public/stylesheets/layout.css +++ b/client/public/stylesheets/layout.css @@ -109,7 +109,7 @@ dl.ol-data-grid dd { } .ol-panel.ol-dialog { - padding: 20px; + padding: 24px 30px; } .ol-dialog-close { diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css index d7905e9b..64647448 100644 --- a/client/public/stylesheets/olympus.css +++ b/client/public/stylesheets/olympus.css @@ -645,13 +645,15 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { } #roe-buttons-container button.selected, -#reaction-to-threat-buttons-container button.selected { +#reaction-to-threat-buttons-container button.selected, +#emissions-countermeasures-buttons-container button.selected { background-color: white; border-color: white; } #roe-buttons-container button::before, -#reaction-to-threat-buttons-container button::before { +#reaction-to-threat-buttons-container button::before, +#emissions-countermeasures-buttons-container button::before { background-position: center; background-repeat: no-repeat; content: ""; @@ -660,68 +662,104 @@ body[data-hide-navyunit] #unit-visibility-control-navyunit { width: 24px; } -#roe-buttons-container button[title="Hold"]::before { +#roe-buttons-container button[value="Hold"]::before { background-image: url("/themes/olympus/images/icons_roe_stop_light.svg"); } -#roe-buttons-container button[title="Hold"].selected::before { +#roe-buttons-container button[value="Hold"].selected::before { background-image: url("/themes/olympus/images/icons_roe_stop_dark.svg"); } /**/ -#roe-buttons-container button[title="Return"]::before { +#roe-buttons-container button[value="Return"]::before { background-image: url("/themes/olympus/images/icons_roe_defend_light.svg"); } -#roe-buttons-container button[title="Return"].selected::before { +#roe-buttons-container button[value="Return"].selected::before { background-image: url("/themes/olympus/images/icons_roe_defend_dark.svg"); } /**/ -#roe-buttons-container button[title="Designated"]::before { +#roe-buttons-container button[value="Designated"]::before { background-image: url("/themes/olympus/images/icons_roe_target_light.svg"); } -#roe-buttons-container button[title="Designated"].selected::before { +#roe-buttons-container button[value="Designated"].selected::before { background-image: url("/themes/olympus/images/icons_roe_target_dark.svg"); } /**/ -#roe-buttons-container button[title="Free"]::before { +#roe-buttons-container button[value="Free"]::before { background-image: url("/themes/olympus/images/icons_roe_free_light.svg"); } -#roe-buttons-container button[title="Free"].selected::before { +#roe-buttons-container button[value="Free"].selected::before { background-image: url("/themes/olympus/images/icons_roe_free_dark.svg"); } /****************************************************************************************/ -#reaction-to-threat-buttons-container button[title="None"]::before { +#reaction-to-threat-buttons-container button[value="None"]::before { background-image: url("/themes/olympus/images/icons_threat_nothing_light.svg"); } -#reaction-to-threat-buttons-container button[title="None"].selected::before { +#reaction-to-threat-buttons-container button[value="None"].selected::before { background-image: url("/themes/olympus/images/icons_threat_nothing_dark.svg"); } /**/ -#reaction-to-threat-buttons-container button[title="Passive"]::before { +#reaction-to-threat-buttons-container button[value="Passive"]::before { background-image: url("/themes/olympus/images/icons_threat_cms_light.svg"); } -#reaction-to-threat-buttons-container button[title="Passive"].selected::before { +#reaction-to-threat-buttons-container button[value="Passive"].selected::before { background-image: url("/themes/olympus/images/icons_threat_cms_dark.svg"); } /**/ -#reaction-to-threat-buttons-container button[title="Evade"]::before { +#reaction-to-threat-buttons-container button[value="Evade"]::before { background-image: url("/themes/olympus/images/icons_threat_defend_light.svg"); } -#reaction-to-threat-buttons-container button[title="Evade"].selected::before { +#reaction-to-threat-buttons-container button[value="Evade"].selected::before { background-image: url("/themes/olympus/images/icons_threat_defend_dark.svg"); } +/****************************************************************************************/ +#emissions-countermeasures-buttons-container button[value="Silent"]::before { + background-image: url("/themes/olympus/images/icons_roe_stop_light.svg"); +} + +#emissions-countermeasures-buttons-container button[value="Silent"].selected::before { + background-image: url("/themes/olympus/images/icons_roe_stop_dark.svg"); +} + +/**/ +#emissions-countermeasures-buttons-container button[value="Defend"]::before { + background-image: url("/themes/olympus/images/icons_roe_defend_light.svg"); +} + +#emissions-countermeasures-buttons-container button[value="Defend"].selected::before { + background-image: url("/themes/olympus/images/icons_roe_defend_dark.svg"); +} + +/**/ +#emissions-countermeasures-buttons-container button[value="Attack"]::before { + background-image: url("/themes/olympus/images/icons_roe_target_light.svg"); +} + +#emissions-countermeasures-buttons-container button[value="Attack"].selected::before { + background-image: url("/themes/olympus/images/icons_roe_target_dark.svg"); +} + +/**/ +#emissions-countermeasures-buttons-container button[value="Free"]::before { + background-image: url("/themes/olympus/images/icons_roe_free_light.svg"); +} + +#emissions-countermeasures-buttons-container button[value="Free"].selected::before { + background-image: url("/themes/olympus/images/icons_roe_free_dark.svg"); +} + /****************************************************************************************/ #splash-screen { background-image: url("/images/splash/splash_pic_ship.png"); diff --git a/client/public/stylesheets/unitcontrolpanel.css b/client/public/stylesheets/unitcontrolpanel.css index 85e5bf05..44bd5802 100644 --- a/client/public/stylesheets/unitcontrolpanel.css +++ b/client/public/stylesheets/unitcontrolpanel.css @@ -8,7 +8,7 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { left: 10px; position: absolute; top: 80px; - width: 250px; + width: 260px; z-index: 1000; } @@ -94,7 +94,8 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { } #unit-control-panel #threat, -#unit-control-panel #roe { +#unit-control-panel #roe, +#unit-control-panel #emissions-countermeasures { margin-top: 12px; } @@ -113,4 +114,24 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { #advanced-settings-dialog>.ol-dialog-content>.ol-group { justify-content: space-between; + +} + +#advanced-settings-dialog h4 { + white-space: nowrap; +} + +#advanced-settings-dialog hr { + margin-top: 15px; + margin-bottom: 10px; +} + +#advanced-options-grid { + display: grid; + grid-template-columns: 1fr 1fr; + row-gap: 10px; +} + +#advanced-options-grid>div { + width: 49%; } \ No newline at end of file diff --git a/client/src/index.ts b/client/src/index.ts index b3e7e63e..deb58810 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -89,7 +89,7 @@ function readConfig(config: any) { setAddress(address == "*" ? window.location.hostname : address, port); } else { - throw new Error('Could not read configuration file!'); + throw new Error('Could not read configuration file'); } } diff --git a/client/src/panels/unitcontrolpanel.ts b/client/src/panels/unitcontrolpanel.ts index 75056e4a..23b9c3cb 100644 --- a/client/src/panels/unitcontrolpanel.ts +++ b/client/src/panels/unitcontrolpanel.ts @@ -1,7 +1,6 @@ import { getUnitsManager } from ".."; import { Dropdown } from "../controls/dropdown"; import { Slider } from "../controls/slider"; -import { dataPointMap } from "../other/utils"; import { aircraftDatabase } from "../units/aircraftdatabase"; import { groundUnitsDatabase } from "../units/groundunitsdatabase"; import { Aircraft, GroundUnit, Unit } from "../units/unit"; @@ -10,6 +9,11 @@ import { Panel } from "./panel"; const ROEs: string[] = ["Hold", "Return", "Designated", "Free"]; const reactionsToThreat: string[] = ["None", "Passive", "Evade"]; +const emissionsCountermeasures: string[] = ["Silent", "Attack", "Defend", "Free"]; + +const ROEDescriptions: string[] = ["Hold (Never fire)", "Return (Only fire if fired upon)", "Designated (Attack the designated target only)", "Free (Attack anyone)"]; +const reactionsToThreatDescriptions: string[] = ["None (No reaction)", "Passive (Countermeasures only, no manoeuvre)", "Evade (Countermeasures and manoeuvers)"]; +const emissionsCountermeasuresDescriptions: string[] = ["Silent (Radar off, no countermeasures)", "Attack (Radar only for targeting, countermeasures only if attacked/locked)", "Defend (Radar for searching, jammer if locked, countermeasures inside WEZ)", "Always on (Radar and jammer always on, countermeasures when hostile detected)"]; const minSpeedValues: { [key: string]: number } = { Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0 }; const maxSpeedValues: { [key: string]: number } = { Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60 }; @@ -52,23 +56,20 @@ export class UnitControlPanel extends Panel { /* Option buttons */ this.#optionButtons["ROE"] = ROEs.map((option: string, index: number) => { - var button = document.createElement("button"); - button.title = option; - button.value = option; - button.addEventListener("click", () => { getUnitsManager().selectedUnitsSetROE(button.title); }); - return button; + return this.#createOptionButton(option, ROEDescriptions[index], () => { getUnitsManager().selectedUnitsSetROE(option); }); }); this.#optionButtons["reactionToThreat"] = reactionsToThreat.map((option: string, index: number) => { - var button = document.createElement("button"); - button.title = option; - button.value = option; - button.addEventListener("click", () => { getUnitsManager().selectedUnitsSetReactionToThreat(button.title); }); - return button; + return this.#createOptionButton(option, reactionsToThreatDescriptions[index],() => { getUnitsManager().selectedUnitsSetReactionToThreat(option); }); + }); + + this.#optionButtons["emissionsCountermeasures"] = emissionsCountermeasures.map((option: string, index: number) => { + return this.#createOptionButton(option, emissionsCountermeasuresDescriptions[index],() => { getUnitsManager().selectedUnitsSetEmissionsCountermeasures(option); }); }); this.getElement().querySelector("#roe-buttons-container")?.append(...this.#optionButtons["ROE"]); this.getElement().querySelector("#reaction-to-threat-buttons-container")?.append(...this.#optionButtons["reactionToThreat"]); + this.getElement().querySelector("#emissions-countermeasures-buttons-container")?.append(...this.#optionButtons["emissionsCountermeasures"]); this.#advancedSettingsDialog = document.querySelector("#advanced-settings-dialog"); @@ -122,7 +123,7 @@ export class UnitControlPanel extends Panel { })); } else { var el = document.createElement("div"); - el.innerText = "Too many units selected" + el.innerText = "Too many units selected"; this.getElement().querySelector("#selected-units-container")?.replaceChildren(el); } } @@ -298,4 +299,12 @@ export class UnitControlPanel extends Panel { this.#advancedSettingsDialog.classList.add("hide"); } + + #createOptionButton(option: string, title: string, callback: EventListenerOrEventListenerObject) { + var button = document.createElement("button"); + button.value = option; + button.title = title; + button.addEventListener("click", callback); + return button; + } } \ No newline at end of file diff --git a/client/src/server/server.ts b/client/src/server/server.ts index 92c5b2d2..2452bff4 100644 --- a/client/src/server/server.ts +++ b/client/src/server/server.ts @@ -209,6 +209,12 @@ export function setReactionToThreat(ID: number, reactionToThreat: string) { POST(data, () => { }); } +export function setEmissionsCountermeasures(ID: number, emissionCountermeasure: string) { + var command = {"ID": ID, "emissionCountermeasure": emissionCountermeasure} + var data = {"setEmissionsCountermeasures": command} + POST(data, () => { }); +} + export function refuel(ID: number) { var command = { "ID": ID }; var data = { "refuel": command } diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index f1350faa..2648fc72 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -1,7 +1,7 @@ import { Marker, LatLng, Polyline, Icon, DivIcon, CircleMarker, Map } from 'leaflet'; import { getMap, getUnitsManager } from '..'; import { rad2deg } from '../other/utils'; -import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit } from '../server/server'; +import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed, refuel, setAdvacedOptions, followUnit, setEmissionsCountermeasures } from '../server/server'; import { aircraftDatabase } from './aircraftdatabase'; import { groundUnitsDatabase } from './groundunitsdatabase'; import { field } from 'geomag' @@ -365,6 +365,11 @@ export class Unit extends Marker { setReactionToThreat(this.ID, reactionToThreat); } + setEmissionsCountermeasures(emissionCountermeasure: string) { + if (!this.getMissionData().flags.Human) + setEmissionsCountermeasures(this.ID, emissionCountermeasure); + } + setLeader(isLeader: boolean, wingmenIDs: number[] = []) { if (!this.getMissionData().flags.Human) setLeader(this.ID, isLeader, wingmenIDs); diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index 62ac5db6..8684c13d 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -242,6 +242,15 @@ export class UnitsManager { this.#showActionMessage(selectedUnits, `reaction to threat set to ${reactionToThreat}`); } + selectedUnitsSetEmissionsCountermeasures(emissionCountermeasure: string) { + var selectedUnits = this.getSelectedUnits({excludeHumans: true}); + for (let idx in selectedUnits) { + selectedUnits[idx].setEmissionsCountermeasures(emissionCountermeasure); + } + this.#showActionMessage(selectedUnits, `reaction to threat set to ${emissionCountermeasure}`); + } + + selectedUnitsAttackUnit(ID: number) { var selectedUnits = this.getSelectedUnits({excludeHumans: true}); for (let idx in selectedUnits) { diff --git a/client/views/dialogs.ejs b/client/views/dialogs.ejs index 442b89d9..1e667624 100644 --- a/client/views/dialogs.ejs +++ b/client/views/dialogs.ejs @@ -30,43 +30,46 @@
- +
+
+ +
+ +
+ +
+ +
+ +
+ +
+ +
+
+ +
+

Tasking

+
+
+
+
+

Radio options

+
+
diff --git a/client/views/unitcontrolpanel.ejs b/client/views/unitcontrolpanel.ejs index 8518555a..49f9701c 100644 --- a/client/views/unitcontrolpanel.ejs +++ b/client/views/unitcontrolpanel.ejs @@ -52,6 +52,13 @@
+
+

Emissions & countermeasures

+
+ +
+
+