From f3155e618b08da02b1121caba70f74e1c4a029e3 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Fri, 22 Sep 2023 16:05:03 +0200 Subject: [PATCH] Added target altitude effect to simulated fire fight --- client/demo.js | 18 ++++++++++++++++- client/public/stylesheets/leaflet/leaflet.css | 7 +------ client/src/map/map.ts | 4 ++-- client/src/other/utils.ts | 15 ++++++++++++++ client/src/server/servermanager.ts | 4 ++-- client/src/unit/unit.ts | 4 ++-- client/src/unit/unitsmanager.ts | 20 +++++++++++++------ src/core/src/groundunit.cpp | 2 +- src/core/src/scheduler.cpp | 3 ++- 9 files changed, 56 insertions(+), 21 deletions(-) diff --git a/client/demo.js b/client/demo.js index 99c65f9a..3a5b86a5 100644 --- a/client/demo.js +++ b/client/demo.js @@ -96,7 +96,23 @@ const DEMO_UNIT_DATA = { ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ], contacts: [{ID: 1, detectionMethod: 16}], activePath: [ ] - }, + }, ["7"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "T-55", unitName: "Cool guy 2-1", groupName: "Cool group 10", state: 1, task: "Being cool", + hasTask: false, position: { lat: 37.2, lng: -116.2, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isTanker: false, isAWACS: false, onOff: true, followRoads: false, fuel: 50, + desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0, + formationOffset: { x: 0, y: 0, z: 0 }, + targetID: 0, + targetPosition: { lat: 0, lng: 0, alt: 0 }, + ROE: 1, + reactionToThreat: 1, + emissionsCountermeasures: 1, + TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 }, + radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 }, + generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false }, + ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ], + contacts: [{ID: 1001, detectionMethod: 16}], + activePath: [ ], + isLeader: true + }, } const DEMO_WEAPONS_DATA = { diff --git a/client/public/stylesheets/leaflet/leaflet.css b/client/public/stylesheets/leaflet/leaflet.css index 9ade8dc4..1981009f 100644 --- a/client/public/stylesheets/leaflet/leaflet.css +++ b/client/public/stylesheets/leaflet/leaflet.css @@ -60,11 +60,6 @@ padding: 0; } -.leaflet-container img.leaflet-tile { - /* See: https://bugs.chromium.org/p/chromium/issues/detail?id=600120 */ - mix-blend-mode: plus-lighter; -} - .leaflet-container.leaflet-touch-zoom { -ms-touch-action: pan-x pan-y; touch-action: pan-x pan-y; @@ -651,7 +646,7 @@ svg.leaflet-image-layer.leaflet-interactive path { } /* Printing */ - + @media print { /* Prevent printers from removing background-images of controls. */ .leaflet-control { diff --git a/client/src/map/map.ts b/client/src/map/map.ts index 89a967e5..e4a4c05c 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -608,8 +608,8 @@ export class Map extends L.Map { getApp().getUnitsManager().selectedUnitsFireAtArea(this.getMouseCoordinates()); } else if (option === "simulate-fire-fight") { - getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE); - getUnitsManager().selectedUnitsSimulateFireFight(this.getMouseCoordinates()); + getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE); + getApp().getUnitsManager().selectedUnitsSimulateFireFight(this.getMouseCoordinates()); } }); } diff --git a/client/src/other/utils.ts b/client/src/other/utils.ts index 78d025e2..29956750 100644 --- a/client/src/other/utils.ts +++ b/client/src/other/utils.ts @@ -397,4 +397,19 @@ export function getCheckboxOptions(dropdown: Dropdown) { values[key] = value; } return values; +} + +export function getGroundElevation(latlng: LatLng, callback: CallableFunction) { + /* Get the ground elevation from the server endpoint */ + const xhr = new XMLHttpRequest(); + xhr.open('GET', `api/elevation/${latlng.lat}/${latlng.lng}`, true); + xhr.timeout = 500; // ms + xhr.responseType = 'json'; + xhr.onload = () => { + var status = xhr?.status; + if (status === 200) { + callback(xhr.response) + } + }; + xhr.send(); } \ No newline at end of file diff --git a/client/src/server/servermanager.ts b/client/src/server/servermanager.ts index 8df86f62..2af8f08b 100644 --- a/client/src/server/servermanager.ts +++ b/client/src/server/servermanager.ts @@ -322,8 +322,8 @@ export class ServerManager { this.POST(data, callback); } - simulateFireFight(ID: number, latlng: LatLng, callback: CallableFunction = () => {}) { - var command = { "ID": ID, "location": latlng } + simulateFireFight(ID: number, latlng: LatLng, altitude: number, callback: CallableFunction = () => {}) { + var command = { "ID": ID, "location": latlng, "altitude": altitude } var data = { "simulateFireFight": command } this.POST(data, callback); } diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts index ee73bdc0..272067d1 100644 --- a/client/src/unit/unit.ts +++ b/client/src/unit/unit.ts @@ -722,8 +722,8 @@ export class Unit extends CustomMarker { getApp().getServerManager().fireAtArea(this.ID, latlng); } - simulateFireFight(latlng: LatLng) { - getApp().getServerManager().simulateFireFight(this.ID, latlng); + simulateFireFight(latlng: LatLng, groundElevation: number | null) { + getApp().getServerManager().simulateFireFight(this.ID, latlng, groundElevation?? 0); } /***********************************************/ diff --git a/client/src/unit/unitsmanager.ts b/client/src/unit/unitsmanager.ts index 71720d6b..a5b05bb8 100644 --- a/client/src/unit/unitsmanager.ts +++ b/client/src/unit/unitsmanager.ts @@ -1,7 +1,7 @@ import { LatLng, LatLngBounds } from "leaflet"; import { getApp } from ".."; import { Unit } from "./unit"; -import { bearingAndDistanceToLatLng, deg2rad, getUnitDatabaseByCategory, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils"; +import { bearingAndDistanceToLatLng, deg2rad, getGroundElevation, getUnitDatabaseByCategory, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polyContains, polygonArea, randomPointInPoly, randomUnitBlueprint } from "../other/utils"; import { CoalitionArea } from "../map/coalitionarea/coalitionarea"; import { groundUnitDatabase } from "./databases/groundunitdatabase"; import { DataIndexes, GAME_MASTER, IADSDensities, IDLE, MOVE_UNIT } from "../constants/constants"; @@ -590,7 +590,7 @@ export class UnitsManager { for (let idx in selectedUnits) { selectedUnits[idx].carpetBomb(latlng); } - this.#showActionMessage(selectedUnits, `unit bombing point`); + this.#showActionMessage(selectedUnits, `unit carpet bombing point`); } /** Instruct the selected units to fire at specific coordinates @@ -602,7 +602,7 @@ export class UnitsManager { for (let idx in selectedUnits) { selectedUnits[idx].fireAtArea(latlng); } - this.#showActionMessage(selectedUnits, `unit bombing point`); + this.#showActionMessage(selectedUnits, `unit firing at area`); } /** Instruct the selected units to simulate a fire fight at specific coordinates @@ -611,9 +611,17 @@ export class UnitsManager { */ selectedUnitsSimulateFireFight(latlng: LatLng) { var selectedUnits = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }); - for (let idx in selectedUnits) { - selectedUnits[idx].simulateFireFight(latlng); - } + getGroundElevation(latlng, (response: string) => { + var groundElevation: number | null = null; + try { + groundElevation = parseFloat(response); + } catch { + console.log("Simulate fire fight: could not retrieve ground elevation") + } + for (let idx in selectedUnits) { + selectedUnits[idx].simulateFireFight(latlng, groundElevation); + } + }); this.#showActionMessage(selectedUnits, `unit simulating fire fight`); } diff --git a/src/core/src/groundunit.cpp b/src/core/src/groundunit.cpp index 61aa867f..1d54b8b4 100644 --- a/src/core/src/groundunit.cpp +++ b/src/core/src/groundunit.cpp @@ -179,7 +179,7 @@ void GroundUnit::AIloop() } } - double barrelElevation = r * (9.81 * dist / (2 * muzzleVelocity * muzzleVelocity) - barrelHeight / dist); /* m */ + double barrelElevation = r * (9.81 * dist / (2 * muzzleVelocity * muzzleVelocity) + (targetPosition.alt - (position.alt + barrelHeight)) / dist); /* m */ double lat = 0; double lng = 0; diff --git a/src/core/src/scheduler.cpp b/src/core/src/scheduler.cpp index 182318bd..095764d2 100644 --- a/src/core/src/scheduler.cpp +++ b/src/core/src/scheduler.cpp @@ -568,7 +568,8 @@ void Scheduler::handleRequest(string key, json::value value, string username, js unitsManager->acquireControl(ID); double lat = value[L"location"][L"lat"].as_double(); double lng = value[L"location"][L"lng"].as_double(); - Coords loc; loc.lat = lat; loc.lng = lng; + double alt = value[L"altitude"].as_double(); + Coords loc; loc.lat = lat; loc.lng = lng; loc.alt = alt; Unit* unit = unitsManager->getGroupLeader(ID); unit->setState(State::SIMULATE_FIRE_FIGHT); unit->setTargetPosition(loc);