diff --git a/client/src/constants/constants.ts b/client/src/constants/constants.ts
index 8eb1663f..fe1a07fc 100644
--- a/client/src/constants/constants.ts
+++ b/client/src/constants/constants.ts
@@ -262,6 +262,7 @@ export enum DataIndexes {
operateAs,
shotsScatter,
shotsIntensity,
+ health,
endOfData = 255
};
diff --git a/client/src/interfaces.ts b/client/src/interfaces.ts
index f1fdb028..9cd04796 100644
--- a/client/src/interfaces.ts
+++ b/client/src/interfaces.ts
@@ -182,6 +182,7 @@ export interface UnitData {
operateAs: string;
shotsScatter: number;
shotsIntensity: number;
+ health: number;
}
export interface LoadoutItemBlueprint {
diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts
index a6a25fe5..5f529327 100644
--- a/client/src/unit/unit.ts
+++ b/client/src/unit/unit.ts
@@ -47,7 +47,6 @@ export class Unit extends CustomMarker {
#onOff: boolean = true;
#followRoads: boolean = false;
#fuel: number = 0;
- #health: number = Math.round(Math.random()*100);
#desiredSpeed: number = 0;
#desiredSpeedType: string = "CAS";
#desiredAltitude: number = 0;
@@ -88,6 +87,7 @@ export class Unit extends CustomMarker {
#operateAs: string = "blue";
#shotsScatter: number = 2;
#shotsIntensity: number = 2;
+ #health: number = 100;
#selectable: boolean;
#selected: boolean = false;
@@ -122,7 +122,6 @@ export class Unit extends CustomMarker {
getHorizontalVelocity() { return this.#horizontalVelocity };
getVerticalVelocity() { return this.#verticalVelocity };
getHeading() { return this.#heading };
- getHealth() { return this.#health };
getIsActiveAWACS() { return this.#isActiveAWACS };
getIsActiveTanker() { return this.#isActiveTanker };
getOnOff() { return this.#onOff };
@@ -147,8 +146,9 @@ export class Unit extends CustomMarker {
getActivePath() { return this.#activePath };
getIsLeader() { return this.#isLeader };
getOperateAs() { return this.#operateAs };
- getShotsScatter() { return this.#shotsScatter};
- getShotsIntensity() { return this.#shotsIntensity};
+ getShotsScatter() { return this.#shotsScatter };
+ getShotsIntensity() { return this.#shotsIntensity };
+ getHealth() { return this.#health };
static getConstructor(type: string) {
if (type === "GroundUnit") return GroundUnit;
@@ -198,9 +198,9 @@ export class Unit extends CustomMarker {
this.#updateMarker();
/* Circles don't like to be updated when the map is zooming */
- if (!getApp().getMap().isZooming())
+ if (!getApp().getMap().isZooming())
this.#drawRanges();
- else
+ else
this.once("zoomend", () => { this.#drawRanges(); })
if (this.getSelected())
@@ -243,7 +243,6 @@ export class Unit extends CustomMarker {
case DataIndexes.onOff: this.#onOff = dataExtractor.extractBool(); break;
case DataIndexes.followRoads: this.#followRoads = dataExtractor.extractBool(); break;
case DataIndexes.fuel: this.#fuel = dataExtractor.extractUInt16(); break;
- // case DataIndexes.health: this.#health = dataExtractor.extractUInt16(); break; // To be dynamic
case DataIndexes.desiredSpeed: this.#desiredSpeed = dataExtractor.extractFloat64(); break;
case DataIndexes.desiredSpeedType: this.#desiredSpeedType = dataExtractor.extractBool() ? "GS" : "CAS"; break;
case DataIndexes.desiredAltitude: this.#desiredAltitude = dataExtractor.extractFloat64(); break;
@@ -265,6 +264,7 @@ export class Unit extends CustomMarker {
case DataIndexes.operateAs: this.#operateAs = enumToCoalition(dataExtractor.extractUInt8()); break;
case DataIndexes.shotsScatter: this.#shotsScatter = dataExtractor.extractUInt8(); break;
case DataIndexes.shotsIntensity: this.#shotsIntensity = dataExtractor.extractUInt8(); break;
+ case DataIndexes.health: this.#health = dataExtractor.extractUInt8(); updateMarker = true; break;
}
}
@@ -336,7 +336,8 @@ export class Unit extends CustomMarker {
isLeader: this.#isLeader,
operateAs: this.#operateAs,
shotsScatter: this.#shotsScatter,
- shotsIntensity: this.#shotsIntensity
+ shotsIntensity: this.#shotsIntensity,
+ health: this.#health
}
}
@@ -398,9 +399,9 @@ export class Unit extends CustomMarker {
this.#selected = selected;
/* Circles don't like to be updated when the map is zooming */
- if (!getApp().getMap().isZooming())
+ if (!getApp().getMap().isZooming())
this.#drawRanges();
- else
+ else
this.once("zoomend", () => { this.#drawRanges(); })
if (selected) {
@@ -635,9 +636,9 @@ export class Unit extends CustomMarker {
this.getElement()?.appendChild(el);
/* Circles don't like to be updated when the map is zooming */
- if (!getApp().getMap().isZooming())
+ if (!getApp().getMap().isZooming())
this.#drawRanges();
- else
+ else
this.once("zoomend", () => { this.#drawRanges(); })
}
@@ -673,9 +674,9 @@ export class Unit extends CustomMarker {
if (!this.getHidden()) {
/* Circles don't like to be updated when the map is zooming */
- if (!getApp().getMap().isZooming())
+ if (!getApp().getMap().isZooming())
this.#drawRanges();
- else
+ else
this.once("zoomend", () => { this.#drawRanges(); })
} else {
this.#clearRanges();
@@ -929,7 +930,7 @@ export class Unit extends CustomMarker {
}
/***********************************************/
- getActions(): { [key: string]: { text: string, tooltip: string, type: string } } {
+ getActions(): { [key: string]: { text: string, tooltip: string, type: string } } {
/* To be implemented by child classes */ // TODO make Unit an abstract class
return {};
}
@@ -1045,14 +1046,14 @@ export class Unit extends CustomMarker {
var options: { [key: string]: { text: string, tooltip: string } } = {};
options = {
- 'trail': { text: "Trail", tooltip: "Follow unit in trail formation" },
- 'echelon-lh': { text: "Echelon (LH)", tooltip: "Follow unit in echelon left formation" },
- 'echelon-rh': { text: "Echelon (RH)", tooltip: "Follow unit in echelon right formation" },
- 'line-abreast-lh': { text: "Line abreast (LH)", tooltip: "Follow unit in line abreast left formation" },
- 'line-abreast-rh': { text: "Line abreast (RH)", tooltip: "Follow unit in line abreast right formation" },
- 'front': { text: "Front", tooltip: "Fly in front of unit" },
- 'diamond': { text: "Diamond", tooltip: "Follow unit in diamond formation" },
- 'custom': { text: "Custom", tooltip: "Set a custom formation position" },
+ 'trail': { text: "Trail", tooltip: "Follow unit in trail formation" },
+ 'echelon-lh': { text: "Echelon (LH)", tooltip: "Follow unit in echelon left formation" },
+ 'echelon-rh': { text: "Echelon (RH)", tooltip: "Follow unit in echelon right formation" },
+ 'line-abreast-lh': { text: "Line abreast (LH)", tooltip: "Follow unit in line abreast left formation" },
+ 'line-abreast-rh': { text: "Line abreast (RH)", tooltip: "Follow unit in line abreast right formation" },
+ 'front': { text: "Front", tooltip: "Fly in front of unit" },
+ 'diamond': { text: "Diamond", tooltip: "Follow unit in diamond formation" },
+ 'custom': { text: "Custom", tooltip: "Set a custom formation position" },
}
getApp().getMap().getUnitContextMenu().setOptions(options, (option: string) => {
@@ -1157,7 +1158,7 @@ export class Unit extends CustomMarker {
else if (!this.#controlled) { // Unit is under DCS control (not Olympus)
element.querySelector(".unit")?.setAttribute("data-state", "dcs");
}
- else if ((this.getCategory() == "Aircraft" || this.getCategory() == "Helicopter") && !this.#hasTask){
+ else if ((this.getCategory() == "Aircraft" || this.getCategory() == "Helicopter") && !this.#hasTask) {
element.querySelector(".unit")?.setAttribute("data-state", "no-task");
}
else { // Unit is under Olympus control
@@ -1325,13 +1326,13 @@ export class Unit extends CustomMarker {
/* Get the acquisition and engagement ranges of the entire group, not for each unit */
if (this.getIsLeader()) {
- var engagementRange = this.getDatabase()?.getByName(this.getName())?.engagementRange?? 0;
- var acquisitionRange = this.getDatabase()?.getByName(this.getName())?.acquisitionRange?? 0;
+ var engagementRange = this.getDatabase()?.getByName(this.getName())?.engagementRange ?? 0;
+ var acquisitionRange = this.getDatabase()?.getByName(this.getName())?.acquisitionRange ?? 0;
this.getGroupMembers().forEach((unit: Unit) => {
if (unit.getAlive()) {
- let unitEngagementRange = unit.getDatabase()?.getByName(unit.getName())?.engagementRange?? 0;
- let unitAcquisitionRange = unit.getDatabase()?.getByName(unit.getName())?.acquisitionRange?? 0;
+ let unitEngagementRange = unit.getDatabase()?.getByName(unit.getName())?.engagementRange ?? 0;
+ let unitAcquisitionRange = unit.getDatabase()?.getByName(unit.getName())?.acquisitionRange ?? 0;
if (unitEngagementRange > engagementRange)
engagementRange = unitEngagementRange;
@@ -1342,12 +1343,12 @@ export class Unit extends CustomMarker {
})
if (acquisitionRange !== this.#acquisitionCircle.getRadius())
- this.#acquisitionCircle.setRadius(acquisitionRange);
+ this.#acquisitionCircle.setRadius(acquisitionRange);
if (engagementRange !== this.#engagementCircle.getRadius())
this.#engagementCircle.setRadius(engagementRange);
- this.#engagementCircle.options.fillOpacity = this.getSelected() && getApp().getMap().getVisibilityOptions()[FILL_SELECTED_RING]? 0.3: 0;
+ this.#engagementCircle.options.fillOpacity = this.getSelected() && getApp().getMap().getVisibilityOptions()[FILL_SELECTED_RING] ? 0.3 : 0;
/* Acquisition circles */
var shortAcquisitionRangeCheck = (acquisitionRange > nmToM(3) || !getApp().getMap().getVisibilityOptions()[HIDE_UNITS_SHORT_RANGE_RINGS]);
@@ -1373,7 +1374,7 @@ export class Unit extends CustomMarker {
if (getApp().getMap().hasLayer(this.#acquisitionCircle))
this.#acquisitionCircle.removeFrom(getApp().getMap());
}
-
+
/* Engagement circles */
var shortEngagementRangeCheck = (engagementRange > nmToM(3) || !getApp().getMap().getVisibilityOptions()[HIDE_UNITS_SHORT_RANGE_RINGS]);
if (getApp().getMap().getVisibilityOptions()[SHOW_UNITS_ENGAGEMENT_RINGS] && shortEngagementRangeCheck && (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, IRST, RWR].includes(value)))) {
diff --git a/scripts/OlympusCommand.lua b/scripts/OlympusCommand.lua
index 7be6dc31..480e907d 100644
--- a/scripts/OlympusCommand.lua
+++ b/scripts/OlympusCommand.lua
@@ -937,11 +937,15 @@ function Olympus.setUnitsData(arg, time)
table["hasTask"] = controller:hasTask()
table["ammo"] = unit:getAmmo() --TODO remove a lot of stuff we don't really need
table["fuel"] = unit:getFuel()
- table["life"] = unit:getLife() / unit:getLife0()
+ table["health"] = unit:getLife() / unit:getLife0() * 100
table["contacts"] = contacts
units[ID] = table
end
+ else
+ -- If the unit reference is nil it means the unit no longer exits
+ units[ID] = {isAlive = false}
+ Olympus.units[ID] = nil
end
end
else
diff --git a/src/core/core.vcxproj b/src/core/core.vcxproj
index 7c46020d..65110b14 100644
--- a/src/core/core.vcxproj
+++ b/src/core/core.vcxproj
@@ -37,7 +37,6 @@
-
@@ -55,7 +54,6 @@
-
diff --git a/src/core/core.vcxproj.filters b/src/core/core.vcxproj.filters
index 56fade36..1878b7a9 100644
--- a/src/core/core.vcxproj.filters
+++ b/src/core/core.vcxproj.filters
@@ -45,9 +45,6 @@
Header Files
-
- Header Files
-
Header Files
@@ -95,9 +92,6 @@
Source Files
-
- Source Files
-
Source Files
diff --git a/src/core/include/datatypes.h b/src/core/include/datatypes.h
index 1ab55cb1..8928ab20 100644
--- a/src/core/include/datatypes.h
+++ b/src/core/include/datatypes.h
@@ -48,6 +48,7 @@ namespace DataIndex {
operateAs,
shotsScatter,
shotsIntensity,
+ health,
lastIndex,
endOfData = 255
};
diff --git a/src/core/include/measure.h b/src/core/include/measure.h
deleted file mode 100644
index 61ff410d..00000000
--- a/src/core/include/measure.h
+++ /dev/null
@@ -1,19 +0,0 @@
-#pragma once
-#include "framework.h"
-
-class Measure
-{
-public:
- Measure(json::value value, long long time): value(value), time(time) {};
-
- void setValue(json::value newValue) { value = newValue; }
- void setTime(long long newTime) { time = newTime; }
- json::value getValue() { return value; }
- long long getTime() { return time; }
-
-private:
- json::value value;
- long long time;
-
-};
-
diff --git a/src/core/include/unit.h b/src/core/include/unit.h
index c85cbf44..a4ee4744 100644
--- a/src/core/include/unit.h
+++ b/src/core/include/unit.h
@@ -3,7 +3,6 @@
#include "utils.h"
#include "dcstools.h"
#include "luatools.h"
-#include "measure.h"
#include "logger.h"
#include "commands.h"
#include "datatypes.h"
@@ -107,6 +106,7 @@ public:
virtual void setOperateAs(unsigned char newValue) { updateValue(operateAs, newValue, DataIndex::operateAs); }
virtual void setShotsScatter(unsigned char newValue) { updateValue(shotsScatter, newValue, DataIndex::shotsScatter); }
virtual void setShotsIntensity(unsigned char newValue) { updateValue(shotsIntensity, newValue, DataIndex::shotsIntensity); }
+ virtual void setHealth(unsigned char newValue) { updateValue(health, newValue, DataIndex::health); }
/********** Getters **********/
virtual string getCategory() { return category; };
@@ -152,6 +152,7 @@ public:
virtual unsigned char getOperateAs() { return operateAs; }
virtual unsigned char getShotsScatter() { return shotsScatter; }
virtual unsigned char getShotsIntensity() { return shotsIntensity; }
+ virtual unsigned char getHealth() { return health; }
protected:
unsigned int ID;
@@ -200,6 +201,7 @@ protected:
Coords activeDestination = Coords(NULL);
unsigned char shotsScatter = 2;
unsigned char shotsIntensity = 2;
+ unsigned char health = 100;
/********** Other **********/
unsigned int taskCheckCounter = 0;
diff --git a/src/core/include/weapon.h b/src/core/include/weapon.h
index a387a111..5ca44170 100644
--- a/src/core/include/weapon.h
+++ b/src/core/include/weapon.h
@@ -3,7 +3,6 @@
#include "utils.h"
#include "dcstools.h"
#include "luatools.h"
-#include "measure.h"
#include "logger.h"
#include "commands.h"
#include "datatypes.h"
diff --git a/src/core/src/measure.cpp b/src/core/src/measure.cpp
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/core/src/unit.cpp b/src/core/src/unit.cpp
index 58ef3a8e..6bcf1b10 100644
--- a/src/core/src/unit.cpp
+++ b/src/core/src/unit.cpp
@@ -137,6 +137,9 @@ void Unit::update(json::value json, double dt)
if (json.has_boolean_field(L"hasTask"))
setHasTask(json[L"hasTask"].as_bool());
+ if (json.has_number_field(L"health"))
+ setHealth(static_cast(json[L"health"].as_number().to_uint32()));
+
runAILoop();
}
@@ -241,49 +244,50 @@ void Unit::getData(stringstream& ss, unsigned long long time)
{
if (checkFreshness(datumIndex, time)) {
switch (datumIndex) {
- case DataIndex::category: appendString(ss, datumIndex, category); break;
- case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
- case DataIndex::human: appendNumeric(ss, datumIndex, human); break;
- case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break;
- case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
- case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
- case DataIndex::name: appendString(ss, datumIndex, name); break;
- case DataIndex::unitName: appendString(ss, datumIndex, unitName); break;
- case DataIndex::groupName: appendString(ss, datumIndex, groupName); break;
- case DataIndex::state: appendNumeric(ss, datumIndex, state); break;
- case DataIndex::task: appendString(ss, datumIndex, task); break;
- case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
- case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
- case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
- case DataIndex::horizontalVelocity: appendNumeric(ss, datumIndex, horizontalVelocity); break;
- case DataIndex::verticalVelocity: appendNumeric(ss, datumIndex, verticalVelocity); break;
- case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
- case DataIndex::isActiveTanker: appendNumeric(ss, datumIndex, isActiveTanker); break;
- case DataIndex::isActiveAWACS: appendNumeric(ss, datumIndex, isActiveAWACS); break;
- case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break;
- case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break;
- case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break;
- case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break;
- case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break;
- case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break;
- case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break;
- case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break;
- case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break;
- case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break;
- case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break;
- case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break;
- case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break;
- case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break;
- case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break;
- case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break;
- case DataIndex::generalSettings: appendNumeric(ss, datumIndex, generalSettings); break;
- case DataIndex::ammo: appendVector(ss, datumIndex, ammo); break;
- case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break;
- case DataIndex::activePath: appendList(ss, datumIndex, activePath); break;
- case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); break;
- case DataIndex::operateAs: appendNumeric(ss, datumIndex, operateAs); break;
- case DataIndex::shotsScatter: appendNumeric(ss, datumIndex, shotsScatter); break;
- case DataIndex::shotsIntensity: appendNumeric(ss, datumIndex, shotsIntensity); break;
+ case DataIndex::category: appendString(ss, datumIndex, category); break;
+ case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
+ case DataIndex::human: appendNumeric(ss, datumIndex, human); break;
+ case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break;
+ case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
+ case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
+ case DataIndex::name: appendString(ss, datumIndex, name); break;
+ case DataIndex::unitName: appendString(ss, datumIndex, unitName); break;
+ case DataIndex::groupName: appendString(ss, datumIndex, groupName); break;
+ case DataIndex::state: appendNumeric(ss, datumIndex, state); break;
+ case DataIndex::task: appendString(ss, datumIndex, task); break;
+ case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
+ case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
+ case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
+ case DataIndex::horizontalVelocity: appendNumeric(ss, datumIndex, horizontalVelocity); break;
+ case DataIndex::verticalVelocity: appendNumeric(ss, datumIndex, verticalVelocity); break;
+ case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
+ case DataIndex::isActiveTanker: appendNumeric(ss, datumIndex, isActiveTanker); break;
+ case DataIndex::isActiveAWACS: appendNumeric(ss, datumIndex, isActiveAWACS); break;
+ case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break;
+ case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break;
+ case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break;
+ case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break;
+ case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break;
+ case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break;
+ case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break;
+ case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break;
+ case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break;
+ case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break;
+ case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break;
+ case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break;
+ case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break;
+ case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break;
+ case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break;
+ case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break;
+ case DataIndex::generalSettings: appendNumeric(ss, datumIndex, generalSettings); break;
+ case DataIndex::ammo: appendVector(ss, datumIndex, ammo); break;
+ case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break;
+ case DataIndex::activePath: appendList(ss, datumIndex, activePath); break;
+ case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); break;
+ case DataIndex::operateAs: appendNumeric(ss, datumIndex, operateAs); break;
+ case DataIndex::shotsScatter: appendNumeric(ss, datumIndex, shotsScatter); break;
+ case DataIndex::shotsIntensity: appendNumeric(ss, datumIndex, shotsIntensity); break;
+ case DataIndex::health: appendNumeric(ss, datumIndex, health); break;
}
}
}