From 9caee0c77c74a81d4d817f43efbb52af2f88f621 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Wed, 8 Nov 2023 23:33:27 +0100 Subject: [PATCH] Implemented buttons to apply advanced controls directly to units --- .../public/stylesheets/panels/unitcontrol.css | 37 ++++- client/public/stylesheets/style/style.css | 2 +- .../olympus/images/icons/fire-solid.svg | 1 + .../themes/olympus/images/icons/napalm.svg | 41 +++++ .../olympus/images/icons/secondaries.svg | 49 ++++++ .../images/icons/white-phosphorous.svg | 41 +++++ client/src/server/servermanager.ts | 4 +- client/src/unit/unit.ts | 4 +- client/src/unit/unitsmanager.ts | 14 +- client/views/panels/unitcontrol.ejs | 154 +++++++++--------- scripts/OlympusCommand.lua | 8 +- src/core/include/commands.h | 4 +- src/core/include/unitsmanager.h | 2 +- src/core/src/commands.cpp | 3 +- src/core/src/scheduler.cpp | 3 +- src/core/src/unitsmanager.cpp | 4 +- 16 files changed, 276 insertions(+), 95 deletions(-) create mode 100644 client/public/themes/olympus/images/icons/fire-solid.svg create mode 100644 client/public/themes/olympus/images/icons/napalm.svg create mode 100644 client/public/themes/olympus/images/icons/secondaries.svg create mode 100644 client/public/themes/olympus/images/icons/white-phosphorous.svg diff --git a/client/public/stylesheets/panels/unitcontrol.css b/client/public/stylesheets/panels/unitcontrol.css index 69ecb6b5..4e659fbd 100644 --- a/client/public/stylesheets/panels/unitcontrol.css +++ b/client/public/stylesheets/panels/unitcontrol.css @@ -9,11 +9,15 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { row-gap: 10px; } -#unit-control-panel>div:nth-child(2) { +#unit-control-panel>div:nth-child(2), +#unit-controls { display: flex; flex-direction: column; row-gap: 10px; - width: 300px; +} + +#unit-control-panel>div:nth-child(2) { + width: 330px; } #unit-control-panel>*:nth-child(1) { @@ -262,18 +266,47 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { } #advanced-settings-div { + position: relative; column-gap: 5px; display: flex; + height: fit-content; } #advanced-settings-div>*:nth-child(2) { margin-left: auto; + margin-right: 58px; } #advanced-settings-div button { height: 40px; } +#explosion-types-selector { + padding-right: 5px; + border-radius: var(--border-radius-sm); + display: flex; + flex-direction: column; + row-gap: 5px; + background-color: var(--background-steel); + position: absolute; + right: 0px; + bottom: 0px; + height: fit-content; + overflow: hidden; +} + +#explosion-types-selector>*:not(:last-child) { + display: none; +} + +#explosion-types-selector:hover { + padding: 5px 5px 0px 5px; +} + +#explosion-types-selector:hover>*:not(:last-child) { + display: block; +} + /* Element visibility control */ #unit-control-panel:not([data-show-categories-tooltip]) #categories-tooltip, #unit-control-panel:not([data-show-speed-slider]) #speed-slider, diff --git a/client/public/stylesheets/style/style.css b/client/public/stylesheets/style/style.css index 1ff9293e..b8d68b6f 100644 --- a/client/public/stylesheets/style/style.css +++ b/client/public/stylesheets/style/style.css @@ -88,7 +88,7 @@ form { } .ol-scrollable { - overflow-y: scroll; + overflow-y: auto; scrollbar-color: white transparent; scrollbar-width: thin; } diff --git a/client/public/themes/olympus/images/icons/fire-solid.svg b/client/public/themes/olympus/images/icons/fire-solid.svg new file mode 100644 index 00000000..c227821a --- /dev/null +++ b/client/public/themes/olympus/images/icons/fire-solid.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/public/themes/olympus/images/icons/napalm.svg b/client/public/themes/olympus/images/icons/napalm.svg new file mode 100644 index 00000000..b82d15a8 --- /dev/null +++ b/client/public/themes/olympus/images/icons/napalm.svg @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/client/public/themes/olympus/images/icons/secondaries.svg b/client/public/themes/olympus/images/icons/secondaries.svg new file mode 100644 index 00000000..2863e9a4 --- /dev/null +++ b/client/public/themes/olympus/images/icons/secondaries.svg @@ -0,0 +1,49 @@ + + + + + + + + + + diff --git a/client/public/themes/olympus/images/icons/white-phosphorous.svg b/client/public/themes/olympus/images/icons/white-phosphorous.svg new file mode 100644 index 00000000..95627c72 --- /dev/null +++ b/client/public/themes/olympus/images/icons/white-phosphorous.svg @@ -0,0 +1,41 @@ + + + + + + + + diff --git a/client/src/server/servermanager.ts b/client/src/server/servermanager.ts index 528a539e..f1ec0a54 100644 --- a/client/src/server/servermanager.ts +++ b/client/src/server/servermanager.ts @@ -212,8 +212,8 @@ export class ServerManager { this.PUT(data, callback); } - deleteUnit(ID: number, explosion: boolean, immediate: boolean, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "explosion": explosion, "immediate": immediate }; + deleteUnit(ID: number, explosion: boolean, explosionType: string, immediate: boolean, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "explosion": explosion, "explosionType": explosionType, "immediate": immediate }; var data = { "deleteUnit": command } this.PUT(data, callback); } diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts index 5f529327..47968e04 100644 --- a/client/src/unit/unit.ts +++ b/client/src/unit/unit.ts @@ -851,8 +851,8 @@ export class Unit extends CustomMarker { getApp().getServerManager().setOperateAs(this.ID, coalitionToEnum(operateAs)); } - delete(explosion: boolean, immediate: boolean) { - getApp().getServerManager().deleteUnit(this.ID, explosion, immediate); + delete(explosion: boolean, explosionType: string, immediate: boolean) { + getApp().getServerManager().deleteUnit(this.ID, explosion, explosionType, immediate); } refuel() { diff --git a/client/src/unit/unitsmanager.ts b/client/src/unit/unitsmanager.ts index f50e0d23..c1e159ab 100644 --- a/client/src/unit/unitsmanager.ts +++ b/client/src/unit/unitsmanager.ts @@ -37,7 +37,7 @@ export class UnitsManager { document.addEventListener('contactsUpdated', (e: CustomEvent) => { this.#requestDetectionUpdate = true }); document.addEventListener('copy', () => this.selectedUnitsCopy()); document.addEventListener('deleteSelectedUnits', () => this.selectedUnitsDelete()); - document.addEventListener('explodeSelectedUnits', () => this.selectedUnitsDelete(true)); + document.addEventListener('explodeSelectedUnits', (e: any) => this.selectedUnitsDelete(true, e.detail.type)); document.addEventListener('exportToFile', () => this.exportToFile()); document.addEventListener('importFromFile', () => this.importFromFile()); document.addEventListener('keyup', (event) => this.#onKeyUp(event)); @@ -794,7 +794,7 @@ export class UnitsManager { * @param explosion If true, the unit will be deleted using an explosion * @returns */ - selectedUnitsDelete(explosion: boolean = false) { + selectedUnitsDelete(explosion: boolean = false, explosionType: string = "") { var selectedUnits = this.getSelectedUnits({excludeProtected:true}); /* Can be applied to humans too */ const selectionContainsAHuman = selectedUnits.some((unit: Unit) => { return unit.getHuman() === true; @@ -804,9 +804,9 @@ export class UnitsManager { return; } - const doDelete = (explosion = false, immediate = false) => { + const doDelete = (explosion = false, explosionType = "", immediate = false) => { for (let idx in selectedUnits) { - selectedUnits[idx].delete(explosion, immediate); + selectedUnits[idx].delete(explosion, explosionType, immediate); } this.#showActionMessage(selectedUnits, `deleted`); } @@ -814,12 +814,12 @@ export class UnitsManager { if (selectedUnits.length >= DELETE_SLOW_THRESHOLD) this.#showSlowDeleteDialog(selectedUnits).then((action:any) => { if (action === "delete-slow") - doDelete(explosion, false); + doDelete(explosion, explosionType, false); else if (action === "delete-immediate") - doDelete(explosion, true); + doDelete(explosion, explosionType, true); }) else - doDelete(explosion); + doDelete(explosion, explosionType); } diff --git a/client/views/panels/unitcontrol.ejs b/client/views/panels/unitcontrol.ejs index ec9d2b3b..b308cd5f 100644 --- a/client/views/panels/unitcontrol.ejs +++ b/client/views/panels/unitcontrol.ejs @@ -1,7 +1,7 @@
-
+

Selected Units

@@ -14,100 +14,108 @@
-
-

Controls

-
-
-
Speed
-
-
-
-
-
- -
+
+
+

Controls

+
+
+
Speed
+
+
+
+
+
+ +
+
+
+
+
Altitude +
+
+
+
+
+
+ +
+
+
Multiple categories selected
-
-
-
Altitude -
-
-
-
-
-
- -
+ +
+

Rules of engagement

+
+ +
-
Multiple categories selected
-
-
-

Rules of engagement

-
- +
+

Reaction to threat

+
+ +
-
-
-

Reaction to threat

-
- +
+

Radar & ECM

+
+ +
-
-
-

Radar & ECM

-
- +
+

Shots scatter

+
+ +
-
-
-

Shots scatter

-
- +
+

Shots intensity

+
+ +
-
-
-

Shots intensity

-
- +
+

Enable tanker

+
-
-
-

Enable tanker

-
-
+
+

Airborne Early Warning

+
+
-
-

Airborne Early Warning

-
-
+
+

Operate as

+
+
-
-

Operate as

-
-
+
+

Unit active

+
+
-
-

Unit active

-
-
- -
-

Follow roads

-
+
+

Follow roads

+
+

- - + +
+ + + + +
+
diff --git a/scripts/OlympusCommand.lua b/scripts/OlympusCommand.lua index 5b457626..d1d00b3f 100644 --- a/scripts/OlympusCommand.lua +++ b/scripts/OlympusCommand.lua @@ -870,12 +870,16 @@ function Olympus.clone(cloneTable, deleteOriginal) end -- Delete a unit by ID, optionally use an explosion -function Olympus.delete(ID, explosion) +function Olympus.delete(ID, explosion, explosionType) Olympus.debug("Olympus.delete " .. ID .. " " .. tostring(explosion), 2) local unit = Olympus.getUnitByID(ID) if unit then if unit:getPlayerName() or explosion then - trigger.action.explosion(unit:getPoint() , 250 ) --consider replacing with forcibly deslotting the player, however this will work for now + if explosionType == nil then + explosionType = "normal" + end + local lat, lng, alt = coord.LOtoLL(unit:getPoint()) + Olympus.explosion(250, explosionType, lat, lng) Olympus.debug("Olympus.delete completed successfully", 2) else unit:destroy(); --works for AI units not players diff --git a/src/core/include/commands.h b/src/core/include/commands.h index c12af0ef..02707ad0 100644 --- a/src/core/include/commands.h +++ b/src/core/include/commands.h @@ -278,10 +278,11 @@ private: class Delete : public Command { public: - Delete(unsigned int ID, bool explosion, bool immediate, function callback = [](){}) : + Delete(unsigned int ID, bool explosion, string explosionType, bool immediate, function callback = [](){}) : Command(callback), ID(ID), explosion(explosion), + explosionType(explosionType), immediate(immediate) { priority = CommandPriority::HIGH; @@ -293,6 +294,7 @@ public: private: const unsigned int ID; const bool explosion; + const string explosionType; const bool immediate; }; diff --git a/src/core/include/unitsmanager.h b/src/core/include/unitsmanager.h index 56b21d18..b3e0f6e7 100644 --- a/src/core/include/unitsmanager.h +++ b/src/core/include/unitsmanager.h @@ -20,7 +20,7 @@ public: void update(json::value& missionData, double dt); void runAILoop(); void getUnitData(stringstream &ss, unsigned long long time); - void deleteUnit(unsigned int ID, bool explosion, bool immediate); + void deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate); void acquireControl(unsigned int ID); void loadDatabases(); Unit* getClosestUnit(Unit* unit, unsigned char coalition, vector categories, double &distance); diff --git a/src/core/src/commands.cpp b/src/core/src/commands.cpp index 3cd58e18..9910ff9d 100644 --- a/src/core/src/commands.cpp +++ b/src/core/src/commands.cpp @@ -165,7 +165,8 @@ string Delete::getString() commandSS.precision(10); commandSS << "Olympus.delete, " << ID << ", " - << (explosion ? "true" : "false"); + << (explosion ? "true" : "false") << ", " + << "\"" << explosionType << "\""; return commandSS.str(); } diff --git a/src/core/src/scheduler.cpp b/src/core/src/scheduler.cpp index 489becf8..a5289b5b 100644 --- a/src/core/src/scheduler.cpp +++ b/src/core/src/scheduler.cpp @@ -408,10 +408,11 @@ void Scheduler::handleRequest(string key, json::value value, string username, js { unsigned int ID = value[L"ID"].as_integer(); bool explosion = value[L"explosion"].as_bool(); + string explosionType = to_string(value[L"explosionType"]); bool immediate = value[L"immediate"].as_bool(); Unit* unit = unitsManager->getUnit(ID); if (unit != nullptr) { - unitsManager->deleteUnit(ID, explosion, immediate); + unitsManager->deleteUnit(ID, explosion, explosionType, immediate); log(username + " deleted unit " + unit->getUnitName() + "(" + unit->getName() + ")", true); } } diff --git a/src/core/src/unitsmanager.cpp b/src/core/src/unitsmanager.cpp index 30a5ac20..0e175f4c 100644 --- a/src/core/src/unitsmanager.cpp +++ b/src/core/src/unitsmanager.cpp @@ -142,11 +142,11 @@ void UnitsManager::getUnitData(stringstream &ss, unsigned long long time) p.second->getData(ss, time); } -void UnitsManager::deleteUnit(unsigned int ID, bool explosion, bool immediate) +void UnitsManager::deleteUnit(unsigned int ID, bool explosion, string explosionType, bool immediate) { if (getUnit(ID) != nullptr) { - Command* command = dynamic_cast(new Delete(ID, explosion, immediate)); + Command* command = dynamic_cast(new Delete(ID, explosion, explosionType, immediate)); scheduler->appendCommand(command); } }