mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added more functions to edit Coalition Areas
This commit is contained in:
parent
ad3b1cb167
commit
f9f02c3eb0
3362
client/package-lock.json
generated
3362
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -10,6 +10,7 @@
|
||||
"watch": "watchify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ]"
|
||||
},
|
||||
"dependencies": {
|
||||
"@turf/turf": "^6.5.0",
|
||||
"@types/formatcoords": "^1.1.0",
|
||||
"@types/geojson": "^7946.0.10",
|
||||
"@types/leaflet": "^1.9.0",
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import { getUnitsManager } from "..";
|
||||
import { CoalitionArea } from "../map/coalitionarea";
|
||||
import { groundUnitsDatabase } from "../units/groundunitsdatabase";
|
||||
import { ContextMenu } from "./contextmenu";
|
||||
import { Dropdown } from "./dropdown";
|
||||
import { Slider } from "./slider";
|
||||
import { Switch } from "./switch";
|
||||
|
||||
const unitRole = ["AAA", "MANPADS", "Short range SAM", "Long range SAM", "Radar"];
|
||||
const unitRole = ["AAA", "MANPADS", "SAM Sites", "Radar"];
|
||||
|
||||
export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
#coalitionSwitch: Switch;
|
||||
@ -30,6 +30,22 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
this.showSubMenu(e.detail.type);
|
||||
});
|
||||
|
||||
document.addEventListener("contextMenuCreateIads", (e: any) => {
|
||||
const values: {[key: string]: boolean} = {};
|
||||
const element = this.#iadsRoleDropdown.getOptionElements();
|
||||
for (let idx = 0; idx < element.length; idx++) {
|
||||
const option = element.item(idx) as HTMLElement;
|
||||
const key = option.querySelector("span")?.innerText;
|
||||
const value = option.querySelector("input")?.checked;
|
||||
if (key !== undefined && value !== undefined)
|
||||
values[key] = value;
|
||||
}
|
||||
|
||||
const area = this.getCoalitionArea();
|
||||
if (area)
|
||||
getUnitsManager().createIADS(area, values, this.#iadsDensitySlider.getValue());
|
||||
})
|
||||
|
||||
/* Create the checkboxes to select the unit roles */
|
||||
this.#iadsRoleDropdown.setOptionsElements(unitRole.map((unitRole: string) => {
|
||||
var div = document.createElement("div");
|
||||
@ -38,6 +54,7 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
label.title = `Add ${unitRole}s to the IADS`;
|
||||
var input = document.createElement("input");
|
||||
input.type = "checkbox";
|
||||
input.checked = true;
|
||||
var span = document.createElement("span");
|
||||
span.innerText = unitRole;
|
||||
label.appendChild(input);
|
||||
@ -46,8 +63,6 @@ export class CoalitionAreaContextMenu extends ContextMenu {
|
||||
return div as HTMLElement;
|
||||
}));
|
||||
|
||||
|
||||
|
||||
this.hide();
|
||||
}
|
||||
|
||||
|
||||
@ -55,6 +55,10 @@ export class Dropdown {
|
||||
this.#options.replaceChildren(...optionsElements);
|
||||
}
|
||||
|
||||
getOptionElements() {
|
||||
return this.#options.children;
|
||||
}
|
||||
|
||||
selectText(text: string) {
|
||||
const index = [].slice.call(this.#options.children).findIndex((opt: Element) => opt.querySelector("button")?.innerText === text);
|
||||
if (index > -1) {
|
||||
|
||||
@ -14,9 +14,10 @@ export interface SpawnOptions {
|
||||
type: string;
|
||||
latlng: LatLng;
|
||||
coalition: string;
|
||||
loadout: string | null;
|
||||
airbaseName: string | null;
|
||||
altitude: number | null;
|
||||
loadout?: string | null;
|
||||
airbaseName?: string | null;
|
||||
altitude?: number | null;
|
||||
immediate?: boolean;
|
||||
}
|
||||
|
||||
export class MapContextMenu extends ContextMenu {
|
||||
|
||||
@ -223,6 +223,10 @@ export function getUnitsManager() {
|
||||
return unitsManager;
|
||||
}
|
||||
|
||||
export function getMissionHandler() {
|
||||
return missionHandler;
|
||||
}
|
||||
|
||||
export function getUnitInfoPanel() {
|
||||
return unitInfoPanel;
|
||||
}
|
||||
|
||||
@ -1,20 +1,105 @@
|
||||
import { LatLngExpression, Polygon, PolylineOptions } from "leaflet";
|
||||
import { LatLng, LatLngExpression, Polygon, PolylineOptions } from "leaflet";
|
||||
import { getMap } from "..";
|
||||
import { DRAW_POLYGON } from "./map";
|
||||
import { CoalitionAreaHandle } from "./coalitionareahandle";
|
||||
|
||||
export class CoalitionArea extends Polygon {
|
||||
#coalition: string = "blue";
|
||||
#selected: boolean = true;
|
||||
#editing: boolean = true;
|
||||
#handles: CoalitionAreaHandle[] = [];
|
||||
|
||||
constructor(latlngs: LatLngExpression[] | LatLngExpression[][] | LatLngExpression[][][], options?: PolylineOptions) {
|
||||
if (options === undefined)
|
||||
options = {};
|
||||
|
||||
|
||||
options.bubblingMouseEvents = false;
|
||||
super(latlngs, options);
|
||||
|
||||
this.on("click", (e: any) => {
|
||||
if (!this.getSelected()) {
|
||||
this.setSelected(true);
|
||||
getMap().setState(DRAW_POLYGON);
|
||||
}
|
||||
else if (this.getEditing()) {
|
||||
this.addLatLng(e.latlng);
|
||||
this.addTemporaryLatLng(e.latlng);
|
||||
}
|
||||
});
|
||||
|
||||
this.on("contextmenu", (e: any) => {
|
||||
getMap().showCoalitionAreaContextMenu(e, this);
|
||||
})
|
||||
if (!this.#editing)
|
||||
getMap().showCoalitionAreaContextMenu(e, this);
|
||||
else
|
||||
this.setEditing(false);
|
||||
});
|
||||
|
||||
this.#setColors();
|
||||
}
|
||||
|
||||
setCoalition(coalition: string) {
|
||||
this.setStyle({color: coalition, fillColor: coalition});
|
||||
this.#coalition = coalition;
|
||||
this.#setColors();
|
||||
}
|
||||
|
||||
getCoalition() {
|
||||
return this.#coalition;
|
||||
}
|
||||
|
||||
setSelected(selected: boolean) {
|
||||
this.#selected = selected;
|
||||
this.#setColors();
|
||||
this.#setHandles();
|
||||
if (!selected)
|
||||
this.setEditing(false);
|
||||
}
|
||||
|
||||
getSelected() {
|
||||
return this.#selected;
|
||||
}
|
||||
|
||||
setEditing(editing: boolean) {
|
||||
this.#editing = editing;
|
||||
this.#setHandles();
|
||||
}
|
||||
|
||||
getEditing() {
|
||||
return this.#editing;
|
||||
}
|
||||
|
||||
addTemporaryLatLng(latlng: LatLng) {
|
||||
this.addLatLng(latlng);
|
||||
}
|
||||
|
||||
moveTemporaryLatLng(latlng: LatLng) {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs[latlngs.length - 1] = latlng;
|
||||
this.setLatLngs(latlngs);
|
||||
}
|
||||
|
||||
addLatLng(latlng: LatLngExpression | LatLngExpression[], latlngs?: LatLng[] | undefined): this {
|
||||
super.addLatLng(latlng, latlngs)
|
||||
this.#setHandles();
|
||||
return this;
|
||||
}
|
||||
|
||||
#setColors() {
|
||||
this.setStyle({color: this.getSelected()? "white": this.#coalition, fillColor: this.#coalition});
|
||||
}
|
||||
|
||||
#setHandles() {
|
||||
this.#handles.forEach((handle: CoalitionAreaHandle) => handle.removeFrom(getMap()));
|
||||
this.#handles = [];
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs.forEach((latlng: LatLng, idx: number) => {
|
||||
const handle = new CoalitionAreaHandle(latlng);
|
||||
handle.addTo(getMap());
|
||||
handle.on("dragend", (e: any) => {
|
||||
var latlngs = this.getLatLngs()[0] as LatLng[];
|
||||
latlngs[idx] = e.latlng;
|
||||
this.setLatLngs(latlngs);
|
||||
});
|
||||
this.#handles.push(handle);
|
||||
});
|
||||
}
|
||||
}
|
||||
19
client/src/map/coalitionareahandle.ts
Normal file
19
client/src/map/coalitionareahandle.ts
Normal file
@ -0,0 +1,19 @@
|
||||
import { DivIcon, LatLng } from "leaflet";
|
||||
import { CustomMarker } from "./custommarker";
|
||||
|
||||
export class CoalitionAreaHandle extends CustomMarker {
|
||||
constructor(latlng: LatLng) {
|
||||
super(latlng, {interactive: true, draggable: true});
|
||||
}
|
||||
|
||||
createIcon() {
|
||||
this.setIcon(new DivIcon({
|
||||
iconSize: [52, 52],
|
||||
iconAnchor: [26, 26],
|
||||
className: "leaflet-target-marker",
|
||||
}));
|
||||
var el = document.createElement("div");
|
||||
el.classList.add("ol-target-icon");
|
||||
this.getElement()?.appendChild(el);
|
||||
}
|
||||
}
|
||||
@ -55,7 +55,7 @@ export class Map extends L.Map {
|
||||
#destinationGroupRotation: number = 0;
|
||||
#computeDestinationRotation: boolean = false;
|
||||
#destinationRotationCenter: L.LatLng | null = null;
|
||||
#polygons: CoalitionArea[] = [];
|
||||
#coalitionAreas: CoalitionArea[] = [];
|
||||
|
||||
#mapContextMenu: MapContextMenu = new MapContextMenu("map-contextmenu");
|
||||
#unitContextMenu: UnitContextMenu = new UnitContextMenu("unit-contextmenu");
|
||||
@ -175,16 +175,19 @@ export class Map extends L.Map {
|
||||
if (this.#state === IDLE) {
|
||||
this.#resetDestinationMarkers();
|
||||
this.#resetTargetMarker();
|
||||
this.#deselectCoalitionAreas();
|
||||
this.#showCursor();
|
||||
}
|
||||
else if (this.#state === MOVE_UNIT) {
|
||||
this.#resetTargetMarker();
|
||||
this.#deselectCoalitionAreas();
|
||||
this.#createDestinationMarkers();
|
||||
if (this.#destinationPreviewMarkers.length > 0)
|
||||
this.#hideCursor();
|
||||
}
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) {
|
||||
this.#resetDestinationMarkers();
|
||||
this.#deselectCoalitionAreas();
|
||||
this.#createTargetMarker();
|
||||
this.#hideCursor();
|
||||
}
|
||||
@ -193,8 +196,8 @@ export class Map extends L.Map {
|
||||
this.#resetTargetMarker();
|
||||
this.#showCursor();
|
||||
//@ts-ignore draggable option added by plugin
|
||||
this.#polygons.push(new CoalitionArea([]));
|
||||
this.#polygons[this.#polygons.length - 1].addTo(this);
|
||||
this.#coalitionAreas.push(new CoalitionArea([]));
|
||||
this.#coalitionAreas[this.#coalitionAreas.length - 1].addTo(this);
|
||||
}
|
||||
document.dispatchEvent(new CustomEvent("mapStateChanged"));
|
||||
}
|
||||
@ -394,6 +397,10 @@ export class Map extends L.Map {
|
||||
}
|
||||
}
|
||||
|
||||
getSelectedCoalitionArea() {
|
||||
return this.#coalitionAreas.find((area: CoalitionArea) => {return area.getSelected()});
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
#onClick(e: any) {
|
||||
if (!this.#preventLeftClick) {
|
||||
@ -402,7 +409,14 @@ export class Map extends L.Map {
|
||||
|
||||
}
|
||||
else if (this.#state === DRAW_POLYGON) {
|
||||
this.#polygons[this.#polygons.length - 1].addLatLng(e.latlng);
|
||||
/* This gets only called to create the first point of the area. All other points are added by the area itself */
|
||||
if (this.getSelectedCoalitionArea()?.getEditing()) {
|
||||
this.getSelectedCoalitionArea()?.addLatLng(e.latlng);
|
||||
this.getSelectedCoalitionArea()?.addTemporaryLatLng(e.latlng);
|
||||
}
|
||||
else {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.setState(IDLE);
|
||||
@ -448,17 +462,6 @@ export class Map extends L.Map {
|
||||
}
|
||||
}
|
||||
|
||||
#executeAction(e: any, action: string) {
|
||||
if (action === "bomb")
|
||||
getUnitsManager().selectedUnitsBombPoint(this.getMouseCoordinates());
|
||||
else if (action === "carpet-bomb")
|
||||
getUnitsManager().selectedUnitsCarpetBomb(this.getMouseCoordinates());
|
||||
else if (action === "building-bomb")
|
||||
getUnitsManager().selectedUnitsBombBuilding(this.getMouseCoordinates());
|
||||
else if (action === "fire-at-area")
|
||||
getUnitsManager().selectedUnitsFireAtArea(this.getMouseCoordinates());
|
||||
}
|
||||
|
||||
#onSelectionEnd(e: any) {
|
||||
clearTimeout(this.#leftClickTimer);
|
||||
this.#preventLeftClick = true;
|
||||
@ -497,6 +500,10 @@ export class Map extends L.Map {
|
||||
else if ([BOMBING, CARPET_BOMBING, FIRE_AT_AREA].includes(this.#state)) {
|
||||
this.#targetMarker.setLatLng(this.getMouseCoordinates());
|
||||
}
|
||||
else if (this.#state === DRAW_POLYGON) {
|
||||
if (this.getSelectedCoalitionArea()?.getEditing())
|
||||
this.getSelectedCoalitionArea()?.moveTemporaryLatLng(e.latlng);
|
||||
}
|
||||
}
|
||||
|
||||
#onZoom(e: any) {
|
||||
@ -569,6 +576,10 @@ export class Map extends L.Map {
|
||||
this.removeLayer(this.#targetMarker);
|
||||
}
|
||||
|
||||
#deselectCoalitionAreas() {
|
||||
this.getSelectedCoalitionArea()?.setSelected(false);
|
||||
}
|
||||
|
||||
#showCursor() {
|
||||
document.getElementById(this.#ID)?.classList.remove("hidden-cursor");
|
||||
}
|
||||
|
||||
@ -3,50 +3,41 @@ import { getInfoPopup, getMap } from "..";
|
||||
import { Airbase } from "./airbase";
|
||||
import { Bullseye } from "./bullseye";
|
||||
|
||||
export class MissionHandler
|
||||
{
|
||||
#bullseyes : {[name: string]: Bullseye} = {};
|
||||
#airbases : {[name: string]: Airbase} = {};
|
||||
#theatre : string = "";
|
||||
export class MissionHandler {
|
||||
#bullseyes: { [name: string]: Bullseye } = {};
|
||||
#airbases: { [name: string]: Airbase } = {};
|
||||
#theatre: string = "";
|
||||
|
||||
#airbaseData : { [name: string]: object } = {};
|
||||
#airbaseData: { [name: string]: object } = {};
|
||||
|
||||
// Time
|
||||
#date : any;
|
||||
#elapsedTime : any;
|
||||
#startTime : any;
|
||||
#time : any;
|
||||
#date: any;
|
||||
#elapsedTime: any;
|
||||
#startTime: any;
|
||||
#time: any;
|
||||
|
||||
#updateTime : any;
|
||||
#updateTime: any;
|
||||
|
||||
constructor()
|
||||
{
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
update(data: BullseyesData | AirbasesData | any)
|
||||
{
|
||||
if ("bullseyes" in data)
|
||||
{
|
||||
for (let idx in data.bullseyes)
|
||||
{
|
||||
update(data: BullseyesData | AirbasesData | any) {
|
||||
if ("bullseyes" in data) {
|
||||
for (let idx in data.bullseyes) {
|
||||
const bullseye = data.bullseyes[idx];
|
||||
if (!(idx in this.#bullseyes))
|
||||
this.#bullseyes[idx] = new Bullseye([0, 0]).addTo(getMap());
|
||||
|
||||
if (bullseye.latitude && bullseye.longitude && bullseye.coalition)
|
||||
{
|
||||
this.#bullseyes[idx].setLatLng(new LatLng(bullseye.latitude, bullseye.longitude));
|
||||
|
||||
if (bullseye.latitude && bullseye.longitude && bullseye.coalition) {
|
||||
this.#bullseyes[idx].setLatLng(new LatLng(bullseye.latitude, bullseye.longitude));
|
||||
this.#bullseyes[idx].setCoalition(bullseye.coalition);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ("mission" in data)
|
||||
{
|
||||
if (data.mission != null && data.mission.theatre != this.#theatre)
|
||||
{
|
||||
if ("mission" in data) {
|
||||
if (data.mission != null && data.mission.theatre != this.#theatre) {
|
||||
this.#theatre = data.mission.theatre;
|
||||
getMap().setTheatre(this.#theatre);
|
||||
|
||||
@ -55,30 +46,18 @@ export class MissionHandler
|
||||
}
|
||||
|
||||
|
||||
if ("airbases" in data)
|
||||
{
|
||||
/*
|
||||
console.log( Object.values( data.airbases ).sort( ( a:any, b:any ) => {
|
||||
const aVal = a.callsign.toLowerCase();
|
||||
const bVal = b.callsign.toLowerCase();
|
||||
|
||||
return aVal > bVal ? 1 : -1;
|
||||
}) );
|
||||
//*/
|
||||
for (let idx in data.airbases)
|
||||
{
|
||||
if ("airbases" in data) {
|
||||
for (let idx in data.airbases) {
|
||||
var airbase = data.airbases[idx]
|
||||
if (this.#airbases[idx] === undefined && airbase.callsign != '')
|
||||
{
|
||||
if (this.#airbases[idx] === undefined && airbase.callsign != '') {
|
||||
this.#airbases[idx] = new Airbase({
|
||||
position: new LatLng(airbase.latitude, airbase.longitude),
|
||||
position: new LatLng(airbase.latitude, airbase.longitude),
|
||||
name: airbase.callsign
|
||||
}).addTo(getMap());
|
||||
this.#airbases[idx].on('contextmenu', (e) => this.#onAirbaseClick(e));
|
||||
}
|
||||
|
||||
if (this.#airbases[idx] != undefined && airbase.latitude && airbase.longitude && airbase.coalition)
|
||||
{
|
||||
if (this.#airbases[idx] != undefined && airbase.latitude && airbase.longitude && airbase.coalition) {
|
||||
this.#airbases[idx].setLatLng(new LatLng(airbase.latitude, airbase.longitude));
|
||||
this.#airbases[idx].setCoalition(airbase.coalition);
|
||||
}
|
||||
@ -87,83 +66,68 @@ export class MissionHandler
|
||||
}
|
||||
}
|
||||
|
||||
if ("mission" in data && data.mission != null)
|
||||
{
|
||||
if (data.mission != null && data.mission.theatre != this.#theatre)
|
||||
{
|
||||
if ("mission" in data && data.mission != null) {
|
||||
if (data.mission != null && data.mission.theatre != this.#theatre) {
|
||||
this.#theatre = data.mission.theatre;
|
||||
getMap().setTheatre(this.#theatre);
|
||||
|
||||
getInfoPopup().setText("Map set to " + this.#theatre);
|
||||
}
|
||||
|
||||
if ( "date" in data.mission ) {
|
||||
if ("date" in data.mission)
|
||||
this.#date = data.mission.date;
|
||||
}
|
||||
|
||||
if ( "elapsedTime" in data.mission ) {
|
||||
if ("elapsedTime" in data.mission)
|
||||
this.#elapsedTime = data.mission.elapsedTime;
|
||||
}
|
||||
|
||||
if ( "startTime" in data.mission ) {
|
||||
if ("startTime" in data.mission)
|
||||
this.#startTime = data.mission.startTime;
|
||||
}
|
||||
|
||||
if ( "time" in data.mission ) {
|
||||
if ("time" in data.mission)
|
||||
this.#time = data.mission.time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ( "time" in data ) {
|
||||
if ("time" in data)
|
||||
this.#updateTime = data.time;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
getBullseyes()
|
||||
{
|
||||
getBullseyes() {
|
||||
return this.#bullseyes;
|
||||
}
|
||||
|
||||
getAirbases() {
|
||||
return this.#airbases;
|
||||
}
|
||||
|
||||
getDate() {
|
||||
return this.#date;
|
||||
}
|
||||
|
||||
|
||||
getNowDate() {
|
||||
|
||||
const date = this.getDate();
|
||||
const time = this.getTime();
|
||||
|
||||
if ( !date ) {
|
||||
if (!date) {
|
||||
return new Date();
|
||||
}
|
||||
|
||||
let year = date.Year;
|
||||
|
||||
let year = date.Year;
|
||||
let month = date.Month - 1;
|
||||
|
||||
if ( month < 0 ) {
|
||||
if (month < 0) {
|
||||
month = 11;
|
||||
year--;
|
||||
}
|
||||
|
||||
return new Date( year, month, date.Day, time.h, time.m, time.s );
|
||||
return new Date(year, month, date.Day, time.h, time.m, time.s);
|
||||
}
|
||||
|
||||
|
||||
getTime() {
|
||||
return this.#time;
|
||||
}
|
||||
|
||||
|
||||
getUpdateTime() {
|
||||
return this.#updateTime;
|
||||
}
|
||||
|
||||
#onAirbaseClick(e: any)
|
||||
{
|
||||
#onAirbaseClick(e: any) {
|
||||
getMap().showAirbaseContextMenu(e, e.sourceTarget);
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,7 @@
|
||||
import { LatLng, Point, Polygon } from "leaflet";
|
||||
import * as turf from "@turf/turf";
|
||||
import { UnitDatabase } from "../units/unitdatabase";
|
||||
|
||||
export function bearing(lat1: number, lon1: number, lat2: number, lon2: number) {
|
||||
const φ1 = deg2rad(lat1); // φ, λ in radians
|
||||
const φ2 = deg2rad(lat2);
|
||||
@ -184,4 +188,35 @@ export function mToNm(m: number) {
|
||||
|
||||
export function nmToFt(nm: number) {
|
||||
return nm * 6076.12;
|
||||
}
|
||||
|
||||
export function randomPointInPoly(polygon: Polygon): LatLng {
|
||||
var bounds = polygon.getBounds();
|
||||
var x_min = bounds.getEast();
|
||||
var x_max = bounds.getWest();
|
||||
var y_min = bounds.getSouth();
|
||||
var y_max = bounds.getNorth();
|
||||
|
||||
var lat = y_min + (Math.random() * (y_max - y_min));
|
||||
var lng = x_min + (Math.random() * (x_max - x_min));
|
||||
|
||||
var poly = polygon.toGeoJSON();
|
||||
var inside = turf.inside(turf.point([lng, lat]), poly);
|
||||
|
||||
if (inside) {
|
||||
return new LatLng(lat, lng);
|
||||
} else {
|
||||
return randomPointInPoly(polygon);
|
||||
}
|
||||
}
|
||||
|
||||
export function polygonArea(polygon: Polygon) {
|
||||
var poly = polygon.toGeoJSON();
|
||||
return turf.area(poly);
|
||||
}
|
||||
|
||||
export function randomUnitBlueprintByRole(unitDatabse: UnitDatabase, role: string) {
|
||||
const unitBlueprints = unitDatabse.getByRole(role);
|
||||
var index = Math.floor(Math.random() * unitBlueprints.length);
|
||||
return unitBlueprints[index];
|
||||
}
|
||||
@ -134,13 +134,13 @@ export function spawnExplosion(intensity: number, latlng: LatLng) {
|
||||
}
|
||||
|
||||
export function spawnGroundUnit(spawnOptions: SpawnOptions) {
|
||||
var command = { "type": spawnOptions.type, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition };
|
||||
var command = { "type": spawnOptions.type, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "immediate": spawnOptions.immediate? true: false };
|
||||
var data = { "spawnGround": command }
|
||||
POST(data, () => { });
|
||||
}
|
||||
|
||||
export function spawnAircraft(spawnOptions: SpawnOptions) {
|
||||
var command = { "type": spawnOptions.type, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "altitude": spawnOptions.altitude, "payloadName": spawnOptions.loadout != null ? spawnOptions.loadout : "", "airbaseName": spawnOptions.airbaseName != null ? spawnOptions.airbaseName : "" };
|
||||
var command = { "type": spawnOptions.type, "location": spawnOptions.latlng, "coalition": spawnOptions.coalition, "altitude": spawnOptions.altitude, "payloadName": spawnOptions.loadout != null ? spawnOptions.loadout : "", "airbaseName": spawnOptions.airbaseName != null ? spawnOptions.airbaseName : "", "immediate": spawnOptions.immediate? true: false };
|
||||
var data = { "spawnAir": command }
|
||||
POST(data, () => { });
|
||||
}
|
||||
|
||||
@ -14,7 +14,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"items": [
|
||||
],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -31,7 +31,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"fuel": 1,
|
||||
"items": [],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -48,7 +48,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"fuel": 1,
|
||||
"items": [],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -65,7 +65,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"fuel": 1,
|
||||
"items": [],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -82,7 +82,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"fuel": 1,
|
||||
"items": [],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -99,7 +99,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"fuel": 1,
|
||||
"items": [],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -116,7 +116,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
"fuel": 1,
|
||||
"items": [],
|
||||
"roles": [
|
||||
"SAM Site"
|
||||
"SAM Sites"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -1544,7 +1544,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
"SAM"
|
||||
"MANPADS"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -1590,7 +1590,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
"SAM"
|
||||
"MANPADS"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -1613,7 +1613,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
"SAM"
|
||||
"MANPADS"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -1927,7 +1927,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
"SAM"
|
||||
"MANPADS"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
@ -1973,7 +1973,7 @@ export class GroundUnitsDatabase extends UnitDatabase {
|
||||
}
|
||||
],
|
||||
"roles": [
|
||||
"SAM"
|
||||
"MANPADS"
|
||||
],
|
||||
"code": "",
|
||||
"name": "Default"
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { getHotgroupPanel, getInfoPopup, getMap, getUnitDataTable } from "..";
|
||||
import { getHotgroupPanel, getInfoPopup, getMap, getMissionHandler, getUnitDataTable } from "..";
|
||||
import { Unit } from "./unit";
|
||||
import { cloneUnit } from "../server/server";
|
||||
import { deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots } from "../other/utils";
|
||||
import { cloneUnit, spawnGroundUnit } from "../server/server";
|
||||
import { deg2rad, keyEventWasInInput, latLngToMercator, mToFt, mercatorToLatLng, msToKnots, polygonArea, randomPointInPoly, randomUnitBlueprintByRole } from "../other/utils";
|
||||
import { IDLE, MOVE_UNIT } from "../map/map";
|
||||
import { CoalitionArea } from "../map/coalitionarea";
|
||||
import { Airbase } from "../missionhandler/airbase";
|
||||
import { groundUnitsDatabase } from "./groundunitsdatabase";
|
||||
|
||||
export class UnitsManager {
|
||||
#units: { [ID: number]: Unit };
|
||||
@ -499,6 +502,35 @@ export class UnitsManager {
|
||||
}
|
||||
}
|
||||
|
||||
createIADS(coalitionArea: CoalitionArea, options: {[key: string]: boolean}, density: number) {
|
||||
const activeRoles = Object.keys(options).filter((key: string) => { return options[key]; });
|
||||
const airbases = getMissionHandler().getAirbases();
|
||||
const pointsNumber = polygonArea(coalitionArea) / 1e7 * density / 100;
|
||||
for (let i = 0; i < pointsNumber; i++) {
|
||||
const latlng = randomPointInPoly(coalitionArea);
|
||||
var minDistance: number = Infinity;
|
||||
var maxDistance: number = 0;
|
||||
Object.values(airbases).forEach((airbase: Airbase) => {
|
||||
var distance = airbase.getLatLng().distanceTo(latlng);
|
||||
if (distance < minDistance) minDistance = distance;
|
||||
if (distance > maxDistance) maxDistance = distance;
|
||||
});
|
||||
|
||||
const probability = Math.pow(1 - minDistance / 50e3, 5);
|
||||
if (Math.random() < probability){
|
||||
const role = activeRoles[Math.floor(Math.random() * activeRoles.length)];
|
||||
const unitBlueprint = randomUnitBlueprintByRole(groundUnitsDatabase, role);
|
||||
spawnGroundUnit({
|
||||
role: role,
|
||||
latlng: latlng,
|
||||
type: unitBlueprint.name,
|
||||
coalition: coalitionArea.getCoalition(),
|
||||
immediate: true
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************/
|
||||
#onKeyUp(event: KeyboardEvent) {
|
||||
if (!keyEventWasInInput(event) && event.key === "Delete" ) {
|
||||
|
||||
@ -112,7 +112,7 @@
|
||||
<div id="area-coalition-label" data-active-coalition="blue"></div>
|
||||
<div id="upper-bar" class="ol-panel">
|
||||
<div id="coalition-area-switch" class="ol-switch ol-coalition-switch"></div>
|
||||
<button data-active-coalition="blue" id="iads-button" title="Create Integrated Air Defens System" data-on-click="coalitionAreaContextMenuShow"
|
||||
<button data-active-coalition="blue" id="iads-button" title="Create Integrated Air Defense System" data-on-click="coalitionAreaContextMenuShow"
|
||||
data-on-click-params='{ "type": "iads" }' class="ol-contexmenu-button"></button>
|
||||
</div>
|
||||
<div id="iads-menu" class="ol-panel ol-contexmenu-panel hide">
|
||||
@ -123,11 +123,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
<div class="ol-select-container">
|
||||
<div id="iads-period-options" class="ol-select">
|
||||
<div class="ol-select-value">Units period</div>
|
||||
<div class="ol-select-options">
|
||||
<!-- This is where all the iads unit period buttons will be shown-->
|
||||
<!-- This is where all the iads unit period buttons will be shown--><!--
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -138,6 +139,7 @@
|
||||
Coalition specific units
|
||||
</label>
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div id="iads-density-slider" class="ol-slider-container">
|
||||
<dl class="ol-data-grid">
|
||||
@ -145,6 +147,6 @@
|
||||
</dl>
|
||||
<input type="range" min="0" max="100" value="0" class="ol-slider">
|
||||
</div>
|
||||
<button class="create-iads-button" title="" data-active-coalition="blue" data-on-click="contextMenuCreateIads" disabled>Add units to IADS</button>
|
||||
<button class="create-iads-button" title="" data-active-coalition="blue" data-on-click="contextMenuCreateIads">Add units to IADS</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -1,6 +1,6 @@
|
||||
local version = "v0.3.0-alpha"
|
||||
|
||||
local debug = false
|
||||
local debug = true
|
||||
|
||||
Olympus.unitCounter = 1
|
||||
Olympus.payloadRegistry = {}
|
||||
|
||||
@ -145,37 +145,40 @@ private:
|
||||
class SpawnGroundUnit : public Command
|
||||
{
|
||||
public:
|
||||
SpawnGroundUnit(wstring coalition, wstring unitType, Coords location) :
|
||||
SpawnGroundUnit(wstring coalition, wstring unitType, Coords location, bool immediate) :
|
||||
coalition(coalition),
|
||||
unitType(unitType),
|
||||
location(location)
|
||||
location(location),
|
||||
immediate(immediate)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 100; }
|
||||
virtual int getLoad() { return 100 * !immediate; }
|
||||
|
||||
private:
|
||||
const wstring coalition;
|
||||
const wstring unitType;
|
||||
const Coords location;
|
||||
const bool immediate;
|
||||
};
|
||||
|
||||
/* Spawn air unit command */
|
||||
class SpawnAircraft : public Command
|
||||
{
|
||||
public:
|
||||
SpawnAircraft(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName) :
|
||||
SpawnAircraft(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName, bool immediate) :
|
||||
coalition(coalition),
|
||||
unitType(unitType),
|
||||
location(location),
|
||||
payloadName(payloadName),
|
||||
airbaseName(airbaseName)
|
||||
airbaseName(airbaseName),
|
||||
immediate(immediate)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 100; }
|
||||
virtual int getLoad() { return 100 * !immediate; }
|
||||
|
||||
private:
|
||||
const wstring coalition;
|
||||
@ -183,6 +186,7 @@ private:
|
||||
const Coords location;
|
||||
const wstring payloadName;
|
||||
const wstring airbaseName;
|
||||
const bool immediate;
|
||||
};
|
||||
|
||||
/* Clone unit command */
|
||||
@ -232,7 +236,7 @@ public:
|
||||
priority = CommandPriority::MEDIUM;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 10; }
|
||||
virtual int getLoad() { return 2; }
|
||||
|
||||
private:
|
||||
const wstring groupName;
|
||||
@ -249,7 +253,7 @@ public:
|
||||
priority = CommandPriority::HIGH;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 10; }
|
||||
virtual int getLoad() { return 2; }
|
||||
|
||||
private:
|
||||
const wstring groupName;
|
||||
@ -266,7 +270,7 @@ public:
|
||||
priority = CommandPriority::HIGH;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 10; }
|
||||
virtual int getLoad() { return 2; }
|
||||
|
||||
private:
|
||||
const wstring groupName;
|
||||
@ -297,7 +301,7 @@ public:
|
||||
priority = CommandPriority::HIGH;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 10; }
|
||||
virtual int getLoad() { return 2; }
|
||||
|
||||
private:
|
||||
const wstring groupName;
|
||||
@ -318,7 +322,7 @@ public:
|
||||
priority = CommandPriority::HIGH;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
virtual int getLoad() { return 10; }
|
||||
virtual int getLoad() { return 2; }
|
||||
|
||||
private:
|
||||
const wstring groupName;
|
||||
|
||||
@ -92,16 +92,18 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
}
|
||||
else if (key.compare(L"spawnGround") == 0)
|
||||
{
|
||||
bool immediate = value[L"immediate"].as_bool();
|
||||
wstring coalition = value[L"coalition"].as_string();
|
||||
wstring type = value[L"type"].as_string();
|
||||
double lat = value[L"location"][L"lat"].as_double();
|
||||
double lng = value[L"location"][L"lng"].as_double();
|
||||
log(L"Spawning " + coalition + L" ground unit of type " + type + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")");
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
command = dynamic_cast<Command*>(new SpawnGroundUnit(coalition, type, loc));
|
||||
command = dynamic_cast<Command*>(new SpawnGroundUnit(coalition, type, loc, immediate));
|
||||
}
|
||||
else if (key.compare(L"spawnAir") == 0)
|
||||
{
|
||||
bool immediate = value[L"immediate"].as_bool();
|
||||
wstring coalition = value[L"coalition"].as_string();
|
||||
wstring type = value[L"type"].as_string();
|
||||
double lat = value[L"location"][L"lat"].as_double();
|
||||
@ -111,7 +113,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
wstring payloadName = value[L"payloadName"].as_string();
|
||||
wstring airbaseName = value[L"airbaseName"].as_string();
|
||||
log(L"Spawning " + coalition + L" air unit of type " + type + L" with payload " + payloadName + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L" " + airbaseName + L")");
|
||||
command = dynamic_cast<Command*>(new SpawnAircraft(coalition, type, loc, payloadName, airbaseName));
|
||||
command = dynamic_cast<Command*>(new SpawnAircraft(coalition, type, loc, payloadName, airbaseName, immediate));
|
||||
}
|
||||
else if (key.compare(L"attackUnit") == 0)
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user