mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Merge pull request #504 from Pax1601/484-add-life-meter-to-ground-units
484 add life meter to ground units
This commit is contained in:
commit
02a0a9b783
13
client/@types/olympus/index.d.ts
vendored
13
client/@types/olympus/index.d.ts
vendored
@ -659,7 +659,7 @@ declare module "unit/databases/unitdatabase" {
|
||||
[key: string]: UnitBlueprint;
|
||||
};
|
||||
getRoles(): string[];
|
||||
getTypes(): string[];
|
||||
getTypes(unitFilter?: CallableFunction): string[];
|
||||
getEras(): string[];
|
||||
getByRange(range: string): UnitBlueprint[];
|
||||
getByType(type: string): UnitBlueprint[];
|
||||
@ -810,6 +810,7 @@ declare module "controls/unitspawnmenu" {
|
||||
#private;
|
||||
protected showRangeCircles: boolean;
|
||||
protected spawnOptions: UnitSpawnOptions;
|
||||
protected unitTypeFilter: (unit: any) => boolean;
|
||||
constructor(ID: string, unitDatabase: UnitDatabase, orderByRole: boolean);
|
||||
getContainer(): HTMLElement;
|
||||
getVisible(): boolean;
|
||||
@ -849,6 +850,7 @@ declare module "controls/unitspawnmenu" {
|
||||
}
|
||||
export class GroundUnitSpawnMenu extends UnitSpawnMenu {
|
||||
protected showRangeCircles: boolean;
|
||||
protected unitTypeFilter: (unit: any) => boolean;
|
||||
/**
|
||||
*
|
||||
* @param ID - the ID of the HTML element which will contain the context menu
|
||||
@ -856,6 +858,14 @@ declare module "controls/unitspawnmenu" {
|
||||
constructor(ID: string);
|
||||
deployUnits(spawnOptions: UnitSpawnOptions, unitsCount: number): void;
|
||||
}
|
||||
export class AirDefenceUnitSpawnMenu extends GroundUnitSpawnMenu {
|
||||
protected unitTypeFilter: (unit: any) => boolean;
|
||||
/**
|
||||
*
|
||||
* @param ID - the ID of the HTML element which will contain the context menu
|
||||
*/
|
||||
constructor(ID: string);
|
||||
}
|
||||
export class NavyUnitSpawnMenu extends UnitSpawnMenu {
|
||||
/**
|
||||
*
|
||||
@ -1510,6 +1520,7 @@ declare module "map/map" {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
unitIsProtected(unit: Unit): boolean;
|
||||
getMapMarkerControls(): MapMarkerControl[];
|
||||
}
|
||||
}
|
||||
declare module "mission/bullseye" {
|
||||
|
||||
@ -97,6 +97,18 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
/*** Health indicator ***/
|
||||
[data-object|="unit"] .unit-health {
|
||||
background: white;
|
||||
border: var(--unit-health-border-width) solid var(--secondary-dark-steel);
|
||||
border-radius: var(--border-radius-sm);
|
||||
display: none;
|
||||
height: var(--unit-health-height);
|
||||
position: absolute;
|
||||
translate: var(--unit-health-x) var(--unit-health-y);
|
||||
width: var(--unit-health-width);
|
||||
}
|
||||
|
||||
/*** Fuel indicator ***/
|
||||
[data-object|="unit"] .unit-fuel {
|
||||
background: white;
|
||||
@ -109,7 +121,8 @@
|
||||
width: var(--unit-fuel-width);
|
||||
}
|
||||
|
||||
[data-object|="unit"] .unit-fuel-level {
|
||||
[data-object|="unit"] .unit-fuel-level,
|
||||
[data-object|="unit"] .unit-health-level {
|
||||
background-color: var(--secondary-light-grey);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
@ -178,6 +191,7 @@
|
||||
|
||||
/*** Common ***/
|
||||
[data-object|="unit"]:hover .unit-ammo,
|
||||
[data-object|="unit"]:hover .unit-health ,
|
||||
[data-object|="unit"]:hover .unit-fuel {
|
||||
display: flex;
|
||||
}
|
||||
@ -188,13 +202,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-has-low-fuel] .unit-fuel {
|
||||
[data-object|="unit"][data-has-low-fuel] .unit-fuel, [data-object|="unit"][data-has-low-health] .unit-health {
|
||||
animation: pulse 1.5s linear infinite;
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-is-in-hotgroup] .unit-hotgroup,
|
||||
[data-object|="unit"][data-is-selected] .unit-ammo,
|
||||
[data-object|="unit"][data-is-selected] .unit-fuel,
|
||||
[data-object|="unit"][data-is-selected] .unit-health,
|
||||
[data-object|="unit"][data-is-selected] .unit-selected-spotlight {
|
||||
display: flex;
|
||||
}
|
||||
@ -211,6 +226,7 @@
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-coalition="blue"] .unit-fuel-level,
|
||||
[data-object|="unit"][data-coalition="blue"] .unit-health-level,
|
||||
[data-object|="unit"][data-coalition="blue"][data-has-fox-1] .unit-ammo>div:nth-child(1),
|
||||
[data-object|="unit"][data-coalition="blue"][data-has-fox-2] .unit-ammo>div:nth-child(2),
|
||||
[data-object|="unit"][data-coalition="blue"][data-has-fox-3] .unit-ammo>div:nth-child(3),
|
||||
@ -227,6 +243,7 @@
|
||||
}
|
||||
|
||||
[data-object|="unit"][data-coalition="red"] .unit-fuel-level,
|
||||
[data-object|="unit"][data-coalition="red"] .unit-health-level,
|
||||
[data-object|="unit"][data-coalition="red"][data-has-fox-1] .unit-ammo>div:nth-child(1),
|
||||
[data-object|="unit"][data-coalition="red"][data-has-fox-2] .unit-ammo>div:nth-child(2),
|
||||
[data-object|="unit"][data-coalition="red"][data-has-fox-3] .unit-ammo>div:nth-child(3),
|
||||
@ -307,6 +324,19 @@
|
||||
background-image: url("/resources/theme/images/states/awacs.svg");
|
||||
}
|
||||
|
||||
[data-object|="unit"] .unit-health::before {
|
||||
background-image: url("/resources/theme/images/icons/health.svg");
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
content: " ";
|
||||
height: 6px;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
translate: -10px -2px;
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
|
||||
/*** Dead unit ***/
|
||||
[data-object|="unit"][data-is-dead] .unit-selected-spotlight,
|
||||
@ -316,6 +346,7 @@
|
||||
[data-object|="unit"][data-is-dead] .unit-hotgroup-id,
|
||||
[data-object|="unit"][data-is-dead] .unit-state,
|
||||
[data-object|="unit"][data-is-dead] .unit-fuel,
|
||||
[data-object|="unit"][data-is-dead] .unit-health,
|
||||
[data-object|="unit"][data-is-dead] .unit-ammo,
|
||||
[data-object|="unit"][data-is-dead]:hover .unit-fuel,
|
||||
[data-object|="unit"][data-is-dead]:hover .unit-ammo {
|
||||
|
||||
4
client/public/themes/olympus/images/icons/health.svg
Normal file
4
client/public/themes/olympus/images/icons/health.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="6" height="6" viewBox="0 0 6 6" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<line x1="3" y1="4.37115e-08" x2="3" y2="6.00083" stroke="white" stroke-width="2"/>
|
||||
<line x1="6" y1="3" y2="3" stroke="white" stroke-width="2"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 244 B |
@ -67,6 +67,12 @@
|
||||
--unit-height: 50px;
|
||||
--unit-width: 50px;
|
||||
|
||||
--unit-health-border-width: 2px;
|
||||
--unit-health-height: 6px;
|
||||
--unit-health-width: 36px;
|
||||
--unit-health-x: 0px;
|
||||
--unit-health-y: 26px;
|
||||
|
||||
/*** Air units ***/
|
||||
--unit-ammo-gap: calc(2px + var(--unit-stroke-width));
|
||||
--unit-ammo-border-radius: 50%;
|
||||
|
||||
@ -262,6 +262,7 @@ export enum DataIndexes {
|
||||
operateAs,
|
||||
shotsScatter,
|
||||
shotsIntensity,
|
||||
health,
|
||||
endOfData = 255
|
||||
};
|
||||
|
||||
|
||||
@ -86,6 +86,7 @@ export interface UnitSpawnTable {
|
||||
export interface ObjectIconOptions {
|
||||
showState: boolean,
|
||||
showVvi: boolean,
|
||||
showHealth: boolean,
|
||||
showHotgroup: boolean,
|
||||
showUnitIcon: boolean,
|
||||
showShortLabel: boolean,
|
||||
@ -181,6 +182,7 @@ export interface UnitData {
|
||||
operateAs: string;
|
||||
shotsScatter: number;
|
||||
shotsIntensity: number;
|
||||
health: number;
|
||||
}
|
||||
|
||||
export interface LoadoutItemBlueprint {
|
||||
|
||||
@ -18,6 +18,11 @@ var pathIcon = new Icon({
|
||||
iconAnchor: [13, 41]
|
||||
});
|
||||
|
||||
/**
|
||||
* Unit class which controls unit behaviour
|
||||
*
|
||||
* Just about everything is a unit - even missiles!
|
||||
*/
|
||||
export class Unit extends CustomMarker {
|
||||
ID: number;
|
||||
|
||||
@ -82,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;
|
||||
@ -116,8 +122,8 @@ export class Unit extends CustomMarker {
|
||||
getHorizontalVelocity() { return this.#horizontalVelocity };
|
||||
getVerticalVelocity() { return this.#verticalVelocity };
|
||||
getHeading() { return this.#heading };
|
||||
getIsActiveTanker() { return this.#isActiveTanker };
|
||||
getIsActiveAWACS() { return this.#isActiveAWACS };
|
||||
getIsActiveTanker() { return this.#isActiveTanker };
|
||||
getOnOff() { return this.#onOff };
|
||||
getFollowRoads() { return this.#followRoads };
|
||||
getFuel() { return this.#fuel };
|
||||
@ -140,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;
|
||||
@ -191,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())
|
||||
@ -257,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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -279,6 +287,10 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
}
|
||||
|
||||
/** Get unit data collated into an object
|
||||
*
|
||||
* @returns object populated by unit information which can also be retrieved using getters
|
||||
*/
|
||||
getData(): UnitData {
|
||||
return {
|
||||
category: this.getCategory(),
|
||||
@ -324,23 +336,38 @@ export class Unit extends CustomMarker {
|
||||
isLeader: this.#isLeader,
|
||||
operateAs: this.#operateAs,
|
||||
shotsScatter: this.#shotsScatter,
|
||||
shotsIntensity: this.#shotsIntensity
|
||||
shotsIntensity: this.#shotsIntensity,
|
||||
health: this.#health
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @returns string containing the marker category
|
||||
*/
|
||||
getMarkerCategory(): string {
|
||||
return getMarkerCategoryByName(this.getName());
|
||||
}
|
||||
|
||||
/** Get a database of information also in this unit's category
|
||||
*
|
||||
* @returns UnitDatabase
|
||||
*/
|
||||
getDatabase(): UnitDatabase | null {
|
||||
return getUnitDatabaseByCategory(this.getMarkerCategory());
|
||||
}
|
||||
|
||||
/** Get the icon options
|
||||
* Used to configure how the marker appears on the map
|
||||
*
|
||||
* @returns ObjectIconOptions
|
||||
*/
|
||||
getIconOptions(): ObjectIconOptions {
|
||||
// Default values, overloaded by child classes if needed
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: false,
|
||||
showHealth: true,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: false,
|
||||
@ -352,21 +379,29 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
}
|
||||
|
||||
/** Set the unit as alive or dead
|
||||
*
|
||||
* @param newAlive (boolean) true = alive, false = dead
|
||||
*/
|
||||
setAlive(newAlive: boolean) {
|
||||
if (newAlive != this.#alive)
|
||||
document.dispatchEvent(new CustomEvent("unitDeath", { detail: this }));
|
||||
this.#alive = newAlive;
|
||||
}
|
||||
|
||||
/** Set the unit as user-selected
|
||||
*
|
||||
* @param selected (boolean)
|
||||
*/
|
||||
setSelected(selected: boolean) {
|
||||
/* Only alive units can be selected. Some units are not selectable (weapons) */
|
||||
if ((this.#alive || !selected) && this.getSelectable() && this.getSelected() != selected && this.belongsToCommandedCoalition()) {
|
||||
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) {
|
||||
@ -396,27 +431,51 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
}
|
||||
|
||||
/** Is this unit selected?
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
getSelected() {
|
||||
return this.#selected;
|
||||
}
|
||||
|
||||
/** Set whether this unit is selectable
|
||||
*
|
||||
* @param selectable (boolean)
|
||||
*/
|
||||
setSelectable(selectable: boolean) {
|
||||
this.#selectable = selectable;
|
||||
}
|
||||
|
||||
/** Get whether this unit is selectable
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
getSelectable() {
|
||||
return this.#selectable;
|
||||
}
|
||||
|
||||
/** Set the number of the hotgroup to which the unit belongs
|
||||
*
|
||||
* @param hotgroup (number)
|
||||
*/
|
||||
setHotgroup(hotgroup: number | null) {
|
||||
this.#hotgroup = hotgroup;
|
||||
this.#updateMarker();
|
||||
}
|
||||
|
||||
/** Get the unit's hotgroup number
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
getHotgroup() {
|
||||
return this.#hotgroup;
|
||||
}
|
||||
|
||||
/** Set the unit as highlighted
|
||||
*
|
||||
* @param highlighted (boolean)
|
||||
*/
|
||||
setHighlighted(highlighted: boolean) {
|
||||
if (this.getSelectable() && this.#highlighted != highlighted) {
|
||||
this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted);
|
||||
@ -425,18 +484,28 @@ export class Unit extends CustomMarker {
|
||||
}
|
||||
}
|
||||
|
||||
/** Get whether the unit is highlighted or not
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
getHighlighted() {
|
||||
return this.#highlighted;
|
||||
}
|
||||
|
||||
/** Get the other members of the group which this unit is in
|
||||
*
|
||||
* @returns Unit[]
|
||||
*/
|
||||
getGroupMembers() {
|
||||
return Object.values(getApp().getUnitsManager().getUnits()).filter((unit: Unit) => { return unit != this && unit.getGroupName() === this.getGroupName(); });
|
||||
}
|
||||
|
||||
/** Returns whether the user is allowed to command this unit, based on coalition
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
belongsToCommandedCoalition() {
|
||||
if (getApp().getMissionManager().getCommandModeOptions().commandMode !== GAME_MASTER && getApp().getMissionManager().getCommandedCoalition() !== this.#coalition)
|
||||
return false;
|
||||
return true;
|
||||
return (getApp().getMissionManager().getCommandModeOptions().commandMode !== GAME_MASTER && getApp().getMissionManager().getCommandedCoalition() !== this.#coalition) ? false : true;
|
||||
}
|
||||
|
||||
getType() {
|
||||
@ -528,6 +597,16 @@ export class Unit extends CustomMarker {
|
||||
el.append(fuelIndicator);
|
||||
}
|
||||
|
||||
// Health indicator
|
||||
if (iconOptions.showHealth) {
|
||||
var healthIndicator = document.createElement("div");
|
||||
healthIndicator.classList.add("unit-health");
|
||||
var healthLevel = document.createElement("div");
|
||||
healthLevel.classList.add("unit-health-level");
|
||||
healthIndicator.appendChild(healthLevel);
|
||||
el.append(healthIndicator);
|
||||
}
|
||||
|
||||
// Ammo indicator
|
||||
if (iconOptions.showAmmo) {
|
||||
var ammoIndicator = document.createElement("div");
|
||||
@ -557,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(); })
|
||||
}
|
||||
|
||||
@ -595,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();
|
||||
@ -851,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 {};
|
||||
}
|
||||
@ -967,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) => {
|
||||
@ -1065,6 +1144,10 @@ export class Unit extends CustomMarker {
|
||||
element.querySelector(".unit-fuel-level")?.setAttribute("style", `width: ${this.#fuel}%`);
|
||||
element.querySelector(".unit")?.toggleAttribute("data-has-low-fuel", this.#fuel < 20);
|
||||
|
||||
/* Set health data */
|
||||
element.querySelector(".unit-health-level")?.setAttribute("style", `width: ${this.#health}%`);
|
||||
element.querySelector(".unit")?.toggleAttribute("data-has-low-health", this.#health < 20);
|
||||
|
||||
/* Set dead/alive flag */
|
||||
element.querySelector(".unit")?.toggleAttribute("data-is-dead", !this.#alive);
|
||||
|
||||
@ -1075,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
|
||||
@ -1243,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;
|
||||
@ -1260,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]);
|
||||
@ -1291,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)))) {
|
||||
@ -1368,6 +1451,7 @@ export class AirUnit extends Unit {
|
||||
return {
|
||||
showState: belongsToCommandedCoalition,
|
||||
showVvi: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showHealth: false,
|
||||
showHotgroup: belongsToCommandedCoalition,
|
||||
showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value))),
|
||||
@ -1441,6 +1525,7 @@ export class GroundUnit extends Unit {
|
||||
return {
|
||||
showState: belongsToCommandedCoalition,
|
||||
showVvi: false,
|
||||
showHealth: true,
|
||||
showHotgroup: belongsToCommandedCoalition,
|
||||
showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: false,
|
||||
@ -1505,6 +1590,7 @@ export class NavyUnit extends Unit {
|
||||
return {
|
||||
showState: belongsToCommandedCoalition,
|
||||
showVvi: false,
|
||||
showHealth: true,
|
||||
showHotgroup: true,
|
||||
showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: false,
|
||||
|
||||
@ -100,6 +100,7 @@ export class Weapon extends CustomMarker {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: false,
|
||||
showHealth: false,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: true,
|
||||
showShortLabel: false,
|
||||
@ -276,6 +277,7 @@ export class Missile extends Weapon {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: (!this.belongsToCommandedCoalition() && !this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)) && this.getDetectionMethods().some(value => [RADAR, IRST, DLINK].includes(value))),
|
||||
showHealth: false,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: false,
|
||||
@ -308,6 +310,7 @@ export class Bomb extends Weapon {
|
||||
return {
|
||||
showState: false,
|
||||
showVvi: (!this.belongsToCommandedCoalition() && !this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)) && this.getDetectionMethods().some(value => [RADAR, IRST, DLINK].includes(value))),
|
||||
showHealth: false,
|
||||
showHotgroup: false,
|
||||
showUnitIcon: (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
|
||||
showShortLabel: false,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -37,7 +37,6 @@
|
||||
<ClInclude Include="include\airunit.h" />
|
||||
<ClInclude Include="include\commands.h" />
|
||||
<ClInclude Include="include\datatypes.h" />
|
||||
<ClInclude Include="include\measure.h" />
|
||||
<ClInclude Include="include\groundunit.h" />
|
||||
<ClInclude Include="include\helicopter.h" />
|
||||
<ClInclude Include="include\navyunit.h" />
|
||||
@ -55,7 +54,6 @@
|
||||
<ClCompile Include="src\commands.cpp" />
|
||||
<ClCompile Include="src\core.cpp" />
|
||||
<ClCompile Include="src\datatypes.cpp" />
|
||||
<ClCompile Include="src\measure.cpp" />
|
||||
<ClCompile Include="src\groundunit.cpp" />
|
||||
<ClCompile Include="src\helicopter.cpp" />
|
||||
<ClCompile Include="src\navyunit.cpp" />
|
||||
|
||||
@ -45,9 +45,6 @@
|
||||
<ClInclude Include="include\weapon.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\measure.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\datatypes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
@ -95,9 +92,6 @@
|
||||
<ClCompile Include="src\weapon.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\measure.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\datatypes.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
||||
@ -48,6 +48,7 @@ namespace DataIndex {
|
||||
operateAs,
|
||||
shotsScatter,
|
||||
shotsIntensity,
|
||||
health,
|
||||
lastIndex,
|
||||
endOfData = 255
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
};
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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<unsigned char>(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user