mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Added speed and altitude controls
Fixed Clone Added "Land here" command Added ROE and reaction to threat buttons
This commit is contained in:
parent
3cf133a10e
commit
30a9d4e730
@ -5,4 +5,5 @@ explosion
|
||||
wrong name for ground units
|
||||
improve map zIndex
|
||||
fuel is wrong (either 0 or 1, its is casting it to int somewhere)
|
||||
weapons should not be selectable
|
||||
weapons should not be selectable
|
||||
human symbol if user
|
||||
47
client/public/stylesheets/slider.css
Normal file
47
client/public/stylesheets/slider.css
Normal file
@ -0,0 +1,47 @@
|
||||
.slider-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.slider {
|
||||
width: 100%;
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
height: 2px;
|
||||
background: #d3d3d3;
|
||||
outline: none;
|
||||
opacity: 0.7;
|
||||
-webkit-transition: .2s;
|
||||
transition: opacity .2s;
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.slider:hover {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.slider::-webkit-slider-thumb {
|
||||
-webkit-appearance: none;
|
||||
appearance: none;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: gray;
|
||||
cursor: pointer;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.active .slider::-webkit-slider-thumb {
|
||||
background: #5ca7ff;
|
||||
}
|
||||
|
||||
.slider::-moz-range-thumb {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: gray;
|
||||
cursor: pointer;
|
||||
border-radius: 999px;
|
||||
}
|
||||
|
||||
.active .slider::-moz-range-thumb {
|
||||
background: #5ca7ff;
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
@import url("button.css");
|
||||
@import url("slider.css");
|
||||
@import url("dropdown.css");
|
||||
|
||||
@import url("selectionwheel.css");
|
||||
|
||||
@ -52,7 +52,7 @@
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#threat-reaction-buttons-container {
|
||||
#reaction-to-threat-buttons-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
@ -106,4 +106,25 @@
|
||||
color: white;
|
||||
font-size: 13px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.flight-control-slider {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.flight-control-title {
|
||||
font-size: 13px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.flight-control-value {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: gray;
|
||||
}
|
||||
|
||||
.active .flight-control-value {
|
||||
color: #5ca7ff;
|
||||
}
|
||||
|
||||
83
client/src/controls/slider.ts
Normal file
83
client/src/controls/slider.ts
Normal file
@ -0,0 +1,83 @@
|
||||
export class Slider {
|
||||
#container: HTMLElement | null;
|
||||
#callback: CallableFunction;
|
||||
#slider: HTMLInputElement | null = null;
|
||||
#value: HTMLElement | null = null;
|
||||
#minValue: number;
|
||||
#maxValue: number;
|
||||
#minValueDiv: HTMLElement | null = null;
|
||||
#maxValueDiv: HTMLElement | null = null;
|
||||
#unit: string;
|
||||
#display: string = "";
|
||||
|
||||
constructor(ID: string, minValue: number, maxValue: number, unit: string, callback: CallableFunction) {
|
||||
this.#container = document.getElementById(ID);
|
||||
this.#callback = callback;
|
||||
this.#minValue = minValue;
|
||||
this.#maxValue = maxValue;
|
||||
this.#unit = unit;
|
||||
if (this.#container != null) {
|
||||
this.#display = this.#container.style.display;
|
||||
this.#slider = <HTMLInputElement>this.#container.querySelector("input");
|
||||
if (this.#slider != null)
|
||||
{
|
||||
this.#slider.addEventListener("input", (e: any) => this.#onInput());
|
||||
this.#slider.addEventListener("mouseup", (e: any) => this.#onFinalize());
|
||||
}
|
||||
this.#value = <HTMLElement>this.#container.querySelector("#value");
|
||||
}
|
||||
}
|
||||
|
||||
#onValue()
|
||||
{
|
||||
if (this.#value != null && this.#slider != null)
|
||||
this.#value.innerHTML = this.#minValue + Math.round(parseFloat(this.#slider.value) / 100 * (this.#maxValue - this.#minValue)) + this.#unit
|
||||
this.setActive(true);
|
||||
}
|
||||
|
||||
#onInput()
|
||||
{
|
||||
this.#onValue();
|
||||
}
|
||||
|
||||
#onFinalize()
|
||||
{
|
||||
if (this.#slider != null)
|
||||
this.#callback(this.#minValue + parseFloat(this.#slider.value) / 100 * (this.#maxValue - this.#minValue));
|
||||
}
|
||||
|
||||
show()
|
||||
{
|
||||
if (this.#container != null)
|
||||
this.#container.style.display = this.#display;
|
||||
}
|
||||
|
||||
hide()
|
||||
{
|
||||
if (this.#container != null)
|
||||
this.#container.style.display = 'none';
|
||||
}
|
||||
|
||||
setActive(newActive: boolean)
|
||||
{
|
||||
if (this.#container)
|
||||
{
|
||||
this.#container.classList.toggle("active", newActive);
|
||||
if (!newActive && this.#value != null)
|
||||
this.#value.innerHTML = "Mixed values"
|
||||
}
|
||||
}
|
||||
|
||||
setMinMax(newMinValue: number, newMaxValue: number)
|
||||
{
|
||||
this.#minValue = newMinValue;
|
||||
this.#maxValue = newMaxValue;
|
||||
}
|
||||
|
||||
setValue(newValue: number)
|
||||
{
|
||||
if (this.#slider != null)
|
||||
this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * 100);
|
||||
this.#onValue()
|
||||
}
|
||||
}
|
||||
@ -99,7 +99,7 @@ export function attackUnit(ID: number, targetID: number) {
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function cloneUnit(ID: number) {
|
||||
export function cloneUnit(ID: number, latlng: L.LatLng) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
@ -109,12 +109,28 @@ export function cloneUnit(ID: number) {
|
||||
}
|
||||
};
|
||||
|
||||
var command = { "ID": ID };
|
||||
var command = { "ID": ID, "location": latlng };
|
||||
var data = { "cloneUnit": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function landAt(ID: number, latlng: L.LatLng) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
//console.log("Unit " + getUnitsManager().getUnitByID(ID).unitName + " cloned");
|
||||
}
|
||||
};
|
||||
|
||||
var command = { "ID": ID, "location": latlng };
|
||||
var data = { "landAt": command }
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function changeSpeed(ID: number, speedChange: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
@ -131,6 +147,22 @@ export function changeSpeed(ID: number, speedChange: string) {
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function setSpeed(ID: number, speed: number) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
//console.log(getUnitsManager().getUnitByID(ID).unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "speed": speed}
|
||||
var data = {"setSpeed": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function changeAltitude(ID: number, altitudeChange: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
@ -147,6 +179,22 @@ export function changeAltitude(ID: number, altitudeChange: string) {
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function setAltitude(ID: number, altitude: number) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
//console.log(getUnitsManager().getUnitByID(ID).unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "altitude": altitude}
|
||||
var data = {"setAltitude": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function createFormation(ID: number, isLeader: boolean, wingmenIDs: number[]) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
@ -160,5 +208,37 @@ export function createFormation(ID: number, isLeader: boolean, wingmenIDs: numbe
|
||||
var command = {"ID": ID, "wingmenIDs": wingmenIDs, "isLeader": isLeader}
|
||||
var data = {"setLeader": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function setROE(ID: number, ROE: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
//console.log(getUnitsManager().getUnitByID(ID).unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "ROE": ROE}
|
||||
var data = {"setROE": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
|
||||
export function setReactionToThreat(ID: number, reactionToThreat: string) {
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("PUT", RESTaddress);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.onreadystatechange = () => {
|
||||
if (xhr.readyState === 4) {
|
||||
//console.log(getUnitsManager().getUnitByID(ID).unitName + " speed change request: " + speedChange);
|
||||
}
|
||||
};
|
||||
|
||||
var command = {"ID": ID, "reactionToThreat": reactionToThreat}
|
||||
var data = {"setReactionToThreat": command}
|
||||
|
||||
xhr.send(JSON.stringify(data));
|
||||
}
|
||||
@ -10,6 +10,7 @@ import { Button } from "./controls/button";
|
||||
import { MissionData } from "./missiondata/missiondata";
|
||||
import { UnitControlPanel } from "./panels/unitcontrolpanel";
|
||||
import { MouseInfoPanel } from "./panels/mouseInfoPanel";
|
||||
import { Slider } from "./controls/slider";
|
||||
|
||||
/* TODO: should this be a class? */
|
||||
var map: Map;
|
||||
@ -36,6 +37,9 @@ var aiVisibilityButton: Button;
|
||||
var weaponVisibilityButton: Button;
|
||||
var deadVisibilityButton: Button;
|
||||
|
||||
var altitudeSlider: Slider;
|
||||
var airspeedSlider: Slider;
|
||||
|
||||
var connected: boolean;
|
||||
var activeCoalition: string;
|
||||
|
||||
@ -59,6 +63,10 @@ function setup() {
|
||||
climbButton = new Button("climb-button", ["images/buttons/climb.svg"], () => { getUnitsManager().selectedUnitsChangeAltitude("climb"); });
|
||||
descendButton = new Button("descend-button", ["images/buttons/descend.svg"], () => { getUnitsManager().selectedUnitsChangeAltitude("descend"); });
|
||||
|
||||
/* Unit control sliders */
|
||||
altitudeSlider = new Slider("altitude-slider", 0, 100, "ft", (value: number) => getUnitsManager().selectedUnitsSetAltitude(value * 0.3048));
|
||||
airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => getUnitsManager().selectedUnitsSetSpeed(value / 1.94384));
|
||||
|
||||
/* Visibility buttons */
|
||||
userVisibilityButton = new Button("user-visibility-button", ["images/buttons/user-full.svg", "images/buttons/user-partial.svg", "images/buttons/user-none.svg", "images/buttons/user-hidden.svg"], () => { });
|
||||
aiVisibilityButton = new Button("ai-visibility-button", ["images/buttons/ai-full.svg", "images/buttons/ai-partial.svg", "images/buttons/ai-none.svg", "images/buttons/ai-hidden.svg"], () => { });
|
||||
@ -184,4 +192,12 @@ export function getVisibilitySettings() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
export function getVisibilityButtons() {
|
||||
return {user: userVisibilityButton, ai: aiVisibilityButton, weapon: weaponVisibilityButton, dead: deadVisibilityButton}
|
||||
}
|
||||
|
||||
export function getUnitControlSliders() {
|
||||
return {altitude: altitudeSlider, airspeed: airspeedSlider}
|
||||
}
|
||||
|
||||
window.onload = setup;
|
||||
@ -154,6 +154,14 @@ export class Map extends L.Map {
|
||||
getSelectionScroll().hide();
|
||||
}
|
||||
|
||||
getMousePosition() {
|
||||
return this.#lastMousePosition;
|
||||
}
|
||||
|
||||
getMouseCoordinates() {
|
||||
return this.containerPointToLatLng(this.#lastMousePosition);
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
#onClick(e: any) {
|
||||
if (!this.#preventLeftClick) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import { imageOverlay } from "leaflet";
|
||||
import { getUnitsManager } from "..";
|
||||
import { getUnitControlSliders, getUnitsManager } from "..";
|
||||
import { ConvertDDToDMS, rad2deg } from "../other/utils";
|
||||
import { AirUnit, Unit } from "../units/unit";
|
||||
import { Aircraft, AirUnit, GroundUnit, Helicopter, NavyUnit, Unit } from "../units/unit";
|
||||
|
||||
export class UnitControlPanel {
|
||||
#element: HTMLElement
|
||||
@ -21,6 +21,25 @@ export class UnitControlPanel {
|
||||
var undoButton = <HTMLElement>formationCreationContainer.querySelector("#undo-formation");
|
||||
undoButton?.addEventListener("click", () => getUnitsManager().selectedUnitsUndoFormation());
|
||||
}
|
||||
var ROEButtonsContainer = <HTMLElement>(this.#element.querySelector("#roe-buttons-container"));
|
||||
if (ROEButtonsContainer != null)
|
||||
{
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#free"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetROE("Free"));
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#designated-free"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetROE("Designated free"));
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#designated"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetROE("Designated"));
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#return"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetROE("Return"));
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#hold"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetROE("Hold"));
|
||||
}
|
||||
|
||||
var reactionToThreatButtonsContainer = <HTMLElement>(this.#element.querySelector("#reaction-to-threat-buttons-container"));
|
||||
if (reactionToThreatButtonsContainer != null)
|
||||
{
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#none"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetReactionToThreat("None"));
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#passive"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetReactionToThreat("Passive"));
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#evade"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetReactionToThreat("Evade"));
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#escape"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetReactionToThreat("Escape"));
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#abort"))?.addEventListener("click", () => getUnitsManager().selectedUnitsSetReactionToThreat("Abort"));
|
||||
}
|
||||
this.hide();
|
||||
}
|
||||
}
|
||||
@ -41,8 +60,83 @@ export class UnitControlPanel {
|
||||
if (selectedUnitsContainer != null && formationCreationContainer != null)
|
||||
{
|
||||
this.#addUnitsButtons(units, selectedUnitsContainer);
|
||||
this.#showFlightControlSliders(units);
|
||||
this.#showFormationButtons(units, formationCreationContainer);
|
||||
}
|
||||
|
||||
var ROEButtonsContainer = <HTMLElement>(this.#element.querySelector("#roe-buttons-container"));
|
||||
if (ROEButtonsContainer != null)
|
||||
{
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#free"))?.classList.toggle("white", this.#getROE(units) === "Free");
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#designated-free"))?.classList.toggle("white", this.#getROE(units) === "Designated free");
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#designated"))?.classList.toggle("white", this.#getROE(units) === "Designated");
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#return"))?.classList.toggle("white", this.#getROE(units) === "Return");
|
||||
(<HTMLElement>ROEButtonsContainer.querySelector("#hold"))?.classList.toggle("white", this.#getROE(units) === "Hold");
|
||||
}
|
||||
|
||||
var reactionToThreatButtonsContainer = <HTMLElement>(this.#element.querySelector("#reaction-to-threat-buttons-container"));
|
||||
if (reactionToThreatButtonsContainer != null)
|
||||
{
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#none"))?.classList.toggle("white", this.#getReactionToThreat(units) === "None");
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#passive"))?.classList.toggle("white", this.#getReactionToThreat(units) === "Passive");
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#evade"))?.classList.toggle("white", this.#getReactionToThreat(units) === "Evade");
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#escape"))?.classList.toggle("white", this.#getReactionToThreat(units) === "Escape");
|
||||
(<HTMLElement>reactionToThreatButtonsContainer.querySelector("#abort"))?.classList.toggle("white", this.#getReactionToThreat(units) === "Abort");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#showFlightControlSliders(units: Unit[])
|
||||
{
|
||||
var sliders = getUnitControlSliders();
|
||||
sliders.airspeed.show();
|
||||
sliders.altitude.show();
|
||||
|
||||
if (this.#checkAllUnitsAircraft(units))
|
||||
{
|
||||
sliders.airspeed.setMinMax(100, 600);
|
||||
sliders.altitude.setMinMax(0, 50000);
|
||||
}
|
||||
else if (this.#checkAllUnitsHelicopter(units))
|
||||
{
|
||||
sliders.airspeed.setMinMax(0, 200);
|
||||
sliders.altitude.setMinMax(0, 10000);
|
||||
}
|
||||
else if (this.#checkAllUnitsGroundUnit(units))
|
||||
{
|
||||
sliders.airspeed.setMinMax(0, 60);
|
||||
sliders.altitude.hide();
|
||||
}
|
||||
else if (this.#checkAllUnitsNavyUnit(units))
|
||||
{
|
||||
sliders.airspeed.setMinMax(0, 60);
|
||||
sliders.altitude.hide();
|
||||
}
|
||||
else {
|
||||
sliders.airspeed.hide();
|
||||
sliders.altitude.hide();
|
||||
}
|
||||
|
||||
var targetSpeed = this.#getTargetAirspeed(units);
|
||||
if (targetSpeed != null)
|
||||
{
|
||||
sliders.airspeed.setActive(true);
|
||||
sliders.airspeed.setValue(targetSpeed * 1.94384);
|
||||
}
|
||||
else
|
||||
{
|
||||
sliders.airspeed.setActive(false);
|
||||
}
|
||||
|
||||
var targetAltitude = this.#getTargetAltitude(units);
|
||||
if (targetAltitude != null)
|
||||
{
|
||||
sliders.altitude.setActive(true);
|
||||
sliders.altitude.setValue(targetAltitude / 0.3048);
|
||||
}
|
||||
else
|
||||
{
|
||||
sliders.altitude.setActive(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -157,6 +251,38 @@ export class UnitControlPanel {
|
||||
return true
|
||||
}
|
||||
|
||||
#checkAllUnitsAircraft(units: Unit[])
|
||||
{
|
||||
for (let unit of units)
|
||||
if (!(unit instanceof Aircraft))
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
#checkAllUnitsHelicopter(units: Unit[])
|
||||
{
|
||||
for (let unit of units)
|
||||
if (!(unit instanceof Helicopter))
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
#checkAllUnitsGroundUnit(units: Unit[])
|
||||
{
|
||||
for (let unit of units)
|
||||
if (!(unit instanceof GroundUnit))
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
#checkAllUnitsNavyUnit(units: Unit[])
|
||||
{
|
||||
for (let unit of units)
|
||||
if (!(unit instanceof NavyUnit))
|
||||
return false
|
||||
return true
|
||||
}
|
||||
|
||||
#checkAllUnitsSameFormation(units: Unit[])
|
||||
{
|
||||
var leaderFound = false;
|
||||
@ -182,4 +308,56 @@ export class UnitControlPanel {
|
||||
return true
|
||||
return false
|
||||
}
|
||||
|
||||
#getTargetAirspeed(units: Unit[])
|
||||
{
|
||||
var airspeed = null;
|
||||
for (let unit of units)
|
||||
{
|
||||
if (unit.targetSpeed != airspeed && airspeed != null)
|
||||
return null
|
||||
else
|
||||
airspeed = unit.targetSpeed;
|
||||
}
|
||||
return airspeed;
|
||||
}
|
||||
|
||||
#getTargetAltitude(units: Unit[])
|
||||
{
|
||||
var altitude = null;
|
||||
for (let unit of units)
|
||||
{
|
||||
if (unit.targetAltitude != altitude && altitude != null)
|
||||
return null
|
||||
else
|
||||
altitude = unit.targetAltitude;
|
||||
}
|
||||
return altitude;
|
||||
}
|
||||
|
||||
#getROE(units: Unit[])
|
||||
{
|
||||
var ROE = null;
|
||||
for (let unit of units)
|
||||
{
|
||||
if (unit.ROE !== ROE && ROE != null)
|
||||
return null
|
||||
else
|
||||
ROE = unit.ROE;
|
||||
}
|
||||
return ROE;
|
||||
}
|
||||
|
||||
#getReactionToThreat(units: Unit[])
|
||||
{
|
||||
var reactionToThreat = null;
|
||||
for (let unit of units)
|
||||
{
|
||||
if (unit.reactionToThreat !== reactionToThreat && reactionToThreat != null)
|
||||
return null
|
||||
else
|
||||
reactionToThreat = unit.reactionToThreat;
|
||||
}
|
||||
return reactionToThreat;
|
||||
}
|
||||
}
|
||||
@ -2,7 +2,7 @@ import { Marker, LatLng, Polyline, Icon } from 'leaflet';
|
||||
import { ConvertDDToDMS } from '../other/utils';
|
||||
import { getMap, getUnitsManager, getVisibilitySettings } from '..';
|
||||
import { UnitMarker, MarkerOptions, AircraftMarker, HelicopterMarker, GroundUnitMarker, NavyUnitMarker, WeaponMarker } from './unitmarker';
|
||||
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader } from '../dcs/dcs';
|
||||
import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, landAt, setAltitude, setReactionToThreat, setROE, setSpeed } from '../dcs/dcs';
|
||||
|
||||
var pathIcon = new Icon({
|
||||
iconUrl: 'images/marker-icon.png',
|
||||
@ -36,6 +36,10 @@ export class Unit {
|
||||
leaderID: number = 0;
|
||||
wingmen: Unit[] = [];
|
||||
wingmenIDs: number[] = [];
|
||||
targetSpeed: number = 0;
|
||||
targetAltitude: number = 0;
|
||||
ROE: string = "";
|
||||
reactionToThreat: string = "";
|
||||
|
||||
#selectable: boolean;
|
||||
#selected: boolean = false;
|
||||
@ -296,7 +300,6 @@ export class Unit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
attackUnit(targetID: number) {
|
||||
/* Call DCS attackUnit function */
|
||||
if (this.ID != targetID) {
|
||||
@ -307,7 +310,11 @@ export class Unit {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
landAt(latlng: LatLng)
|
||||
{
|
||||
landAt(this.ID, latlng);
|
||||
}
|
||||
|
||||
changeSpeed(speedChange: string)
|
||||
{
|
||||
changeSpeed(this.ID, speedChange);
|
||||
@ -318,6 +325,26 @@ export class Unit {
|
||||
changeAltitude(this.ID, altitudeChange);
|
||||
}
|
||||
|
||||
setSpeed(speed: number)
|
||||
{
|
||||
setSpeed(this.ID, speed);
|
||||
}
|
||||
|
||||
setAltitude(altitude: number)
|
||||
{
|
||||
setAltitude(this.ID, altitude);
|
||||
}
|
||||
|
||||
setROE(ROE: string)
|
||||
{
|
||||
setROE(this.ID, ROE);
|
||||
}
|
||||
|
||||
setReactionToThreat(reactionToThreat: string)
|
||||
{
|
||||
setReactionToThreat(this.ID, reactionToThreat);
|
||||
}
|
||||
|
||||
/*
|
||||
setformation(formation)
|
||||
{
|
||||
|
||||
@ -15,6 +15,17 @@ export class UnitsManager {
|
||||
document.addEventListener('paste', () => this.pasteUnits());
|
||||
}
|
||||
|
||||
#updateUnitControlPanel() {
|
||||
/* Update the unit control panel */
|
||||
if (this.getSelectedUnits().length > 0) {
|
||||
getUnitControlPanel().show();
|
||||
getUnitControlPanel().update(this.getSelectedLeaders().concat(this.getSelectedSingletons()));
|
||||
}
|
||||
else {
|
||||
getUnitControlPanel().hide();
|
||||
}
|
||||
}
|
||||
|
||||
getUnits() {
|
||||
return this.#units;
|
||||
}
|
||||
@ -167,7 +178,11 @@ export class UnitsManager {
|
||||
|
||||
selectedUnitsLandAt(latlng: LatLng)
|
||||
{
|
||||
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].landAt(latlng);
|
||||
}
|
||||
}
|
||||
|
||||
selectedUnitsChangeSpeed(speedChange: string)
|
||||
@ -177,6 +192,8 @@ export class UnitsManager {
|
||||
{
|
||||
selectedUnits[idx].changeSpeed(speedChange);
|
||||
}
|
||||
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 300); // TODO find better method, may fail
|
||||
}
|
||||
|
||||
selectedUnitsChangeAltitude(altitudeChange: string)
|
||||
@ -186,8 +203,51 @@ export class UnitsManager {
|
||||
{
|
||||
selectedUnits[idx].changeAltitude(altitudeChange);
|
||||
}
|
||||
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 300); // TODO find better method, may fail
|
||||
}
|
||||
|
||||
selectedUnitsSetSpeed(speed: number)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].setSpeed(speed);
|
||||
}
|
||||
}
|
||||
|
||||
selectedUnitsSetAltitude(altitude: number)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].setAltitude(altitude);
|
||||
}
|
||||
}
|
||||
|
||||
selectedUnitsSetROE(ROE: string)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].setROE(ROE);
|
||||
}
|
||||
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 300); // TODO find better method, may fail
|
||||
}
|
||||
|
||||
selectedUnitsSetReactionToThreat(reactionToThreat: string)
|
||||
{
|
||||
var selectedUnits = this.getSelectedUnits();
|
||||
for (let idx in selectedUnits)
|
||||
{
|
||||
selectedUnits[idx].setReactionToThreat(reactionToThreat);
|
||||
}
|
||||
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 300); // TODO find better method, may fail
|
||||
}
|
||||
|
||||
|
||||
copyUnits()
|
||||
{
|
||||
this.#copiedUnits = this.getSelectedUnits();
|
||||
@ -198,7 +258,7 @@ export class UnitsManager {
|
||||
for (let idx in this.#copiedUnits)
|
||||
{
|
||||
var unit = this.#copiedUnits[idx];
|
||||
cloneUnit(unit.ID);
|
||||
cloneUnit(unit.ID, getMap().getMouseCoordinates());
|
||||
}
|
||||
}
|
||||
|
||||
@ -259,7 +319,7 @@ export class UnitsManager {
|
||||
console.log("At least 2 units must be selected to create a formation.");
|
||||
}
|
||||
}
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 1000); // TODO find better method, may fail
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 300); // TODO find better method, may fail
|
||||
}
|
||||
|
||||
selectedUnitsUndoFormation(ID: number | null = null)
|
||||
@ -268,17 +328,6 @@ export class UnitsManager {
|
||||
{
|
||||
leader.setLeader(false);
|
||||
}
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 1000); // TODO find better method, may fail
|
||||
}
|
||||
|
||||
#updateUnitControlPanel() {
|
||||
/* Update the unit control panel */
|
||||
if (this.getSelectedUnits().length > 0) {
|
||||
getUnitControlPanel().show();
|
||||
getUnitControlPanel().update(this.getSelectedLeaders().concat(this.getSelectedSingletons()));
|
||||
}
|
||||
else {
|
||||
getUnitControlPanel().hide();
|
||||
}
|
||||
setTimeout(() => this.#updateUnitControlPanel(), 300); // TODO find better method, may fail
|
||||
}
|
||||
}
|
||||
@ -18,7 +18,20 @@
|
||||
</div>
|
||||
<div class="hl"></div>
|
||||
|
||||
<!--
|
||||
<div id="section-label">Controls</div>
|
||||
<div id="flight-controls-buttons-container">
|
||||
<div class="slider-container flight-control-slider" id="altitude-slider">
|
||||
<div class="flight-control-title">Altitude</div>
|
||||
<div class="flight-control-value" id="value"></div>
|
||||
<input type="range" min="1" max="100" value="50" class="slider">
|
||||
</div>
|
||||
<div class="slider-container flight-control-slider" id="airspeed-slider">
|
||||
<div class="flight-control-title">Speed</div>
|
||||
<div class="flight-control-value" id="value"></div>
|
||||
<input type="range" min="1" max="100" value="50" class="slider">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="section-label">Formation</div>
|
||||
<div id="formation-buttons-container">
|
||||
<div class="rectangular-button">Echelon</div>
|
||||
@ -31,22 +44,22 @@
|
||||
|
||||
<div id="section-label">Rules of engagement</div>
|
||||
<div id="roe-buttons-container">
|
||||
<div class="rectangular-button">Free</div>
|
||||
<div class="rectangular-button">Designated free</div>
|
||||
<div class="rectangular-button">Designated</div>
|
||||
<div class="rectangular-button">Return</div>
|
||||
<div class="rectangular-button">Hold</div>
|
||||
<div class="rectangular-button" id="free">Free</div>
|
||||
<div class="rectangular-button" id="designated-free">Designated free</div>
|
||||
<div class="rectangular-button" id="designated">Designated</div>
|
||||
<div class="rectangular-button" id="return">Return</div>
|
||||
<div class="rectangular-button" id="hold">Hold</div>
|
||||
</div>
|
||||
|
||||
<div class="hl"></div>
|
||||
|
||||
<div id="section-label">Reaction to threat</div>
|
||||
<div id="threat-reaction-buttons-container">
|
||||
<div class="rectangular-button">None</div>
|
||||
<div class="rectangular-button">Passive</div>
|
||||
<div class="rectangular-button">Evade</div>
|
||||
<div class="rectangular-button">Escape</div>
|
||||
<div class="rectangular-button">Abort</div>
|
||||
<div id="reaction-to-threat-buttons-container">
|
||||
<div class="rectangular-button" id="none">None</div>
|
||||
<div class="rectangular-button" id="passive">Passive</div>
|
||||
<div class="rectangular-button" id="evade">Evade</div>
|
||||
<div class="rectangular-button" id="escape">Escape</div>
|
||||
<div class="rectangular-button" id="abort">Abort</div>
|
||||
</div>
|
||||
-->
|
||||
|
||||
</div>
|
||||
@ -2,7 +2,7 @@
|
||||
|
||||
[Setup]
|
||||
AppName=DCS Olympus
|
||||
AppVerName=DCS Olympus Alpha v0.0.3
|
||||
AppVerName=DCS Olympus Alpha v0.0.5
|
||||
DefaultDirName={usersavedgames}\DCS.openbeta
|
||||
DefaultGroupName=DCSOlympus
|
||||
OutputBaseFilename=DCSOlympus
|
||||
|
||||
@ -82,12 +82,20 @@ function Olympus.move(ID, lat, lng, altitude, speed, category, taskOptions)
|
||||
if unit then
|
||||
if category == "Aircraft" then
|
||||
local startPoint = mist.getLeadPos(unit:getGroup())
|
||||
local endPoint = coord.LLtoLO(lat, lng, 0)
|
||||
local endPoint = coord.LLtoLO(lat, lng, 0)
|
||||
|
||||
local path = {
|
||||
[1] = mist.fixedWing.buildWP(startPoint, flyOverPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.fixedWing.buildWP(endPoint, turningPoint, speed, altitude, 'BARO')
|
||||
}
|
||||
local path = {}
|
||||
if taskOptions and taskOptions['id'] == 'Land' then
|
||||
path = {
|
||||
[1] = mist.fixedWing.buildWP(startPoint, flyOverPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.fixedWing.buildWP(endPoint, landing, speed, 0, 'AGL')
|
||||
}
|
||||
else
|
||||
path = {
|
||||
[1] = mist.fixedWing.buildWP(startPoint, flyOverPoint, speed, altitude, 'BARO'),
|
||||
[2] = mist.fixedWing.buildWP(endPoint, turningPoint, speed, altitude, 'BARO')
|
||||
}
|
||||
end
|
||||
|
||||
-- If a task exists assign it to the controller
|
||||
if taskOptions then
|
||||
@ -273,7 +281,7 @@ function Olympus.spawnAircraft(coalition, unitType, lat, lng, spawnOptions)
|
||||
task = 'CAP',
|
||||
}
|
||||
|
||||
mist.dynAdd(vars)
|
||||
local newGroup = mist.dynAdd(vars)
|
||||
|
||||
-- Save the payload to be reused in case the unit is cloned. TODO: save by ID not by name (it works but I like consistency)
|
||||
Olympus.payloadRegistry[vars.name] = payload
|
||||
@ -282,22 +290,30 @@ function Olympus.spawnAircraft(coalition, unitType, lat, lng, spawnOptions)
|
||||
end
|
||||
|
||||
-- Clones a unit by ID. Will clone the unit with the same original payload as the source unit. TODO: only works on Olympus unit not ME units.
|
||||
function Olympus.clone(ID)
|
||||
function Olympus.clone(ID, lat, lng)
|
||||
Olympus.notify("Olympus.clone " .. ID, 2)
|
||||
local unit = Olympus.getUnitByID(ID)
|
||||
if unit then
|
||||
local coalition = Olympus.getCoalitionByCoalitionID(unit:getCoalition())
|
||||
local lat, lng, alt = coord.LOtoLL(unit:getPoint())
|
||||
|
||||
-- TODO: only works on Aircraft
|
||||
local spawnOptions = {
|
||||
payload = Olympus.payloadRegistry[unitName]
|
||||
payload = Olympus.payloadRegistry[unit:getName()]
|
||||
}
|
||||
Olympus.spawnAircraft(coalition, unit:getTypeName(), lat + 0.001, lng + 0.001, spawnOptions)
|
||||
Olympus.spawnAircraft(coalition, unit:getTypeName(), lat, lng, spawnOptions)
|
||||
end
|
||||
Olympus.notify("Olympus.clone completed successfully", 2)
|
||||
end
|
||||
|
||||
function Olympus.delete(ID, lat, lng)
|
||||
Olympus.notify("Olympus.delete " .. ID, 2)
|
||||
local unit = Olympus.getUnitByID(ID)
|
||||
if unit then
|
||||
unit:destroy();
|
||||
Olympus.notify("Olympus.delete completed successfully", 2)
|
||||
end
|
||||
end
|
||||
|
||||
function Olympus.setTask(ID, taskOptions)
|
||||
Olympus.notify("Olympus.setTask " .. ID .. " " .. Olympus.serializeTable(taskOptions), 2)
|
||||
local unit = Olympus.getUnitByID(ID)
|
||||
@ -337,7 +353,6 @@ function Olympus.setOption(ID, optionID, optionValue)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Olympus.serializeTable(val, name, skipnewlines, depth)
|
||||
skipnewlines = skipnewlines or false
|
||||
depth = depth or 0
|
||||
@ -370,5 +385,4 @@ function Olympus.serializeTable(val, name, skipnewlines, depth)
|
||||
return tmp
|
||||
end
|
||||
|
||||
|
||||
Olympus.notify("OlympusCommand script loaded successfully", 2)
|
||||
@ -11,6 +11,54 @@ namespace CommandType {
|
||||
enum CommandTypes { NO_TYPE, MOVE, SMOKE, SPAWN_AIR, SPAWN_GROUND, CLONE, FOLLOW, RESET_TASK, SET_OPTION, SET_COMMAND, SET_TASK };
|
||||
};
|
||||
|
||||
namespace SetCommandType {
|
||||
enum SetCommandTypes {
|
||||
ROE = 0,
|
||||
REACTION_ON_THREAT = 1,
|
||||
RADAR_USING = 3,
|
||||
FLARE_USING = 4,
|
||||
Formation = 5,
|
||||
RTB_ON_BINGO = 6,
|
||||
SILENCE = 7,
|
||||
RTB_ON_OUT_OF_AMMO = 10,
|
||||
ECM_USING = 13,
|
||||
PROHIBIT_AA = 14,
|
||||
PROHIBIT_JETT = 15,
|
||||
PROHIBIT_AB = 16,
|
||||
PROHIBIT_AG = 17,
|
||||
MISSILE_ATTACK = 18,
|
||||
PROHIBIT_WP_PASS_REPORT = 19,
|
||||
OPTION_RADIO_USAGE_CONTACT = 21,
|
||||
OPTION_RADIO_USAGE_ENGAGE = 22,
|
||||
OPTION_RADIO_USAGE_KILL = 23,
|
||||
JETT_TANKS_IF_EMPTY = 25,
|
||||
FORCED_ATTACK = 26
|
||||
};
|
||||
}
|
||||
|
||||
namespace ROE {
|
||||
enum ROEs {
|
||||
WEAPON_FREE = 0,
|
||||
OPEN_FIRE_WEAPON_FREE = 1,
|
||||
OPEN_FIRE = 2,
|
||||
RETURN_FIRE = 3,
|
||||
WEAPON_HOLD = 4,
|
||||
};
|
||||
}
|
||||
|
||||
namespace ReactionToThreat {
|
||||
enum ReactionToThreats {
|
||||
NO_REACTION = 0,
|
||||
PASSIVE_DEFENCE = 1,
|
||||
EVADE_FIRE = 2,
|
||||
BYPASS_AND_ESCAPE = 3,
|
||||
ALLOW_ABORT_MISSION = 4
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* Base command class */
|
||||
class Command
|
||||
{
|
||||
@ -117,14 +165,32 @@ private:
|
||||
class Clone : public Command
|
||||
{
|
||||
public:
|
||||
Clone(int ID) :
|
||||
ID(ID)
|
||||
Clone(int ID, Coords location) :
|
||||
ID(ID),
|
||||
location(location)
|
||||
{
|
||||
priority = CommandPriority::LOW;
|
||||
type = CommandType::CLONE;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
|
||||
private:
|
||||
const int ID;
|
||||
const Coords location;
|
||||
};
|
||||
|
||||
/* Delete unit command */
|
||||
class Delete : public Command
|
||||
{
|
||||
public:
|
||||
Delete(int ID) :
|
||||
ID(ID)
|
||||
{
|
||||
priority = CommandPriority::HIGH;
|
||||
type = CommandType::CLONE;
|
||||
};
|
||||
virtual wstring getString(lua_State* L);
|
||||
|
||||
private:
|
||||
const int ID;
|
||||
};
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
#include "luatools.h"
|
||||
|
||||
namespace State {
|
||||
enum States { IDLE, REACH_DESTINATION, ATTACK, WINGMAN, FOLLOW, RTB, REFUEL, AWACS, EWR, TANKER, RUN_AWAY };
|
||||
enum States { IDLE, REACH_DESTINATION, ATTACK, WINGMAN, FOLLOW, LAND, REFUEL, AWACS, EWR, TANKER, RUN_AWAY };
|
||||
};
|
||||
|
||||
class Unit
|
||||
@ -31,6 +31,9 @@ public:
|
||||
void setWingmen(vector<Unit*> newWingmen) { wingmen = newWingmen; }
|
||||
void setFormation(wstring newFormation) { formation = newFormation; }
|
||||
void setFormationOffset(Offset formationOffset);
|
||||
void setROE(wstring newROE);
|
||||
void setReactionToThreat(wstring newReactionToThreat);
|
||||
void landAt(Coords loc);
|
||||
|
||||
int getID() { return ID; }
|
||||
wstring getName() { return name; }
|
||||
@ -65,33 +68,35 @@ public:
|
||||
|
||||
protected:
|
||||
int ID;
|
||||
int state = State::IDLE;
|
||||
bool hasTask = false;
|
||||
bool AI = false;
|
||||
bool alive = true;
|
||||
wstring name = L"undefined";
|
||||
wstring unitName = L"undefined";
|
||||
wstring groupName = L"undefined";
|
||||
json::value type = json::value::null();
|
||||
int country = NULL;
|
||||
int coalitionID = NULL;
|
||||
double latitude = NULL;
|
||||
double longitude = NULL;
|
||||
double altitude = NULL;
|
||||
double heading = NULL;
|
||||
double speed = NULL;
|
||||
json::value flags = json::value::null();
|
||||
int targetID = NULL;
|
||||
wstring currentTask = L"";
|
||||
bool isLeader = false;
|
||||
bool isWingman = false;
|
||||
Offset formationOffset = Offset(NULL);
|
||||
wstring formation = L"";
|
||||
Unit* leader = nullptr;
|
||||
int state = State::IDLE;
|
||||
bool hasTask = false;
|
||||
bool AI = false;
|
||||
bool alive = true;
|
||||
wstring name = L"undefined";
|
||||
wstring unitName = L"undefined";
|
||||
wstring groupName = L"undefined";
|
||||
json::value type = json::value::null();
|
||||
int country = NULL;
|
||||
int coalitionID = NULL;
|
||||
double latitude = NULL;
|
||||
double longitude = NULL;
|
||||
double altitude = NULL;
|
||||
double heading = NULL;
|
||||
double speed = NULL;
|
||||
json::value flags = json::value::null();
|
||||
int targetID = NULL;
|
||||
wstring currentTask = L"";
|
||||
bool isLeader = false;
|
||||
bool isWingman = false;
|
||||
Offset formationOffset = Offset(NULL);
|
||||
wstring formation = L"";
|
||||
Unit* leader = nullptr;
|
||||
wstring ROE = L"";
|
||||
wstring reactionToThreat = L"";
|
||||
vector<Unit*> wingmen;
|
||||
double targetSpeed = 0;
|
||||
double targetAltitude = 0;
|
||||
double fuel = 0;
|
||||
double targetSpeed = 0;
|
||||
double targetAltitude = 0;
|
||||
double fuel = 0;
|
||||
json::value ammo;
|
||||
json::value targets;
|
||||
|
||||
|
||||
@ -12,8 +12,10 @@ public:
|
||||
virtual void changeAltitude(wstring change);
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
virtual double getTargetAltitude() { return targetAltitude; };
|
||||
virtual void setTargetSpeed(double newTargetSpeed);
|
||||
virtual void setTargetAltitude(double newTargetAltitude);
|
||||
|
||||
protected:
|
||||
double targetSpeed = 150;
|
||||
double targetAltitude = 5000;
|
||||
double targetSpeed = 300 / 1.94384;
|
||||
double targetAltitude = 20000 * 0.3048;
|
||||
};
|
||||
@ -15,8 +15,8 @@ public:
|
||||
virtual wstring getCategory() = 0;
|
||||
virtual void changeSpeed(wstring change) {};
|
||||
virtual void changeAltitude(wstring change) {};
|
||||
virtual void setTargetSpeed(double newTargetSpeed);
|
||||
virtual void setTargetAltitude(double newTargetAltitude);
|
||||
virtual void setTargetSpeed(double newTargetSpeed) {};
|
||||
virtual void setTargetAltitude(double newTargetAltitude) {};
|
||||
|
||||
protected:
|
||||
virtual void AIloop();
|
||||
|
||||
@ -12,8 +12,10 @@ public:
|
||||
virtual void changeAltitude(wstring change);
|
||||
virtual double getTargetSpeed() { return targetSpeed; };
|
||||
virtual double getTargetAltitude() { return targetAltitude; };
|
||||
virtual void setTargetSpeed(double newTargetSpeed);
|
||||
virtual void setTargetAltitude(double newTargetAltitude);
|
||||
|
||||
protected:
|
||||
double targetSpeed = 50;
|
||||
double targetAltitude = 1000;
|
||||
double targetSpeed = 100 / 1.94384;
|
||||
double targetAltitude = 5000 * 0.3048;
|
||||
};
|
||||
@ -14,6 +14,7 @@ public:
|
||||
void updateExportData(lua_State* L);
|
||||
void updateMissionData(json::value missionData);
|
||||
void updateAnswer(json::value& answer);
|
||||
void deleteUnit(int ID);
|
||||
|
||||
private:
|
||||
map<int, Unit*> units;
|
||||
|
||||
@ -69,7 +69,19 @@ wstring Clone::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.clone, "
|
||||
commandSS << "Olympus.clone, "
|
||||
<< ID << ", "
|
||||
<< location.lat << ", "
|
||||
<< location.lng;
|
||||
return commandSS.str();
|
||||
}
|
||||
|
||||
/* Delete unit command */
|
||||
wstring Delete::getString(lua_State* L)
|
||||
{
|
||||
std::wostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.delete, "
|
||||
<< ID;
|
||||
return commandSS.str();
|
||||
}
|
||||
|
||||
@ -182,7 +182,10 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
else if (key.compare(L"cloneUnit") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
command = dynamic_cast<Command*>(new Clone(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;
|
||||
command = dynamic_cast<Command*>(new Clone(ID, loc));
|
||||
log(L"Cloning unit " + to_wstring(ID));
|
||||
}
|
||||
else if (key.compare(L"setLeader") == 0)
|
||||
@ -219,6 +222,34 @@ void Scheduler::handleRequest(wstring key, json::value value)
|
||||
wstring formation = value[L"formation"].as_string();
|
||||
unit->setFormation(formation);
|
||||
}
|
||||
else if (key.compare(L"setROE") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
wstring ROE = value[L"ROE"].as_string();
|
||||
unit->setROE(ROE);
|
||||
}
|
||||
else if (key.compare(L"setReactionToThreat") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(ID);
|
||||
wstring reactionToThreat = value[L"reactionToThreat"].as_string();
|
||||
unit->setReactionToThreat(reactionToThreat);
|
||||
}
|
||||
else if (key.compare(L"landAt") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
Unit* unit = unitsFactory->getUnit(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;
|
||||
unit->landAt(loc);
|
||||
}
|
||||
else if (key.compare(L"deleteUnit") == 0)
|
||||
{
|
||||
int ID = value[L"ID"].as_integer();
|
||||
unitsFactory->deleteUnit(ID);
|
||||
}
|
||||
else
|
||||
{
|
||||
log(L"Unknown command: " + key);
|
||||
|
||||
@ -118,9 +118,11 @@ json::value Unit::json()
|
||||
json[L"fuel"] = fuel;
|
||||
json[L"ammo"] = ammo;
|
||||
json[L"targets"] = targets;
|
||||
json[L"targetSpeed"] = targetSpeed;
|
||||
json[L"targetAltitude"] = targetAltitude;
|
||||
json[L"targetSpeed"] = getTargetSpeed();
|
||||
json[L"targetAltitude"] = getTargetAltitude();
|
||||
json[L"hasTask"] = hasTask;
|
||||
json[L"ROE"] = json::value::string(ROE);
|
||||
json[L"reactionToThreat"] = json::value::string(reactionToThreat);
|
||||
|
||||
int i = 0;
|
||||
for (auto itr = wingmen.begin(); itr != wingmen.end(); itr++)
|
||||
@ -221,4 +223,48 @@ void Unit::setFormationOffset(Offset newFormationOffset)
|
||||
{
|
||||
formationOffset = newFormationOffset;
|
||||
resetTask();
|
||||
}
|
||||
|
||||
void Unit::setROE(wstring newROE) {
|
||||
ROE = newROE;
|
||||
int ROEEnum;
|
||||
if (newROE.compare(L"Free") == 0)
|
||||
ROEEnum = ROE::WEAPON_FREE;
|
||||
else if (newROE.compare(L"Designated free") == 0)
|
||||
ROEEnum = ROE::OPEN_FIRE_WEAPON_FREE;
|
||||
else if (newROE.compare(L"Designated") == 0)
|
||||
ROEEnum = ROE::OPEN_FIRE;
|
||||
else if (newROE.compare(L"Return") == 0)
|
||||
ROEEnum = ROE::RETURN_FIRE;
|
||||
else if (newROE.compare(L"Hold") == 0)
|
||||
ROEEnum = ROE::WEAPON_HOLD;
|
||||
else
|
||||
return;
|
||||
Command* command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::ROE, ROEEnum));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
|
||||
void Unit::setReactionToThreat(wstring newReactionToThreat) {
|
||||
reactionToThreat = newReactionToThreat;
|
||||
int reactionToThreatEnum;
|
||||
if (newReactionToThreat.compare(L"None") == 0)
|
||||
reactionToThreatEnum = ReactionToThreat::NO_REACTION;
|
||||
else if (newReactionToThreat.compare(L"Passive") == 0)
|
||||
reactionToThreatEnum = ReactionToThreat::PASSIVE_DEFENCE;
|
||||
else if (newReactionToThreat.compare(L"Evade") == 0)
|
||||
reactionToThreatEnum = ReactionToThreat::EVADE_FIRE;
|
||||
else if (newReactionToThreat.compare(L"Escape") == 0)
|
||||
reactionToThreatEnum = ReactionToThreat::BYPASS_AND_ESCAPE;
|
||||
else if (newReactionToThreat.compare(L"Abort") == 0)
|
||||
reactionToThreatEnum = ReactionToThreat::ALLOW_ABORT_MISSION;
|
||||
else
|
||||
return;
|
||||
Command* command = dynamic_cast<Command*>(new SetOption(ID, SetCommandType::REACTION_ON_THREAT, reactionToThreatEnum));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
|
||||
void Unit::landAt(Coords loc) {
|
||||
activePath.clear();
|
||||
activePath.push_back(loc);
|
||||
setState(State::LAND);
|
||||
}
|
||||
@ -48,11 +48,21 @@ void Aircraft::changeAltitude(wstring change)
|
||||
{
|
||||
if (targetAltitude > 5000)
|
||||
targetAltitude += 2500 / 3.28084;
|
||||
else if (targetAltitude > 0)
|
||||
else if (targetAltitude >= 0)
|
||||
targetAltitude += 500 / 3.28084;
|
||||
}
|
||||
if (targetAltitude < 0)
|
||||
targetAltitude = 0;
|
||||
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
}
|
||||
|
||||
void Aircraft::setTargetSpeed(double newTargetSpeed) {
|
||||
targetSpeed = newTargetSpeed;
|
||||
goToDestination();
|
||||
}
|
||||
|
||||
void Aircraft::setTargetAltitude(double newTargetAltitude) {
|
||||
targetAltitude = newTargetAltitude;
|
||||
goToDestination();
|
||||
}
|
||||
@ -41,6 +41,9 @@ void AirUnit::setState(int newState)
|
||||
return;
|
||||
break;
|
||||
}
|
||||
case State::LAND: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -72,6 +75,10 @@ void AirUnit::setState(int newState)
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
case State::LAND: {
|
||||
resetActiveDestination();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -242,6 +249,22 @@ void AirUnit::AIloop()
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case State::LAND: {
|
||||
wstring enrouteTask = L"{" "id = 'land' }";
|
||||
currentTask = L"Landing";
|
||||
|
||||
if (activeDestination == NULL)
|
||||
{
|
||||
setActiveDestination();
|
||||
goToDestination(enrouteTask);
|
||||
}
|
||||
|
||||
if (isLeader)
|
||||
taskWingmen();
|
||||
|
||||
break;
|
||||
}
|
||||
case State::ATTACK: {
|
||||
/* If the target is not alive (either not set or was succesfully destroyed) go back to REACH_DESTINATION */
|
||||
if (!isTargetAlive()) {
|
||||
@ -319,13 +342,3 @@ void AirUnit::AIloop()
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void AirUnit::setTargetSpeed(double newTargetSpeed) {
|
||||
targetSpeed = newTargetSpeed;
|
||||
goToDestination();
|
||||
}
|
||||
|
||||
void AirUnit::setTargetAltitude(double newTargetAltitude) {
|
||||
targetAltitude = newTargetAltitude;
|
||||
goToDestination();
|
||||
}
|
||||
@ -48,7 +48,7 @@ void Helicopter::changeAltitude(wstring change)
|
||||
{
|
||||
if (targetAltitude > 100)
|
||||
targetAltitude += 100 / 3.28084;
|
||||
else if (targetAltitude > 0)
|
||||
else if (targetAltitude >= 0)
|
||||
targetAltitude += 10 / 3.28084;
|
||||
}
|
||||
if (targetAltitude < 0)
|
||||
@ -56,3 +56,14 @@ void Helicopter::changeAltitude(wstring change)
|
||||
|
||||
goToDestination(); /* Send the command to reach the destination */
|
||||
}
|
||||
|
||||
|
||||
void Helicopter::setTargetSpeed(double newTargetSpeed) {
|
||||
targetSpeed = newTargetSpeed;
|
||||
goToDestination();
|
||||
}
|
||||
|
||||
void Helicopter::setTargetAltitude(double newTargetAltitude) {
|
||||
targetAltitude = newTargetAltitude;
|
||||
goToDestination();
|
||||
}
|
||||
@ -7,6 +7,10 @@
|
||||
#include "groundunit.h"
|
||||
#include "navyunit.h"
|
||||
#include "weapon.h"
|
||||
#include "commands.h"
|
||||
#include "scheduler.h"
|
||||
|
||||
extern Scheduler* scheduler;
|
||||
|
||||
UnitsFactory::UnitsFactory(lua_State* L)
|
||||
{
|
||||
@ -116,3 +120,12 @@ void UnitsFactory::updateAnswer(json::value& answer)
|
||||
answer[L"units"] = unitsJson;
|
||||
}
|
||||
|
||||
void UnitsFactory::deleteUnit(int ID)
|
||||
{
|
||||
if (getUnit(ID) != nullptr)
|
||||
{
|
||||
Command* command = dynamic_cast<Command*>(new Delete(ID));
|
||||
scheduler->appendCommand(command);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user