Merge branch '153-add-ability-to-take-control-of-existing-units-from-me'

This commit is contained in:
Pax1601 2023-06-13 17:07:21 +02:00
commit 6c24533393
20 changed files with 370 additions and 249 deletions

View File

@ -49,10 +49,10 @@ const DEMO_UNIT_DATA = {
currentTask: "Holding",
currentState: "Idle",
activePath: undefined,
targetSpeed: 400,
targetSpeedType: "CAS",
targetAltitude: 3000,
targetAltitudeType: "ASL",
desiredSpeed: 400,
desiredSpeedType: "CAS",
desiredAltitude: 3000,
desiredAltitudeType: "ASL",
isTanker: false,
},
@ -96,8 +96,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 300,
targetAltitude: 3000
desiredSpeed: 300,
desiredAltitude: 3000
},
optionsData: {
ROE: "Designated",
@ -139,8 +139,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000,
desiredSpeed: 400,
desiredAltitude: 3000,
onOff: false
},
optionsData: {
@ -182,8 +182,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -225,8 +225,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -268,8 +268,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -311,8 +311,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -354,8 +354,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -397,8 +397,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -440,8 +440,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -483,8 +483,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -526,8 +526,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -569,8 +569,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",
@ -612,8 +612,8 @@ const DEMO_UNIT_DATA = {
taskData: {
currentTask: "Example task",
activePath: undefined,
targetSpeed: 400,
targetAltitude: 3000
desiredSpeed: 400,
desiredAltitude: 3000
},
optionsData: {
ROE: "None",

View File

@ -3,7 +3,7 @@ interface UpdateData {
}
interface BaseData {
AI: boolean;
controlled: boolean;
name: string;
unitName: string;
groupName: string;
@ -23,7 +23,7 @@ interface MissionData {
fuel: number;
flags: any;
ammo: any;
targets: any;
contacts: any;
hasTask: boolean;
coalition: string;
}
@ -36,10 +36,10 @@ interface TaskData {
currentState: string;
currentTask: string;
activePath: any;
targetSpeed: number;
targetSpeedType: string;
targetAltitude: number;
targetAltitudeType: string;
desiredSpeed: number;
desiredSpeedType: string;
desiredAltitude: number;
desiredAltitudeType: string;
targetLocation: any;
isTanker: boolean;
isAWACS: boolean;

View File

@ -123,7 +123,7 @@ export abstract class ATCBoard {
return false;
}
if ( baseData.AI === true ) {
if ( baseData.controlled === true ) {
// return false;
}

View File

@ -48,7 +48,7 @@ export class UnitDataTable extends Panel {
for (const unit of unitsArray) {
const dataset = [unit.getBaseData().unitName, unit.getBaseData().name, unit.getBaseData().category, (unit.getBaseData().AI) ? "AI" : "Human"];
const dataset = [unit.getBaseData().unitName, unit.getBaseData().name, unit.getBaseData().category, (unit.getBaseData().controlled) ? "AI" : "Human"];
addRow(el, dataset);
}

View File

@ -139,29 +139,29 @@ export class UnitControlPanel extends Panel {
element.toggleAttribute("data-show-advanced-settings-button", units.length == 1);
/* Flight controls */
var targetAltitude: number | undefined = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().targetAltitude});
var targetAltitudeType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().targetAltitudeType});
var targetSpeed = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().targetSpeed});
var targetSpeedType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().targetSpeedType});
var desiredAltitude: number | undefined = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().desiredAltitude});
var desiredAltitudeType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().desiredAltitudeType});
var desiredSpeed = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().desiredSpeed});
var desiredSpeedType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().desiredSpeedType});
var onOff = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().onOff});
var followRoads = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getTaskData().followRoads});
if (selectedUnitsTypes.length == 1) {
this.#altitudeTypeSwitch.setValue(targetAltitudeType != undefined? targetAltitudeType == "AGL": undefined, false);
this.#speedTypeSwitch.setValue(targetSpeedType != undefined? targetSpeedType == "GS": undefined, false);
this.#altitudeTypeSwitch.setValue(desiredAltitudeType != undefined? desiredAltitudeType == "AGL": undefined, false);
this.#speedTypeSwitch.setValue(desiredSpeedType != undefined? desiredSpeedType == "GS": undefined, false);
this.#speedSlider.setMinMax(minSpeedValues[selectedUnitsTypes[0]], maxSpeedValues[selectedUnitsTypes[0]]);
this.#altitudeSlider.setMinMax(minAltitudeValues[selectedUnitsTypes[0]], maxAltitudeValues[selectedUnitsTypes[0]]);
this.#speedSlider.setIncrement(speedIncrements[selectedUnitsTypes[0]]);
this.#altitudeSlider.setIncrement(altitudeIncrements[selectedUnitsTypes[0]]);
this.#speedSlider.setActive(targetSpeed != undefined);
if (targetSpeed != undefined)
this.#speedSlider.setValue(msToKnots(targetSpeed), false);
this.#speedSlider.setActive(desiredSpeed != undefined);
if (desiredSpeed != undefined)
this.#speedSlider.setValue(msToKnots(desiredSpeed), false);
this.#altitudeSlider.setActive(targetAltitude != undefined);
if (targetAltitude != undefined)
this.#altitudeSlider.setValue(mToFt(targetAltitude), false);
this.#altitudeSlider.setActive(desiredAltitude != undefined);
if (desiredAltitude != undefined)
this.#altitudeSlider.setValue(mToFt(desiredAltitude), false);
}
else {
this.#speedSlider.setActive(false);

View File

@ -24,21 +24,21 @@ export class UnitInfoPanel extends Panel {
constructor(ID: string) {
super(ID);
this.#altitude = (this.getElement().querySelector("#altitude")) as HTMLElement;
this.#currentTask = (this.getElement().querySelector("#current-task")) as HTMLElement;
this.#groundSpeed = (this.getElement().querySelector("#ground-speed")) as HTMLElement;
this.#fuelBar = (this.getElement().querySelector("#fuel-bar")) as HTMLElement;
this.#fuelPercentage = (this.getElement().querySelector("#fuel-percentage")) as HTMLElement;
this.#groupName = (this.getElement().querySelector("#group-name")) as HTMLElement;
this.#heading = (this.getElement().querySelector("#heading")) as HTMLElement;
this.#name = (this.getElement().querySelector("#name")) as HTMLElement;
this.#latitude = (this.getElement().querySelector("#latitude")) as HTMLElement;
this.#altitude = (this.getElement().querySelector("#altitude")) as HTMLElement;
this.#currentTask = (this.getElement().querySelector("#current-task")) as HTMLElement;
this.#groundSpeed = (this.getElement().querySelector("#ground-speed")) as HTMLElement;
this.#fuelBar = (this.getElement().querySelector("#fuel-bar")) as HTMLElement;
this.#fuelPercentage = (this.getElement().querySelector("#fuel-percentage")) as HTMLElement;
this.#groupName = (this.getElement().querySelector("#group-name")) as HTMLElement;
this.#heading = (this.getElement().querySelector("#heading")) as HTMLElement;
this.#name = (this.getElement().querySelector("#name")) as HTMLElement;
this.#latitude = (this.getElement().querySelector("#latitude")) as HTMLElement;
this.#loadoutContainer = (this.getElement().querySelector("#loadout-container")) as HTMLElement;
this.#longitude = (this.getElement().querySelector("#longitude")) as HTMLElement;
this.#silhouette = (this.getElement().querySelector("#loadout-silhouette")) as HTMLImageElement;
this.#unitControl = (this.getElement().querySelector("#unit-control")) as HTMLElement;
this.#unitLabel = (this.getElement().querySelector("#unit-label")) as HTMLElement;
this.#unitName = (this.getElement().querySelector("#unit-name")) as HTMLElement;
this.#longitude = (this.getElement().querySelector("#longitude")) as HTMLElement;
this.#silhouette = (this.getElement().querySelector("#loadout-silhouette")) as HTMLImageElement;
this.#unitControl = (this.getElement().querySelector("#unit-control")) as HTMLElement;
this.#unitLabel = (this.getElement().querySelector("#unit-label")) as HTMLElement;
this.#unitName = (this.getElement().querySelector("#unit-name")) as HTMLElement;
document.addEventListener("unitsSelection", (e: CustomEvent<Unit[]>) => this.#onUnitsSelection(e.detail));
document.addEventListener("unitsDeselection", (e: CustomEvent<Unit[]>) => this.#onUnitsDeselection(e.detail));
@ -47,49 +47,53 @@ export class UnitInfoPanel extends Panel {
this.hide();
}
#onUnitUpdate(unit: Unit) {
if (this.getElement() != null && this.getVisible() && unit.getSelected()) {
const baseData = unit.getBaseData();
/* Set the unit info */
this.#unitLabel.innerText = aircraftDatabase.getByName(baseData.name)?.label || baseData.name;
this.#unitName.innerText = baseData.unitName;
this.#unitControl.innerText = ( ( baseData.AI ) ? "AI" : "Human" ) + " controlled";
this.#unitLabel.innerText = aircraftDatabase.getByName(baseData.name)?.label || baseData.name;
this.#unitName.innerText = baseData.unitName;
if (unit.getMissionData().flags.Human)
this.#unitControl.innerText = "Human";
else if (baseData.controlled)
this.#unitControl.innerText = "Olympus controlled";
else
this.#unitControl.innerText = "DCS Controlled";
this.#fuelBar.style.width = String(unit.getMissionData().fuel + "%");
this.#fuelPercentage.dataset.percentage = "" + unit.getMissionData().fuel;
this.#currentTask.dataset.currentTask = unit.getTaskData().currentTask !== ""? unit.getTaskData().currentTask: "No task";
this.#currentTask.dataset.currentTask = unit.getTaskData().currentTask !== "" ? unit.getTaskData().currentTask : "No task";
this.#currentTask.dataset.coalition = unit.getMissionData().coalition;
this.#silhouette.src = `/images/units/${unit.getDatabase()?.getByName(baseData.name)?.filename}`;
this.#silhouette.classList.toggle("hide", unit.getDatabase()?.getByName(baseData.name)?.filename == undefined || unit.getDatabase()?.getByName(baseData.name)?.filename == '');
/* Add the loadout elements */
const items = <HTMLElement>this.#loadoutContainer.querySelector( "#loadout-items" );
if ( items ) {
const ammo = Object.values( unit.getMissionData().ammo );
if ( ammo.length > 0 ) {
/* Add the loadout elements */
const items = <HTMLElement>this.#loadoutContainer.querySelector("#loadout-items");
if (items) {
const ammo = Object.values(unit.getMissionData().ammo);
if (ammo.length > 0) {
items.replaceChildren(...Object.values(unit.getMissionData().ammo).map(
(ammo: any) => {
var el = document.createElement("div");
el.dataset.qty = ammo.count;
el.dataset.qty = ammo.count;
el.dataset.item = ammo.desc.displayName;
return el;
}
));
} else {
items.innerText = "No loadout";
items.innerText = "No loadout";
}
}
}
}
#onUnitsSelection(units: Unit[]){
if (units.length == 1)
{
#onUnitsSelection(units: Unit[]) {
if (units.length == 1) {
this.show();
this.#onUnitUpdate(units[0]);
}
@ -97,9 +101,8 @@ export class UnitInfoPanel extends Panel {
this.hide();
}
#onUnitsDeselection(units: Unit[]){
if (units.length == 1)
{
#onUnitsDeselection(units: Unit[]) {
if (units.length == 1) {
this.show();
this.#onUnitUpdate(units[0]);
}

View File

@ -2456,8 +2456,8 @@ export class AircraftDatabase extends UnitDatabase {
],
"filename": "kc-135.png"
},
"KC-135MPRS": {
"name": "KC-135MPRS",
"KC135MPRS": {
"name": "KC135MPRS",
"label": "KC-135 MPRS Stratotanker",
"era": ["Early Cold War", "Mid Cold War", "Late Cold War", "Modern"],
"shortLabel": "135M",
@ -2476,6 +2476,26 @@ export class AircraftDatabase extends UnitDatabase {
],
"filename": "kc-135.png"
},
"S-3B Tanker": {
"name": "S-3B Tanker",
"label": "S-3B Tanker",
"era": ["Early Cold War", "Mid Cold War", "Late Cold War", "Modern"],
"shortLabel": "S3B",
"loadouts": [
{
"fuel": 1,
"items": [
],
"roles": [
"Tanker"
],
"code": "",
"name": "Default Tanker"
}
],
"filename": "s-3.png"
},
"MiG-15bis": {
"name": "MiG-15bis",
"label": "MiG-15 Fagot",

View File

@ -21,7 +21,7 @@ export class Unit extends CustomMarker {
#data: UnitData = {
baseData: {
AI: false,
controlled: false,
name: "",
unitName: "",
groupName: "",
@ -39,7 +39,7 @@ export class Unit extends CustomMarker {
fuel: 0,
flags: {},
ammo: {},
targets: {},
contacts: {},
hasTask: false,
coalition: "",
},
@ -50,10 +50,10 @@ export class Unit extends CustomMarker {
currentState: "NONE",
currentTask: "",
activePath: {},
targetSpeed: 0,
targetSpeedType: "GS",
targetAltitude: 0,
targetAltitudeType: "AGL",
desiredSpeed: 0,
desiredSpeedType: "GS",
desiredAltitude: 0,
desiredAltitudeType: "AGL",
targetLocation: {},
isTanker: false,
isAWACS: false,
@ -80,7 +80,7 @@ export class Unit extends CustomMarker {
#pathMarkers: Marker[] = [];
#pathPolyline: Polyline;
#targetsPolylines: Polyline[];
#contactsPolylines: Polyline[];
#miniMapMarker: CircleMarker | null = null;
#targetLocationMarker: TargetMarker;
#targetLocationPolyline: Polyline;
@ -113,7 +113,7 @@ export class Unit extends CustomMarker {
this.#pathPolyline = new Polyline([], { color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1 });
this.#pathPolyline.addTo(getMap());
this.#targetsPolylines = [];
this.#contactsPolylines = [];
this.#targetLocationMarker = new TargetMarker(new LatLng(0, 0));
this.#targetLocationPolyline = new Polyline([], { color: '#FF0000', weight: 3, opacity: 0.5, smoothFactor: 1 });
@ -217,7 +217,9 @@ export class Unit extends CustomMarker {
const positionChanged = (data.flightData != undefined && data.flightData.latitude != undefined && data.flightData.longitude != undefined && (this.getFlightData().latitude != data.flightData.latitude || this.getFlightData().longitude != data.flightData.longitude));
const headingChanged = (data.flightData != undefined && data.flightData.heading != undefined && this.getFlightData().heading != data.flightData.heading);
const aliveChanged = (data.baseData != undefined && data.baseData.alive != undefined && this.getBaseData().alive != data.baseData.alive);
var updateMarker = (positionChanged || headingChanged || aliveChanged || !getMap().hasLayer(this));
const stateChanged = (data.taskData != undefined && data.taskData.currentState != undefined && this.getTaskData().currentState != data.taskData.currentState);
const controlledChanged = (data.baseData != undefined && data.baseData.controlled != undefined && this.getBaseData().controlled != data.baseData.controlled);
var updateMarker = (positionChanged || headingChanged || aliveChanged || stateChanged || controlledChanged || !getMap().hasLayer(this));
/* Load the data from the received json */
Object.keys(this.#data).forEach((key1: string) => {
@ -391,7 +393,7 @@ export class Unit extends CustomMarker {
const hiddenUnits = getUnitsManager().getHiddenTypes();
if (this.getMissionData().flags.Human && hiddenUnits.includes("human"))
hidden = true;
else if (this.getBaseData().AI == false && hiddenUnits.includes("dcs"))
else if (this.getBaseData().controlled == false && hiddenUnits.includes("dcs"))
hidden = true;
else if (hiddenUnits.includes(this.getMarkerCategory()))
hidden = true;
@ -724,7 +726,7 @@ export class Unit extends CustomMarker {
/* Set current unit state */
if (this.getMissionData().flags.Human) // Unit is human
element.querySelector(".unit")?.setAttribute("data-state", "human");
else if (!this.getBaseData().AI) // Unit is under DCS control (not Olympus)
else if (!this.getBaseData().controlled) // Unit is under DCS control (not Olympus)
element.querySelector(".unit")?.setAttribute("data-state", "dcs");
else if ((this.getBaseData().category == "Aircraft" || this.getBaseData().category == "Helicopter") && !this.getMissionData().hasTask)
element.querySelector(".unit")?.setAttribute("data-state", "no-task");
@ -827,8 +829,8 @@ export class Unit extends CustomMarker {
}
#drawDetectedUnits() {
for (let index in this.getMissionData().targets) {
var targetData = this.getMissionData().targets[index];
for (let index in this.getMissionData().contacts) {
var targetData = this.getMissionData().contacts[index];
if (targetData.object != undefined){
var target = getUnitsManager().getUnitByID(targetData.object["id_"])
if (target != null) {
@ -846,15 +848,15 @@ export class Unit extends CustomMarker {
color = "#FFFFFF";
var targetPolyline = new Polyline([startLatLng, endLatLng], { color: color, weight: 3, opacity: 0.4, smoothFactor: 1, dashArray: "4, 8" });
targetPolyline.addTo(getMap());
this.#targetsPolylines.push(targetPolyline)
this.#contactsPolylines.push(targetPolyline)
}
}
}
}
#clearDetectedUnits() {
for (let index in this.#targetsPolylines) {
getMap().removeLayer(this.#targetsPolylines[index])
for (let index in this.#contactsPolylines) {
getMap().removeLayer(this.#contactsPolylines[index])
}
}

View File

@ -98,13 +98,14 @@ function Olympus.buildEnrouteTask(options)
end
-- Builds a valid task depending on the provided options
function Olympus.buildTask(options)
function Olympus.buildTask(groupName, options)
local task = nil
local group = Group.getByName(groupName)
if (Olympus.isArray(options)) then
local tasks = {}
for idx, subOptions in pairs(options) do
tasks[idx] = Olympus.buildTask(subOptions) or Olympus.buildEnrouteTask(subOptions)
tasks[idx] = Olympus.buildTask(groupName, subOptions) or Olympus.buildEnrouteTask(subOptions)
end
task = {
id = 'ComboTask',
@ -139,6 +140,25 @@ function Olympus.buildTask(options)
pattern = options['pattern'] or "Circle"
}
}
if options['altitude'] then
if options ['altitudeType'] then
if options ['altitudeType'] == "AGL" then
local groundHeight = 0
if group then
local groupPos = mist.getLeadPos(group)
groundHeight = land.getHeight({x = groupPos.x, y = groupPos.z})
end
task['params']['altitude'] = groundHeight + options['altitude']
else
task['params']['altitude'] = options['altitude']
end
else
task['params']['altitude'] = options['altitude']
end
end
if options['speed'] then
task['params']['speed'] = options['speed']
end
elseif options['id'] == 'Bombing' and options['lat'] and options['lng'] then
local point = coord.LLtoLO(options['lat'], options['lng'], 0)
task = {
@ -524,7 +544,7 @@ function Olympus.setTask(groupName, taskOptions)
Olympus.debug("Olympus.setTask " .. groupName .. " " .. Olympus.serializeTable(taskOptions), 2)
local group = Group.getByName(groupName)
if group then
local task = Olympus.buildTask(taskOptions);
local task = Olympus.buildTask(groupName, taskOptions);
Olympus.debug("Olympus.setTask " .. Olympus.serializeTable(task), 20)
if task then
group:getController():setTask(task)
@ -664,7 +684,7 @@ function Olympus.setMissionData(arg, time)
for index, unit in pairs(group:getUnits()) do
local unitController = unit:getController()
local table = {}
table["targets"] = {}
table["contacts"] = {}
for i, target in ipairs(controllerTargets) do
for det, enum in pairs(Controller.Detection) do
@ -673,7 +693,7 @@ function Olympus.setMissionData(arg, time)
if detected then
target["detectionMethod"] = det
table["targets"][#table["targets"] + 1] = target
table["contacts"][#table["contacts"] + 1] = target
end
end
end

View File

@ -62,14 +62,16 @@ public:
/********** Public methods **********/
void initialize(json::value json);
void setDefaults(bool force = false);
int getID() { return ID; }
void runAILoop();
void updateExportData(json::value json);
void updateMissionData(json::value json);
json::value getData(long long time, bool getAll = false);
virtual wstring getCategory() { return L"No category"; };
/********** Base data **********/
void setAI(bool newAI) { AI = newAI; addMeasure(L"AI", json::value(newAI)); }
void setControlled(bool newControlled) { controlled = newControlled; addMeasure(L"controlled", json::value(newControlled)); }
void setName(wstring newName) { name = newName; addMeasure(L"name", json::value(newName));}
void setUnitName(wstring newUnitName) { unitName = newUnitName; addMeasure(L"unitName", json::value(newUnitName));}
void setGroupName(wstring newGroupName) { groupName = newGroupName; addMeasure(L"groupName", json::value(newGroupName));}
@ -77,7 +79,7 @@ public:
void setType(json::value newType) { type = newType; addMeasure(L"type", newType);}
void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));}
bool getAI() { return AI; }
bool getControlled() { return controlled; }
wstring getName() { return name; }
wstring getUnitName() { return unitName; }
wstring getGroupName() { return groupName; }
@ -101,14 +103,14 @@ public:
/********** Mission data **********/
void setFuel(double newFuel) { fuel = newFuel; addMeasure(L"fuel", json::value(newFuel));}
void setAmmo(json::value newAmmo) { ammo = newAmmo; addMeasure(L"ammo", json::value(newAmmo));}
void setTargets(json::value newTargets) {targets = newTargets; addMeasure(L"targets", json::value(newTargets));}
void setContacts(json::value newContacts) {contacts = newContacts; addMeasure(L"contacts", json::value(newContacts));}
void setHasTask(bool newHasTask);
void setCoalitionID(int newCoalitionID);
void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));}
double getFuel() { return fuel; }
json::value getAmmo() { return ammo; }
json::value getTargets() { return targets; }
json::value getTargets() { return contacts; }
bool getHasTask() { return hasTask; }
wstring getCoalition() { return coalition; }
int getCoalitionID();
@ -123,10 +125,10 @@ public:
/********** Task data **********/
void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask; addMeasure(L"currentTask", json::value(newCurrentTask)); }
void setTargetSpeed(double newTargetSpeed);
void setTargetAltitude(double newTargetAltitude);
void setTargetSpeedType(wstring newTargetSpeedType);
void setTargetAltitudeType(wstring newTargetAltitudeType);
void setDesiredSpeed(double newDesiredSpeed);
void setDesiredAltitude(double newDesiredAltitude);
void setDesiredSpeedType(wstring newDesiredSpeedType);
void setDesiredAltitudeType(wstring newDesiredAltitudeType);
void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix
void setActivePath(list<Coords> newActivePath);
void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));}
@ -137,10 +139,10 @@ public:
virtual void setFollowRoads(bool newFollowRoads) { followRoads = newFollowRoads; addMeasure(L"followRoads", json::value(newFollowRoads)); };
wstring getCurrentTask() { return currentTask; }
virtual double getTargetSpeed() { return targetSpeed; };
virtual double getTargetAltitude() { return targetAltitude; };
virtual wstring getTargetSpeedType() { return targetSpeedType; };
virtual wstring getTargetAltitudeType() { return targetAltitudeType; };
virtual double getDesiredSpeed() { return desiredSpeed; };
virtual double getDesiredAltitude() { return desiredAltitude; };
virtual wstring getDesiredSpeedType() { return desiredSpeedType; };
virtual wstring getDesiredAltitudeType() { return desiredAltitudeType; };
Coords getActiveDestination() { return activeDestination; }
list<Coords> getActivePath() { return activePath; }
int getTargetID() { return targetID; }
@ -151,13 +153,13 @@ public:
bool getFollowRoads() { return followRoads; };
/********** Options data **********/
void setROE(wstring newROE);
void setReactionToThreat(wstring newReactionToThreat);
void setEmissionsCountermeasures(wstring newEmissionsCountermeasures);
void setTACAN(Options::TACAN newTACAN);
void setRadio(Options::Radio newradio);
void setGeneralSettings(Options::GeneralSettings newGeneralSettings);
void setEPLRS(bool newEPLRS);
void setROE(wstring newROE, bool force = false);
void setReactionToThreat(wstring newReactionToThreat, bool force = false);
void setEmissionsCountermeasures(wstring newEmissionsCountermeasures, bool force = false);
void setTACAN(Options::TACAN newTACAN, bool force = false);
void setRadio(Options::Radio newradio, bool force = false);
void setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool force = false);
void setEPLRS(bool newEPLRS, bool force = false);
wstring getROE() { return ROE; }
wstring getReactionToThreat() { return reactionToThreat; }
@ -186,7 +188,7 @@ protected:
int taskCheckCounter = 0;
/********** Base data **********/
bool AI = false;
bool controlled = false;
wstring name = L"undefined";
wstring unitName = L"undefined";
wstring groupName = L"undefined";
@ -205,7 +207,7 @@ protected:
double fuel = 0;
double initialFuel = 0; // Used internally to detect refueling completed
json::value ammo = json::value::null();
json::value targets = json::value::null();
json::value contacts = json::value::null();
bool hasTask = false;
wstring coalition = L"";
json::value flags = json::value::null();
@ -216,10 +218,10 @@ protected:
/********** Task data **********/
wstring currentTask = L"";
double targetSpeed = 0;
double targetAltitude = 0;
wstring targetSpeedType = L"GS";
wstring targetAltitudeType = L"AGL";
double desiredSpeed = 0;
double desiredAltitude = 0;
wstring desiredSpeedType = L"GS";
wstring desiredAltitudeType = L"AGL";
list<Coords> activePath;
Coords activeDestination = Coords(NULL);
int targetID = NULL;

View File

@ -18,8 +18,10 @@ public:
vector<Unit*> getGroupMembers(wstring groupName);
void updateExportData(lua_State* L);
void updateMissionData(json::value missionData);
void runAILoop();
void getData(json::value& answer, long long time);
void deleteUnit(int ID, bool explosion);
void acquireControl(int ID);
private:
map<int, Unit*> units;

View File

@ -18,10 +18,10 @@ Aircraft::Aircraft(json::value json, int ID) : AirUnit(json, ID)
log("New Aircraft created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory()));
double targetSpeed = knotsToMs(300);
double targetAltitude = ftToM(20000);
setTargetSpeed(targetSpeed);
setTargetAltitude(targetAltitude);
double desiredSpeed = knotsToMs(300);
double desiredAltitude = ftToM(20000);
setDesiredSpeed(desiredSpeed);
setDesiredAltitude(desiredAltitude);
};
void Aircraft::changeSpeed(wstring change)
@ -29,34 +29,40 @@ void Aircraft::changeSpeed(wstring change)
if (change.compare(L"stop") == 0)
setState(State::IDLE);
else if (change.compare(L"slow") == 0)
setTargetSpeed(getTargetSpeed() - knotsToMs(25));
setDesiredSpeed(getDesiredSpeed() - knotsToMs(25));
else if (change.compare(L"fast") == 0)
setTargetSpeed(getTargetSpeed() + knotsToMs(25));
setDesiredSpeed(getDesiredSpeed() + knotsToMs(25));
if (getTargetSpeed() < knotsToMs(50))
setTargetSpeed(knotsToMs(50));
if (getDesiredSpeed() < knotsToMs(50))
setDesiredSpeed(knotsToMs(50));
goToDestination(); /* Send the command to reach the destination */
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
}
void Aircraft::changeAltitude(wstring change)
{
if (change.compare(L"descend") == 0)
{
if (getTargetAltitude() > 5000)
setTargetAltitude(getTargetAltitude() - ftToM(2500));
else if (getTargetAltitude() > 0)
setTargetAltitude(getTargetAltitude() - ftToM(500));
if (getDesiredAltitude() > 5000)
setDesiredAltitude(getDesiredAltitude() - ftToM(2500));
else if (getDesiredAltitude() > 0)
setDesiredAltitude(getDesiredAltitude() - ftToM(500));
}
else if (change.compare(L"climb") == 0)
{
if (getTargetAltitude() > 5000)
setTargetAltitude(getTargetAltitude() + ftToM(2500));
else if (getTargetAltitude() >= 0)
setTargetAltitude(getTargetAltitude() + ftToM(500));
if (getDesiredAltitude() > 5000)
setDesiredAltitude(getDesiredAltitude() + ftToM(2500));
else if (getDesiredAltitude() >= 0)
setDesiredAltitude(getDesiredAltitude() + ftToM(500));
}
if (getTargetAltitude() < 0)
setTargetAltitude(0);
if (getDesiredAltitude() < 0)
setDesiredAltitude(0);
goToDestination(); /* Send the command to reach the destination */
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
}

View File

@ -135,13 +135,13 @@ void AirUnit::AIloop()
{
std::wostringstream taskSS;
if (isTanker) {
taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track' } }";
taskSS << "{ [1] = { id = 'Tanker' }, [2] = { id = 'Orbit', pattern = 'Race-Track', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' } }";
}
else if (isAWACS) {
taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Circle' } }";
taskSS << "{ [1] = { id = 'AWACS' }, [2] = { id = 'Orbit', pattern = 'Circle', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' } }";
}
else {
taskSS << "{ id = 'Orbit', pattern = 'Circle' }";
taskSS << "{ id = 'Orbit', pattern = 'Circle', altitude = " << desiredAltitude << ", speed = " << desiredSpeed << ", altitudeType = '" << desiredAltitudeType << "' }";
}
Command* command = dynamic_cast<Command*>(new SetTask(groupName, taskSS.str()));
scheduler->appendCommand(command);
@ -313,5 +313,4 @@ void AirUnit::AIloop()
}
addMeasure(L"currentTask", json::value(currentTask));
}

View File

@ -69,6 +69,7 @@ extern "C" DllExport int coreFrame(lua_State* L)
if (unitsManager != nullptr)
{
unitsManager->updateExportData(L);
unitsManager->runAILoop();
}
before = std::chrono::system_clock::now();
}

View File

@ -18,8 +18,8 @@ GroundUnit::GroundUnit(json::value json, int ID) : Unit(json, ID)
log("New Ground Unit created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory()));
double targetSpeed = 10;
setTargetSpeed(targetSpeed);
double desiredSpeed = 10;
setDesiredSpeed(desiredSpeed);
};
void GroundUnit::setState(int newState)
@ -128,12 +128,12 @@ void GroundUnit::changeSpeed(wstring change)
if (change.compare(L"stop") == 0)
setState(State::IDLE);
else if (change.compare(L"slow") == 0)
setTargetSpeed(getTargetSpeed() - knotsToMs(5));
setDesiredSpeed(getDesiredSpeed() - knotsToMs(5));
else if (change.compare(L"fast") == 0)
setTargetSpeed(getTargetSpeed() + knotsToMs(5));
setDesiredSpeed(getDesiredSpeed() + knotsToMs(5));
if (getTargetSpeed() < 0)
setTargetSpeed(0);
if (getDesiredSpeed() < 0)
setDesiredSpeed(0);
}
void GroundUnit::setOnOff(bool newOnOff)

View File

@ -18,10 +18,10 @@ Helicopter::Helicopter(json::value json, int ID) : AirUnit(json, ID)
log("New Helicopter created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory()));
double targetSpeed = knotsToMs(100);
double targetAltitude = ftToM(5000);
setTargetSpeed(targetSpeed);
setTargetAltitude(targetAltitude);
double desiredSpeed = knotsToMs(100);
double desiredAltitude = ftToM(5000);
setDesiredSpeed(desiredSpeed);
setDesiredAltitude(desiredAltitude);
};
void Helicopter::changeSpeed(wstring change)
@ -32,11 +32,11 @@ void Helicopter::changeSpeed(wstring change)
clearActivePath();
}
else if (change.compare(L"slow") == 0)
targetSpeed -= knotsToMs(10);
desiredSpeed -= knotsToMs(10);
else if (change.compare(L"fast") == 0)
targetSpeed += knotsToMs(10);
if (targetSpeed < 0)
targetSpeed = 0;
desiredSpeed += knotsToMs(10);
if (desiredSpeed < 0)
desiredSpeed = 0;
goToDestination(); /* Send the command to reach the destination */
}
@ -45,20 +45,20 @@ void Helicopter::changeAltitude(wstring change)
{
if (change.compare(L"descend") == 0)
{
if (targetAltitude > 100)
targetAltitude -= ftToM(100);
else if (targetAltitude > 0)
targetAltitude -= ftToM(10);
if (desiredAltitude > 100)
desiredAltitude -= ftToM(100);
else if (desiredAltitude > 0)
desiredAltitude -= ftToM(10);
}
else if (change.compare(L"climb") == 0)
{
if (targetAltitude > 100)
targetAltitude += ftToM(100);
else if (targetAltitude >= 0)
targetAltitude += ftToM(10);
if (desiredAltitude > 100)
desiredAltitude += ftToM(100);
else if (desiredAltitude >= 0)
desiredAltitude += ftToM(10);
}
if (targetAltitude < 0)
targetAltitude = 0;
if (desiredAltitude < 0)
desiredAltitude = 0;
goToDestination(); /* Send the command to reach the destination */
}

View File

@ -18,8 +18,8 @@ NavyUnit::NavyUnit(json::value json, int ID) : Unit(json, ID)
log("New Navy Unit created with ID: " + to_string(ID));
addMeasure(L"category", json::value(getCategory()));
double targetSpeed = 10;
setTargetSpeed(targetSpeed);
double desiredSpeed = 10;
setDesiredSpeed(desiredSpeed);
};
void NavyUnit::AIloop()

View File

@ -59,8 +59,8 @@ void Scheduler::handleRequest(wstring key, json::value value)
if (key.compare(L"setPath") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
wstring unitName = unit->getUnitName();
@ -116,6 +116,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"attackUnit") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
int targetID = value[L"targetID"].as_integer();
Unit* unit = unitsManager->getGroupLeader(ID);
@ -141,6 +142,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"followUnit") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
int leaderID = value[L"targetID"].as_integer();
int offsetX = value[L"offsetX"].as_integer();
int offsetY = value[L"offsetY"].as_integer();
@ -170,6 +172,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"changeSpeed") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->changeSpeed(value[L"change"].as_string());
@ -177,6 +180,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"changeAltitude") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->changeAltitude(value[L"change"].as_string());
@ -184,30 +188,34 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setSpeed") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetSpeed(value[L"speed"].as_double());
unit->setDesiredSpeed(value[L"speed"].as_double());
}
else if (key.compare(L"setSpeedType") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetSpeedType(value[L"speedType"].as_string());
unit->setDesiredSpeedType(value[L"speedType"].as_string());
}
else if (key.compare(L"setAltitude") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetAltitude(value[L"altitude"].as_double());
unit->setDesiredAltitude(value[L"altitude"].as_double());
}
else if (key.compare(L"setAltitudeType") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
unit->setTargetAltitudeType(value[L"altitudeType"].as_string());
unit->setDesiredAltitudeType(value[L"altitudeType"].as_string());
}
else if (key.compare(L"cloneUnit") == 0)
{
@ -221,6 +229,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setROE") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
wstring ROE = value[L"ROE"].as_string();
unit->setROE(ROE);
@ -228,6 +237,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setReactionToThreat") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
wstring reactionToThreat = value[L"reactionToThreat"].as_string();
unit->setReactionToThreat(reactionToThreat);
@ -235,6 +245,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setEmissionsCountermeasures") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
wstring emissionsCountermeasures = value[L"emissionsCountermeasures"].as_string();
unit->setEmissionsCountermeasures(emissionsCountermeasures);
@ -242,6 +253,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"landAt") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
double lat = value[L"location"][L"lat"].as_double();
double lng = value[L"location"][L"lng"].as_double();
@ -257,12 +269,14 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"refuel") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setState(State::REFUEL);
}
else if (key.compare(L"setAdvancedOptions") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
Unit* unit = unitsManager->getGroupLeader(ID);
if (unit != nullptr)
{
@ -300,6 +314,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setFollowRoads") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
bool followRoads = value[L"followRoads"].as_bool();
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setFollowRoads(followRoads);
@ -307,6 +322,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"setOnOff") == 0)
{
int ID = value[L"ID"].as_integer();
unitsManager->acquireControl(ID);
bool onOff = value[L"onOff"].as_bool();
Unit* unit = unitsManager->getGroupLeader(ID);
unit->setOnOff(onOff);
@ -323,6 +339,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"bombPoint") == 0)
{
int ID = value[L"ID"].as_integer();
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;
@ -333,6 +350,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"carpetBomb") == 0)
{
int ID = value[L"ID"].as_integer();
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;
@ -343,6 +361,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"bombBuilding") == 0)
{
int ID = value[L"ID"].as_integer();
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;
@ -353,6 +372,7 @@ void Scheduler::handleRequest(wstring key, json::value value)
else if (key.compare(L"fireAtArea") == 0)
{
int ID = value[L"ID"].as_integer();
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;

View File

@ -46,19 +46,30 @@ Unit::~Unit()
void Unit::initialize(json::value json)
{
updateExportData(json);
setDefaults();
}
if (getAI()) {
void Unit::setDefaults(bool force)
{
const bool isUnitControlledByOlympus = getControlled();
const bool isUnitAlive = getAlive();
const bool isUnitLeader = unitsManager->isUnitGroupLeader(this);
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
const bool isUnitHuman = getFlags()[L"Human"].as_bool();
if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman) {
/* Set the default IDLE state */
setState(State::IDLE);
/* Set the default options (these are all defaults so will only affect the export data, no DCS command will be sent) */
setROE(L"Designated");
setReactionToThreat(L"Evade");
setEmissionsCountermeasures(L"Defend");
setTACAN(TACAN);
setRadio(radio);
setEPLRS(EPLRS);
setGeneralSettings(generalSettings);
setROE(L"Designated", force);
setReactionToThreat(L"Evade", force);
setEmissionsCountermeasures(L"Defend", force);
setTACAN(TACAN, force);
setRadio(radio, force);
setEPLRS(EPLRS, force);
setGeneralSettings(generalSettings, force);
setOnOff(onOff);
setFollowRoads(followRoads);
}
}
@ -77,6 +88,24 @@ void Unit::addMeasure(wstring key, json::value value)
}
}
void Unit::runAILoop() {
/* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
const bool isUnitControlledByOlympus = getControlled();
const bool isUnitAlive = getAlive();
const bool isUnitLeader = unitsManager->isUnitGroupLeader(this);
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
const bool isUnitHuman = getFlags()[L"Human"].as_bool();
// Keep running the AI loop even if the unit is dead if it is the leader of a group which has other members in it
if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman)
{
if (checkTaskFailed() && state != State::IDLE && State::LAND)
setState(State::IDLE);
AIloop();
}
}
void Unit::updateExportData(json::value json)
{
/* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */
@ -112,25 +141,8 @@ void Unit::updateExportData(json::value json)
setFlags(json[L"Flags"]);
/* All units which contain the name "Olympus" are automatically under AI control */
/* TODO: I don't really like using this method */
setAI(getUnitName().find(L"Olympus") != wstring::npos);
/* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */
// TODO at the moment groups will stop moving correctly if the leader dies
const bool isUnitControlledByOlympus = getAI();
const bool isUnitAlive = getAlive();
const bool isUnitLeader = unitsManager->isUnitGroupLeader(this);
const bool isUnitLeaderOfAGroupWithOtherUnits = unitsManager->isUnitInGroup(this) && unitsManager->isUnitGroupLeader(this);
const bool isUnitHuman = getFlags()[L"Human"].as_bool();
// Keep running the AI loop even if the unit is dead if it is the leader of a group which has other members in it
if (isUnitControlledByOlympus && (isUnitAlive || isUnitLeaderOfAGroupWithOtherUnits) && isUnitLeader && !isUnitHuman)
{
if (checkTaskFailed() && state != State::IDLE && State::LAND)
setState(State::IDLE);
AIloop();
}
if (getUnitName().find(L"Olympus") != wstring::npos)
setControlled(true);
}
void Unit::updateMissionData(json::value json)
@ -139,8 +151,8 @@ void Unit::updateMissionData(json::value json)
setFuel(int(json[L"fuel"].as_number().to_double() * 100));
if (json.has_object_field(L"ammo"))
setAmmo(json[L"ammo"]);
if (json.has_object_field(L"targets"))
setTargets(json[L"targets"]);
if (json.has_object_field(L"contacts"))
setContacts(json[L"contacts"]);
if (json.has_boolean_field(L"hasTask"))
setHasTask(json[L"hasTask"].as_bool());
}
@ -155,7 +167,7 @@ json::value Unit::getData(long long time, bool sendAll)
/********** Base data **********/
json[L"baseData"] = json::value::object();
for (auto key : { L"AI", L"name", L"unitName", L"groupName", L"alive", L"category"})
for (auto key : { L"controlled", L"name", L"unitName", L"groupName", L"alive", L"category"})
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"baseData"][key] = measures[key]->getValue();
@ -176,7 +188,7 @@ json::value Unit::getData(long long time, bool sendAll)
/********** Mission data **********/
json[L"missionData"] = json::value::object();
for (auto key : { L"fuel", L"ammo", L"targets", L"hasTask", L"coalition", L"flags" })
for (auto key : { L"fuel", L"ammo", L"contacts", L"hasTask", L"coalition", L"flags" })
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"missionData"][key] = measures[key]->getValue();
@ -198,7 +210,7 @@ json::value Unit::getData(long long time, bool sendAll)
if (unitsManager->isUnitGroupLeader(this)) {
/********** Task data **********/
json[L"taskData"] = json::value::object();
for (auto key : { L"currentState", L"currentTask", L"targetSpeed", L"targetAltitude", L"targetSpeedType", L"targetAltitudeType", L"activePath", L"isTanker", L"isAWACS", L"onOff", L"followRoads", L"targetID", L"targetLocation" })
for (auto key : { L"currentState", L"currentTask", L"desiredSpeed", L"desiredAltitude", L"desiredSpeedType", L"desiredAltitudeType", L"activePath", L"isTanker", L"isAWACS", L"onOff", L"followRoads", L"targetID", L"targetLocation" })
{
if (measures.find(key) != measures.end() && measures[key]->getTime() > time)
json[L"taskData"][key] = measures[key]->getValue();
@ -354,10 +366,10 @@ void Unit::setFormationOffset(Offset newFormationOffset)
resetTask();
}
void Unit::setROE(wstring newROE) {
void Unit::setROE(wstring newROE, bool force) {
addMeasure(L"ROE", json::value(newROE));
if (ROE != newROE) {
if (ROE != newROE || force) {
ROE = newROE;
int ROEEnum;
@ -379,10 +391,10 @@ void Unit::setROE(wstring newROE) {
}
}
void Unit::setReactionToThreat(wstring newReactionToThreat) {
void Unit::setReactionToThreat(wstring newReactionToThreat, bool force) {
addMeasure(L"reactionToThreat", json::value(newReactionToThreat));
if (reactionToThreat != newReactionToThreat) {
if (reactionToThreat != newReactionToThreat || force) {
reactionToThreat = newReactionToThreat;
int reactionToThreatEnum;
@ -404,10 +416,10 @@ void Unit::setReactionToThreat(wstring newReactionToThreat) {
}
}
void Unit::setEmissionsCountermeasures(wstring newEmissionsCountermeasures) {
void Unit::setEmissionsCountermeasures(wstring newEmissionsCountermeasures, bool force) {
addMeasure(L"emissionsCountermeasures", json::value(newEmissionsCountermeasures));
if (emissionsCountermeasures != newEmissionsCountermeasures) {
if (emissionsCountermeasures != newEmissionsCountermeasures || force) {
emissionsCountermeasures = newEmissionsCountermeasures;
int radarEnum;
@ -472,7 +484,7 @@ void Unit::setIsAWACS(bool newIsAWACS) {
setEPLRS(isAWACS);
}
void Unit::setTACAN(Options::TACAN newTACAN) {
void Unit::setTACAN(Options::TACAN newTACAN, bool force) {
auto json = json::value();
json[L"isOn"] = json::value(newTACAN.isOn);
json[L"channel"] = json::value(newTACAN.channel);
@ -480,7 +492,7 @@ void Unit::setTACAN(Options::TACAN newTACAN) {
json[L"callsign"] = json::value(newTACAN.callsign);
addMeasure(L"TACAN", json);
if (TACAN != newTACAN)
if (TACAN != newTACAN || force)
{
TACAN = newTACAN;
if (TACAN.isOn) {
@ -511,7 +523,7 @@ void Unit::setTACAN(Options::TACAN newTACAN) {
}
}
void Unit::setRadio(Options::Radio newRadio) {
void Unit::setRadio(Options::Radio newRadio, bool force) {
auto json = json::value();
json[L"frequency"] = json::value(newRadio.frequency);
@ -519,7 +531,7 @@ void Unit::setRadio(Options::Radio newRadio) {
json[L"callsignNumber"] = json::value(newRadio.callsignNumber);
addMeasure(L"radio", json);
if (radio != newRadio)
if (radio != newRadio || force)
{
radio = newRadio;
@ -551,11 +563,11 @@ void Unit::setRadio(Options::Radio newRadio) {
}
}
void Unit::setEPLRS(bool newEPLRS)
void Unit::setEPLRS(bool newEPLRS, bool force)
{
//addMeasure(L"EPLRS", json::value(newEPLRS));
//
//if (EPLRS != newEPLRS) {
//if (EPLRS != newEPLRS || force) {
// EPLRS = newEPLRS;
//
// std::wostringstream commandSS;
@ -570,7 +582,7 @@ void Unit::setEPLRS(bool newEPLRS)
//}
}
void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings) {
void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings, bool force) {
auto json = json::value();
json[L"prohibitJettison"] = json::value(newGeneralSettings.prohibitJettison);
@ -598,35 +610,47 @@ void Unit::setGeneralSettings(Options::GeneralSettings newGeneralSettings) {
}
}
void Unit::setTargetSpeed(double newTargetSpeed) {
targetSpeed = newTargetSpeed;
addMeasure(L"targetSpeed", json::value(newTargetSpeed));
goToDestination();
void Unit::setDesiredSpeed(double newDesiredSpeed) {
desiredSpeed = newDesiredSpeed;
addMeasure(L"desiredSpeed", json::value(newDesiredSpeed));
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
}
void Unit::setTargetAltitude(double newTargetAltitude) {
targetAltitude = newTargetAltitude;
addMeasure(L"targetAltitude", json::value(newTargetAltitude));
goToDestination();
void Unit::setDesiredAltitude(double newDesiredAltitude) {
desiredAltitude = newDesiredAltitude;
addMeasure(L"desiredAltitude", json::value(newDesiredAltitude));
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
}
void Unit::setTargetSpeedType(wstring newTargetSpeedType) {
targetSpeedType = newTargetSpeedType;
addMeasure(L"targetSpeedType", json::value(newTargetSpeedType));
goToDestination();
void Unit::setDesiredSpeedType(wstring newDesiredSpeedType) {
desiredSpeedType = newDesiredSpeedType;
addMeasure(L"desiredSpeedType", json::value(newDesiredSpeedType));
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
}
void Unit::setTargetAltitudeType(wstring newTargetAltitudeType) {
targetAltitudeType = newTargetAltitudeType;
addMeasure(L"targetAltitudeType", json::value(newTargetAltitudeType));
goToDestination();
void Unit::setDesiredAltitudeType(wstring newDesiredAltitudeType) {
desiredAltitudeType = newDesiredAltitudeType;
addMeasure(L"desiredAltitudeType", json::value(newDesiredAltitudeType));
if (state == State::IDLE)
resetTask();
else
goToDestination(); /* Send the command to reach the destination */
}
void Unit::goToDestination(wstring enrouteTask)
{
if (activeDestination != NULL)
{
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getTargetSpeed(), getTargetSpeedType(), getTargetAltitude(), getTargetAltitudeType(), enrouteTask, getCategory()));
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType(), getDesiredAltitude(), getDesiredAltitudeType(), enrouteTask, getCategory()));
scheduler->appendCommand(command);
setHasTask(true);
}

View File

@ -156,6 +156,14 @@ void UnitsManager::updateMissionData(json::value missionData)
}
}
void UnitsManager::runAILoop() {
/* Run the AI Loop on all units */
for (auto const& unit : units)
{
unit.second->runAILoop();
}
}
void UnitsManager::getData(json::value& answer, long long time)
{
auto unitsJson = json::value::object();
@ -177,3 +185,17 @@ void UnitsManager::deleteUnit(int ID, bool explosion)
}
}
void UnitsManager::acquireControl(int ID) {
Unit* unit = getUnit(ID);
if (unit != nullptr) {
for (auto const& groupMember : getGroupMembers(unit->getGroupName())) {
if (!groupMember->getControlled()) {
groupMember->setControlled(true);
groupMember->setState(State::IDLE);
groupMember->setDefaults(true);
}
}
}
}