Front end tweaks

Added visibility options and server log panel
This commit is contained in:
Pax1601 2023-07-21 17:33:24 +02:00
parent 5613394a2c
commit 4ae72b7c0b
24 changed files with 238 additions and 104 deletions

View File

@ -393,7 +393,7 @@ class DemoDataGenerator {
ret.mission.RTSOptions = {
restrictSpawns: true,
restrictToCoalition: true,
setupTime: 300,
setupTime: 0,
spawnPoints: {
red: 1000,
blue: 400

View File

@ -101,4 +101,17 @@
left: 50%;
translate: -50% 0%;
z-index: 9999;
}
display: flex;
align-items: center;
}
#log-panel {
position: absolute;
right: 0px;
top: 220px;
width: 310px;
height: fit-content;
z-index: 9990;
overflow: hidden;
padding: 10px;
}

View File

@ -7,6 +7,7 @@
@import url("panels/mouseinfo.css");
@import url("panels/unitcontrol.css");
@import url("panels/unitinfo.css");
@import url("panels/logpanel.css");
@import url("other/contextmenus.css");
@import url("other/popup.css");
@import url("markers/airbase.css");
@ -1351,4 +1352,11 @@ input[type=number]::-webkit-outer-spin-button {
[data-coalition="neutral"].ol-contexmenu-button:hover,
[data-coalition="neutral"].ol-contexmenu-button.is-open {
background-color: var(--primary-neutral)
}
#map-type svg,
#map-visibility-options svg {
height: 20px;
width: 20px;
fill: lightgray;
}

View File

@ -0,0 +1,28 @@
#log-panel>div:first-child {
width: 100%;
height: 38px;
display: flex;
justify-content: space-between;
align-items: center;
cursor: pointer;
}
#log-panel svg {
pointer-events: none;
}
#log-panel>div:nth-child(2) {
display: none;
margin-top: 5px;
width: 100%;
height: calc(100% - 40px);
background-color: #00000055;
}
#log-panel.open {
height: 505px;
}
#log-panel.open>div:nth-child(2) {
display: block;
}

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M288 32c-80.8 0-145.5 36.8-192.6 80.6C48.6 156 17.3 208 2.5 243.7c-3.3 7.9-3.3 16.7 0 24.6C17.3 304 48.6 356 95.4 399.4C142.5 443.2 207.2 480 288 480s145.5-36.8 192.6-80.6c46.8-43.5 78.1-95.4 93-131.1c3.3-7.9 3.3-16.7 0-24.6c-14.9-35.7-46.2-87.7-93-131.1C433.5 68.8 368.8 32 288 32zM144 256a144 144 0 1 1 288 0 144 144 0 1 1 -288 0zm144-64c0 35.3-28.7 64-64 64c-7.1 0-13.9-1.2-20.3-3.3c-5.5-1.8-11.9 1.6-11.7 7.4c.3 6.9 1.3 13.8 3.2 20.7c13.7 51.2 66.4 81.6 117.6 67.9s81.6-66.4 67.9-117.6c-11.1-41.5-47.8-69.4-88.6-71.1c-5.8-.2-9.2 6.1-7.4 11.7c2.1 6.4 3.3 13.2 3.3 20.3z"/></svg>

After

Width:  |  Height:  |  Size: 820 B

View File

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -18,7 +18,7 @@ interface CustomEventMap {
"groupDeletion": CustomEvent<Unit[]>,
"mapStateChanged": CustomEvent<string>,
"mapContextMenu": CustomEvent<>,
"visibilityModeChanged": CustomEvent<string>,
"mapVisibilityOptionsChanged": CustomEvent<>,
"RTSOptionsChanged": CustomEvent<>,
"contactsUpdated": CustomEvent<Unit>,
}

View File

@ -145,6 +145,11 @@ export const visibilityControlsTootlips: string[] = ["Toggle human players visib
export const IADSTypes = ["AAA", "MANPADS", "SAM Site", "Radar"];
export const IADSDensities: {[key: string]: number}= {"AAA": 0.8, "MANPADS": 0.3, "SAM Site": 0.1, "Radar": 0.05};
export const SHOW_CONTACT_LINES = "Show unit contact lines";
export const HIDE_GROUP_MEMBERS = "Hide group members when zoomed out";
export const SHOW_UNIT_PATHS = "Show unit paths";
export const SHOW_UNIT_TARGETS = "Show unit targets";
export enum DataIndexes {
startOfData = 0,
category,

View File

@ -562,7 +562,7 @@ export class MapContextMenu extends ContextMenu {
}
#computeSpawnPoints() {
if (getMissionHandler()){
if (getMissionHandler() && getUnitsManager().getCommandMode() !== GAME_MASTER){
var aircraftCount = parseInt(this.#aircraftCountDropdown.getValue());
var aircraftSpawnPoints = aircraftCount * aircraftDatabase.getSpawnPointsByLabel(this.#aircraftLabelDropdown.getValue());
(<HTMLButtonElement>this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).dataset.points = `${aircraftSpawnPoints}`;

View File

@ -58,8 +58,8 @@ function setup() {
serverStatusPanel = new ServerStatusPanel("server-status-panel");
mouseInfoPanel = new MouseInfoPanel("mouse-info-panel");
hotgroupPanel = new HotgroupPanel("hotgroup-panel");
logPanel = new LogPanel("log-panel");
/* Popups */
infoPopup = new Popup("info-popup");

View File

@ -7,18 +7,16 @@ import { AirbaseContextMenu } from "../controls/airbasecontextmenu";
import { Dropdown } from "../controls/dropdown";
import { Airbase } from "../missionhandler/airbase";
import { Unit } from "../units/unit";
import { bearing } from "../other/utils";
import { bearing, createCheckboxOption } from "../other/utils";
import { DestinationPreviewMarker } from "./destinationpreviewmarker";
import { TemporaryUnitMarker } from "./temporaryunitmarker";
import { ClickableMiniMap } from "./clickableminimap";
import { SVGInjector } from '@tanem/svg-injector'
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTootlips, FIRE_AT_AREA, MOVE_UNIT, CARPET_BOMBING, BOMBING } from "../constants/constants";
import { layers as mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTootlips, FIRE_AT_AREA, MOVE_UNIT, CARPET_BOMBING, BOMBING, SHOW_CONTACT_LINES, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS } from "../constants/constants";
import { TargetMarker } from "./targetmarker";
import { CoalitionArea } from "./coalitionarea";
import { CoalitionAreaContextMenu } from "../controls/coalitionareacontextmenu";
import { DrawingCursor } from "./drawingcursor";
import { aircraftDatabase } from "../units/aircraftdatabase";
import { groundUnitDatabase } from "../units/groundunitdatabase";
L.Map.addInitHook('addHandler', 'boxSelect', BoxSelect);
@ -47,7 +45,7 @@ export class Map extends L.Map {
#temporaryMarkers: TemporaryUnitMarker[] = [];
#selecting: boolean = false;
#isZooming: boolean = false;
#destinationGroupRotation: number = 0;
#computeDestinationRotation: boolean = false;
#destinationRotationCenter: L.LatLng | null = null;
@ -63,7 +61,9 @@ export class Map extends L.Map {
#coalitionAreaContextMenu: CoalitionAreaContextMenu = new CoalitionAreaContextMenu("coalition-area-contextmenu");
#mapSourceDropdown: Dropdown;
#mapVisibilityOptionsDropdown: Dropdown;
#optionButtons: { [key: string]: HTMLButtonElement[] } = {}
#visibiityOptions: { [key: string]: boolean } = {}
constructor(ID: string) {
/* Init the leaflet map */
@ -86,7 +86,10 @@ export class Map extends L.Map {
L.control.scalenautic({ position: "topright", maxWidth: 300, nautic: true, metric: true, imperial: false }).addTo(this);
/* Map source dropdown */
this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers())
this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers());
/* Visibility options dropdown */
this.#mapVisibilityOptionsDropdown = new Dropdown("map-visibility-options", () => {});
/* Init the state machine */
this.#state = IDLE;
@ -123,9 +126,7 @@ export class Map extends L.Map {
document.addEventListener("toggleCoalitionAreaDraw", (ev: CustomEventInit) => {
const el = ev.detail._element;
/* Add listener to set the button to off if the state changes */
document.addEventListener("mapStateChanged", () => el?.classList.toggle("off", !(this.getState() === COALITIONAREA_DRAW_POLYGON)));
this.getMapContextMenu().hide();
this.deselectAllCoalitionAreas();
if (ev.detail?.type == "polygon") {
if (this.getState() !== COALITIONAREA_DRAW_POLYGON)
@ -152,6 +153,18 @@ export class Map extends L.Map {
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTootlips[index], "toggleUnitVisibility", `{"type": "${option}"}`);
});
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
/* Create the checkboxes to select the advanced visibility options */
this.#visibiityOptions[SHOW_CONTACT_LINES] = false;
this.#visibiityOptions[HIDE_GROUP_MEMBERS] = true;
this.#visibiityOptions[SHOW_UNIT_PATHS] = true;
this.#visibiityOptions[SHOW_UNIT_TARGETS] = true;
this.#mapVisibilityOptionsDropdown.setOptionsElements(Object.keys(this.#visibiityOptions).map((option: string) => {
return createCheckboxOption(option, option, this.#visibiityOptions[option], (ev: any) => {
this.#setVisibilityOption(option, ev);
});
}));
}
setLayer(layerName: string) {
@ -410,6 +423,10 @@ export class Map extends L.Map {
this.#coalitionAreas.unshift(coalitionArea);
}
getVisibilityOptions() {
return this.#visibiityOptions;
}
/* Event handlers */
#onClick(e: any) {
if (!this.#preventLeftClick) {
@ -694,5 +711,10 @@ export class Map extends L.Map {
else if (this.#state === COALITIONAREA_DRAW_POLYGON) this.#showDrawingCursor();
}
}
#setVisibilityOption(option: string, ev: any) {
this.#visibiityOptions[option] = ev.currentTarget.checked;
document.dispatchEvent(new CustomEvent("mapVisibilityOptionsChanged"));
}
}

View File

@ -119,10 +119,7 @@ export class MissionHandler {
return 0;
}
refreshSpawnPoints() {
if (getUnitsManager().getCommandMode() === GAME_MASTER)
document.querySelector("#spawn-points-container")?.classList.add("hide");
refreshSpawnPoints() {
var spawnPointsEl = document.querySelector("#spawn-points");
if (spawnPointsEl) {
spawnPointsEl.textContent = `${this.getAvailableSpawnPoints()}`;
@ -193,6 +190,9 @@ export class MissionHandler {
el.textContent = RTSOptions.commandMode.toUpperCase();
}
}
document.querySelector("#spawn-points-container")?.classList.toggle("hide", getUnitsManager().getCommandMode() === GAME_MASTER);
document.querySelector("#rts-settings-button")?.classList.toggle("hide", getUnitsManager().getCommandMode() !== GAME_MASTER);
}
#onAirbaseClick(e: any) {

View File

@ -366,7 +366,7 @@ export function convertDateAndTimeToDate(dateAndTime: DateAndTime) {
return new Date(year, month, date.Day, time.h, time.m, time.s);
}
export function createCheckboxOption(value: string, text: string, checked: boolean = true) {
export function createCheckboxOption(value: string, text: string, checked: boolean = true, callback: CallableFunction = (ev: any) => {}) {
var div = document.createElement("div");
div.classList.add("ol-checkbox");
var label = document.createElement("label");
@ -379,6 +379,7 @@ export function createCheckboxOption(value: string, text: string, checked: boole
label.appendChild(input);
label.appendChild(span);
div.appendChild(label);
input.onclick = (ev: any) => callback(ev);
return div as HTMLElement;
}

View File

@ -1,28 +1,65 @@
import { Panel } from "./panel";
export class LogPanel extends Panel
{
#logs: String[];
export class LogPanel extends Panel {
#open: boolean = false;
#queuedMessages: number = 0;
#scrolledDown: boolean = true;
constructor(ID: string)
{
constructor(ID: string) {
super(ID);
this.#logs = [];
document.addEventListener("toggleLogPanel", () => {
this.getElement().classList.toggle("open");
this.#open = !this.#open;
this.#queuedMessages = 0;
this.#updateHeader();
if (this.#scrolledDown)
this.#scrollDown();
});
const scrollEl = this.getElement().querySelector(".ol-scrollable");
if (scrollEl) {
scrollEl.addEventListener("scroll", () => {
this.#scrolledDown = Math.abs(scrollEl.scrollHeight - scrollEl.scrollTop - scrollEl.clientHeight) < 1
})
}
}
update(data: any)
{
var logs = data["logs"];
for (let idx in logs)
{
if (parseInt(idx) >= this.#logs.length) {
this.#logs.push(logs[idx]);
var el = document.createElement("div");
el.innerText = logs[idx];
el.classList.add("js-log-element", "ol-log-element");
this.getElement().appendChild(el);
this.getElement().scrollTop = this.getElement().scrollHeight;
}
appendLogs(logs: string[]) {
logs.forEach((log: string) => this.appendLog(log));
}
appendLog(log: string) {
var el = document.createElement("div");
el.classList.add("ol-log-entry");
el.textContent = log;
this.getElement().querySelector(".ol-scrollable")?.appendChild(el);
console.log(log);
if (!this.#open)
this.#queuedMessages++;
this.#updateHeader();
if (this.#scrolledDown)
this.#scrollDown();
}
#updateHeader() {
const headerEl = this.getElement().querySelector("#log-panel-header") as HTMLElement;
if (headerEl) {
if (this.#queuedMessages)
headerEl.innerText = `Server log (${this.#queuedMessages})`;
else
headerEl.innerText = `Server log`;
}
}
#scrollDown() {
const scrollEl = this.getElement().querySelector(".ol-scrollable");
if (scrollEl) {
scrollEl.scrollTop = scrollEl.scrollHeight - scrollEl.clientHeight;
}
}
}

View File

@ -1,5 +1,5 @@
import { LatLng } from 'leaflet';
import { getConnectionStatusPanel, getInfoPopup, getMissionHandler, getServerStatusPanel, getUnitDataTable, getUnitsManager, setLoginStatus } from '..';
import { getConnectionStatusPanel, getInfoPopup, getLogPanel, getMissionHandler, getServerStatusPanel, getUnitDataTable, getUnitsManager, setLoginStatus } from '..';
import { GeneralSettings, Radio, TACAN } from '../@types/unit';
import { ROEs, emissionsCountermeasures, reactionsToThreat } from '../constants/constants';
@ -338,18 +338,20 @@ export function startUpdate() {
getAirbases((data: AirbasesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateAirbases(data);
return data.time;
});
getBullseye((data: BullseyesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateBullseyes(data);
return data.time;
});
getMission((data: MissionData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateMission(data);
return data.time;
});
getLogs((data: any) => {
for (let key in data.logs)
console.log(data.logs[key]);
getLogPanel().appendLogs(Object.values(data.logs))
return data.time;
});
getUnits((buffer: ArrayBuffer) => {return getUnitsManager()?.update(buffer), true /* Does a full refresh */});
@ -374,18 +376,20 @@ export function requestRefresh() {
getAirbases((data: AirbasesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateAirbases(data);
return data.time;
});
getBullseye((data: BullseyesData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateBullseyes(data);
return data.time;
});
getMission((data: MissionData) => {
checkSessionHash(data.sessionHash);
getMissionHandler()?.updateMission(data);
return data.time;
});
getLogs((data: any) => {
for (let key in data.logs)
console.log(data.logs[key]);
getLogPanel().appendLogs(Object.values(data.logs))
return data.time;
});

View File

@ -6,7 +6,7 @@ import { CustomMarker } from '../map/custommarker';
import { SVGInjector } from '@tanem/svg-injector';
import { UnitDatabase } from './unitdatabase';
import { TargetMarker } from '../map/targetmarker';
import { BOMBING, CARPET_BOMBING, DLINK, DataIndexes, FIRE_AT_AREA, GAME_MASTER, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, ROEs, RWR, VISUAL, emissionsCountermeasures, reactionsToThreat, states } from '../constants/constants';
import { BOMBING, CARPET_BOMBING, DLINK, DataIndexes, FIRE_AT_AREA, GAME_MASTER, HIDE_GROUP_MEMBERS, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, ROEs, RWR, SHOW_CONTACT_LINES, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, VISUAL, emissionsCountermeasures, reactionsToThreat, states } from '../constants/constants';
import { Ammo, Contact, GeneralSettings, Offset, Radio, TACAN, UnitIconOptions } from '../@types/unit';
import { DataExtractor } from './dataextractor';
import { groundUnitDatabase } from './groundunitdatabase';
@ -166,7 +166,13 @@ export class Unit extends CustomMarker {
document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => {
window.setTimeout(() => { this.setSelected(this.getSelected() && !this.getHidden()) }, 300);
});
});
document.addEventListener("mapVisibilityOptionsChanged", (ev: CustomEventInit) => {
this.#updateMarker();
if (this.getSelected())
this.drawLines();
});
}
getCategory() {
@ -495,7 +501,7 @@ export class Unit extends CustomMarker {
(hiddenUnits.includes(this.getMarkerCategory())) ||
(hiddenUnits.includes(this.#coalition)) ||
(!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0) ||
(!this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13)) &&
(getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getMap().getZoom() < 13)) &&
!(this.getSelected());
this.setHidden(hidden || !this.#alive);
@ -925,7 +931,7 @@ export class Unit extends CustomMarker {
}
#drawPath() {
if (this.#activePath != undefined) {
if (this.#activePath != undefined && getMap().getVisibilityOptions()[SHOW_UNIT_PATHS]) {
var points = [];
points.push(new LatLng(this.#position.lat, this.#position.lng));
@ -952,6 +958,9 @@ export class Unit extends CustomMarker {
if (points.length == 1)
this.#clearPath();
}
else {
this.#clearPath();
}
}
#clearPath() {
@ -964,34 +973,36 @@ export class Unit extends CustomMarker {
#drawContacts() {
this.#clearContacts();
for (let index in this.#contacts) {
var contactData = this.#contacts[index];
var contact = getUnitsManager().getUnitByID(contactData.ID)
if (contact != null && contact.getAlive()) {
var startLatLng = new LatLng(this.#position.lat, this.#position.lng);
var endLatLng: LatLng;
if (contactData.detectionMethod === RWR) {
var bearingToContact = bearing(this.#position.lat, this.#position.lng, contact.#position.lat, contact.#position.lng);
var startXY = getMap().latLngToContainerPoint(startLatLng);
var endX = startXY.x + 80 * Math.sin(deg2rad(bearingToContact));
var endY = startXY.y - 80 * Math.cos(deg2rad(bearingToContact));
endLatLng = getMap().containerPointToLatLng(new Point(endX, endY));
}
else
endLatLng = new LatLng(contact.#position.lat, contact.#position.lng);
if (getMap().getVisibilityOptions()[SHOW_CONTACT_LINES]) {
for (let index in this.#contacts) {
var contactData = this.#contacts[index];
var contact = getUnitsManager().getUnitByID(contactData.ID)
if (contact != null && contact.getAlive()) {
var startLatLng = new LatLng(this.#position.lat, this.#position.lng);
var endLatLng: LatLng;
if (contactData.detectionMethod === RWR) {
var bearingToContact = bearing(this.#position.lat, this.#position.lng, contact.#position.lat, contact.#position.lng);
var startXY = getMap().latLngToContainerPoint(startLatLng);
var endX = startXY.x + 80 * Math.sin(deg2rad(bearingToContact));
var endY = startXY.y - 80 * Math.cos(deg2rad(bearingToContact));
endLatLng = getMap().containerPointToLatLng(new Point(endX, endY));
}
else
endLatLng = new LatLng(contact.#position.lat, contact.#position.lng);
var color;
if (contactData.detectionMethod === VISUAL || contactData.detectionMethod === OPTIC)
color = "#FF00FF";
else if (contactData.detectionMethod === RADAR || contactData.detectionMethod === IRST)
color = "#FFFF00";
else if (contactData.detectionMethod === RWR)
color = "#00FF00";
else
color = "#FFFFFF";
var contactPolyline = new Polyline([startLatLng, endLatLng], { color: color, weight: 3, opacity: 1, smoothFactor: 1, dashArray: "4, 8" });
contactPolyline.addTo(getMap());
this.#contactsPolylines.push(contactPolyline)
var color;
if (contactData.detectionMethod === VISUAL || contactData.detectionMethod === OPTIC)
color = "#FF00FF";
else if (contactData.detectionMethod === RADAR || contactData.detectionMethod === IRST)
color = "#FFFF00";
else if (contactData.detectionMethod === RWR)
color = "#00FF00";
else
color = "#FFFFFF";
var contactPolyline = new Polyline([startLatLng, endLatLng], { color: color, weight: 3, opacity: 1, smoothFactor: 1, dashArray: "4, 8" });
contactPolyline.addTo(getMap());
this.#contactsPolylines.push(contactPolyline)
}
}
}
}
@ -1003,20 +1014,20 @@ export class Unit extends CustomMarker {
}
#drawTarget() {
if (this.#targetPosition.lat != 0 && this.#targetPosition.lng != 0) {
this.#drawtargetPosition(this.#targetPosition);
if (this.#targetPosition.lat != 0 && this.#targetPosition.lng != 0 && getMap().getVisibilityOptions()[SHOW_UNIT_PATHS]) {
this.#drawTargetPosition(this.#targetPosition);
}
else if (this.#targetID != 0) {
else if (this.#targetID != 0 && getMap().getVisibilityOptions()[SHOW_UNIT_TARGETS]) {
const target = getUnitsManager().getUnitByID(this.#targetID);
if (target && (getUnitsManager().getCommandMode() == GAME_MASTER || (this.belongsToCommandedCoalition() && getUnitsManager().getUnitDetectedMethods(target).some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))))) {
this.#drawtargetPosition(target.getPosition());
this.#drawTargetPosition(target.getPosition());
}
}
else
this.#clearTarget();
}
#drawtargetPosition(targetPosition: LatLng) {
#drawTargetPosition(targetPosition: LatLng) {
if (!getMap().hasLayer(this.#targetPositionMarker))
this.#targetPositionMarker.addTo(getMap());
if (!getMap().hasLayer(this.#targetPositionPolyline))

View File

@ -36,7 +36,6 @@ export class UnitDatabase {
var filteredBlueprints: { [key: string]: UnitBlueprint } = {};
for (let unit in this.blueprints) {
const blueprint = this.blueprints[unit];
console.log(blueprint.era)
if (this.getSpawnPointsByName(blueprint.name) < getMissionHandler().getAvailableSpawnPoints() &&
getMissionHandler().getRTSOptions().eras.includes(blueprint.era) &&
(!getMissionHandler().getRTSOptions().restrictToCoalition || blueprint.coalition === getUnitsManager().getCommandedCoalition())) {

View File

@ -701,21 +701,21 @@ export class UnitsManager {
getInfoPopup().setText("Helicopters can be air spawned during the SETUP phase only");
return false;
}
spawnPoints = units.reduce((unit: any, points: number) => {return points + helicopterDatabase.getSpawnPointsByName(unit.unitType)}, 0);
spawnPoints = units.reduce((points: number, unit: any) => {return points + helicopterDatabase.getSpawnPointsByName(unit.unitType)}, 0);
spawnHelicopters(units, coalition, airbase, immediate, spawnPoints);
} else if (category === "GroundUnit") {
if (getMissionHandler().getRemainingSetupTime() < 0 && this.getCommandMode() !== GAME_MASTER) {
getInfoPopup().setText("Ground units can be spawned during the SETUP phase only");
return false;
}
spawnPoints = units.reduce((unit: any, points: number) => {return points + groundUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
spawnPoints = units.reduce((points: number, unit: any) => {return points + groundUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
spawnGroundUnits(units, coalition, immediate, spawnPoints);
} else if (category === "NavyUnit") {
if (getMissionHandler().getRemainingSetupTime() < 0 && this.getCommandMode() !== GAME_MASTER) {
getInfoPopup().setText("Navy units can be spawned during the SETUP phase only");
return false;
}
spawnPoints = units.reduce((unit: any, points: number) => {return points + navyUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
spawnPoints = units.reduce((points: number, unit: any) => {return points + navyUnitDatabase.getSpawnPointsByName(unit.unitType)}, 0);
spawnNavyUnits(units, coalition, immediate, spawnPoints);
}
if (spawnPoints <= getMissionHandler().getAvailableSpawnPoints()) {

View File

@ -26,6 +26,7 @@
<%- include('panels/connectionstatus.ejs') %>
<%- include('panels/serverstatus.ejs') %>
<%- include('panels/hotgroup.ejs') %>
<%- include('panels/logpanel.ejs') %>
<div id="toolbar-container">
<%- include('toolbars/primary.ejs') %>

View File

@ -1,3 +0,0 @@
<div id="log-panel" class="ol-panel">
<!-- Log entries go here -->
</div>

View File

@ -15,15 +15,15 @@
</div>
<div id="more-options-button-bar" class="upper-bar ol-panel hide">
<div id="coalition-switch" class="ol-switch ol-coalition-switch"></div>
<button data-coalition="blue" id="navyunit-spawn-button" title="Spawn navy unit" data-on-click="mapContextMenuShow"
data-on-click-params='{ "type": "navyunit" }' class="ol-contexmenu-button"><img src="/resources/theme/images/buttons/spawn/navyunit.svg" inject-svg></button>
<button data-coalition="blue" id="smoke-spawn-button" title="Spawn smoke" data-on-click="mapContextMenuShow"
data-on-click-params='{ "type": "smoke" }' class="ol-contexmenu-button"><img src="/resources/theme/images/buttons/spawn/smoke.svg" inject-svg></button>
<button data-coalition="blue" id="explosion-spawn-button" title="Explosion" data-on-click="mapContextMenuShow"
data-on-click-params='{ "type": "explosion" }' class="ol-contexmenu-button"><img src="/resources/theme/images/buttons/spawn/explosion.svg" inject-svg></button>
</div>
<button data-coalition="blue" id="polygon-draw-button" title="Enter polygon draw mode" data-on-click="toggleCoalitionAreaDraw"
data-on-click-params='{"type": "polygon"}' class="ol-contexmenu-button"><img src="resources/theme/images/buttons/tools/draw-polygon-solid.svg" inject-svg></button>
</div>
<div id="aircraft-spawn-menu" class="ol-contexmenu-panel ol-panel hide">
<div class="ol-select-container">
<div id="aircraft-role-options" class="ol-select">

View File

@ -0,0 +1,5 @@
<div id="log-panel" oncontextmenu="return false;">
<div class="ol-panel" data-on-click="toggleLogPanel"><div id="log-panel-header">Server log</div><img src="/resources/theme/images/icons/chevron-down.svg" inject-svg></div>
<div class="ol-panel ol-scrollable closed">
</div>
</div>

View File

@ -26,12 +26,21 @@
</div>
</div>
<div id="map-type" class="ol-select">
<div class="ol-select-value map-source-dropdown">
<span>ArcGIS Satellite</span>
<div class="ol-group">
<div id="map-type" class="ol-select">
<div class="ol-select-value">
<img src="resources/theme/images/icons/map-source.svg" inject-svg> ArcGIS Satellite
</div>
<div class="ol-select-options">
<!-- Here the available map sources will be listed-->
</div>
</div>
<div class="ol-select-options">
<!-- Here the available map sources will be listed-->
<div id="map-visibility-options" class="ol-select">
<div class="ol-select-value"><img src="resources/theme/images/icons/eye-solid.svg" inject-svg>Options</div>
<div class="ol-select-options">
<!-- This is where the advanced visibility options will be listed -->
</div>
</div>
</div>
@ -56,6 +65,7 @@
</div>
</div>
<!--
<div id="atc-navbar-control" class="ol-group-container ol-navbar-buttons-group" data-feature-switch="atc">
<div class="ol-group">
<button data-on-click="toggleElements"
@ -63,13 +73,5 @@
<button data-on-click="toggleElements"
data-on-click-params='{"selector": "#strip-board-tower"}' class="off"><img src="resources/theme/images/buttons/tools/tower.svg" inject-svg></button>
</div>
</div>
<div id="map-tools" class="ol-group-container ol-navbar-buttons-group">
<div class="ol-group">
<button title="Draw Coalition Areas on the map" data-on-click="toggleCoalitionAreaDraw" data-on-click-params='{"type": "polygon"}' class="off">
<img src="resources/theme/images/buttons/tools/draw-polygon-solid.svg" inject-svg>
</button>
</div>
</div>
</div> -->
</nav>

View File

@ -2,5 +2,5 @@
<span id="command-mode"></span>
<div id="spawn-points-container">Spawn points<span id="spawn-points"></span></div>
<span id="rts-phase"></span>
<button class="ol-button" data-on-click="showRTSSettingsDialog"><img src="/resources/theme/images/icons/gears-solid.svg" inject-svg>Settings</button>
<button id="rts-settings-button" class="ol-button" data-on-click="showRTSSettingsDialog"><img src="/resources/theme/images/icons/gears-solid.svg" inject-svg>Settings</button>
</nav>