Multiple bug fixes and optimizations

This commit is contained in:
Pax1601
2023-07-28 17:43:31 +02:00
parent bac2c430ef
commit fd7f4b9772
9 changed files with 240 additions and 172 deletions

View File

@@ -616,7 +616,7 @@ export class Map extends L.Map {
#showDestinationCursors() { #showDestinationCursors() {
const singleCursor = !this.#shiftKey; const singleCursor = !this.#shiftKey;
const selectedUnitsCount = getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).length; const selectedUnitsCount = getUnitsManager().getSelectedUnits({ excludeHumans: false, onlyOnePerGroup: true }).length;
if (selectedUnitsCount > 0) { if (selectedUnitsCount > 0) {
if (singleCursor && this.#destinationPreviewCursors.length != 1) { if (singleCursor && this.#destinationPreviewCursors.length != 1) {
this.#hideDestinationCursors(); this.#hideDestinationCursors();

View File

@@ -1,9 +1,9 @@
import { LatLng } from "leaflet"; import { LatLng } from "leaflet";
import { getInfoPopup, getMap, getUnitsManager } from ".."; import { getInfoPopup, getMap } from "..";
import { Airbase } from "./airbase"; import { Airbase } from "./airbase";
import { Bullseye } from "./bullseye"; import { Bullseye } from "./bullseye";
import { BLUE_COMMANDER, GAME_MASTER, RED_COMMANDER } from "../constants/constants"; import { BLUE_COMMANDER, GAME_MASTER, NONE, RED_COMMANDER } from "../constants/constants";
import { setCommandModeOptions } from "../server/server"; import { refreshAll, setCommandModeOptions } from "../server/server";
import { Dropdown } from "../controls/dropdown"; import { Dropdown } from "../controls/dropdown";
import { groundUnitDatabase } from "../unit/groundunitdatabase"; import { groundUnitDatabase } from "../unit/groundunitdatabase";
import { createCheckboxOption, getCheckboxOptions } from "../other/utils"; import { createCheckboxOption, getCheckboxOptions } from "../other/utils";
@@ -16,7 +16,7 @@ export class MissionHandler {
#airbases: { [name: string]: Airbase } = {}; #airbases: { [name: string]: Airbase } = {};
#theatre: string = ""; #theatre: string = "";
#dateAndTime: DateAndTime = {date: {Year: 0, Month: 0, Day: 0}, time: {h: 0, m: 0, s: 0}, startTime: 0, elapsedTime: 0}; #dateAndTime: DateAndTime = {date: {Year: 0, Month: 0, Day: 0}, time: {h: 0, m: 0, s: 0}, startTime: 0, elapsedTime: 0};
#commandModeOptions: CommandModeOptions = {commandMode: "Hide all", restrictSpawns: false, restrictToCoalition: false, setupTime: Infinity, spawnPoints: {red: Infinity, blue: Infinity}, eras: []}; #commandModeOptions: CommandModeOptions = {commandMode: NONE, restrictSpawns: false, restrictToCoalition: false, setupTime: Infinity, spawnPoints: {red: Infinity, blue: Infinity}, eras: []};
#remainingSetupTime: number = 0; #remainingSetupTime: number = 0;
#spentSpawnPoint: number = 0; #spentSpawnPoint: number = 0;
#commandModeDialog: HTMLElement; #commandModeDialog: HTMLElement;
@@ -183,6 +183,15 @@ export class MissionHandler {
} }
#setcommandModeOptions(commandModeOptions: CommandModeOptions) { #setcommandModeOptions(commandModeOptions: CommandModeOptions) {
/* Refresh all the data if we have exited the NONE state */
if (this.#commandModeOptions.commandMode === NONE && commandModeOptions.commandMode !== NONE)
refreshAll();
/* Refresh the page if we have lost Game Master priviledges */
if (this.#commandModeOptions.commandMode === GAME_MASTER && commandModeOptions.commandMode !== GAME_MASTER)
location.reload();
/* Check if any option has changed */
var commandModeOptionsChanged = (!commandModeOptions.eras.every((value: string, idx: number) => {return value === this.getCommandModeOptions().eras[idx]}) || var commandModeOptionsChanged = (!commandModeOptions.eras.every((value: string, idx: number) => {return value === this.getCommandModeOptions().eras[idx]}) ||
commandModeOptions.spawnPoints.red !== this.getCommandModeOptions().spawnPoints.red || commandModeOptions.spawnPoints.red !== this.getCommandModeOptions().spawnPoints.red ||
commandModeOptions.spawnPoints.blue !== this.getCommandModeOptions().spawnPoints.blue || commandModeOptions.spawnPoints.blue !== this.getCommandModeOptions().spawnPoints.blue ||
@@ -195,7 +204,6 @@ export class MissionHandler {
if (commandModeOptionsChanged) { if (commandModeOptionsChanged) {
document.dispatchEvent(new CustomEvent("commandModeOptionsChanged", { detail: this })); document.dispatchEvent(new CustomEvent("commandModeOptionsChanged", { detail: this }));
document.getElementById("command-mode-toolbar")?.classList.remove("hide"); document.getElementById("command-mode-toolbar")?.classList.remove("hide");
const el = document.getElementById("command-mode"); const el = document.getElementById("command-mode");
if (el) { if (el) {

View File

@@ -22,6 +22,8 @@ export class UnitControlPanel extends Panel {
#radioCallsignDropdown: Dropdown; #radioCallsignDropdown: Dropdown;
#optionButtons: { [key: string]: HTMLButtonElement[] } = {} #optionButtons: { [key: string]: HTMLButtonElement[] } = {}
#advancedSettingsDialog: HTMLElement; #advancedSettingsDialog: HTMLElement;
#units: Unit[] = [];
#selectedUnitsTypes: string[] = [];
constructor(ID: string) { constructor(ID: string) {
super(ID); super(ID);
@@ -96,9 +98,11 @@ export class UnitControlPanel extends Panel {
} }
addButtons() { addButtons() {
var units = getUnitsManager().getSelectedUnits(); this.#units = getUnitsManager().getSelectedUnits();
if (units.length < 20) { this.#selectedUnitsTypes = getUnitsManager().getSelectedUnitsTypes();
this.getElement().querySelector("#selected-units-container")?.replaceChildren(...units.map((unit: Unit, index: number) => {
if (this.#units.length < 20) {
this.getElement().querySelector("#selected-units-container")?.replaceChildren(...this.#units.map((unit: Unit, index: number) => {
var button = document.createElement("button"); var button = document.createElement("button");
var callsign = unit.getUnitName() || ""; var callsign = unit.getUnitName() || "";
var label = unit.getDatabase()?.getByName(unit.getName())?.label || unit.getName(); var label = unit.getDatabase()?.getByName(unit.getName())?.label || unit.getName();
@@ -125,37 +129,34 @@ export class UnitControlPanel extends Panel {
update() { update() {
if (this.getVisible()){ if (this.getVisible()){
const element = this.getElement(); const element = this.getElement();
const units = getUnitsManager().getSelectedUnits(); if (element != null && this.#units.length > 0) {
const selectedUnitsTypes = getUnitsManager().getSelectedUnitsTypes();
if (element != null && units.length > 0) {
/* Toggle visibility of control elements */ /* Toggle visibility of control elements */
element.toggleAttribute("data-show-categories-tooltip", selectedUnitsTypes.length > 1); element.toggleAttribute("data-show-categories-tooltip", this.#selectedUnitsTypes.length > 1);
element.toggleAttribute("data-show-speed-slider", selectedUnitsTypes.length == 1); element.toggleAttribute("data-show-speed-slider", this.#selectedUnitsTypes.length == 1);
element.toggleAttribute("data-show-altitude-slider", selectedUnitsTypes.length == 1 && (selectedUnitsTypes.includes("Aircraft") || selectedUnitsTypes.includes("Helicopter"))); element.toggleAttribute("data-show-altitude-slider", this.#selectedUnitsTypes.length == 1 && (this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")));
element.toggleAttribute("data-show-roe", true); element.toggleAttribute("data-show-roe", true);
element.toggleAttribute("data-show-threat", (selectedUnitsTypes.includes("Aircraft") || selectedUnitsTypes.includes("Helicopter")) && !(selectedUnitsTypes.includes("GroundUnit") || selectedUnitsTypes.includes("NavyUnit"))); element.toggleAttribute("data-show-threat", (this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")) && !(this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")));
element.toggleAttribute("data-show-emissions-countermeasures", (selectedUnitsTypes.includes("Aircraft") || selectedUnitsTypes.includes("Helicopter")) && !(selectedUnitsTypes.includes("GroundUnit") || selectedUnitsTypes.includes("NavyUnit"))); element.toggleAttribute("data-show-emissions-countermeasures", (this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")) && !(this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")));
element.toggleAttribute("data-show-on-off", (selectedUnitsTypes.includes("GroundUnit") || selectedUnitsTypes.includes("NavyUnit")) && !(selectedUnitsTypes.includes("Aircraft") || selectedUnitsTypes.includes("Helicopter"))); element.toggleAttribute("data-show-on-off", (this.#selectedUnitsTypes.includes("GroundUnit") || this.#selectedUnitsTypes.includes("NavyUnit")) && !(this.#selectedUnitsTypes.includes("Aircraft") || this.#selectedUnitsTypes.includes("Helicopter")));
element.toggleAttribute("data-show-follow-roads", (selectedUnitsTypes.length == 1 && selectedUnitsTypes.includes("GroundUnit"))); element.toggleAttribute("data-show-follow-roads", (this.#selectedUnitsTypes.length == 1 && this.#selectedUnitsTypes.includes("GroundUnit")));
element.toggleAttribute("data-show-advanced-settings-button", units.length == 1); element.toggleAttribute("data-show-advanced-settings-button", this.#units.length == 1);
/* Flight controls */ if (this.#selectedUnitsTypes.length == 1) {
var desiredAltitude = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitude()}); /* Flight controls */
var desiredAltitudeType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitudeType()}); var desiredAltitude = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitude()});
var desiredSpeed = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeed()}); var desiredAltitudeType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredAltitudeType()});
var desiredSpeedType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeedType()}); var desiredSpeed = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeed()});
var onOff = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getOnOff()}); var desiredSpeedType = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getDesiredSpeedType()});
var followRoads = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getFollowRoads()}); var onOff = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getOnOff()});
var followRoads = getUnitsManager().getSelectedUnitsVariable((unit: Unit) => {return unit.getFollowRoads()});
if (selectedUnitsTypes.length == 1) {
this.#altitudeTypeSwitch.setValue(desiredAltitudeType != undefined? desiredAltitudeType == "AGL": undefined, false); this.#altitudeTypeSwitch.setValue(desiredAltitudeType != undefined? desiredAltitudeType == "AGL": undefined, false);
this.#speedTypeSwitch.setValue(desiredSpeedType != undefined? desiredSpeedType == "GS": undefined, false); this.#speedTypeSwitch.setValue(desiredSpeedType != undefined? desiredSpeedType == "GS": undefined, false);
this.#speedSlider.setMinMax(minSpeedValues[selectedUnitsTypes[0]], maxSpeedValues[selectedUnitsTypes[0]]); this.#speedSlider.setMinMax(minSpeedValues[this.#selectedUnitsTypes[0]], maxSpeedValues[this.#selectedUnitsTypes[0]]);
this.#altitudeSlider.setMinMax(minAltitudeValues[selectedUnitsTypes[0]], maxAltitudeValues[selectedUnitsTypes[0]]); this.#altitudeSlider.setMinMax(minAltitudeValues[this.#selectedUnitsTypes[0]], maxAltitudeValues[this.#selectedUnitsTypes[0]]);
this.#speedSlider.setIncrement(speedIncrements[selectedUnitsTypes[0]]); this.#speedSlider.setIncrement(speedIncrements[this.#selectedUnitsTypes[0]]);
this.#altitudeSlider.setIncrement(altitudeIncrements[selectedUnitsTypes[0]]); this.#altitudeSlider.setIncrement(altitudeIncrements[this.#selectedUnitsTypes[0]]);
this.#speedSlider.setActive(desiredSpeed != undefined); this.#speedSlider.setActive(desiredSpeed != undefined);
if (desiredSpeed != undefined) if (desiredSpeed != undefined)
@@ -172,15 +173,15 @@ export class UnitControlPanel extends Panel {
/* Option buttons */ /* Option buttons */
this.#optionButtons["ROE"].forEach((button: HTMLButtonElement) => { this.#optionButtons["ROE"].forEach((button: HTMLButtonElement) => {
button.classList.toggle("selected", units.every((unit: Unit) => unit.getROE() === button.value)) button.classList.toggle("selected", this.#units.every((unit: Unit) => unit.getROE() === button.value))
}); });
this.#optionButtons["reactionToThreat"].forEach((button: HTMLButtonElement) => { this.#optionButtons["reactionToThreat"].forEach((button: HTMLButtonElement) => {
button.classList.toggle("selected", units.every((unit: Unit) => unit.getReactionToThreat() === button.value)) button.classList.toggle("selected", this.#units.every((unit: Unit) => unit.getReactionToThreat() === button.value))
}); });
this.#optionButtons["emissionsCountermeasures"].forEach((button: HTMLButtonElement) => { this.#optionButtons["emissionsCountermeasures"].forEach((button: HTMLButtonElement) => {
button.classList.toggle("selected", units.every((unit: Unit) => unit.getEmissionsCountermeasures() === button.value)) button.classList.toggle("selected", this.#units.every((unit: Unit) => unit.getEmissionsCountermeasures() === button.value))
}); });
this.#onOffSwitch.setValue(onOff, false); this.#onOffSwitch.setValue(onOff, false);

View File

@@ -1,7 +1,7 @@
import { LatLng } from 'leaflet'; import { LatLng } from 'leaflet';
import { getConnectionStatusPanel, getInfoPopup, getLogPanel, getMissionHandler, getServerStatusPanel, getUnitsManager, getWeaponsManager, setLoginStatus } from '..'; import { getConnectionStatusPanel, getInfoPopup, getLogPanel, getMissionHandler, getServerStatusPanel, getUnitsManager, getWeaponsManager, setLoginStatus } from '..';
import { GeneralSettings, Radio, TACAN } from '../@types/unit'; import { GeneralSettings, Radio, TACAN } from '../@types/unit';
import { ROEs, emissionsCountermeasures, reactionsToThreat } from '../constants/constants'; import { NONE, ROEs, emissionsCountermeasures, reactionsToThreat } from '../constants/constants';
var connected: boolean = false; var connected: boolean = false;
var paused: boolean = false; var paused: boolean = false;
@@ -20,6 +20,13 @@ var password = "";
var sessionHash: string | null = null; var sessionHash: string | null = null;
var lastUpdateTimes: {[key: string]: number} = {} var lastUpdateTimes: {[key: string]: number} = {}
lastUpdateTimes[UNITS_URI] = Date.now();
lastUpdateTimes[WEAPONS_URI] = Date.now();
lastUpdateTimes[LOGS_URI] = Date.now();
lastUpdateTimes[AIRBASES_URI] = Date.now();
lastUpdateTimes[BULLSEYE_URI] = Date.now();
lastUpdateTimes[MISSION_URI] = Date.now();
var demoEnabled = false; var demoEnabled = false;
export function toggleDemoEnabled() { export function toggleDemoEnabled() {
@@ -339,26 +346,6 @@ export function setCommandModeOptions(restrictSpawns: boolean, restrictToCoaliti
} }
export function startUpdate() { export function startUpdate() {
window.setInterval(() => {
if (!getPaused()) {
getAirbases((data: AirbasesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateAirbases(data);
return data.time;
});
}
}, 10000);
window.setInterval(() => {
if (!getPaused()){
getBullseye((data: BullseyesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateBullseyes(data);
return data.time;
});
}
}, 10000);
window.setInterval(() => { window.setInterval(() => {
if (!getPaused()) { if (!getPaused()) {
getMission((data: MissionData) => { getMission((data: MissionData) => {
@@ -370,7 +357,27 @@ export function startUpdate() {
}, 1000); }, 1000);
window.setInterval(() => { window.setInterval(() => {
if (!getPaused()) { if (!getPaused() && getMissionHandler().getCommandModeOptions().commandMode != NONE) {
getAirbases((data: AirbasesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateAirbases(data);
return data.time;
});
}
}, 10000);
window.setInterval(() => {
if (!getPaused() && getMissionHandler().getCommandModeOptions().commandMode != NONE){
getBullseye((data: BullseyesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateBullseyes(data);
return data.time;
});
}
}, 10000);
window.setInterval(() => {
if (!getPaused() && getMissionHandler().getCommandModeOptions().commandMode != NONE) {
getLogs((data: any) => { getLogs((data: any) => {
checkSessionHash(data.sessionHash); checkSessionHash(data.sessionHash);
getLogPanel().appendLogs(data.logs) getLogPanel().appendLogs(data.logs)
@@ -380,7 +387,7 @@ export function startUpdate() {
}, 1000); }, 1000);
window.setInterval(() => { window.setInterval(() => {
if (!getPaused()) { if (!getPaused() && getMissionHandler().getCommandModeOptions().commandMode != NONE) {
getUnits((buffer: ArrayBuffer) => { getUnits((buffer: ArrayBuffer) => {
var time = getUnitsManager()?.update(buffer); var time = getUnitsManager()?.update(buffer);
return time; return time;
@@ -389,7 +396,7 @@ export function startUpdate() {
}, 250); }, 250);
window.setInterval(() => { window.setInterval(() => {
if (!getPaused()) { if (!getPaused() && getMissionHandler().getCommandModeOptions().commandMode != NONE) {
getWeapons((buffer: ArrayBuffer) => { getWeapons((buffer: ArrayBuffer) => {
var time = getWeaponsManager()?.update(buffer); var time = getWeaponsManager()?.update(buffer);
return time; return time;
@@ -398,7 +405,7 @@ export function startUpdate() {
}, 250); }, 250);
window.setInterval(() => { window.setInterval(() => {
if (!getPaused()) { if (!getPaused() && getMissionHandler().getCommandModeOptions().commandMode != NONE) {
getUnits((buffer: ArrayBuffer) => { getUnits((buffer: ArrayBuffer) => {
var time = getUnitsManager()?.update(buffer); var time = getUnitsManager()?.update(buffer);
return time; return time;
@@ -408,9 +415,39 @@ export function startUpdate() {
}, 5000); }, 5000);
} }
export function refreshAll() {
getAirbases((data: AirbasesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateAirbases(data);
return data.time;
});
getBullseye((data: BullseyesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateBullseyes(data);
return data.time;
});
getLogs((data: any) => {
checkSessionHash(data.sessionHash);
getLogPanel().appendLogs(data.logs)
return data.time;
});
getWeapons((buffer: ArrayBuffer) => {
var time = getWeaponsManager()?.update(buffer);
return time;
}, false);
getUnits((buffer: ArrayBuffer) => {
var time = getUnitsManager()?.update(buffer);
return time;
}, true);
}
export function checkSessionHash(newSessionHash: string) { export function checkSessionHash(newSessionHash: string) {
if (sessionHash != null) { if (sessionHash != null) {
if (newSessionHash != sessionHash) if (newSessionHash !== sessionHash)
location.reload(); location.reload();
} }
else else

View File

@@ -406,9 +406,11 @@ export class Unit extends CustomMarker {
el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`); el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`);
el.setAttribute("data-coalition", this.#coalition); el.setAttribute("data-coalition", this.#coalition);
var iconOptions = this.getIconOptions();
// Generate and append elements depending on active options // Generate and append elements depending on active options
// Velocity vector // Velocity vector
if (this.getIconOptions().showVvi) { if (iconOptions.showVvi) {
var vvi = document.createElement("div"); var vvi = document.createElement("div");
vvi.classList.add("unit-vvi"); vvi.classList.add("unit-vvi");
vvi.toggleAttribute("data-rotate-to-heading"); vvi.toggleAttribute("data-rotate-to-heading");
@@ -416,7 +418,7 @@ export class Unit extends CustomMarker {
} }
// Hotgroup indicator // Hotgroup indicator
if (this.getIconOptions().showHotgroup) { if (iconOptions.showHotgroup) {
var hotgroup = document.createElement("div"); var hotgroup = document.createElement("div");
hotgroup.classList.add("unit-hotgroup"); hotgroup.classList.add("unit-hotgroup");
var hotgroupId = document.createElement("div"); var hotgroupId = document.createElement("div");
@@ -426,26 +428,26 @@ export class Unit extends CustomMarker {
} }
// Main icon // Main icon
if (this.getIconOptions().showUnitIcon) { if (iconOptions.showUnitIcon) {
var unitIcon = document.createElement("div"); var unitIcon = document.createElement("div");
unitIcon.classList.add("unit-icon"); unitIcon.classList.add("unit-icon");
var img = document.createElement("img"); var img = document.createElement("img");
img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`; img.src = `/resources/theme/images/units/${this.getMarkerCategory()}.svg`;
img.onload = () => SVGInjector(img); img.onload = () => SVGInjector(img);
unitIcon.appendChild(img); unitIcon.appendChild(img);
unitIcon.toggleAttribute("data-rotate-to-heading", this.getIconOptions().rotateToHeading); unitIcon.toggleAttribute("data-rotate-to-heading", iconOptions.rotateToHeading);
el.append(unitIcon); el.append(unitIcon);
} }
// State icon // State icon
if (this.getIconOptions().showState) { if (iconOptions.showState) {
var state = document.createElement("div"); var state = document.createElement("div");
state.classList.add("unit-state"); state.classList.add("unit-state");
el.appendChild(state); el.appendChild(state);
} }
// Short label // Short label
if (this.getIconOptions().showShortLabel) { if (iconOptions.showShortLabel) {
var shortLabel = document.createElement("div"); var shortLabel = document.createElement("div");
shortLabel.classList.add("unit-short-label"); shortLabel.classList.add("unit-short-label");
shortLabel.innerText = getUnitDatabaseByCategory(this.getMarkerCategory())?.getByName(this.#name)?.shortLabel || ""; shortLabel.innerText = getUnitDatabaseByCategory(this.getMarkerCategory())?.getByName(this.#name)?.shortLabel || "";
@@ -453,7 +455,7 @@ export class Unit extends CustomMarker {
} }
// Fuel indicator // Fuel indicator
if (this.getIconOptions().showFuel) { if (iconOptions.showFuel) {
var fuelIndicator = document.createElement("div"); var fuelIndicator = document.createElement("div");
fuelIndicator.classList.add("unit-fuel"); fuelIndicator.classList.add("unit-fuel");
var fuelLevel = document.createElement("div"); var fuelLevel = document.createElement("div");
@@ -463,7 +465,7 @@ export class Unit extends CustomMarker {
} }
// Ammo indicator // Ammo indicator
if (this.getIconOptions().showAmmo) { if (iconOptions.showAmmo) {
var ammoIndicator = document.createElement("div"); var ammoIndicator = document.createElement("div");
ammoIndicator.classList.add("unit-ammo"); ammoIndicator.classList.add("unit-ammo");
for (let i = 0; i <= 3; i++) for (let i = 0; i <= 3; i++)
@@ -472,7 +474,7 @@ export class Unit extends CustomMarker {
} }
// Unit summary // Unit summary
if (this.getIconOptions().showSummary) { if (iconOptions.showSummary) {
var summary = document.createElement("div"); var summary = document.createElement("div");
summary.classList.add("unit-summary"); summary.classList.add("unit-summary");
var callsign = document.createElement("div"); var callsign = document.createElement("div");
@@ -482,7 +484,7 @@ export class Unit extends CustomMarker {
altitude.classList.add("unit-altitude"); altitude.classList.add("unit-altitude");
var speed = document.createElement("div"); var speed = document.createElement("div");
speed.classList.add("unit-speed"); speed.classList.add("unit-speed");
if (this.getIconOptions().showCallsign) summary.appendChild(callsign); if (iconOptions.showCallsign) summary.appendChild(callsign);
summary.appendChild(altitude); summary.appendChild(altitude);
summary.appendChild(speed); summary.appendChild(speed);
el.appendChild(summary); el.appendChild(summary);
@@ -499,7 +501,7 @@ export class Unit extends CustomMarker {
(hiddenUnits.includes(this.getMarkerCategory())) || (hiddenUnits.includes(this.getMarkerCategory())) ||
(hiddenUnits.includes(this.#coalition)) || (hiddenUnits.includes(this.#coalition)) ||
(!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0) || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0) ||
(getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13)) && (getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13 && (this.belongsToCommandedCoalition() || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0)))) &&
!(this.getSelected()); !(this.getSelected());
this.setHidden(hidden || !this.#alive); this.setHidden(hidden || !this.#alive);

View File

@@ -95,7 +95,7 @@ export class UnitsManager {
if (this.#requestDetectionUpdate && getMissionHandler().getCommandModeOptions().commandMode != GAME_MASTER) { if (this.#requestDetectionUpdate && getMissionHandler().getCommandModeOptions().commandMode != GAME_MASTER) {
for (let ID in this.#units) { for (let ID in this.#units) {
var unit = this.#units[ID]; var unit = this.#units[ID];
if (!unit.belongsToCommandedCoalition()) if (unit.getAlive() && !unit.belongsToCommandedCoalition())
unit.setDetectionMethods(this.getUnitDetectedMethods(unit)); unit.setDetectionMethods(this.getUnitDetectedMethods(unit));
} }
this.#requestDetectionUpdate = false; this.#requestDetectionUpdate = false;
@@ -651,7 +651,8 @@ export class UnitsManager {
var groups = JSON.parse(contents); var groups = JSON.parse(contents);
for (let groupName in groups) { for (let groupName in groups) {
if (groupName !== "" && groups[groupName].length > 0 && groups[groupName].every((unit: any) => {return unit.category == "GroundUnit";})) { if (groupName !== "" && groups[groupName].length > 0 && groups[groupName].every((unit: any) => {return unit.category == "GroundUnit";})) {
var units = groups[groupName].map((unit: any) => {return {unitType: unit.name, location: unit.position}}); var aliveUnits = groups[groupName].filter((unit: any) => {return unit.alive});
var units = aliveUnits.map((unit: any) => {return {unitType: unit.name, location: unit.position}});
getUnitsManager().spawnUnits("GroundUnit", units, groups[groupName][0].coalition, true); getUnitsManager().spawnUnits("GroundUnit", units, groups[groupName][0].coalition, true);
} }
} }
@@ -714,9 +715,9 @@ export class UnitsManager {
#onUnitSelection(unit: Unit) { #onUnitSelection(unit: Unit) {
if (this.getSelectedUnits().length > 0) { if (this.getSelectedUnits().length > 0) {
getMap().setState(MOVE_UNIT);
/* Disable the firing of the selection event for a certain amount of time. This avoids firing many events if many units are selected */ /* Disable the firing of the selection event for a certain amount of time. This avoids firing many events if many units are selected */
if (!this.#selectionEventDisabled) { if (!this.#selectionEventDisabled) {
getMap().setState(MOVE_UNIT);
window.setTimeout(() => { window.setTimeout(() => {
document.dispatchEvent(new CustomEvent("unitsSelection", { detail: this.getSelectedUnits() })); document.dispatchEvent(new CustomEvent("unitsSelection", { detail: this.getSelectedUnits() }));
this.#selectionEventDisabled = false; this.#selectionEventDisabled = false;

View File

@@ -1,6 +1,6 @@
{ {
"server": { "server": {
"address": "localhost", "address": "88.99.250.188",
"port": 30000 "port": 30000
}, },
"authentication": { "authentication": {

View File

@@ -1,6 +1,6 @@
local version = "v0.4.1-alpha" local version = "v0.4.1-alpha"
local debug = true local debug = false
Olympus.OlympusDLL = nil Olympus.OlympusDLL = nil
@@ -53,26 +53,33 @@ function Olympus.getUnitByID(ID)
return Olympus.units[ID]; return Olympus.units[ID];
end end
function Olympus.getCountryIDByCoalition(coalition) function Olympus.getCountryIDByCoalition(coalitionString)
local countryID = 0 for countryName, countryId in pairs(country.id) do
if coalition == 'red' then if coalition.getCountryCoalition(countryId) == Olympus.getCoalitionIDByCoalition(coalitionString) then
countryID = country.id.CJTF_RED return countryId
elseif coalition == 'blue' then end
countryID = country.id.CJTF_BLUE
else
countryID = country.id.UN_PEACEKEEPERS
end end
return countryID return 0
end
function Olympus.getCoalitionIDByCoalition(coalitionString)
local coalitionID = 0
if coalitionString == "red" then
coalitionID = 1
elseif coalitionString == "blue" then
coalitionID = 2
end
return coalitionID
end end
function Olympus.getCoalitionByCoalitionID(coalitionID) function Olympus.getCoalitionByCoalitionID(coalitionID)
local coalition = "neutral" local coalitionString = "neutral"
if coalitionID == 1 then if coalitionID == 1 then
coalition = "red" coalitionString = "red"
elseif coalitionID == 2 then elseif coalitionID == 2 then
coalition = "blue" coalitionString = "blue"
end end
return coalition return coalitionString
end end
-- Builds a valid task depending on the provided options -- Builds a valid task depending on the provided options
@@ -569,10 +576,9 @@ function Olympus.clone(ID, lat, lng, category)
Olympus.debug("Olympus.clone " .. ID .. ", " .. category, 2) Olympus.debug("Olympus.clone " .. ID .. ", " .. category, 2)
local unit = Olympus.getUnitByID(ID) local unit = Olympus.getUnitByID(ID)
if unit then if unit then
local coalition = Olympus.getCoalitionByCoalitionID(unit:getCoalition())
-- TODO: understand category in this script -- TODO: understand category in this script
local spawnTable = { local spawnTable = {
coalition = coalition, coalition = Olympus.getCoalitionByCoalitionID(unit:getCoalition()),
category = category, category = category,
units = { units = {
[1] = { [1] = {
@@ -663,9 +669,7 @@ function Olympus.setUnitsData(arg, time)
index = index + 1 index = index + 1
if index > startIndex then if index > startIndex then
if unit ~= nil then if unit ~= nil then
local table = {} local table = {}
table["category"] = "None"
-- Get the object category in Olympus name -- Get the object category in Olympus name
local objectCategory = unit:getCategory() local objectCategory = unit:getCategory()
if objectCategory == Object.Category.UNIT then if objectCategory == Object.Category.UNIT then
@@ -684,7 +688,7 @@ function Olympus.setUnitsData(arg, time)
end end
-- If the category is handled by Olympus, get the data -- If the category is handled by Olympus, get the data
if table["category"] ~= "None" then if table["category"] ~= nil then
-- Compute unit position and heading -- Compute unit position and heading
local lat, lng, alt = coord.LOtoLL(unit:getPoint()) local lat, lng, alt = coord.LOtoLL(unit:getPoint())
local position = unit:getPosition() local position = unit:getPosition()
@@ -699,34 +703,40 @@ function Olympus.setUnitsData(arg, time)
table["position"]["alt"] = alt table["position"]["alt"] = alt
table["speed"] = mist.vec.mag(unit:getVelocity()) table["speed"] = mist.vec.mag(unit:getVelocity())
table["heading"] = heading table["heading"] = heading
table["isAlive"] = unit:isExist() table["isAlive"] = unit:isExist() and unit:isActive() and unit:getLife() >= 1
-- Get the targets detected by the group controller
local group = unit:getGroup() local group = unit:getGroup()
local controller = group:getController() if group ~= nil then
local controller = group:getController()
local contacts = {} if controller ~= nil then
for det, enum in pairs(Controller.Detection) do -- Get the targets detected by the unit controller
local controllerTargets = unit:getController():getDetectedTargets(enum) local contacts = {}
for i, target in ipairs(controllerTargets) do local unitController = unit:getController()
if target.object ~= nil and target.visible then if unitController ~= nil then
target["detectionMethod"] = det for det, enum in pairs(Controller.Detection) do
contacts[#contacts + 1] = target local controllerTargets = unitController:getDetectedTargets(enum)
for i, target in ipairs(controllerTargets) do
if target ~= nil and target.object ~= nil and target.visible then
target["detectionMethod"] = det
contacts[#contacts + 1] = target
end
end
end
end end
table["country"] = unit:getCountry()
table["unitName"] = unit:getName()
table["groupName"] = group:getName()
table["isHuman"] = (unit:getPlayerName() ~= nil)
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["contacts"] = contacts
units[ID] = table
end end
end end
table["country"] = unit:getCountry()
table["unitName"] = unit:getName()
table["groupName"] = group:getName()
table["isHuman"] = (unit:getPlayerName() ~= nil)
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["contacts"] = contacts
units[ID] = table
end end
else else
units[ID] = {isAlive = false} units[ID] = {isAlive = false}
@@ -762,8 +772,7 @@ function Olympus.setWeaponsData(arg, time)
if index > startIndex then if index > startIndex then
if weapon ~= nil then if weapon ~= nil then
local table = {} local table = {}
table["category"] = "None"
-- Get the object category in Olympus name -- Get the object category in Olympus name
local objectCategory = weapon:getCategory() local objectCategory = weapon:getCategory()
if objectCategory == Object.Category.WEAPON then if objectCategory == Object.Category.WEAPON then
@@ -780,7 +789,7 @@ function Olympus.setWeaponsData(arg, time)
end end
-- If the category is handled by Olympus, get the data -- If the category is handled by Olympus, get the data
if table["category"] ~= "None" then if table["category"] ~= nil then
-- Compute weapon position and heading -- Compute weapon position and heading
local lat, lng, alt = coord.LOtoLL(weapon:getPoint()) local lat, lng, alt = coord.LOtoLL(weapon:getPoint())
local position = weapon:getPosition() local position = weapon:getPosition()
@@ -964,12 +973,16 @@ handler = {}
function handler:onEvent(event) function handler:onEvent(event)
if event.id == 1 then if event.id == 1 then
local weapon = event.weapon local weapon = event.weapon
Olympus.weapons[weapon["id_"]] = weapon if Olympus ~= nil and Olympus.weapons ~= nil then
Olympus.debug("New weapon created " .. weapon["id_"], 2) Olympus.weapons[weapon["id_"]] = weapon
Olympus.debug("New weapon created " .. weapon["id_"], 2)
end
elseif event.id == 15 then elseif event.id == 15 then
local unit = event.initiator local unit = event.initiator
Olympus.units[unit["id_"]] = unit if Olympus ~= nil and Olympus.units ~= nil then
Olympus.debug("New unit created " .. unit["id_"], 2) Olympus.units[unit["id_"]] = unit
Olympus.debug("New unit created " .. unit["id_"], 2)
end
end end
end end
world.addEventHandler(handler) world.addEventHandler(handler)

View File

@@ -85,8 +85,9 @@ void Unit::update(json::value json, double dt)
DataTypes::Ammo ammoItem; DataTypes::Ammo ammoItem;
auto ammoJson = el.second; auto ammoJson = el.second;
ammoItem.quantity = ammoJson[L"count"].as_number().to_uint32(); ammoItem.quantity = ammoJson[L"count"].as_number().to_uint32();
string name = to_string(ammoJson[L"desc"][L"displayName"].as_string()).substr(0, sizeof(ammoItem.name) - 1); string name = to_string(ammoJson[L"desc"][L"displayName"].as_string());
strcpy_s(ammoItem.name, sizeof(ammoItem.name), name.c_str()); name = name.substr(min(name.length(), sizeof(ammoItem.name) - 1));
strcpy_s(ammoItem.name, sizeof(ammoItem.name) - 1, name.c_str());
if (ammoJson[L"desc"].has_number_field(L"guidance")) if (ammoJson[L"desc"].has_number_field(L"guidance"))
ammoItem.guidance = ammoJson[L"desc"][L"guidance"].as_number().to_uint32(); ammoItem.guidance = ammoJson[L"desc"][L"guidance"].as_number().to_uint32();
@@ -211,48 +212,53 @@ void Unit::getData(stringstream& ss, unsigned long long time)
const unsigned char endOfData = DataIndex::endOfData; const unsigned char endOfData = DataIndex::endOfData;
ss.write((const char*)&ID, sizeof(ID)); ss.write((const char*)&ID, sizeof(ID));
for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++) if (!alive) {
{ appendNumeric(ss, DataIndex::alive, alive);
if (checkFreshness(datumIndex, time)) { }
switch (datumIndex) { else {
case DataIndex::category: appendString(ss, datumIndex, category); break; for (unsigned char datumIndex = DataIndex::startOfData + 1; datumIndex < DataIndex::lastIndex; datumIndex++)
case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break; {
case DataIndex::human: appendNumeric(ss, datumIndex, human); break; if (checkFreshness(datumIndex, time)) {
case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break; switch (datumIndex) {
case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break; case DataIndex::category: appendString(ss, datumIndex, category); break;
case DataIndex::country: appendNumeric(ss, datumIndex, country); break; case DataIndex::alive: appendNumeric(ss, datumIndex, alive); break;
case DataIndex::name: appendString(ss, datumIndex, name); break; case DataIndex::human: appendNumeric(ss, datumIndex, human); break;
case DataIndex::unitName: appendString(ss, datumIndex, unitName); break; case DataIndex::controlled: appendNumeric(ss, datumIndex, controlled); break;
case DataIndex::groupName: appendString(ss, datumIndex, groupName); break; case DataIndex::coalition: appendNumeric(ss, datumIndex, coalition); break;
case DataIndex::state: appendNumeric(ss, datumIndex, state); break; case DataIndex::country: appendNumeric(ss, datumIndex, country); break;
case DataIndex::task: appendString(ss, datumIndex, task); break; case DataIndex::name: appendString(ss, datumIndex, name); break;
case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break; case DataIndex::unitName: appendString(ss, datumIndex, unitName); break;
case DataIndex::position: appendNumeric(ss, datumIndex, position); break; case DataIndex::groupName: appendString(ss, datumIndex, groupName); break;
case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break; case DataIndex::state: appendNumeric(ss, datumIndex, state); break;
case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break; case DataIndex::task: appendString(ss, datumIndex, task); break;
case DataIndex::isTanker: appendNumeric(ss, datumIndex, isTanker); break; case DataIndex::hasTask: appendNumeric(ss, datumIndex, hasTask); break;
case DataIndex::isAWACS: appendNumeric(ss, datumIndex, isAWACS); break; case DataIndex::position: appendNumeric(ss, datumIndex, position); break;
case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break; case DataIndex::speed: appendNumeric(ss, datumIndex, speed); break;
case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break; case DataIndex::heading: appendNumeric(ss, datumIndex, heading); break;
case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break; case DataIndex::isTanker: appendNumeric(ss, datumIndex, isTanker); break;
case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break; case DataIndex::isAWACS: appendNumeric(ss, datumIndex, isAWACS); break;
case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break; case DataIndex::onOff: appendNumeric(ss, datumIndex, onOff); break;
case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break; case DataIndex::followRoads: appendNumeric(ss, datumIndex, followRoads); break;
case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break; case DataIndex::fuel: appendNumeric(ss, datumIndex, fuel); break;
case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break; case DataIndex::desiredSpeed: appendNumeric(ss, datumIndex, desiredSpeed); break;
case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break; case DataIndex::desiredSpeedType: appendNumeric(ss, datumIndex, desiredSpeedType); break;
case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break; case DataIndex::desiredAltitude: appendNumeric(ss, datumIndex, desiredAltitude); break;
case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break; case DataIndex::desiredAltitudeType: appendNumeric(ss, datumIndex, desiredAltitudeType); break;
case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break; case DataIndex::leaderID: appendNumeric(ss, datumIndex, leaderID); break;
case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break; case DataIndex::formationOffset: appendNumeric(ss, datumIndex, formationOffset); break;
case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break; case DataIndex::targetID: appendNumeric(ss, datumIndex, targetID); break;
case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break; case DataIndex::targetPosition: appendNumeric(ss, datumIndex, targetPosition); break;
case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break; case DataIndex::ROE: appendNumeric(ss, datumIndex, ROE); break;
case DataIndex::generalSettings: appendNumeric(ss, datumIndex, generalSettings); break; case DataIndex::reactionToThreat: appendNumeric(ss, datumIndex, reactionToThreat); break;
case DataIndex::ammo: appendVector(ss, datumIndex, ammo); break; case DataIndex::emissionsCountermeasures: appendNumeric(ss, datumIndex, emissionsCountermeasures); break;
case DataIndex::contacts: appendVector(ss, datumIndex, contacts); break; case DataIndex::TACAN: appendNumeric(ss, datumIndex, TACAN); break;
case DataIndex::activePath: appendList(ss, datumIndex, activePath); break; case DataIndex::radio: appendNumeric(ss, datumIndex, radio); break;
case DataIndex::isLeader: appendNumeric(ss, datumIndex, isLeader); 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;
}
} }
} }
} }