Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions src/Map.vue
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,20 @@
<v-icon>location_on</v-icon>
</v-list-tile-avatar>
</v-list-tile>
<v-list-tile>
<v-list-tile-action>
<v-switch
v-model="showAccurateMortarRange"
/>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>Show Accurate Range</v-list-tile-title>
<v-list-tile-sub-title>NOTE: Can be slow</v-list-tile-sub-title>
</v-list-tile-content>
<v-list-tile-avatar>
<v-icon>approval</v-icon>
</v-list-tile-avatar>
</v-list-tile>
<v-list-tile>
<v-list-tile-action>
<v-switch
Expand Down Expand Up @@ -951,6 +965,7 @@ export default {
showGrid: this.fromStorage("showGrid", "true") === "true",
showHeightmap: this.fromStorage("showHeightmap", "false") === "true",
showLocations: this.fromStorage("showLocations", "false") === "true",
showAccurateMortarRange: this.fromStorage("showAccurateMortarRange", "false") === "true",
selectedMap: this.initialMap || this.fromStorage("selectedMap", undefined), // selected map in top selector
delayCalcUpdate: this.fromStorage("delayCalcUpdate", "true") === "true",
hideLoadingBar: this.fromStorage("hideLoadingBar", "true") === "true",
Expand Down Expand Up @@ -1468,7 +1483,35 @@ export default {
this.subTargetLine.bringToFront();
}
},
/**
* Updates the polygon around the mortar showing how fare it can shoot
* Note this is a fairly slow function.
*/
updateMortarDistance() {
if (!this.showAccurateMortarRange) {
this.mortar.setMaxRangePolygon([]);
return;
}

if (!this.mortar) {
return;
}

const mPos = this.mortar.pos;
const mVel = this.mortarType.velocity;
const useNatoMils = !this.postScriptum;

let latLngs = [];

/* const bearing = index; */
latLngs = Utils.getMaxMortar360Distance(
mPos,
mVel,
this.squadMap,
useNatoMils,
);
this.mortar.setMaxRangePolygon(latLngs);
},
/**
* Calculates the mortar settings based on the given mortar & target positions.
*
Expand Down Expand Up @@ -1884,13 +1927,20 @@ export default {
}
this.toStorage("showLocations", b);
},
showAccurateMortarRange(b) {
console.log("showAccurateMortarRange:", b);

this.updateMortarDistance();
this.toStorage("showAccurateMortarRange", b);
},
/**
* Triggers calculation on position change of active mortar
*/
"mortar.pos": function mortarPosWatcher() {
console.log("mortarPosWatcher");
this.updateSubTargets();
this.calcAndUpdate();
this.updateMortarDistance();
},
/**
* Triggers calculation on position change of active target
Expand Down
83 changes: 83 additions & 0 deletions src/assets/Utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,89 @@ export function getMortarSettings(mPos, tPos, mVel, dHeight = 0, useNatoMils = t
};
}


/**
* Calculates mortar settings for a mortar to hit a target.
*
* @param {LatLng} mPos - mortar position
* @param {number} bearing - bearing
* @param {number} mVel - mortar shell velocity
* @param {boolean} [useNatoMils] - use regular Milliradians or NATO Milliradians (Squad uses NATO mils)
* @param {SquadMap} [SquadMap] - use regular Milliradians or NATO Milliradians (Squad uses NATO mils)
* @returns {{bearing: number, elevation: (number|NaN), dist: number, dHeight: number}} - bearing and elevation settings
* required to hit target. Elevation is NaN if target is out of range.
*/
export function getMaxMortarDistance(mPos, bearing, mVel, squadMap, useNatoMils = true) {
// This function isn't optimal at all and could be optimized.
// This function takes a direction(bearing) and a initial position(mPos) and attempts to find
// the position which is the furthest away from the mortar but close enough to be hit.

// Parameters which can be tweaked in order to make it more accurate
// Increments in meters which will be checked, less = more accurate and more slow
const increments = 10;

// distanceStart deterine where to start the look for max distance
const distanceStart = 1200;

// distanceStart deterine where to stop the look for max distance
const distanceStop = 1300;

const angle = bearing * Math.PI / 180;

// The position of where the mortar are able to hit
let lastLatLng = null;

for (let dist = distanceStart; dist < distanceStop; dist += increments) {
// Calculating the position

// New latitude
const x1 = mPos.lat - Math.cos(angle) * dist;
// New longitude
const y1 = mPos.lng + Math.sin(angle) * dist;

// Get the height difference between the mortar and target
const mHeight = squadMap.hasHeightmap ? squadMap.getHeightmapHolder().getHeight(mPos.lng, mPos.lat) : 0;
const tHeight = squadMap.hasHeightmap ? squadMap.getHeightmapHolder().getHeight(x1, y1) : 0;
const dHeight = tHeight - mHeight;

const elevation = useNatoMils ? getNatoElevation(dist, dHeight, mVel) : getElevation(dist, dHeight, mVel);

// Check if elevation is valid if not, the best distance has been found
if (Number.isNaN(elevation) || elevation >= 1580) {
break;
} else {
lastLatLng = new LatLng(x1, y1);
}
}

return lastLatLng;
}

/**
* Calculates a series of points indicating the max mortaring distance all around the mortar
* This also accounts for the height difference
*
* @param {LatLng} mPos - mortar position
* @param {number} bearing - bearing
* @param {number} mVel - mortar shell velocity
* @param {boolean} [useNatoMils] - use regular Milliradians or NATO Milliradians (Squad uses NATO mils)
* @param {SquadMap} [SquadMap] - use regular Milliradians or NATO Milliradians (Squad uses NATO mils)
* @returns {LatLng[]} - The coordniates forming a polygon
*/
export function getMaxMortar360Distance(mPos, mVel, squadMap, useNatoMils = true) {
const latLngs = [];

for (let bearing = 0; bearing < 360; bearing += 18) {
const latLng = getMaxMortarDistance(mPos, bearing, mVel, squadMap, useNatoMils);
if (!latLng) {
console.warn("invalid latlng");
}
latLngs.push(latLng);
}

return latLngs;
}

/**
* Get available mortar types for Squad
*
Expand Down
8 changes: 7 additions & 1 deletion src/assets/marker/MarkerHolder.js
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,13 @@ export default class MarkerHolder {
*/
_moveAttachments(latlng) {
this._attachments.forEach((a) => {
a.setLatLng(latlng);
try {
a.setLatLng(latlng);
} catch (error) {
// This error happens because you can't call .setLatLng() on the polygram attachment
// Feel free to find a better way to handle this error
console.log("this is fine");
}
});
}

Expand Down
28 changes: 26 additions & 2 deletions src/assets/marker/pin/MortarPin.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Circle } from "leaflet";
import { Circle, Polygon } from "leaflet";

import PinHolder from "./PinHolder";
import { MIN_DISTANCE, SQUAD_MAX_DISTANCE } from "../../Vars";
Expand Down Expand Up @@ -37,6 +37,16 @@ export default class MortarPin extends PinHolder {
}
}

/**
* This postions in which the mortar are actually able to hit
* @param {LatLng[]} latlngs
*/
setMaxRangePolygon(latlngs) {
if (this.maxRangePolygon) {
this.maxRangePolygon.setLatLngs(latlngs);
}
}

/**
* Creates min and max range circles for mortar marker
*/
Expand Down Expand Up @@ -64,6 +74,20 @@ export default class MortarPin extends PinHolder {
clickable: false, // legacy support
});

this._attachments = [this.minRangeCircle, this.maxRangeCircle];
/**
* This shows the actual range in which the mortar are able to hit. This accounts for height differences
*/
this.maxRangePolygon = new Polygon(this.pos, {
draggable: "false",
radius: this.maxDistance,
color: "red",
fillOpacity: 0.1,
fillColor: this.color,
dashArray: "5, 5",
interactive: false,
clickable: false, // legacy support
});

this._attachments = [this.minRangeCircle, this.maxRangeCircle, this.maxRangePolygon];
}
}