Compare commits
116 Commits
v0.4.5-alp
...
v0.4.7-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
283b9e682e | ||
|
|
8b5956e76b | ||
|
|
017a89b945 | ||
|
|
5bc685182b | ||
|
|
f47fc2fb19 | ||
|
|
11d6f25606 | ||
|
|
331692e3d3 | ||
|
|
7483225e0d | ||
|
|
22ae882032 | ||
|
|
fbab82e4de | ||
|
|
ca81d1c4ce | ||
|
|
a1884ab19f | ||
|
|
8905cd5e85 | ||
|
|
8d5ed33ad8 | ||
|
|
b747752b76 | ||
|
|
4e13daa270 | ||
|
|
c00096bd9a | ||
|
|
4a54011aac | ||
|
|
0c50141be6 | ||
|
|
a71b8806e7 | ||
|
|
e0a27c574f | ||
|
|
8d7a49a31f | ||
|
|
25e2c50438 | ||
|
|
e3423ea9a3 | ||
|
|
812112858c | ||
|
|
8db1357904 | ||
|
|
bba0aa9f52 | ||
|
|
1cc549b24a | ||
|
|
7cafeb73ca | ||
|
|
772f082913 | ||
|
|
9f7efe3018 | ||
|
|
a28584b08b | ||
|
|
5cba46a482 | ||
|
|
a15b7620eb | ||
|
|
49bff88c4e | ||
|
|
80af34fa3e | ||
|
|
1d6f2644aa | ||
|
|
dc61d364d1 | ||
|
|
78de9dd538 | ||
|
|
ccaea5b9d1 | ||
|
|
e02e9de55d | ||
|
|
40da192dbb | ||
|
|
c8254238c7 | ||
|
|
9caee0c77c | ||
|
|
b9830f0190 | ||
|
|
02a0a9b783 | ||
|
|
ea1758a1a9 | ||
|
|
d5d8391f63 | ||
|
|
b508d2301b | ||
|
|
01b3336709 | ||
|
|
6ba37aefd6 | ||
|
|
a804904ff5 | ||
|
|
eacb89176c | ||
|
|
ec971aa822 | ||
|
|
e1f404c647 | ||
|
|
5f1e32d610 | ||
|
|
732ee2bbb9 | ||
|
|
1e461250d5 | ||
|
|
f727174044 | ||
|
|
7edc687f7b | ||
|
|
596fbf0b87 | ||
|
|
5db90e5896 | ||
|
|
dd811def07 | ||
|
|
5273291e9a | ||
|
|
130dbda499 | ||
|
|
769aea7e4e | ||
|
|
fa3d65bde6 | ||
|
|
073281135c | ||
|
|
4c7f979e56 | ||
|
|
a5bfb4f8d2 | ||
|
|
a04780f311 | ||
|
|
aad0fd22ad | ||
|
|
bc1c3994d3 | ||
|
|
840033aa6a | ||
|
|
9cc6e9e790 | ||
|
|
b1ad2f409e | ||
|
|
7106646042 | ||
|
|
31405119f0 | ||
|
|
2e5ee93361 | ||
|
|
f981a661d5 | ||
|
|
7e05bbf5e3 | ||
|
|
4465f4a3bb | ||
|
|
ade4f183cd | ||
|
|
99dc61799f | ||
|
|
a213b94606 | ||
|
|
6600ed8cbb | ||
|
|
826bf12bd6 | ||
|
|
528e0db79c | ||
|
|
11a5fec195 | ||
|
|
c0f3f3a40a | ||
|
|
88844db23a | ||
|
|
31710b4e28 | ||
|
|
42d2f6400b | ||
|
|
2701d6adc0 | ||
|
|
5a4b203937 | ||
|
|
74cb7877cb | ||
|
|
f954338c27 | ||
|
|
cc729b1d25 | ||
|
|
4a4b1d6b00 | ||
|
|
d14741f3b1 | ||
|
|
94684fff9f | ||
|
|
44deef4a5a | ||
|
|
67079e1c0b | ||
|
|
005ffc55ce | ||
|
|
1691b0b30c | ||
|
|
e4e55430ca | ||
|
|
4d31d9d748 | ||
|
|
1413f596fb | ||
|
|
c0aee94da5 | ||
|
|
8e545346e6 | ||
|
|
2b1272c70d | ||
|
|
121f9b6ec3 | ||
|
|
6f9722143e | ||
|
|
5bf62f4b93 | ||
|
|
79319dd006 | ||
|
|
fdcff53697 |
1
.gitignore
vendored
@@ -14,3 +14,4 @@ node_modules
|
||||
/client/plugins/controltips/index.js
|
||||
hgt
|
||||
/client/public/databases/units/old
|
||||
/client/plugins/databasemanager/index.js
|
||||
|
||||
@@ -1,4 +1,33 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
DCS Olympus
|
||||
|
||||
A real-time AI unit control mod for DCS World
|
||||
|
||||
Copyright (C) 2023 Veltro & Gang
|
||||
|
||||
DCS Olympus (the "MATERIAL" or "Software") is provided completely free
|
||||
to users subject to the it under both the terms of version 3 of the GNU
|
||||
General Public License as published by the Free Software Foundation, and
|
||||
the additional terms set out below; except where such terms conflict with this
|
||||
disclaimer, in which case, the terms of this disclaimer shall prevail.
|
||||
|
||||
The authors and/or copyright holders of the Software have not received any
|
||||
financial benefit in connection with the Software. In any event, the
|
||||
Software is provided “as is”, without warranty of any kind, express or
|
||||
implied, including but not limited to the warranties of merchantability,
|
||||
fitness for a particular purpose and non-infringement. In no event shall
|
||||
the authors and/or copyright holders be liable for any claim, damages or
|
||||
other liability, whether in an action of contract, tort or otherwise,
|
||||
arising from, out of or in connection with the Software or the use or o
|
||||
ther dealings in the Software.
|
||||
|
||||
Any party making use of the Software in any manner agrees to be
|
||||
bound by the terms set out in this disclaimer, version 3 of the GNU
|
||||
General Public Licence, and the Additional Terms below.
|
||||
|
||||
THIS MATERIAL IS NOT MADE OR SUPPORTED BY EAGLE DYNAMICS SA.
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||
@@ -618,57 +647,14 @@ an absolute waiver of all civil liability in connection with the
|
||||
Program, unless a warranty or assumption of liability accompanies a
|
||||
copy of the Program in return for a fee.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
END OF GNU GENERAL PUBLIC LICENCE
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
ADDITIONAL TERMS & CONDITIONS
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
1. Governing Law
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
state the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program does terminal interaction, make it output a short
|
||||
notice like this when it starts in an interactive mode:
|
||||
|
||||
<program> Copyright (C) <year> <name of author>
|
||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, your program's commands
|
||||
might be different; for a GUI interface, you would use an "about box".
|
||||
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||
Save where specifically provided for otherwise, the provisions of the
|
||||
GNU General Public Licence Version 3 above shall be governed by and
|
||||
interpreted in accordance with English Law and the parties submit to the
|
||||
exclusive jurisdiction of the English Courts.
|
||||
|
||||
324
client/@types/olympus/index.d.ts
vendored
@@ -83,6 +83,7 @@ declare module "controls/switch" {
|
||||
}
|
||||
declare module "constants/constants" {
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { MapMarkerControl } from "map/map";
|
||||
export const UNITS_URI = "units";
|
||||
export const WEAPONS_URI = "weapons";
|
||||
export const LOGS_URI = "logs";
|
||||
@@ -107,6 +108,8 @@ declare module "constants/constants" {
|
||||
export const ROEDescriptions: string[];
|
||||
export const reactionsToThreatDescriptions: string[];
|
||||
export const emissionsCountermeasuresDescriptions: string[];
|
||||
export const shotsScatterDescriptions: string[];
|
||||
export const shotsIntensityDescriptions: string[];
|
||||
export const minSpeedValues: {
|
||||
[key: string]: number;
|
||||
};
|
||||
@@ -192,6 +195,7 @@ declare module "constants/constants" {
|
||||
export const visibilityControls: string[];
|
||||
export const visibilityControlsTypes: string[][];
|
||||
export const visibilityControlsTooltips: string[];
|
||||
export const MAP_MARKER_CONTROLS: MapMarkerControl[];
|
||||
export const IADSTypes: string[];
|
||||
export const IADSDensities: {
|
||||
[key: string]: number;
|
||||
@@ -221,31 +225,36 @@ declare module "constants/constants" {
|
||||
hasTask = 12,
|
||||
position = 13,
|
||||
speed = 14,
|
||||
heading = 15,
|
||||
isActiveTanker = 16,
|
||||
isActiveAWACS = 17,
|
||||
onOff = 18,
|
||||
followRoads = 19,
|
||||
fuel = 20,
|
||||
desiredSpeed = 21,
|
||||
desiredSpeedType = 22,
|
||||
desiredAltitude = 23,
|
||||
desiredAltitudeType = 24,
|
||||
leaderID = 25,
|
||||
formationOffset = 26,
|
||||
targetID = 27,
|
||||
targetPosition = 28,
|
||||
ROE = 29,
|
||||
reactionToThreat = 30,
|
||||
emissionsCountermeasures = 31,
|
||||
TACAN = 32,
|
||||
radio = 33,
|
||||
generalSettings = 34,
|
||||
ammo = 35,
|
||||
contacts = 36,
|
||||
activePath = 37,
|
||||
isLeader = 38,
|
||||
operateAs = 39,
|
||||
horizontalVelocity = 15,
|
||||
verticalVelocity = 16,
|
||||
heading = 17,
|
||||
isActiveTanker = 18,
|
||||
isActiveAWACS = 19,
|
||||
onOff = 20,
|
||||
followRoads = 21,
|
||||
fuel = 22,
|
||||
desiredSpeed = 23,
|
||||
desiredSpeedType = 24,
|
||||
desiredAltitude = 25,
|
||||
desiredAltitudeType = 26,
|
||||
leaderID = 27,
|
||||
formationOffset = 28,
|
||||
targetID = 29,
|
||||
targetPosition = 30,
|
||||
ROE = 31,
|
||||
reactionToThreat = 32,
|
||||
emissionsCountermeasures = 33,
|
||||
TACAN = 34,
|
||||
radio = 35,
|
||||
generalSettings = 36,
|
||||
ammo = 37,
|
||||
contacts = 38,
|
||||
activePath = 39,
|
||||
isLeader = 40,
|
||||
operateAs = 41,
|
||||
shotsScatter = 42,
|
||||
shotsIntensity = 43,
|
||||
health = 44,
|
||||
endOfData = 255
|
||||
}
|
||||
export const MGRS_PRECISION_10KM = 2;
|
||||
@@ -253,6 +262,8 @@ declare module "constants/constants" {
|
||||
export const MGRS_PRECISION_100M = 4;
|
||||
export const MGRS_PRECISION_10M = 5;
|
||||
export const MGRS_PRECISION_1M = 6;
|
||||
export const DELETE_CYCLE_TIME = 0.05;
|
||||
export const DELETE_SLOW_THRESHOLD = 50;
|
||||
}
|
||||
declare module "map/markers/custommarker" {
|
||||
import { Map, Marker } from "leaflet";
|
||||
@@ -303,7 +314,7 @@ declare module "controls/dropdown" {
|
||||
#private;
|
||||
constructor(ID: string | null, callback: CallableFunction, options?: string[] | null, defaultText?: string);
|
||||
getContainer(): HTMLElement;
|
||||
setOptions(optionsList: string[], sortAlphabetically?: boolean): void;
|
||||
setOptions(optionsList: string[], sort?: "" | "string" | "number" | "string+number"): void;
|
||||
setOptionsElements(optionsElements: HTMLElement[]): void;
|
||||
getOptionElements(): HTMLCollection;
|
||||
addOptionElement(optionElement: HTMLElement): void;
|
||||
@@ -439,6 +450,7 @@ declare module "interfaces" {
|
||||
export interface ObjectIconOptions {
|
||||
showState: boolean;
|
||||
showVvi: boolean;
|
||||
showHealth: boolean;
|
||||
showHotgroup: boolean;
|
||||
showUnitIcon: boolean;
|
||||
showShortLabel: boolean;
|
||||
@@ -498,6 +510,8 @@ declare module "interfaces" {
|
||||
hasTask: boolean;
|
||||
position: LatLng;
|
||||
speed: number;
|
||||
horizontalVelocity: number;
|
||||
verticalVelocity: number;
|
||||
heading: number;
|
||||
isActiveTanker: boolean;
|
||||
isActiveAWACS: boolean;
|
||||
@@ -523,6 +537,9 @@ declare module "interfaces" {
|
||||
activePath: LatLng[];
|
||||
isLeader: boolean;
|
||||
operateAs: string;
|
||||
shotsScatter: number;
|
||||
shotsIntensity: number;
|
||||
health: number;
|
||||
}
|
||||
export interface LoadoutItemBlueprint {
|
||||
name: string;
|
||||
@@ -558,12 +575,22 @@ declare module "interfaces" {
|
||||
muzzleVelocity?: number;
|
||||
aimTime?: number;
|
||||
shotsToFire?: number;
|
||||
shotsBaseInterval?: number;
|
||||
shotsBaseScatter?: number;
|
||||
description?: string;
|
||||
abilities?: string;
|
||||
tags?: string;
|
||||
acquisitionRange?: number;
|
||||
engagementRange?: number;
|
||||
targetingRange?: number;
|
||||
aimMethodRange?: number;
|
||||
alertnessTimeConstant?: number;
|
||||
canTargetPoint?: boolean;
|
||||
canRearm?: boolean;
|
||||
canAAA?: boolean;
|
||||
indirectFire?: boolean;
|
||||
markerFile?: string;
|
||||
unitWhenGrouped?: string;
|
||||
}
|
||||
export interface UnitSpawnOptions {
|
||||
roleType: string;
|
||||
@@ -604,6 +631,7 @@ declare module "interfaces" {
|
||||
export interface ShortcutOptions {
|
||||
altKey?: boolean;
|
||||
callback: CallableFunction;
|
||||
context?: string;
|
||||
ctrlKey?: boolean;
|
||||
name?: string;
|
||||
shiftKey?: boolean;
|
||||
@@ -637,7 +665,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[];
|
||||
@@ -746,7 +774,7 @@ declare module "other/utils" {
|
||||
ranges?: string[];
|
||||
eras?: string[];
|
||||
}): UnitBlueprint | null;
|
||||
export function getMarkerCategoryByName(name: string): "aircraft" | "helicopter" | "groundunit-sam" | "groundunit-other" | "groundunit-sam-radar" | "groundunit-sam-launcher" | "groundunit-ewr";
|
||||
export function getMarkerCategoryByName(name: string): "aircraft" | "helicopter" | "groundunit-other" | "navyunit" | "groundunit";
|
||||
export function getUnitDatabaseByCategory(category: string): import("unit/databases/aircraftdatabase").AircraftDatabase | import("unit/databases/helicopterdatabase").HelicopterDatabase | import("unit/databases/groundunitdatabase").GroundUnitDatabase | import("unit/databases/navyunitdatabase").NavyUnitDatabase | null;
|
||||
export function base64ToBytes(base64: string): ArrayBufferLike;
|
||||
export function enumToState(state: number): string;
|
||||
@@ -786,9 +814,12 @@ declare module "controls/unitspawnmenu" {
|
||||
import { UnitSpawnOptions } from "interfaces";
|
||||
export class UnitSpawnMenu {
|
||||
#private;
|
||||
spawnOptions: UnitSpawnOptions;
|
||||
protected showRangeCircles: boolean;
|
||||
protected spawnOptions: UnitSpawnOptions;
|
||||
protected unitTypeFilter: (unit: any) => boolean;
|
||||
constructor(ID: string, unitDatabase: UnitDatabase, orderByRole: boolean);
|
||||
getContainer(): HTMLElement;
|
||||
getVisible(): boolean;
|
||||
reset(): void;
|
||||
setCountries(): void;
|
||||
refreshOptions(): void;
|
||||
@@ -824,6 +855,8 @@ declare module "controls/unitspawnmenu" {
|
||||
deployUnits(spawnOptions: UnitSpawnOptions, unitsCount: number): void;
|
||||
}
|
||||
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
|
||||
@@ -831,6 +864,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 {
|
||||
/**
|
||||
*
|
||||
@@ -869,7 +910,7 @@ declare module "contextmenus/mapcontextmenu" {
|
||||
* @param y Y screen coordinate of the top left corner of the context menu
|
||||
* @param latlng Leaflet latlng object of the mouse click
|
||||
*/
|
||||
show(x: number, y: number, latlng: LatLng): void;
|
||||
show(x: number, y: number, latlng: LatLng): false | undefined;
|
||||
/** If the user rightclicked on a CoalitionArea, it will be given the ability to edit it.
|
||||
*
|
||||
* @param coalitionArea The CoalitionArea the user can edit
|
||||
@@ -986,6 +1027,7 @@ declare module "weapon/weapon" {
|
||||
getIconOptions(): {
|
||||
showState: boolean;
|
||||
showVvi: boolean;
|
||||
showHealth: boolean;
|
||||
showHotgroup: boolean;
|
||||
showUnitIcon: boolean;
|
||||
showShortLabel: boolean;
|
||||
@@ -1003,6 +1045,7 @@ declare module "weapon/weapon" {
|
||||
getIconOptions(): {
|
||||
showState: boolean;
|
||||
showVvi: boolean;
|
||||
showHealth: boolean;
|
||||
showHotgroup: boolean;
|
||||
showUnitIcon: boolean;
|
||||
showShortLabel: boolean;
|
||||
@@ -1014,12 +1057,29 @@ declare module "weapon/weapon" {
|
||||
};
|
||||
}
|
||||
}
|
||||
declare module "map/rangecircle" {
|
||||
import { Circle } from 'leaflet';
|
||||
/**
|
||||
* This custom Circle object implements a faster render method for very big circles. When zoomed in, the default ctx.arc method
|
||||
* is very slow since the circle is huge. Also, when zoomed in most of the circle points will be outside the screen and not needed. This
|
||||
* simpler, faster renderer approximates the circle with line segements and only draws those currently visibile.
|
||||
* A more refined version using arcs could be implemented but this works good enough.
|
||||
*/
|
||||
export class RangeCircle extends Circle {
|
||||
_updatePath(): void;
|
||||
}
|
||||
}
|
||||
declare module "unit/unit" {
|
||||
import { LatLng, Map } from 'leaflet';
|
||||
import { CustomMarker } from "map/markers/custommarker";
|
||||
import { UnitDatabase } from "unit/databases/unitdatabase";
|
||||
import { DataExtractor } from "server/dataextractor";
|
||||
import { Ammo, Contact, GeneralSettings, ObjectIconOptions, Offset, Radio, TACAN, UnitData } from "interfaces";
|
||||
/**
|
||||
* Unit class which controls unit behaviour
|
||||
*
|
||||
* Just about everything is a unit - even missiles!
|
||||
*/
|
||||
export class Unit extends CustomMarker {
|
||||
#private;
|
||||
ID: number;
|
||||
@@ -1036,9 +1096,11 @@ declare module "unit/unit" {
|
||||
getHasTask(): boolean;
|
||||
getPosition(): LatLng;
|
||||
getSpeed(): number;
|
||||
getHorizontalVelocity(): number;
|
||||
getVerticalVelocity(): number;
|
||||
getHeading(): number;
|
||||
getIsActiveTanker(): boolean;
|
||||
getIsActiveAWACS(): boolean;
|
||||
getIsActiveTanker(): boolean;
|
||||
getOnOff(): boolean;
|
||||
getFollowRoads(): boolean;
|
||||
getFuel(): number;
|
||||
@@ -1061,26 +1123,90 @@ declare module "unit/unit" {
|
||||
getActivePath(): LatLng[];
|
||||
getIsLeader(): boolean;
|
||||
getOperateAs(): string;
|
||||
getShotsScatter(): number;
|
||||
getShotsIntensity(): number;
|
||||
getHealth(): number;
|
||||
static getConstructor(type: string): typeof GroundUnit | undefined;
|
||||
constructor(ID: number);
|
||||
getCategory(): string;
|
||||
/********************** Unit data *************************/
|
||||
setData(dataExtractor: DataExtractor): void;
|
||||
drawLines(): void;
|
||||
/** Get unit data collated into an object
|
||||
*
|
||||
* @returns object populated by unit information which can also be retrieved using getters
|
||||
*/
|
||||
getData(): UnitData;
|
||||
/**
|
||||
*
|
||||
* @returns string containing the marker category
|
||||
*/
|
||||
getMarkerCategory(): string;
|
||||
/** Get a database of information also in this unit's category
|
||||
*
|
||||
* @returns UnitDatabase
|
||||
*/
|
||||
getDatabase(): UnitDatabase | null;
|
||||
/** Get the icon options
|
||||
* Used to configure how the marker appears on the map
|
||||
*
|
||||
* @returns ObjectIconOptions
|
||||
*/
|
||||
getIconOptions(): ObjectIconOptions;
|
||||
/** Set the unit as alive or dead
|
||||
*
|
||||
* @param newAlive (boolean) true = alive, false = dead
|
||||
*/
|
||||
setAlive(newAlive: boolean): void;
|
||||
/** Set the unit as user-selected
|
||||
*
|
||||
* @param selected (boolean)
|
||||
*/
|
||||
setSelected(selected: boolean): void;
|
||||
/** Is this unit selected?
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
getSelected(): boolean;
|
||||
/** Set whether this unit is selectable
|
||||
*
|
||||
* @param selectable (boolean)
|
||||
*/
|
||||
setSelectable(selectable: boolean): void;
|
||||
/** Get whether this unit is selectable
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
getSelectable(): boolean;
|
||||
/** Set the number of the hotgroup to which the unit belongs
|
||||
*
|
||||
* @param hotgroup (number)
|
||||
*/
|
||||
setHotgroup(hotgroup: number | null): void;
|
||||
/** Get the unit's hotgroup number
|
||||
*
|
||||
* @returns number
|
||||
*/
|
||||
getHotgroup(): number | null;
|
||||
/** Set the unit as highlighted
|
||||
*
|
||||
* @param highlighted (boolean)
|
||||
*/
|
||||
setHighlighted(highlighted: boolean): void;
|
||||
/** Get whether the unit is highlighted or not
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
getHighlighted(): boolean;
|
||||
/** Get the other members of the group which this unit is in
|
||||
*
|
||||
* @returns Unit[]
|
||||
*/
|
||||
getGroupMembers(): Unit[];
|
||||
/** Returns whether the user is allowed to command this unit, based on coalition
|
||||
*
|
||||
* @returns boolean
|
||||
*/
|
||||
belongsToCommandedCoalition(): boolean;
|
||||
getType(): string;
|
||||
getSpawnPoints(): number | undefined;
|
||||
@@ -1097,6 +1223,9 @@ declare module "unit/unit" {
|
||||
isInViewport(): boolean;
|
||||
canTargetPoint(): boolean;
|
||||
canRearm(): boolean;
|
||||
canLandAtPoint(): boolean;
|
||||
canAAA(): boolean;
|
||||
indirectFire(): boolean;
|
||||
isTanker(): boolean;
|
||||
isAWACS(): boolean;
|
||||
/********************** Unit commands *************************/
|
||||
@@ -1121,7 +1250,7 @@ declare module "unit/unit" {
|
||||
setOnOff(onOff: boolean): void;
|
||||
setFollowRoads(followRoads: boolean): void;
|
||||
setOperateAs(operateAs: string): void;
|
||||
delete(explosion: boolean, immediate: boolean): void;
|
||||
delete(explosion: boolean, explosionType: string, immediate: boolean): void;
|
||||
refuel(): void;
|
||||
setAdvancedOptions(isActiveTanker: boolean, isActiveAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings): void;
|
||||
bombPoint(latlng: LatLng): void;
|
||||
@@ -1132,6 +1261,8 @@ declare module "unit/unit" {
|
||||
scenicAAA(): void;
|
||||
missOnPurpose(): void;
|
||||
landAtPoint(latlng: LatLng): void;
|
||||
setShotsScatter(shotsScatter: number): void;
|
||||
setShotsIntensity(shotsIntensity: number): void;
|
||||
/***********************************************/
|
||||
getActions(): {
|
||||
[key: string]: {
|
||||
@@ -1149,6 +1280,7 @@ declare module "unit/unit" {
|
||||
getIconOptions(): {
|
||||
showState: boolean;
|
||||
showVvi: boolean;
|
||||
showHealth: boolean;
|
||||
showHotgroup: boolean;
|
||||
showUnitIcon: boolean;
|
||||
showShortLabel: boolean;
|
||||
@@ -1179,6 +1311,7 @@ declare module "unit/unit" {
|
||||
getIconOptions(): {
|
||||
showState: boolean;
|
||||
showVvi: boolean;
|
||||
showHealth: boolean;
|
||||
showHotgroup: boolean;
|
||||
showUnitIcon: boolean;
|
||||
showShortLabel: boolean;
|
||||
@@ -1203,6 +1336,7 @@ declare module "unit/unit" {
|
||||
getIconOptions(): {
|
||||
showState: boolean;
|
||||
showVvi: boolean;
|
||||
showHealth: boolean;
|
||||
showHotgroup: boolean;
|
||||
showUnitIcon: boolean;
|
||||
showShortLabel: boolean;
|
||||
@@ -1331,6 +1465,20 @@ declare module "contextmenus/airbasespawnmenu" {
|
||||
setAirbase(airbase: Airbase): void;
|
||||
}
|
||||
}
|
||||
declare module "context/context" {
|
||||
export interface ContextInterface {
|
||||
useSpawnMenu?: boolean;
|
||||
useUnitControlPanel?: boolean;
|
||||
useUnitInfoPanel?: boolean;
|
||||
}
|
||||
export class Context {
|
||||
#private;
|
||||
constructor(config: ContextInterface);
|
||||
getUseSpawnMenu(): boolean;
|
||||
getUseUnitControlPanel(): boolean;
|
||||
getUseUnitInfoPanel(): boolean;
|
||||
}
|
||||
}
|
||||
declare module "other/manager" {
|
||||
export class Manager {
|
||||
#private;
|
||||
@@ -1406,6 +1554,14 @@ declare module "map/map" {
|
||||
import { CoalitionArea } from "map/coalitionarea/coalitionarea";
|
||||
import { CoalitionAreaContextMenu } from "contextmenus/coalitionareacontextmenu";
|
||||
import { AirbaseSpawnContextMenu } from "contextmenus/airbasespawnmenu";
|
||||
export type MapMarkerControl = {
|
||||
"image": string;
|
||||
"isProtected"?: boolean;
|
||||
"name": string;
|
||||
"protectable"?: boolean;
|
||||
"toggles": string[];
|
||||
"tooltip": string;
|
||||
};
|
||||
export class Map extends L.Map {
|
||||
#private;
|
||||
/**
|
||||
@@ -1453,6 +1609,8 @@ declare module "map/map" {
|
||||
getVisibilityOptions(): {
|
||||
[key: string]: boolean;
|
||||
};
|
||||
unitIsProtected(unit: Unit): boolean;
|
||||
getMapMarkerControls(): MapMarkerControl[];
|
||||
}
|
||||
}
|
||||
declare module "mission/bullseye" {
|
||||
@@ -1550,6 +1708,30 @@ declare module "panels/serverstatuspanel" {
|
||||
update(frameRate: number, load: number): void;
|
||||
}
|
||||
}
|
||||
declare module "toolbars/toolbar" {
|
||||
export class Toolbar {
|
||||
#private;
|
||||
/**
|
||||
*
|
||||
* @param ID - the ID of the HTML element which will contain the context menu
|
||||
*/
|
||||
constructor(ID: string);
|
||||
show(): void;
|
||||
hide(): void;
|
||||
toggle(): void;
|
||||
getElement(): HTMLElement;
|
||||
getVisible(): boolean;
|
||||
}
|
||||
}
|
||||
declare module "toolbars/primarytoolbar" {
|
||||
import { Dropdown } from "controls/dropdown";
|
||||
import { Toolbar } from "toolbars/toolbar";
|
||||
export class PrimaryToolbar extends Toolbar {
|
||||
#private;
|
||||
constructor(ID: string);
|
||||
getMainDropdown(): Dropdown;
|
||||
}
|
||||
}
|
||||
declare module "panels/unitcontrolpanel" {
|
||||
import { Panel } from "panels/panel";
|
||||
export class UnitControlPanel extends Panel {
|
||||
@@ -1569,6 +1751,7 @@ declare module "panels/unitinfopanel" {
|
||||
export class UnitInfoPanel extends Panel {
|
||||
#private;
|
||||
constructor(ID: string);
|
||||
show(): void;
|
||||
}
|
||||
}
|
||||
declare module "plugin/pluginmanager" {
|
||||
@@ -1611,35 +1794,11 @@ declare module "shortcut/shortcutmanager" {
|
||||
onKeyUp(callback: CallableFunction): void;
|
||||
}
|
||||
}
|
||||
declare module "toolbars/toolbar" {
|
||||
export class Toolbar {
|
||||
#private;
|
||||
/**
|
||||
*
|
||||
* @param ID - the ID of the HTML element which will contain the context menu
|
||||
*/
|
||||
constructor(ID: string);
|
||||
show(): void;
|
||||
hide(): void;
|
||||
toggle(): void;
|
||||
getElement(): HTMLElement;
|
||||
getVisible(): boolean;
|
||||
}
|
||||
}
|
||||
declare module "toolbars/commandmodetoolbar" {
|
||||
import { Toolbar } from "toolbars/toolbar";
|
||||
export class CommandModeToolbar extends Toolbar {
|
||||
}
|
||||
}
|
||||
declare module "toolbars/primarytoolbar" {
|
||||
import { Dropdown } from "controls/dropdown";
|
||||
import { Toolbar } from "toolbars/toolbar";
|
||||
export class PrimaryToolbar extends Toolbar {
|
||||
#private;
|
||||
constructor(ID: string);
|
||||
getMainDropdown(): Dropdown;
|
||||
}
|
||||
}
|
||||
declare module "unit/citiesDatabase" {
|
||||
export var citiesDatabase: {
|
||||
lat: number;
|
||||
@@ -1647,6 +1806,14 @@ declare module "unit/citiesDatabase" {
|
||||
pop: number;
|
||||
}[];
|
||||
}
|
||||
declare module "dialog/dialog" {
|
||||
import { Panel } from "panels/panel";
|
||||
export class Dialog extends Panel {
|
||||
constructor(element: string);
|
||||
hide(): void;
|
||||
show(): void;
|
||||
}
|
||||
}
|
||||
declare module "unit/unitsmanager" {
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { Unit } from "unit/unit";
|
||||
@@ -1713,7 +1880,9 @@ declare module "unit/unitsmanager" {
|
||||
*/
|
||||
getSelectedUnits(options?: {
|
||||
excludeHumans?: boolean;
|
||||
excludeProtected?: boolean;
|
||||
onlyOnePerGroup?: boolean;
|
||||
showProtectionReminder?: boolean;
|
||||
}): Unit[];
|
||||
/** Deselects all currently selected units
|
||||
*
|
||||
@@ -1876,6 +2045,16 @@ declare module "unit/unitsmanager" {
|
||||
* @param latlng Point where to land
|
||||
*/
|
||||
selectedUnitsLandAtPoint(latlng: LatLng): void;
|
||||
/** Set a specific shots scatter to all the selected units
|
||||
*
|
||||
* @param shotsScatter Value to set
|
||||
*/
|
||||
selectedUnitsSetShotsScatter(shotsScatter: number): void;
|
||||
/** Set a specific shots intensity to all the selected units
|
||||
*
|
||||
* @param shotsScatter Value to set
|
||||
*/
|
||||
selectedUnitsSetShotsIntensity(shotsIntensity: number): void;
|
||||
/*********************** Control operations on selected units ************************/
|
||||
/** See getUnitsCategories for more info
|
||||
*
|
||||
@@ -1907,7 +2086,7 @@ declare module "unit/unitsmanager" {
|
||||
* @param explosion If true, the unit will be deleted using an explosion
|
||||
* @returns
|
||||
*/
|
||||
selectedUnitsDelete(explosion?: boolean): void;
|
||||
selectedUnitsDelete(explosion?: boolean, explosionType?: string): void;
|
||||
/** Compute the destinations of every unit in the selected units. This function preserves the relative positions of the units, and rotates the whole formation by rotation.
|
||||
*
|
||||
* @param latlng Center of the group after the translation
|
||||
@@ -2027,7 +2206,7 @@ declare module "server/servermanager" {
|
||||
isCommandExecuted(callback: CallableFunction, commandHash: string): void;
|
||||
addDestination(ID: number, path: any, callback?: CallableFunction): void;
|
||||
spawnSmoke(color: string, latlng: LatLng, callback?: CallableFunction): void;
|
||||
spawnExplosion(intensity: number, latlng: LatLng, callback?: CallableFunction): void;
|
||||
spawnExplosion(intensity: number, explosionType: string, latlng: LatLng, callback?: CallableFunction): void;
|
||||
spawnAircrafts(units: any, coalition: string, airbaseName: string, country: string, immediate: boolean, spawnPoints: number, callback?: CallableFunction): void;
|
||||
spawnHelicopters(units: any, coalition: string, airbaseName: string, country: string, immediate: boolean, spawnPoints: number, callback?: CallableFunction): void;
|
||||
spawnGroundUnits(units: any, coalition: string, country: string, immediate: boolean, spawnPoints: number, callback?: CallableFunction): void;
|
||||
@@ -2042,7 +2221,7 @@ declare module "server/servermanager" {
|
||||
ID: number;
|
||||
location: LatLng;
|
||||
}[], deleteOriginal: boolean, spawnPoints: number, callback?: CallableFunction): void;
|
||||
deleteUnit(ID: number, explosion: boolean, immediate: boolean, callback?: CallableFunction): void;
|
||||
deleteUnit(ID: number, explosion: boolean, explosionType: string, immediate: boolean, callback?: CallableFunction): void;
|
||||
landAt(ID: number, latlng: LatLng, callback?: CallableFunction): void;
|
||||
changeSpeed(ID: number, speedChange: string, callback?: CallableFunction): void;
|
||||
setSpeed(ID: number, speed: number, callback?: CallableFunction): void;
|
||||
@@ -2066,6 +2245,8 @@ declare module "server/servermanager" {
|
||||
scenicAAA(ID: number, coalition: string, callback?: CallableFunction): void;
|
||||
missOnPurpose(ID: number, coalition: string, callback?: CallableFunction): void;
|
||||
landAtPoint(ID: number, latlng: LatLng, callback?: CallableFunction): void;
|
||||
setShotsScatter(ID: number, shotsScatter: number, callback?: CallableFunction): void;
|
||||
setShotsIntensity(ID: number, shotsIntensity: number, callback?: CallableFunction): void;
|
||||
setAdvacedOptions(ID: number, isActiveTanker: boolean, isActiveAWACS: boolean, TACAN: TACAN, radio: Radio, generalSettings: GeneralSettings, callback?: CallableFunction): void;
|
||||
setCommandModeOptions(restrictSpawns: boolean, restrictToCoalition: boolean, spawnPoints: {
|
||||
blue: number;
|
||||
@@ -2094,6 +2275,18 @@ declare module "panels/unitlistpanel" {
|
||||
toggle(): void;
|
||||
}
|
||||
}
|
||||
declare module "context/contextmanager" {
|
||||
import { Manager } from "other/manager";
|
||||
import { ContextInterface } from "context/context";
|
||||
export class ContextManager extends Manager {
|
||||
#private;
|
||||
constructor();
|
||||
add(name: string, contextConfig: ContextInterface): this;
|
||||
currentContextIs(contextName: string): boolean;
|
||||
getCurrentContext(): any;
|
||||
setContext(contextName: string): false | undefined;
|
||||
}
|
||||
}
|
||||
declare module "olympusapp" {
|
||||
import { Map } from "map/map";
|
||||
import { MissionManager } from "mission/missionmanager";
|
||||
@@ -2103,10 +2296,15 @@ declare module "olympusapp" {
|
||||
import { WeaponsManager } from "weapon/weaponsmanager";
|
||||
import { Manager } from "other/manager";
|
||||
import { ServerManager } from "server/servermanager";
|
||||
import { ContextManager } from "context/contextmanager";
|
||||
import { Context } from "context/context";
|
||||
export class OlympusApp {
|
||||
#private;
|
||||
constructor();
|
||||
getDialogManager(): Manager;
|
||||
getMap(): Map;
|
||||
getCurrentContext(): Context;
|
||||
getContextManager(): ContextManager;
|
||||
getServerManager(): ServerManager;
|
||||
getPanelsManager(): Manager;
|
||||
getPopupsManager(): Manager;
|
||||
@@ -2158,3 +2356,11 @@ declare module "index" {
|
||||
import { OlympusApp } from "olympusapp";
|
||||
export function getApp(): OlympusApp;
|
||||
}
|
||||
declare module "context/contextmenumanager" {
|
||||
import { ContextMenu } from "contextmenus/contextmenu";
|
||||
import { Manager } from "other/manager";
|
||||
export class ContextMenuManager extends Manager {
|
||||
constructor();
|
||||
add(name: string, contextMenu: ContextMenu): this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var fs = require('fs');
|
||||
let rawdata = fs.readFileSync('../olympus.json');
|
||||
let config = JSON.parse(rawdata);
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
@@ -12,8 +16,14 @@ var http = require('http');
|
||||
* Get port from environment and store in Express.
|
||||
*/
|
||||
|
||||
var port = normalizePort(process.env.PORT || '3000');
|
||||
var configPort = null;
|
||||
if (config["client"] != undefined && config["client"]["port"] != undefined) {
|
||||
configPort = config["client"]["port"];
|
||||
}
|
||||
|
||||
var port = normalizePort(configPort || '3000');
|
||||
app.set('port', port);
|
||||
console.log("Express server listening on port: " + port)
|
||||
|
||||
/**
|
||||
* Create HTTP server.
|
||||
|
||||
345
client/demo.js
@@ -2,124 +2,15 @@ const { random } = require('@turf/turf');
|
||||
var basicAuth = require('express-basic-auth')
|
||||
var enc = new TextEncoder();
|
||||
|
||||
const DEMO_UNIT_DATA = {
|
||||
["1"]:{ category: "Aircraft", alive: true, human: false, controlled: true, coalition: 2, country: 0, name: "KC-135", unitName: "Cool guy 1-1 who also has a very long name", groupName: "Cool group 1", state: 1, task: "Being cool!",
|
||||
hasTask: true, position: { lat: 37, lng: -116, alt: 1000 }, speed: 200, heading: 45, isActiveTanker: true, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 }, { quantity: 2, name: "A cool missile with a longer name\0Ciao", guidance: 0, category: 0, missileCategory: 0 }, { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}, {ID: 4, detectionMethod: 1}],
|
||||
activePath: [{lat: 38, lng: -115, alt: 0}, {lat: 38, lng: -114, alt: 0}]
|
||||
},
|
||||
["2"]:{ category: "Aircraft", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "E-3A", unitName: "Cool guy 1-2", groupName: "Cool group 2", state: 1, task: "Being cool",
|
||||
hasTask: true, position: { lat: 36.9, lng: -116, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isActiveTanker: false, isActiveAWACS: true, onOff: true, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 4, detectionMethod: 1}],
|
||||
activePath: [ ]
|
||||
}, ["3"]:{ category: "Helicopter", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "AH-64D_BLK_II", unitName: "Cool guy 1-4", groupName: "Cool group 3", state: 1, task: "Being cool",
|
||||
hasTask: false, position: { lat: 37.1, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isActiveTanker: false, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 1, detectionMethod: 16}],
|
||||
activePath: [ ]
|
||||
}, ["4"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 2, country: 0, name: "Tor 9A331", unitName: "Cool guy 2-1", groupName: "Cool group 4", state: 1, task: "Being cool",
|
||||
hasTask: false, position: { lat: 37.2, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isActiveTanker: false, isActiveAWACS: false, onOff: false, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 1001, detectionMethod: 16}],
|
||||
activePath: [ ],
|
||||
isLeader: true,
|
||||
operateAs: 2
|
||||
}, ["5"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 2, country: 0, name: "Gepard", unitName: "Cool guy 2-2", groupName: "Cool group 4", state: 1, task: "Being cool",
|
||||
hasTask: false, position: { lat: 37.21, lng: -116.1, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isActiveTanker: false, isActiveAWACS: false, onOff: false, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [],
|
||||
activePath: [ ],
|
||||
isLeader: false,
|
||||
operateAs: 2
|
||||
},
|
||||
["6"]:{ category: "Aircraft", alive: true, human: false, controlled: false, coalition: 1, country: 0, name: "FA-18C_hornet", unitName: "Bad boi 1-2", groupName: "Bad group 1", state: 1, task: "Being bad",
|
||||
hasTask: false, position: { lat: 36.8, lng: -116, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isActiveTanker: false, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 1, detectionMethod: 16}],
|
||||
activePath: [ ]
|
||||
}, ["7"]:{ category: "GroundUnit", alive: true, human: false, controlled: true, coalition: 1, country: 0, name: "Tor 9A331", unitName: "Cool guy 2-1", groupName: "Cool group 10", state: 1, task: "Being cool",
|
||||
hasTask: false, position: { lat: 37.2, lng: -116.2, alt: 1000 }, speed: 200, heading: 315 * Math.PI / 180, isActiveTanker: false, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
contacts: [{ID: 1001, detectionMethod: 16}],
|
||||
activePath: [ ],
|
||||
isLeader: true
|
||||
},
|
||||
}
|
||||
const aircraftDatabase = require('./public/databases/units/aircraftDatabase.json');
|
||||
const helicopterDatabase = require('./public/databases/units/helicopterDatabase.json');
|
||||
const groundUnitDatabase = require('./public/databases/units/groundUnitDatabase.json');
|
||||
const navyUnitDatabase = require('./public/databases/units/navyUnitDatabase.json');
|
||||
|
||||
const DEMO_UNIT_DATA = {}
|
||||
|
||||
const DEMO_WEAPONS_DATA = {
|
||||
["1001"]:{ category: "Missile", alive: true, coalition: 2, name: "", position: { lat: 37.1, lng: -116, alt: 1000 }, speed: 200, heading: 45 * Math.PI / 180 },
|
||||
/*["1001"]:{ category: "Missile", alive: true, coalition: 2, name: "", position: { lat: 37.1, lng: -116, alt: 1000 }, speed: 200, heading: 45 * Math.PI / 180 }, */
|
||||
}
|
||||
|
||||
class DemoDataGenerator {
|
||||
@@ -142,26 +33,120 @@ class DemoDataGenerator {
|
||||
},
|
||||
}))
|
||||
|
||||
//for (let i = 8; i < 100; i++) {
|
||||
// var randomUnit = { category: "Aircraft", alive: true, human: false, controlled: true, coalition: 2, country: 0, name: "KC-135", unitName: "Cool guy 1-1 who also has a very long name", groupName: "Cool group 1", state: 1, task: "Being cool!",
|
||||
// hasTask: true, position: { lat: 37 + Math.random(), lng: -116 + Math.random(), alt: 1000 }, speed: 200, heading: 45, isActiveTanker: true, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
// desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
// formationOffset: { x: 0, y: 0, z: 0 },
|
||||
// targetID: 0,
|
||||
// targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
// ROE: 1,
|
||||
// reactionToThreat: 1,
|
||||
// emissionsCountermeasures: 1,
|
||||
// TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
// radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
// generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
// ammo: [{ quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 }, { quantity: 2, name: "A cool missile with a longer name\0Ciao", guidance: 0, category: 0, missileCategory: 0 }, { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } , { quantity: 2, name: "A cool missile\0Ciao", guidance: 0, category: 0, missileCategory: 0 } ],
|
||||
// contacts: [{ID: 2, detectionMethod: 1}, {ID: 3, detectionMethod: 4}, {ID: 4, detectionMethod: 1}],
|
||||
// activePath: []
|
||||
// }
|
||||
// DEMO_UNIT_DATA[i.toString()] = randomUnit;
|
||||
//}
|
||||
|
||||
let baseData = { alive: true, human: false, controlled: true, coalition: 2, country: 0, unitName: "Cool guy", groupName: "Cool group 1", state: 1, task: "Being cool!",
|
||||
hasTask: true, position: { lat: 37, lng: -116, alt: 1000 }, speed: 200, horizontalVelocity: 200, verticalVelicity: 0, heading: 45, isActiveTanker: false, isActiveAWACS: false, onOff: true, followRoads: false, fuel: 50,
|
||||
desiredSpeed: 300, desiredSpeedType: 1, desiredAltitude: 1000, desiredAltitudeType: 1, leaderID: 0,
|
||||
formationOffset: { x: 0, y: 0, z: 0 },
|
||||
targetID: 0,
|
||||
targetPosition: { lat: 0, lng: 0, alt: 0 },
|
||||
ROE: 1,
|
||||
reactionToThreat: 1,
|
||||
emissionsCountermeasures: 1,
|
||||
TACAN: { isOn: false, XY: 'Y', callsign: 'TKR', channel: 40 },
|
||||
radio: { frequency: 124000000, callsign: 1, callsignNumber: 1 },
|
||||
generalSettings: { prohibitAA: false, prohibitAfterburner: false, prohibitAG: false, prohibitAirWpn: false, prohibitJettison: false },
|
||||
ammo: [],
|
||||
contacts: [],
|
||||
activePath: [],
|
||||
isLeader: true
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
***************** UNCOMMENT TO TEST ALL UNITS ****************
|
||||
|
||||
var databases = Object.assign({}, aircraftDatabase, helicopterDatabase, groundUnitDatabase, navyUnitDatabase);
|
||||
var t = Object.keys(databases).length;
|
||||
var l = Math.floor(Math.sqrt(t));
|
||||
let latIdx = 0;
|
||||
let lngIdx = 0;
|
||||
let idx = 1;
|
||||
console.log(l)
|
||||
for (let name in databases) {
|
||||
if (databases[name].enabled) {
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = name;
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group-${idx}`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += latIdx / 5;
|
||||
DEMO_UNIT_DATA[idx].position.lng += lngIdx / 5;
|
||||
|
||||
latIdx += 1;
|
||||
if (latIdx === l) {
|
||||
latIdx = 0;
|
||||
lngIdx += 1;
|
||||
}
|
||||
|
||||
if (name in aircraftDatabase)
|
||||
DEMO_UNIT_DATA[idx].category = "Aircraft";
|
||||
else if (name in helicopterDatabase)
|
||||
DEMO_UNIT_DATA[idx].category = "Helicopter";
|
||||
else if (name in groundUnitDatabase)
|
||||
DEMO_UNIT_DATA[idx].category = "GroundUnit";
|
||||
else if (name in navyUnitDatabase)
|
||||
DEMO_UNIT_DATA[idx].category = "NavyUnit";
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
let idx = 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "S_75M_Volhov";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "GroundUnit";
|
||||
DEMO_UNIT_DATA[idx].isLeader = true;
|
||||
|
||||
idx += 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "SNR_75V";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "GroundUnit";
|
||||
DEMO_UNIT_DATA[idx].isLeader = false;
|
||||
|
||||
idx += 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "Ural-4320 APA-5D";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "GroundUnit";
|
||||
DEMO_UNIT_DATA[idx].isLeader = false;
|
||||
|
||||
idx += 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "F-14B";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group-1`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "Aircraft";
|
||||
DEMO_UNIT_DATA[idx].isLeader = false;
|
||||
|
||||
idx += 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "Infantry AK";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group-2`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "GroundUnit";
|
||||
DEMO_UNIT_DATA[idx].isLeader = true;
|
||||
|
||||
idx += 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "Infantry AK";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group-3`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "GroundUnit";
|
||||
DEMO_UNIT_DATA[idx].isLeader = true;
|
||||
|
||||
idx += 1;
|
||||
DEMO_UNIT_DATA[idx] = JSON.parse(JSON.stringify(baseData));
|
||||
DEMO_UNIT_DATA[idx].name = "KC-135";
|
||||
DEMO_UNIT_DATA[idx].groupName = `Group-4`;
|
||||
DEMO_UNIT_DATA[idx].position.lat += idx / 100;
|
||||
DEMO_UNIT_DATA[idx].category = "Aircraft";
|
||||
DEMO_UNIT_DATA[idx].isLeader = true;
|
||||
|
||||
|
||||
this.startTime = Date.now();
|
||||
}
|
||||
@@ -170,49 +155,53 @@ class DemoDataGenerator {
|
||||
var array = new Uint8Array();
|
||||
var time = Date.now();
|
||||
array = this.concat(array, this.uint64ToByteArray(BigInt(time)));
|
||||
for (let idx in DEMO_UNIT_DATA) {
|
||||
const unit = DEMO_UNIT_DATA[idx];
|
||||
array = this.concat(array, this.uint32ToByteArray(idx));
|
||||
array = this.appendString(array, unit.category, 1);
|
||||
array = this.appendUint8(array, unit.alive, 2);
|
||||
array = this.appendUint8(array, unit.human, 3);
|
||||
array = this.appendUint8(array, unit.controlled, 4);
|
||||
array = this.appendUint16(array, unit.coalition, 5);
|
||||
array = this.appendUint8(array, unit.country, 6);
|
||||
array = this.appendString(array, unit.name, 7);
|
||||
array = this.appendString(array, unit.unitName, 8);
|
||||
array = this.appendString(array, unit.groupName, 9);
|
||||
array = this.appendUint8(array, unit.state, 10);
|
||||
array = this.appendString(array, unit.task, 11);
|
||||
array = this.appendUint8(array, unit.hasTask, 12);
|
||||
array = this.appendCoordinates(array, unit.position, 13);
|
||||
array = this.appendDouble(array, unit.speed, 14);
|
||||
array = this.appendDouble(array, unit.heading, 15);
|
||||
array = this.appendUint8(array, unit.isActiveTanker, 16);
|
||||
array = this.appendUint8(array, unit.isActiveAWACS, 17);
|
||||
array = this.appendUint8(array, unit.onOff, 18);
|
||||
array = this.appendUint8(array, unit.followRoads, 19);
|
||||
array = this.appendUint16(array, unit.fuel, 20);
|
||||
array = this.appendDouble(array, unit.desiredSpeed, 21);
|
||||
array = this.appendUint8(array, unit.desiredSpeedType, 22);
|
||||
array = this.appendDouble(array, unit.desiredAltitude, 23);
|
||||
array = this.appendUint8(array, unit.desiredAltitudeType, 24);
|
||||
array = this.appendUint32(array, unit.leaderID, 25);
|
||||
array = this.appendOffset(array, unit.formationOffset, 26);
|
||||
array = this.appendUint32(array, unit.targetID, 27);
|
||||
array = this.appendCoordinates(array, unit.targetPosition, 28);
|
||||
array = this.appendUint8(array, unit.ROE, 29);
|
||||
array = this.appendUint8(array, unit.reactionToThreat, 30);
|
||||
array = this.appendUint8(array, unit.emissionsCountermeasures, 31);
|
||||
array = this.appendTACAN(array, unit.TACAN, 32);
|
||||
array = this.appendRadio(array, unit.radio, 33);
|
||||
array = this.appendRadio(array, unit.generalSettings, 34);
|
||||
array = this.appendAmmo(array, unit.ammo, 35);
|
||||
array = this.appendContacts(array, unit.contacts, 36);
|
||||
array = this.appendActivePath(array, unit.activePath, 37);
|
||||
array = this.appendUint8(array, unit.isLeader, 38);
|
||||
array = this.appendUint8(array, unit.operateAs, 39);
|
||||
array = this.concat(array, this.uint8ToByteArray(255));
|
||||
if (req.query["time"] == 0){
|
||||
for (let idx in DEMO_UNIT_DATA) {
|
||||
const unit = DEMO_UNIT_DATA[idx];
|
||||
array = this.concat(array, this.uint32ToByteArray(idx));
|
||||
array = this.appendString(array, unit.category, 1);
|
||||
array = this.appendUint8(array, unit.alive, 2);
|
||||
array = this.appendUint8(array, unit.human, 3);
|
||||
array = this.appendUint8(array, unit.controlled, 4);
|
||||
array = this.appendUint16(array, unit.coalition, 5);
|
||||
array = this.appendUint8(array, unit.country, 6);
|
||||
array = this.appendString(array, unit.name, 7);
|
||||
array = this.appendString(array, unit.unitName, 8);
|
||||
array = this.appendString(array, unit.groupName, 9);
|
||||
array = this.appendUint8(array, unit.state, 10);
|
||||
array = this.appendString(array, unit.task, 11);
|
||||
array = this.appendUint8(array, unit.hasTask, 12);
|
||||
array = this.appendCoordinates(array, unit.position, 13);
|
||||
array = this.appendDouble(array, unit.speed, 14);
|
||||
array = this.appendDouble(array, unit.horizontalVelocity, 15);
|
||||
array = this.appendDouble(array, unit.verticalVelicity, 16);
|
||||
array = this.appendDouble(array, unit.heading, 17);
|
||||
array = this.appendUint8(array, unit.isActiveTanker, 18);
|
||||
array = this.appendUint8(array, unit.isActiveAWACS, 19);
|
||||
array = this.appendUint8(array, unit.onOff, 20);
|
||||
array = this.appendUint8(array, unit.followRoads, 21);
|
||||
array = this.appendUint16(array, unit.fuel, 22);
|
||||
array = this.appendDouble(array, unit.desiredSpeed, 23);
|
||||
array = this.appendUint8(array, unit.desiredSpeedType, 24);
|
||||
array = this.appendDouble(array, unit.desiredAltitude, 25);
|
||||
array = this.appendUint8(array, unit.desiredAltitudeType, 26);
|
||||
array = this.appendUint32(array, unit.leaderID, 27);
|
||||
array = this.appendOffset(array, unit.formationOffset, 28);
|
||||
array = this.appendUint32(array, unit.targetID, 29);
|
||||
array = this.appendCoordinates(array, unit.targetPosition, 30);
|
||||
array = this.appendUint8(array, unit.ROE, 31);
|
||||
array = this.appendUint8(array, unit.reactionToThreat, 32);
|
||||
array = this.appendUint8(array, unit.emissionsCountermeasures, 33);
|
||||
array = this.appendTACAN(array, unit.TACAN, 34);
|
||||
array = this.appendRadio(array, unit.radio, 35);
|
||||
array = this.appendRadio(array, unit.generalSettings, 36);
|
||||
array = this.appendAmmo(array, unit.ammo, 37);
|
||||
array = this.appendContacts(array, unit.contacts, 38);
|
||||
array = this.appendActivePath(array, unit.activePath, 39);
|
||||
array = this.appendUint8(array, unit.isLeader, 40);
|
||||
array = this.appendUint8(array, unit.operateAs, 41);
|
||||
array = this.concat(array, this.uint8ToByteArray(255));
|
||||
}
|
||||
}
|
||||
res.end(Buffer.from(array, 'binary'));
|
||||
};
|
||||
|
||||
4
client/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "DCSOlympus",
|
||||
"version": "v0.4.5-alpha",
|
||||
"version": "v0.4.7-alpha",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "DCSOlympus",
|
||||
"version": "v0.4.5-alpha",
|
||||
"version": "v0.4.7-alpha",
|
||||
"dependencies": {
|
||||
"@turf/turf": "^6.5.0",
|
||||
"body-parser": "^1.20.2",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "DCSOlympus",
|
||||
"node-main": "./bin/www",
|
||||
"main": "http://localhost:3000",
|
||||
"version": "v0.4.5-alpha",
|
||||
"version": "v0.4.7-alpha",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "browserify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ] && copy.bat",
|
||||
|
||||
@@ -273,6 +273,11 @@ _ControlTipsPlugin_element = new WeakMap(), _ControlTipsPlugin_app = new WeakMap
|
||||
"showIfUnitSelected": true,
|
||||
"minSelectedUnits": 2
|
||||
},
|
||||
{
|
||||
"key": `[Num 1-9]`,
|
||||
"action": "Add to hotgroup",
|
||||
"showIfUnitSelected": true
|
||||
},
|
||||
{
|
||||
"key": "CTRL",
|
||||
"action": "<em> ... more</em>",
|
||||
@@ -292,6 +297,16 @@ _ControlTipsPlugin_element = new WeakMap(), _ControlTipsPlugin_app = new WeakMap
|
||||
"showIfUnitSelected": true,
|
||||
"minSelectedUnits": 2,
|
||||
"unitsMustBeControlled": true
|
||||
}, {
|
||||
"key": `[Num 1-9]`,
|
||||
"action": "Add hotgroup to selection",
|
||||
"callback": (tip) => {
|
||||
return (Object.values(__classPrivateFieldGet(this, _ControlTipsPlugin_app, "f").getUnitsManager().getUnits()).some((unit) => {
|
||||
return unit.getHotgroup();
|
||||
}));
|
||||
},
|
||||
"showIfUnitSelected": true,
|
||||
"minSelectedUnits": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -351,6 +366,9 @@ _ControlTipsPlugin_element = new WeakMap(), _ControlTipsPlugin_app = new WeakMap
|
||||
if (!tipsIncludesActiveMouseover && typeof tip.mouseoverSelector === "string") {
|
||||
return false;
|
||||
}
|
||||
if (typeof tip.callback === "function" && !tip.callback(tip)) {
|
||||
return false;
|
||||
}
|
||||
element.innerHTML += `<div><span class="key">${tip.key}</span><span class="action">${tip.action}</span></div>`;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { OlympusPlugin } from "interfaces";
|
||||
import { OlympusApp } from "olympusapp";
|
||||
import { Unit } from "unit/unit";
|
||||
|
||||
|
||||
const SHOW_CONTROL_TIPS = "Show control tips"
|
||||
@@ -279,6 +281,11 @@ export class ControlTipsPlugin implements OlympusPlugin {
|
||||
"showIfUnitSelected": true,
|
||||
"minSelectedUnits": 2
|
||||
},
|
||||
{
|
||||
"key": `[Num 1-9]`,
|
||||
"action": "Add to hotgroup",
|
||||
"showIfUnitSelected": true
|
||||
},
|
||||
{
|
||||
"key": "CTRL",
|
||||
"action": "<em> ... more</em>",
|
||||
@@ -298,6 +305,16 @@ export class ControlTipsPlugin implements OlympusPlugin {
|
||||
"showIfUnitSelected": true,
|
||||
"minSelectedUnits": 2,
|
||||
"unitsMustBeControlled": true
|
||||
}, {
|
||||
"key": `[Num 1-9]`,
|
||||
"action": "Add hotgroup to selection",
|
||||
"callback": ( tip:object ) => {
|
||||
return (Object.values<Unit>( this.#app.getUnitsManager().getUnits() ).some( ( unit:Unit ) => {
|
||||
return unit.getAlive() && unit.getControlled() && unit.getHotgroup();
|
||||
}));
|
||||
},
|
||||
"showIfUnitSelected": true,
|
||||
"minSelectedUnits": 1
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -375,6 +392,10 @@ export class ControlTipsPlugin implements OlympusPlugin {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ( typeof tip.callback === "function" && !tip.callback( tip ) ) {
|
||||
return false;
|
||||
}
|
||||
|
||||
element.innerHTML += `<div><span class="key">${tip.key}</span><span class="action">${tip.action}</span></div>`;
|
||||
|
||||
});
|
||||
|
||||
@@ -54,7 +54,7 @@ class AirUnitEditor extends uniteditor_1.UnitEditor {
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Cost", (_b = String(blueprint.cost)) !== null && _b !== void 0 ? _b : "", "number", (value) => { blueprint.cost = parseFloat(value); });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Can target point", (_c = blueprint.canTargetPoint) !== null && _c !== void 0 ? _c : false, (value) => { blueprint.canTargetPoint = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Description", (_d = blueprint.description) !== null && _d !== void 0 ? _d : "", "text", (value) => { blueprint.description = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Abilities", (_e = blueprint.abilities) !== null && _e !== void 0 ? _e : "", "text", (value) => { blueprint.abilities = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Tags", (_e = blueprint.tags) !== null && _e !== void 0 ? _e : "", "text", (value) => { blueprint.tags = value; });
|
||||
/* Add a scrollable list of loadouts that the user can edit */
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Loadouts";
|
||||
@@ -206,13 +206,13 @@ class DatabaseManagerPlugin {
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_mainContentContainer, "f").classList.add("dm-container");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_element, "f").appendChild(__classPrivateFieldGet(this, _DatabaseManagerPlugin_mainContentContainer, "f"));
|
||||
__classPrivateFieldSet(this, _DatabaseManagerPlugin_contentDiv1, document.createElement("div"), "f");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv1, "f").classList.add("dm-content-container");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv1, "f").classList.add("dm-content-container", "ol-scrollable");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_mainContentContainer, "f").appendChild(__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv1, "f"));
|
||||
__classPrivateFieldSet(this, _DatabaseManagerPlugin_contentDiv2, document.createElement("div"), "f");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv2, "f").classList.add("dm-content-container");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv2, "f").classList.add("dm-content-container", "ol-scrollable");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_mainContentContainer, "f").appendChild(__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv2, "f"));
|
||||
__classPrivateFieldSet(this, _DatabaseManagerPlugin_contentDiv3, document.createElement("div"), "f");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv3, "f").classList.add("dm-content-container");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv3, "f").classList.add("dm-content-container", "ol-scrollable");
|
||||
__classPrivateFieldGet(this, _DatabaseManagerPlugin_mainContentContainer, "f").appendChild(__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv3, "f"));
|
||||
/* Create the database editors, which use the three divs created before */
|
||||
__classPrivateFieldSet(this, _DatabaseManagerPlugin_aircraftEditor, new airuniteditor_1.AirUnitEditor(__classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv1, "f"), __classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv2, "f"), __classPrivateFieldGet(this, _DatabaseManagerPlugin_contentDiv3, "f")), "f");
|
||||
@@ -508,7 +508,7 @@ class GroundUnitEditor extends uniteditor_1.UnitEditor {
|
||||
* @param blueprint The blueprint to edit
|
||||
*/
|
||||
setBlueprint(blueprint) {
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
|
||||
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w;
|
||||
__classPrivateFieldSet(this, _GroundUnitEditor_blueprint, blueprint, "f");
|
||||
if (__classPrivateFieldGet(this, _GroundUnitEditor_blueprint, "f") !== null) {
|
||||
this.contentDiv2.replaceChildren();
|
||||
@@ -519,20 +519,29 @@ class GroundUnitEditor extends uniteditor_1.UnitEditor {
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Label", blueprint.label, "text", (value) => { blueprint.label = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Short label", blueprint.shortLabel, "text", (value) => { blueprint.shortLabel = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Type", (_a = blueprint.type) !== null && _a !== void 0 ? _a : "", "text", (value) => { blueprint.type = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Unit when grouped", (_b = blueprint.unitWhenGrouped) !== null && _b !== void 0 ? _b : "", "text", (value) => { blueprint.unitWhenGrouped = value; });
|
||||
(0, utils_1.addDropdownInput)(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"], (value) => { blueprint.coalition = value; });
|
||||
(0, utils_1.addDropdownInput)(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"], (value) => { blueprint.era = value; });
|
||||
//addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Cost", (_b = String(blueprint.cost)) !== null && _b !== void 0 ? _b : "", "number", (value) => { blueprint.cost = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Acquisition range [m]", (_c = String(blueprint.acquisitionRange)) !== null && _c !== void 0 ? _c : "", "number", (value) => { blueprint.acquisitionRange = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Engagement range [m]", (_d = String(blueprint.engagementRange)) !== null && _d !== void 0 ? _d : "", "number", (value) => { blueprint.engagementRange = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Barrel height [m]", (_e = String(blueprint.barrelHeight)) !== null && _e !== void 0 ? _e : "", "number", (value) => { blueprint.barrelHeight = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Muzzle velocity [m/s]", (_f = String(blueprint.muzzleVelocity)) !== null && _f !== void 0 ? _f : "", "number", (value) => { blueprint.muzzleVelocity = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Aim time [s]", (_g = String(blueprint.aimTime)) !== null && _g !== void 0 ? _g : "", "number", (value) => { blueprint.aimTime = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Burst quantity", (_h = String(blueprint.shotsToFire)) !== null && _h !== void 0 ? _h : "", "number", (value) => { blueprint.shotsToFire = Math.round(parseFloat(value)); });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Can target point", (_j = blueprint.canTargetPoint) !== null && _j !== void 0 ? _j : false, (value) => { blueprint.canTargetPoint = value; });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Can rearm", (_k = blueprint.canRearm) !== null && _k !== void 0 ? _k : false, (value) => { blueprint.canRearm = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Description", (_l = blueprint.description) !== null && _l !== void 0 ? _l : "", "text", (value) => { blueprint.description = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Abilities", (_m = blueprint.abilities) !== null && _m !== void 0 ? _m : "", "text", (value) => { blueprint.abilities = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Cost", (_c = String(blueprint.cost)) !== null && _c !== void 0 ? _c : "", "number", (value) => { blueprint.cost = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Acquisition range [m]", (_d = String(blueprint.acquisitionRange)) !== null && _d !== void 0 ? _d : "", "number", (value) => { blueprint.acquisitionRange = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Engagement range [m]", (_e = String(blueprint.engagementRange)) !== null && _e !== void 0 ? _e : "", "number", (value) => { blueprint.engagementRange = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Targeting range [m]", (_f = String(blueprint.targetingRange)) !== null && _f !== void 0 ? _f : "", "number", (value) => { blueprint.targetingRange = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Aim method range [m]", (_g = String(blueprint.aimMethodRange)) !== null && _g !== void 0 ? _g : "", "number", (value) => { blueprint.aimMethodRange = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Barrel height [m]", (_h = String(blueprint.barrelHeight)) !== null && _h !== void 0 ? _h : "", "number", (value) => { blueprint.barrelHeight = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Muzzle velocity [m/s]", (_j = String(blueprint.muzzleVelocity)) !== null && _j !== void 0 ? _j : "", "number", (value) => { blueprint.muzzleVelocity = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Aim time [s]", (_k = String(blueprint.aimTime)) !== null && _k !== void 0 ? _k : "", "number", (value) => { blueprint.aimTime = parseFloat(value); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Shots to fire", (_l = String(blueprint.shotsToFire)) !== null && _l !== void 0 ? _l : "", "number", (value) => { blueprint.shotsToFire = Math.round(parseFloat(value)); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Shots base interval [s]", (_m = String(blueprint.shotsBaseInterval)) !== null && _m !== void 0 ? _m : "", "number", (value) => { blueprint.shotsBaseInterval = Math.round(parseFloat(value)); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Shots base scatter [°]", (_o = String(blueprint.shotsBaseScatter)) !== null && _o !== void 0 ? _o : "", "number", (value) => { blueprint.shotsBaseScatter = Math.round(parseFloat(value)); });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Alertness time constant [s]", (_p = String(blueprint.alertnessTimeConstant)) !== null && _p !== void 0 ? _p : "", "number", (value) => { blueprint.alertnessTimeConstant = Math.round(parseFloat(value)); });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Can target point", (_q = blueprint.canTargetPoint) !== null && _q !== void 0 ? _q : false, (value) => { blueprint.canTargetPoint = value; });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Can rearm", (_r = blueprint.canRearm) !== null && _r !== void 0 ? _r : false, (value) => { blueprint.canRearm = value; });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Can operate as AAA", (_s = blueprint.canAAA) !== null && _s !== void 0 ? _s : false, (value) => { blueprint.canAAA = value; });
|
||||
(0, utils_1.addCheckboxInput)(this.contentDiv2, "Indirect fire (e.g. mortar)", (_t = blueprint.indirectFire) !== null && _t !== void 0 ? _t : false, (value) => { blueprint.indirectFire = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Description", (_u = blueprint.description) !== null && _u !== void 0 ? _u : "", "text", (value) => { blueprint.description = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Tags", (_v = blueprint.tags) !== null && _v !== void 0 ? _v : "", "text", (value) => { blueprint.tags = value; });
|
||||
(0, utils_1.addStringInput)(this.contentDiv2, "Marker file", (_w = blueprint.markerFile) !== null && _w !== void 0 ? _w : "", "text", (value) => { blueprint.markerFile = value; });
|
||||
}
|
||||
}
|
||||
/** Add a new empty blueprint
|
||||
@@ -613,10 +622,10 @@ class LoadoutEditor {
|
||||
title.innerText = "Loadout properties";
|
||||
__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f").appendChild(title);
|
||||
if (__classPrivateFieldGet(this, _LoadoutEditor_loadout, "f")) {
|
||||
var laodout = __classPrivateFieldGet(this, _LoadoutEditor_loadout, "f");
|
||||
(0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Name", laodout.name, "text", (value) => { laodout.name = value; __classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f").dispatchEvent(new Event("refresh")); });
|
||||
(0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Code", laodout.code, "text", (value) => { laodout.code = value; });
|
||||
(0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Roles", (0, utils_1.arrayToString)(laodout.roles), "text", (value) => { laodout.roles = (0, utils_1.stringToArray)(value); });
|
||||
var loadout = __classPrivateFieldGet(this, _LoadoutEditor_loadout, "f");
|
||||
(0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Name", loadout.name, "text", (value) => { loadout.name = value; __classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f").dispatchEvent(new Event("refresh")); });
|
||||
(0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Code", loadout.code, "text", (value) => { loadout.code = value; });
|
||||
(0, utils_1.addStringInput)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), "Roles", (0, utils_1.arrayToString)(loadout.roles), "text", (value) => { loadout.roles = (0, utils_1.stringToArray)(value); });
|
||||
(0, utils_1.addLoadoutItemsEditor)(__classPrivateFieldGet(this, _LoadoutEditor_contentDiv, "f"), __classPrivateFieldGet(this, _LoadoutEditor_loadout, "f"));
|
||||
}
|
||||
}
|
||||
@@ -746,9 +755,9 @@ class UnitEditor {
|
||||
this.database = JSON.parse(JSON.stringify({ blueprints: database.getBlueprints(true) }));
|
||||
}
|
||||
/** Show the editor
|
||||
*
|
||||
* @param filter String filter
|
||||
*/
|
||||
show() {
|
||||
show(filter = "") {
|
||||
this.visible = true;
|
||||
this.contentDiv1.replaceChildren();
|
||||
this.contentDiv2.replaceChildren();
|
||||
@@ -758,17 +767,16 @@ class UnitEditor {
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Units list";
|
||||
this.contentDiv1.appendChild(title);
|
||||
(0, utils_1.addBlueprintsScroll)(this.contentDiv1, this.database, (key) => {
|
||||
if (this.database != null)
|
||||
this.setBlueprint(this.database.blueprints[key]);
|
||||
});
|
||||
(0, utils_1.addNewElementInput)(this.contentDiv1, (ev, input) => {
|
||||
if (input.value != "")
|
||||
this.addBlueprint((input).value);
|
||||
});
|
||||
var filterInput = document.createElement("input");
|
||||
filterInput.value = filter;
|
||||
this.contentDiv1.appendChild(filterInput);
|
||||
filterInput.onchange = (e) => {
|
||||
this.show(e.target.value);
|
||||
};
|
||||
this.addBlueprints(filter);
|
||||
}
|
||||
}
|
||||
/** Hid the editor
|
||||
/** Hide the editor
|
||||
*
|
||||
*/
|
||||
hide() {
|
||||
@@ -784,6 +792,22 @@ class UnitEditor {
|
||||
getDatabase() {
|
||||
return this.database;
|
||||
}
|
||||
/**
|
||||
*
|
||||
* @param filter String filter
|
||||
*/
|
||||
addBlueprints(filter = "") {
|
||||
if (this.database) {
|
||||
(0, utils_1.addBlueprintsScroll)(this.contentDiv1, this.database, filter, (key) => {
|
||||
if (this.database != null)
|
||||
this.setBlueprint(this.database.blueprints[key]);
|
||||
});
|
||||
(0, utils_1.addNewElementInput)(this.contentDiv1, (ev, input) => {
|
||||
if (input.value != "")
|
||||
this.addBlueprint((input).value);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.UnitEditor = UnitEditor;
|
||||
|
||||
@@ -953,36 +977,56 @@ exports.addNewElementInput = addNewElementInput;
|
||||
*
|
||||
* @param div The HTMLElement that will contain the list
|
||||
* @param database The database that will be used to fill the list of blueprints
|
||||
* @param filter A string filter that will be executed to filter the blueprints to add
|
||||
* @param callback Callback called when the user clicks on one of the elements
|
||||
*/
|
||||
function addBlueprintsScroll(div, database, callback) {
|
||||
function addBlueprintsScroll(div, database, filter, callback) {
|
||||
var scrollDiv = document.createElement("div");
|
||||
scrollDiv.classList.add("dm-scroll-container");
|
||||
if (database !== null) {
|
||||
var blueprints = database.blueprints;
|
||||
for (let key of Object.keys(blueprints).sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }))) {
|
||||
var rowDiv = document.createElement("div");
|
||||
scrollDiv.appendChild(rowDiv);
|
||||
var text = document.createElement("label");
|
||||
text.textContent = key;
|
||||
text.onclick = () => callback(key);
|
||||
rowDiv.appendChild(text);
|
||||
let checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.checked = blueprints[key].enabled;
|
||||
checkbox.onclick = () => {
|
||||
console.log(checkbox.checked);
|
||||
blueprints[key].enabled = checkbox.checked;
|
||||
};
|
||||
rowDiv.appendChild(checkbox);
|
||||
/* This button allows to remove an element from the list. It requires a refresh. */
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "X";
|
||||
button.onclick = () => {
|
||||
delete blueprints[key];
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
};
|
||||
rowDiv.appendChild(button);
|
||||
var addKey = true;
|
||||
if (filter !== "") {
|
||||
try {
|
||||
var blueprint = blueprints[key];
|
||||
addKey = eval(filter);
|
||||
}
|
||||
catch (_a) {
|
||||
console.error("An error has occurred evaluating the blueprint filter");
|
||||
}
|
||||
}
|
||||
if (addKey) {
|
||||
var rowDiv = document.createElement("div");
|
||||
scrollDiv.appendChild(rowDiv);
|
||||
let text = document.createElement("div");
|
||||
text.innerHTML = `<div>${key}</div> <div>${blueprints[key].label}</div>`;
|
||||
text.onclick = () => {
|
||||
callback(key);
|
||||
const collection = document.getElementsByClassName("blueprint-selected");
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
collection[i].classList.remove("blueprint-selected");
|
||||
}
|
||||
text.classList.add("blueprint-selected");
|
||||
};
|
||||
rowDiv.appendChild(text);
|
||||
let checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.checked = blueprints[key].enabled;
|
||||
checkbox.onclick = () => {
|
||||
console.log(checkbox.checked);
|
||||
blueprints[key].enabled = checkbox.checked;
|
||||
};
|
||||
rowDiv.appendChild(checkbox);
|
||||
/* This button allows to remove an element from the list. It requires a refresh. */
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "X";
|
||||
button.onclick = () => {
|
||||
delete blueprints[key];
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
};
|
||||
rowDiv.appendChild(button);
|
||||
}
|
||||
}
|
||||
}
|
||||
div.appendChild(scrollDiv);
|
||||
@@ -1034,25 +1078,17 @@ exports.addLoadoutsScroll = addLoadoutsScroll;
|
||||
* @returns The string
|
||||
*/
|
||||
function arrayToString(array) {
|
||||
var value = "[";
|
||||
var firstRole = true;
|
||||
array.forEach((role) => {
|
||||
value += firstRole ? "" : ", ";
|
||||
firstRole = false;
|
||||
value += role;
|
||||
});
|
||||
value += "]";
|
||||
return value;
|
||||
return "[" + array.join(", ") + "]";
|
||||
}
|
||||
exports.arrayToString = arrayToString;
|
||||
/** Converts an a single string like [val1, val2, val3] into an array
|
||||
*
|
||||
* @param input The input string
|
||||
* @returns The array
|
||||
*/
|
||||
function stringToArray(input) {
|
||||
input = input.replace("[", "").replace("]", "");
|
||||
var values = input.split(",");
|
||||
var result = [];
|
||||
values.forEach((value) => {
|
||||
result.push(value.trim());
|
||||
});
|
||||
return result;
|
||||
var _a;
|
||||
return (_a = input.match(/(\w)+/g)) !== null && _a !== void 0 ? _a : [];
|
||||
}
|
||||
exports.stringToArray = stringToArray;
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export class AirUnitEditor extends UnitEditor {
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost) ?? "", "number", (value: string) => { blueprint.cost = parseFloat(value); });
|
||||
addCheckboxInput(this.contentDiv2, "Can target point", blueprint.canTargetPoint ?? false, (value: boolean) => {blueprint.canTargetPoint = value;})
|
||||
addStringInput(this.contentDiv2, "Description", blueprint.description ?? "", "text", (value: string) => {blueprint.description = value; });
|
||||
addStringInput(this.contentDiv2, "Abilities", blueprint.abilities ?? "", "text", (value: string) => {blueprint.abilities = value; });
|
||||
addStringInput(this.contentDiv2, "Tags", blueprint.tags ?? "", "text", (value: string) => {blueprint.tags = value; });
|
||||
|
||||
/* Add a scrollable list of loadouts that the user can edit */
|
||||
var title = document.createElement("label");
|
||||
|
||||
@@ -86,18 +86,18 @@ export class DatabaseManagerPlugin implements OlympusPlugin {
|
||||
/* Create the container for the database editor elements and the elements themselves */
|
||||
this.#mainContentContainer = document.createElement("div");
|
||||
this.#mainContentContainer.classList.add("dm-container");
|
||||
this.#element.appendChild(this.#mainContentContainer)
|
||||
this.#element.appendChild(this.#mainContentContainer);
|
||||
|
||||
this.#contentDiv1 = document.createElement("div");
|
||||
this.#contentDiv1.classList.add("dm-content-container");
|
||||
this.#contentDiv1.classList.add("dm-content-container", "ol-scrollable");
|
||||
this.#mainContentContainer.appendChild(this.#contentDiv1);
|
||||
|
||||
this.#contentDiv2 = document.createElement("div");
|
||||
this.#contentDiv2.classList.add("dm-content-container");
|
||||
this.#contentDiv2.classList.add("dm-content-container", "ol-scrollable");
|
||||
this.#mainContentContainer.appendChild(this.#contentDiv2);
|
||||
|
||||
this.#contentDiv3 = document.createElement("div");
|
||||
this.#contentDiv3.classList.add("dm-content-container");
|
||||
this.#contentDiv3.classList.add("dm-content-container", "ol-scrollable");
|
||||
this.#mainContentContainer.appendChild(this.#contentDiv3);
|
||||
|
||||
/* Create the database editors, which use the three divs created before */
|
||||
|
||||
@@ -30,20 +30,29 @@ export class GroundUnitEditor extends UnitEditor {
|
||||
addStringInput(this.contentDiv2, "Label", blueprint.label, "text", (value: string) => {blueprint.label = value; });
|
||||
addStringInput(this.contentDiv2, "Short label", blueprint.shortLabel, "text", (value: string) => {blueprint.shortLabel = value; });
|
||||
addStringInput(this.contentDiv2, "Type", blueprint.type?? "", "text", (value: string) => {blueprint.type = value; });
|
||||
addStringInput(this.contentDiv2, "Unit when grouped", blueprint.unitWhenGrouped?? "", "text", (value: string) => {blueprint.unitWhenGrouped = value; });
|
||||
addDropdownInput(this.contentDiv2, "Coalition", blueprint.coalition, ["", "blue", "red"], (value: string) => {blueprint.coalition = value; });
|
||||
addDropdownInput(this.contentDiv2, "Era", blueprint.era, ["WW2", "Early Cold War", "Mid Cold War", "Late Cold War", "Modern"], (value: string) => {blueprint.era = value; });
|
||||
//addStringInput(this.contentDiv2, "Filename", blueprint.filename?? "", "text", (value: string) => {blueprint.filename = value; });
|
||||
addStringInput(this.contentDiv2, "Cost", String(blueprint.cost)?? "", "number", (value: string) => {blueprint.cost = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Acquisition range [m]", String(blueprint.acquisitionRange)?? "", "number", (value: string) => {blueprint.acquisitionRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Engagement range [m]", String(blueprint.engagementRange)?? "", "number", (value: string) => {blueprint.engagementRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Targeting range [m]", String(blueprint.targetingRange)?? "", "number", (value: string) => {blueprint.targetingRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Aim method range [m]", String(blueprint.aimMethodRange)?? "", "number", (value: string) => {blueprint.aimMethodRange = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Barrel height [m]", String(blueprint.barrelHeight)?? "", "number", (value: string) => {blueprint.barrelHeight = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Muzzle velocity [m/s]", String(blueprint.muzzleVelocity)?? "", "number", (value: string) => {blueprint.muzzleVelocity = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Aim time [s]", String(blueprint.aimTime)?? "", "number", (value: string) => {blueprint.aimTime = parseFloat(value); });
|
||||
addStringInput(this.contentDiv2, "Burst quantity", String(blueprint.shotsToFire)?? "", "number", (value: string) => {blueprint.shotsToFire = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Shots to fire", String(blueprint.shotsToFire)?? "", "number", (value: string) => {blueprint.shotsToFire = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Shots base interval [s]", String(blueprint.shotsBaseInterval)?? "", "number", (value: string) => {blueprint.shotsBaseInterval = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Shots base scatter [°]", String(blueprint.shotsBaseScatter)?? "", "number", (value: string) => {blueprint.shotsBaseScatter = Math.round(parseFloat(value)); });
|
||||
addStringInput(this.contentDiv2, "Alertness time constant [s]", String(blueprint.alertnessTimeConstant)?? "", "number", (value: string) => {blueprint.alertnessTimeConstant = Math.round(parseFloat(value)); });
|
||||
addCheckboxInput(this.contentDiv2, "Can target point", blueprint.canTargetPoint ?? false, (value: boolean) => {blueprint.canTargetPoint = value;})
|
||||
addCheckboxInput(this.contentDiv2, "Can rearm", blueprint.canRearm ?? false, (value: boolean) => {blueprint.canRearm = value;})
|
||||
addCheckboxInput(this.contentDiv2, "Can operate as AAA", blueprint.canAAA ?? false, (value: boolean) => {blueprint.canAAA = value;})
|
||||
addCheckboxInput(this.contentDiv2, "Indirect fire (e.g. mortar)", blueprint.indirectFire ?? false, (value: boolean) => {blueprint.indirectFire = value;})
|
||||
addStringInput(this.contentDiv2, "Description", blueprint.description ?? "", "text", (value: string) => {blueprint.description = value; });
|
||||
addStringInput(this.contentDiv2, "Abilities", blueprint.abilities ?? "", "text", (value: string) => {blueprint.abilities = value; });
|
||||
addStringInput(this.contentDiv2, "Tags", blueprint.tags ?? "", "text", (value: string) => {blueprint.tags = value; });
|
||||
addStringInput(this.contentDiv2, "Marker file", blueprint.markerFile ?? "", "text", (value: string) => {blueprint.markerFile = value; });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -37,10 +37,10 @@ export class LoadoutEditor {
|
||||
this.#contentDiv.appendChild(title);
|
||||
|
||||
if (this.#loadout) {
|
||||
var laodout = this.#loadout;
|
||||
addStringInput(this.#contentDiv, "Name", laodout.name, "text", (value: string) => {laodout.name = value; this.#contentDiv.dispatchEvent(new Event("refresh"));});
|
||||
addStringInput(this.#contentDiv, "Code", laodout.code, "text", (value: string) => {laodout.code = value; });
|
||||
addStringInput(this.#contentDiv, "Roles", arrayToString(laodout.roles), "text", (value: string) => {laodout.roles = stringToArray(value);});
|
||||
var loadout = this.#loadout;
|
||||
addStringInput(this.#contentDiv, "Name", loadout.name, "text", (value: string) => {loadout.name = value; this.#contentDiv.dispatchEvent(new Event("refresh"));});
|
||||
addStringInput(this.#contentDiv, "Code", loadout.code, "text", (value: string) => {loadout.code = value; });
|
||||
addStringInput(this.#contentDiv, "Roles", arrayToString(loadout.roles), "text", (value: string) => {loadout.roles = stringToArray(value);});
|
||||
addLoadoutItemsEditor(this.#contentDiv, this.#loadout);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,9 +49,9 @@ export abstract class UnitEditor {
|
||||
}
|
||||
|
||||
/** Show the editor
|
||||
*
|
||||
* @param filter String filter
|
||||
*/
|
||||
show() {
|
||||
show(filter: string = "") {
|
||||
this.visible = true;
|
||||
this.contentDiv1.replaceChildren();
|
||||
this.contentDiv2.replaceChildren();
|
||||
@@ -62,20 +62,20 @@ export abstract class UnitEditor {
|
||||
var title = document.createElement("label");
|
||||
title.innerText = "Units list";
|
||||
this.contentDiv1.appendChild(title);
|
||||
|
||||
addBlueprintsScroll(this.contentDiv1, this.database, (key: string) => {
|
||||
if (this.database != null)
|
||||
this.setBlueprint(this.database.blueprints[key])
|
||||
})
|
||||
|
||||
addNewElementInput(this.contentDiv1, (ev: MouseEvent, input: HTMLInputElement) => {
|
||||
if (input.value != "")
|
||||
this.addBlueprint((input).value);
|
||||
});
|
||||
var filterInput = document.createElement("input");
|
||||
filterInput.value = filter;
|
||||
this.contentDiv1.appendChild(filterInput);
|
||||
|
||||
filterInput.onchange = (e: Event) => {
|
||||
this.show((e.target as HTMLInputElement).value);
|
||||
}
|
||||
|
||||
this.addBlueprints(filter);
|
||||
}
|
||||
}
|
||||
|
||||
/** Hid the editor
|
||||
/** Hide the editor
|
||||
*
|
||||
*/
|
||||
hide() {
|
||||
@@ -93,6 +93,24 @@ export abstract class UnitEditor {
|
||||
return this.database;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param filter String filter
|
||||
*/
|
||||
addBlueprints(filter: string = "") {
|
||||
if (this.database) {
|
||||
addBlueprintsScroll(this.contentDiv1, this.database, filter, (key: string) => {
|
||||
if (this.database != null)
|
||||
this.setBlueprint(this.database.blueprints[key])
|
||||
});
|
||||
|
||||
addNewElementInput(this.contentDiv1, (ev: MouseEvent, input: HTMLInputElement) => {
|
||||
if (input.value != "")
|
||||
this.addBlueprint((input).value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* Abstract methods which will depend on the specific type of units */
|
||||
abstract setBlueprint(blueprint: UnitBlueprint): void;
|
||||
abstract addBlueprint(key: string): void;
|
||||
|
||||
@@ -174,40 +174,60 @@ export function addNewElementInput(div: HTMLElement, callback: CallableFunction)
|
||||
*
|
||||
* @param div The HTMLElement that will contain the list
|
||||
* @param database The database that will be used to fill the list of blueprints
|
||||
* @param filter A string filter that will be executed to filter the blueprints to add
|
||||
* @param callback Callback called when the user clicks on one of the elements
|
||||
*/
|
||||
export function addBlueprintsScroll(div: HTMLElement, database: {blueprints: {[key: string]: UnitBlueprint}}, callback: CallableFunction) {
|
||||
export function addBlueprintsScroll(div: HTMLElement, database: {blueprints: {[key: string]: UnitBlueprint}}, filter: string, callback: CallableFunction) {
|
||||
var scrollDiv = document.createElement("div");
|
||||
scrollDiv.classList.add("dm-scroll-container");
|
||||
if (database !== null) {
|
||||
var blueprints: {[key: string]: UnitBlueprint} = database.blueprints;
|
||||
|
||||
for (let key of Object.keys(blueprints).sort((a, b) => a.localeCompare(b, undefined, {sensitivity: 'base'}))) {
|
||||
var rowDiv = document.createElement("div");
|
||||
scrollDiv.appendChild(rowDiv);
|
||||
|
||||
var text = document.createElement("label");
|
||||
text.textContent = key;
|
||||
text.onclick = () => callback(key);
|
||||
rowDiv.appendChild(text);
|
||||
|
||||
let checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.checked = blueprints[key].enabled;
|
||||
checkbox.onclick = () => {
|
||||
console.log(checkbox.checked);
|
||||
blueprints[key].enabled = checkbox.checked;
|
||||
var addKey = true;
|
||||
if (filter !== "") {
|
||||
try {
|
||||
var blueprint = blueprints[key];
|
||||
addKey = eval(filter);
|
||||
} catch {
|
||||
console.error("An error has occurred evaluating the blueprint filter")
|
||||
}
|
||||
}
|
||||
rowDiv.appendChild(checkbox);
|
||||
|
||||
/* This button allows to remove an element from the list. It requires a refresh. */
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "X";
|
||||
button.onclick = () => {
|
||||
delete blueprints[key];
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
if (addKey) {
|
||||
var rowDiv = document.createElement("div");
|
||||
scrollDiv.appendChild(rowDiv);
|
||||
|
||||
let text = document.createElement("div");
|
||||
text.innerHTML = `<div>${key}</div> <div>${blueprints[key].label}</div>`;
|
||||
text.onclick = () => {
|
||||
callback(key);
|
||||
const collection = document.getElementsByClassName("blueprint-selected");
|
||||
for (let i = 0; i < collection.length; i++) {
|
||||
collection[i].classList.remove("blueprint-selected");
|
||||
}
|
||||
text.classList.add("blueprint-selected");
|
||||
}
|
||||
rowDiv.appendChild(text);
|
||||
|
||||
let checkbox = document.createElement("input");
|
||||
checkbox.type = "checkbox";
|
||||
checkbox.checked = blueprints[key].enabled;
|
||||
checkbox.onclick = () => {
|
||||
console.log(checkbox.checked);
|
||||
blueprints[key].enabled = checkbox.checked;
|
||||
}
|
||||
rowDiv.appendChild(checkbox);
|
||||
|
||||
/* This button allows to remove an element from the list. It requires a refresh. */
|
||||
var button = document.createElement("button");
|
||||
button.innerText = "X";
|
||||
button.onclick = () => {
|
||||
delete blueprints[key];
|
||||
div.dispatchEvent(new Event("refresh"));
|
||||
}
|
||||
rowDiv.appendChild(button);
|
||||
}
|
||||
rowDiv.appendChild(button);
|
||||
}
|
||||
}
|
||||
div.appendChild(scrollDiv);
|
||||
@@ -264,24 +284,14 @@ export function addLoadoutsScroll(div: HTMLElement, loadouts: LoadoutBlueprint[]
|
||||
* @returns The string
|
||||
*/
|
||||
export function arrayToString(array: string[]) {
|
||||
var value = "[";
|
||||
var firstRole = true;
|
||||
array.forEach((role: string) => {
|
||||
value += firstRole? "": ", ";
|
||||
firstRole = false;
|
||||
value += role;
|
||||
})
|
||||
value += "]";
|
||||
return value;
|
||||
return "[" + array.join( ", " ) + "]";
|
||||
}
|
||||
|
||||
|
||||
/** Converts an a single string like [val1, val2, val3] into an array
|
||||
*
|
||||
* @param input The input string
|
||||
* @returns The array
|
||||
*/
|
||||
export function stringToArray(input: string) {
|
||||
input = input.replace("[", "").replace("]", "");
|
||||
var values = input.split(",");
|
||||
var result: string[] = [];
|
||||
values.forEach((value: string) => {
|
||||
result.push(value.trim());
|
||||
})
|
||||
return result;
|
||||
return input.match( /(\w)+/g ) ?? [];
|
||||
}
|
||||
@@ -63,6 +63,8 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 5px;
|
||||
max-height: 100%;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
@media (min-width: 1200px) {
|
||||
@@ -71,7 +73,7 @@
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(1) {
|
||||
width: 300px;
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.dm-content-container:nth-of-type(2) {
|
||||
@@ -115,6 +117,10 @@
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#database-manager-panel input {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div:nth-child(even) {
|
||||
background-color: gainsboro;
|
||||
}
|
||||
@@ -131,23 +137,45 @@
|
||||
}
|
||||
|
||||
.dm-scroll-container>div *:nth-child(1):hover {
|
||||
background-color: var(--secondary-blue-text);
|
||||
background-color: var(--accent-dark-blue);
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.blueprint-selected {
|
||||
background-color: var(--accent-light-blue) !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>div {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>button {
|
||||
height: 20px;
|
||||
width: 20px;
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>div>div:nth-child(1) {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
.dm-scroll-container>div>div>div:nth-child(2) {
|
||||
overflow: hidden;
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
.input-row {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
|
||||
BIN
client/public/images/favicons/android-chrome-192x192.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
client/public/images/favicons/android-chrome-512x512.png
Normal file
|
After Width: | Height: | Size: 88 KiB |
BIN
client/public/images/favicons/apple-touch-icon.png
Normal file
|
After Width: | Height: | Size: 20 KiB |
BIN
client/public/images/favicons/favicon-16x16.png
Normal file
|
After Width: | Height: | Size: 779 B |
BIN
client/public/images/favicons/favicon-32x32.png
Normal file
|
After Width: | Height: | Size: 1.9 KiB |
BIN
client/public/images/favicons/favicon.ico
Normal file
|
After Width: | Height: | Size: 15 KiB |
16
client/public/images/favicons/site.webmanifest
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "DCS Olympus",
|
||||
"short_name": "DCS Olympus",
|
||||
"icons": [{
|
||||
"src": "/images/favicons/android-chrome-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png"
|
||||
}, {
|
||||
"src": "/images/favicons/android-chrome-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png"
|
||||
}],
|
||||
"theme_color": "#ffffff",
|
||||
"background_color": "#ffffff",
|
||||
"display": "standalone"
|
||||
}
|
||||
@@ -1,7 +1,3 @@
|
||||
:root {
|
||||
--right-panel-width:190px;
|
||||
}
|
||||
|
||||
/* Page style */
|
||||
#map-container {
|
||||
height: 100%;
|
||||
@@ -17,54 +13,10 @@
|
||||
top: 10px;
|
||||
z-index: 99999;
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
margin-right: 320px;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
@media (max-width: 1820px) {
|
||||
#toolbar-container {
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
row-gap: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
#primary-toolbar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: fit-content;
|
||||
min-width: 650px;
|
||||
}
|
||||
|
||||
@media (max-width: 1820px) {
|
||||
#primary-toolbar {
|
||||
row-gap: 10px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
|
||||
#command-mode-toolbar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#app-icon>.ol-select-options {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#toolbar-summary {
|
||||
background-image: url("/images/icon-round.png");
|
||||
background-position: 20px 22px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 45px 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
text-indent: 60px;
|
||||
}
|
||||
|
||||
#toolbar-summary {
|
||||
white-space: nowrap;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
#connection-status-panel {
|
||||
@@ -72,7 +24,7 @@
|
||||
font-size: 12px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
width: var( --right-panel-width );
|
||||
width: 190px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
@@ -84,35 +36,21 @@
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
row-gap: 10px;
|
||||
width: var( --right-panel-width );
|
||||
width: 190px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
#unit-control-panel {
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
left: 10px;
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
width: 320px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
@media (max-width: 1820px) {
|
||||
#unit-control-panel {
|
||||
top: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1350px) {
|
||||
#unit-control-panel {
|
||||
top: 190px;
|
||||
}
|
||||
}
|
||||
|
||||
#unit-info-panel {
|
||||
bottom: 20px;
|
||||
font-size: 12px;
|
||||
left: 10px;
|
||||
position: absolute;
|
||||
width: fit-content;
|
||||
z-index: 9999;
|
||||
@@ -120,12 +58,8 @@
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
|
||||
@media (max-width: 1525px) {
|
||||
#unit-info-panel {
|
||||
flex-direction: column;
|
||||
}
|
||||
right: 210px;
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
#info-popup {
|
||||
@@ -140,6 +74,16 @@
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#slow-delete-popup {
|
||||
align-self: center;
|
||||
display:flex;
|
||||
justify-self: center;
|
||||
position: absolute;
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
z-index: 9999999999;
|
||||
}
|
||||
|
||||
#log-panel {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
|
||||
@@ -97,6 +97,22 @@
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
[data-object|="unit-groundunit"] .unit-short-label {
|
||||
transform: translateY(7px);
|
||||
}
|
||||
|
||||
/*** 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 +125,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 +195,7 @@
|
||||
|
||||
/*** Common ***/
|
||||
[data-object|="unit"]:hover .unit-ammo,
|
||||
[data-object|="unit"]:hover .unit-health ,
|
||||
[data-object|="unit"]:hover .unit-fuel {
|
||||
display: flex;
|
||||
}
|
||||
@@ -188,13 +206,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 +230,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 +247,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),
|
||||
@@ -260,7 +281,8 @@
|
||||
background-image: url("/resources/theme/images/states/idle.svg");
|
||||
}
|
||||
|
||||
[data-object*="groundunit"][data-state="idle"] .unit-state {
|
||||
[data-object*="groundunit"][data-state="idle"] .unit-state,
|
||||
[data-object*="navyunit"][data-state="idle"] .unit-state {
|
||||
background-image: url(""); /* To avoid clutter, dont show the idle state for non flying units */
|
||||
}
|
||||
|
||||
@@ -307,6 +329,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 +351,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 {
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
|
||||
@import url("other/contextmenus.css");
|
||||
@import url("other/popup.css");
|
||||
@import url("other/toolbar.css");
|
||||
|
||||
|
||||
@import url("markers/airbase.css");
|
||||
@import url("markers/bullseye.css");
|
||||
|
||||
@@ -124,6 +124,28 @@
|
||||
max-height: 300px;
|
||||
}
|
||||
|
||||
.ol-tag {
|
||||
background-color: #FFFFFF11;
|
||||
color: #FFFFFFDD;
|
||||
border: 1px solid #FFFFFF55;
|
||||
font-weight: normal;
|
||||
padding: 2px 5px;
|
||||
}
|
||||
|
||||
/*
|
||||
.ol-tag-CA {
|
||||
background-color: #FF000022;
|
||||
}
|
||||
|
||||
.ol-tag-Radar {
|
||||
background-color: #00FF0022;
|
||||
}
|
||||
|
||||
.ol-tag-IR {
|
||||
background-color: #0000FF22;
|
||||
}
|
||||
*/
|
||||
|
||||
.unit-loadout-list {
|
||||
min-width: 0;
|
||||
}
|
||||
@@ -225,13 +247,14 @@
|
||||
column-gap: 5px;
|
||||
}
|
||||
|
||||
.unit-label-count-container>div:nth-child(1) {
|
||||
width: 100%;
|
||||
min-width: 0;
|
||||
.unit-label-count-container button {
|
||||
display: flex !important;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.unit-label-count-container>div:nth-child(2) {
|
||||
font-size: large;
|
||||
.unit-label-count-container button>*:nth-child(1) {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.unit-loadout-preview {
|
||||
|
||||
74
client/public/stylesheets/other/toolbar.css
Normal file
@@ -0,0 +1,74 @@
|
||||
|
||||
#primary-toolbar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
#command-mode-toolbar {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#app-icon>.ol-select-options {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#toolbar-summary {
|
||||
background-image: url("/images/icon-round.png");
|
||||
background-position: 20px 22px;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 45px 45px;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
padding: 20px;
|
||||
text-indent: 60px;
|
||||
}
|
||||
|
||||
#toolbar-summary {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#toolbar-container>*:nth-child(2)>svg {
|
||||
display: none;
|
||||
width: 0px;
|
||||
height: 0px;
|
||||
}
|
||||
|
||||
#toolbar-container>*:nth-child(3)>svg {
|
||||
display: none;
|
||||
}
|
||||
|
||||
@media (max-width: 1145px) {
|
||||
#toolbar-container {
|
||||
flex-direction: column;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
#toolbar-container>*:nth-child(1):not(:hover) {
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
#toolbar-container>*:nth-child(1):not(:hover)>*:not(:first-child) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#toolbar-container>*:not(:first-child):not(:hover) {
|
||||
height: 52px;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
aspect-ratio: 1/1;
|
||||
}
|
||||
|
||||
#toolbar-container>*:not(:first-child):not(:hover)>svg {
|
||||
display: block;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
filter: invert();
|
||||
}
|
||||
|
||||
#toolbar-container>*:not(:first-child):not(:hover)>*:not(:first-child) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,58 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
}
|
||||
|
||||
#unit-control-panel {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 10px;
|
||||
row-gap: 10px;
|
||||
}
|
||||
|
||||
#unit-control-panel>div:nth-child(2),
|
||||
#unit-controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 10px;
|
||||
}
|
||||
|
||||
#unit-controls {
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#unit-control-panel>div:nth-child(2) {
|
||||
width: 330px;
|
||||
}
|
||||
|
||||
#unit-control-panel>*:nth-child(1) {
|
||||
display: none;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
@media (max-width: 1145px) {
|
||||
#unit-control-panel>*:nth-child(1) {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
#unit-control-panel>*:nth-child(1) svg {
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
#unit-control-panel:hover>*:nth-child(1) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#unit-control-panel:not(:hover) {
|
||||
width: fit-content;
|
||||
}
|
||||
|
||||
#unit-control-panel:not(:hover)>*:nth-child(2),
|
||||
#unit-control-panel:not(:hover)>*:nth-child(3) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#unit-control-panel h3 {
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
@@ -166,20 +213,23 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
|
||||
#unit-control-panel .switch-control {
|
||||
align-items: center;
|
||||
display: grid;
|
||||
grid-template-columns: 1.35fr 0.65fr;
|
||||
}
|
||||
|
||||
#unit-control-panel .switch-control>*:nth-child(2) {
|
||||
justify-self: end;
|
||||
}
|
||||
|
||||
#unit-control-panel .switch-control>*:nth-child(3) {
|
||||
color: var(--secondary-semitransparent-white);
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
#unit-control-panel .switch-control h4 {
|
||||
margin: 0px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
#unit-control-panel .switch-control h4 img {
|
||||
height: 15px;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
filter: invert(100%);
|
||||
opacity: 80%;
|
||||
}
|
||||
|
||||
#unit-control-panel .switch-control .ol-switch {
|
||||
@@ -220,18 +270,32 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
}
|
||||
|
||||
#advanced-settings-div {
|
||||
position: relative;
|
||||
column-gap: 5px;
|
||||
display: flex;
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
#advanced-settings-div>*:nth-child(2) {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
#advanced-settings-div button {
|
||||
#advanced-settings-div>button {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
#delete-options button {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-content: center;
|
||||
}
|
||||
|
||||
#delete-options button svg {
|
||||
margin-right: 10px;
|
||||
width: 18px;
|
||||
max-height: 18px;
|
||||
}
|
||||
|
||||
/* Element visibility control */
|
||||
#unit-control-panel:not([data-show-categories-tooltip]) #categories-tooltip,
|
||||
#unit-control-panel:not([data-show-speed-slider]) #speed-slider,
|
||||
@@ -239,6 +303,8 @@ body.feature-forceShowUnitControlPanel #unit-control-panel {
|
||||
#unit-control-panel:not([data-show-roe]) #roe,
|
||||
#unit-control-panel:not([data-show-threat]) #threat,
|
||||
#unit-control-panel:not([data-show-emissions-countermeasures]) #emissions-countermeasures,
|
||||
#unit-control-panel:not([data-show-shots-scatter]) #shots-scatter,
|
||||
#unit-control-panel:not([data-show-shots-intensity]) #shots-intensity,
|
||||
#unit-control-panel:not([data-show-tanker-button]) #tanker-on,
|
||||
#unit-control-panel:not([data-show-AWACS-button]) #AWACS-on,
|
||||
#unit-control-panel:not([data-show-on-off]) #ai-on-off,
|
||||
|
||||
@@ -1,47 +1,47 @@
|
||||
#unit-info-panel>* {
|
||||
position: relative;
|
||||
min-height: 100px;
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
@media (min-width: 1525px) {
|
||||
#unit-info-panel>.panel-section {
|
||||
border-right: 1px solid #555;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:first-child {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-child {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-of-type {
|
||||
border-right-width: 0;
|
||||
}
|
||||
#unit-info-panel>*:nth-child(1) {
|
||||
display: flex;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 6px;
|
||||
filter: invert(100%);
|
||||
}
|
||||
|
||||
@media (max-width: 1525px) {
|
||||
#unit-info-panel>.panel-section {
|
||||
border-bottom: 1px solid #555;
|
||||
padding: 30px 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-child {
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-of-type {
|
||||
border-bottom-width: 0;
|
||||
}
|
||||
#unit-info-panel:hover>*:nth-child(1) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#unit-info-panel:not(:hover) {
|
||||
width: fit-content;
|
||||
height: fit-content;
|
||||
padding: 10px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel:not(:hover)>*:not(:first-child) {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section {
|
||||
border-right: 1px solid #555;
|
||||
padding: 0 30px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:first-of-type {
|
||||
padding-left: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-of-type{
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
#unit-info-panel>.panel-section:last-of-type {
|
||||
border-right-width: 0;
|
||||
}
|
||||
|
||||
#general {
|
||||
display: flex;
|
||||
@@ -49,6 +49,7 @@
|
||||
justify-content: space-between;
|
||||
row-gap: 4px;
|
||||
position: relative;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#unit-label {
|
||||
@@ -63,6 +64,10 @@
|
||||
#unit-name {
|
||||
margin-bottom: 4px;
|
||||
padding: 0px 0;
|
||||
width: 100%;
|
||||
text-overflow: ellipsis;
|
||||
text-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#current-task {
|
||||
@@ -87,24 +92,24 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
#loadout-silhouette {
|
||||
filter: invert(100%);
|
||||
height: 100px;
|
||||
height: 75px;
|
||||
margin-right: 25px;
|
||||
width: 100px;
|
||||
width: 75px;
|
||||
}
|
||||
|
||||
#loadout-items {
|
||||
margin-right: 20px;
|
||||
align-self: center;
|
||||
display: flex;
|
||||
flex-flow: column;
|
||||
row-gap: 8px;
|
||||
column-gap: 8px;
|
||||
max-height: 90px;
|
||||
flex-wrap: wrap;
|
||||
display: flex;
|
||||
flex-flow: column nowrap;
|
||||
height: 100px;
|
||||
row-gap: 6px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
|
||||
#loadout-items>* {
|
||||
@@ -122,7 +127,7 @@
|
||||
display: flex;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
padding: 4px 6px;
|
||||
padding: 3px 4px;
|
||||
}
|
||||
|
||||
#loadout-items>*::after {
|
||||
@@ -137,7 +142,7 @@
|
||||
#fuel-percentage {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
margin-top: auto;
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
#fuel-percentage::before {
|
||||
|
||||
@@ -72,10 +72,6 @@ form {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
form>div {
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.pill {
|
||||
background-color: var(--background-steel);
|
||||
border-radius: 999px;
|
||||
@@ -92,7 +88,7 @@ form>div {
|
||||
}
|
||||
|
||||
.ol-scrollable {
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
scrollbar-color: white transparent;
|
||||
scrollbar-width: thin;
|
||||
}
|
||||
@@ -343,10 +339,32 @@ h4 {
|
||||
font-weight: normal;
|
||||
}
|
||||
|
||||
button.ol-button-white {
|
||||
border: 1px solid white;
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
button.ol-button-white>svg:first-child {
|
||||
stroke: white;
|
||||
fill: white;
|
||||
}
|
||||
|
||||
.ol-select-warning {
|
||||
border: 1px solid var(--primary-red);
|
||||
color: var(--primary-red) !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.ol-select-warning::after {
|
||||
stroke: var(--primary-red);
|
||||
fill: var(--primary-red);
|
||||
}
|
||||
|
||||
button.ol-button-warning {
|
||||
border: 1px solid var(--primary-red);
|
||||
color: var(--primary-red);
|
||||
font-weight: bold;
|
||||
color: var(--primary-red) !important;
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
button.ol-button-warning>svg:first-child {
|
||||
@@ -605,6 +623,12 @@ nav.ol-panel> :last-child {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > div {
|
||||
align-items: center;
|
||||
display:flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group button {
|
||||
border: none;
|
||||
height: 32px;
|
||||
@@ -638,9 +662,65 @@ nav.ol-panel> :last-child {
|
||||
stroke: var(--background-steel) !important;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group .protectable button:first-of-type {
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-right-radius: 0;
|
||||
width:28px;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button.lock {
|
||||
align-items: center;
|
||||
background-color: var(--primary-red);
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-left-radius: 0;
|
||||
display:flex;
|
||||
justify-content: center;
|
||||
width:18px;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button[data-protected].lock {
|
||||
background-color: var(--background-grey);
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button.lock svg {
|
||||
height:10px;
|
||||
width:10px;
|
||||
}
|
||||
|
||||
@keyframes lock-prompt {
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
0% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button[data-protected].lock.prompt svg {
|
||||
animation: lock-prompt .25s alternate infinite;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button.lock svg.locked * {
|
||||
fill:white !important;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button:not([data-protected]).lock svg.unlocked,
|
||||
.ol-navbar-buttons-group > .protectable > button[data-protected].lock svg.locked {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group > .protectable > button[data-protected].lock svg.unlocked,
|
||||
.ol-navbar-buttons-group > .protectable > button:not([data-protected]).lock svg.locked {
|
||||
display:none;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#roe-buttons-container button,
|
||||
#reaction-to-threat-buttons-container button,
|
||||
#emissions-countermeasures-buttons-container button {
|
||||
#emissions-countermeasures-buttons-container button,
|
||||
#shots-scatter-buttons-container button
|
||||
#shots-intensity-buttons-container button {
|
||||
align-items: center;
|
||||
background-color: transparent;
|
||||
border: 1px solid var(--accent-light-blue);
|
||||
@@ -662,17 +742,15 @@ nav.ol-panel> :last-child {
|
||||
|
||||
#unit-control-panel .ol-option-button button.selected svg * {
|
||||
fill: var(--background-steel);
|
||||
stroke: var(--background-steel);
|
||||
}
|
||||
|
||||
#rapid-controls {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
row-gap: 5px;
|
||||
position: absolute;
|
||||
height: fit-content;
|
||||
width: fit-content;
|
||||
left: calc(100% + 10px);
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
#rapid-controls button {
|
||||
@@ -699,12 +777,11 @@ nav.ol-panel> :last-child {
|
||||
overflow: hidden;
|
||||
width: 70%;
|
||||
max-width: 1200px;
|
||||
z-index: 99999;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
@media (min-width: 1700px) {
|
||||
#splash-screen {
|
||||
background-image: url("/resources/theme/images/splash/1.png");
|
||||
background-position: 100% 50%;
|
||||
background-size: contain;
|
||||
}
|
||||
@@ -736,7 +813,7 @@ nav.ol-panel> :last-child {
|
||||
top: 0;
|
||||
transform: rotate(-23deg);
|
||||
transform-origin: top right;
|
||||
width: 200px;
|
||||
width: 300px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
@@ -796,7 +873,7 @@ nav.ol-panel> :last-child {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
width: 100%;
|
||||
z-index: 9999;
|
||||
z-index: 99999;
|
||||
}
|
||||
|
||||
#authentication-form {
|
||||
@@ -804,7 +881,7 @@ nav.ol-panel> :last-child {
|
||||
column-gap: 10px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 10px 0px;
|
||||
margin: 20px 0px;
|
||||
flex-wrap: wrap;
|
||||
width: 100%;
|
||||
row-gap: 10px;
|
||||
@@ -1148,7 +1225,7 @@ dl.ol-data-grid dd {
|
||||
background-color: var(--background-slate-blue);
|
||||
color: white;
|
||||
position: absolute;
|
||||
z-index: 9999;
|
||||
z-index: 999999;
|
||||
}
|
||||
|
||||
.ol-panel.ol-dialog {
|
||||
@@ -1178,8 +1255,10 @@ dl.ol-data-grid dd {
|
||||
}
|
||||
|
||||
.ol-dialog-footer {
|
||||
align-content: center;
|
||||
border-top: 1px solid var(--background-grey);
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding-top: 15px;
|
||||
row-gap: 10px;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<path
|
||||
style="stroke: none"
|
||||
d="m 7.5000002,0 c 0.498,0 0.9375,0.4395 0.9375,0.9375 V 1.2598 C 11.1621,1.6699 13.3301,3.8379002 13.7402,6.5625002 h 0.3223 c 0.498,0 0.9375,0.4395 0.9375,0.9375 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 H 13.7402 C 13.3301,11.1914 11.1621,13.3594 8.4375002,13.7695 v 0.293 c 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 v -0.293 C 3.8086002,13.3594 1.6406,11.1914 1.2305,8.4375002 h -0.293 c -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 h 0.293 C 1.6406,3.8379002 3.8086002,1.6699 6.5625002,1.2598 V 0.9375 c 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 z m -4.3652,8.4375002 c 0.3515,1.7284998 1.6992,3.0761998 3.4277,3.4276998 V 11.25 c 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 0.498,0 0.9375,0.4395 0.9375,0.9375 v 0.6152 C 10.1367,11.5137 11.4844,10.166 11.8359,8.4375002 H 11.25 c -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 h 0.5859 c -0.3515,-1.6992 -1.6992,-3.0469 -3.3983998,-3.3984 v 0.5859 c 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 v -0.5859 c -1.7285,0.3515 -3.0762,1.6992 -3.4277,3.3984 h 0.6152 c 0.498,0 0.9375,0.4395 0.9375,0.9375 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 z m 4.3652,0 c -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 0.498,0 0.9375,0.4395 0.9375,0.9375 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 7.0324294,0 c 0.1172,0 0.2637,0.0293 0.3809,0.0879 l 5.5077996,2.3437 c 0.6445,0.293 1.1425,0.9082 1.1425,1.67 -0.0292,2.9296 -1.2304,8.2324 -6.2694996,10.664 -0.498,0.2344 -1.0547,0.2344 -1.5527,0 -5.0391,-2.4316 -6.24020004,-7.7344 -6.24020004,-10.664 -0.0293,-0.7618 0.4687,-1.377 1.11320004,-1.67 l 5.5078,-2.3437 C 6.7394294,0.0293 6.8859294,0 7.0324294,0 Z m 0,1.9629 V 13.0371 C 11.075429,11.0742 12.159429,6.7676 12.188629,4.1602 Z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 10.796771,3.75 c 0,1.31836 -0.7618,2.46094 -1.8750496,3.13476 v 0.61525 c 0,0.5273 -0.43945,0.9375 -0.9375,0.9375 h -2.8125 c -0.52734,0 -0.9375,-0.4102 -0.9375,-0.9375 V 6.88476 c -1.14258,-0.67382 -1.875,-1.8164 -1.875,-3.13476 0,-2.05078 1.875,-3.75 4.21875,-3.75 2.31445,0 4.2187996,1.69922 4.2187996,3.75 z M 4.9373514,5.15625 c 0.49804,0 0.9375,-0.41016 0.9375,-0.9375 0,-0.49805 -0.43946,-0.9375 -0.9375,-0.9375 -0.52735,0 -0.9375,0.43945 -0.9375,0.9375 0,0.52734 0.41015,0.9375 0.9375,0.9375 z m 4.21872,-0.9375 c 0,-0.49805 -0.43943,-0.9375 -0.93748,-0.9375 -0.52734,0 -0.9375,0.43945 -0.9375,0.9375 0,0.52734 0.41016,0.9375 0.9375,0.9375 0.49805,0 0.93748,-0.41016 0.93748,-0.9375 z M 0.10336144,8.02731 c 0.23438,-0.4687 0.79102,-0.6445 1.25976996,-0.4101 l 5.21484,2.6074 5.1854996,-2.6074 c 0.4688,-0.2344 1.0254,-0.0586 1.2598,0.4101 0.2344,0.4688 0.0586,1.0254 -0.4101,1.2598 l -3.9551196,1.9629 3.9551196,1.9922 c 0.4687,0.2344 0.6445,0.791 0.4101,1.2597 -0.2344,0.4688 -0.791,0.6446 -1.2598,0.4102 l -5.1854996,-2.6074 -5.21484,2.6074 c -0.46874996,0.2344 -1.02538996,0.0586 -1.25976996,-0.4102 -0.234374,-0.4687 -0.058593,-1.0253 0.41016,-1.2597 L 4.4685914,11.25001 0.51352144,9.28711 c -0.468753,-0.2344 -0.644534,-0.791 -0.41016,-1.2598 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 9.103975,1.603975 c 0.3809,-0.3515 0.3809,-0.9668 0,-1.3183 -0.3515,-0.3809 -0.9668,-0.3809 -1.3183,0 l -3.0762,3.0761 -3.1055,-3.0761 c -0.3515,-0.3809 -0.9668,-0.3809 -1.3183,0 -0.3809,0.3515 -0.3809,0.9668 0,1.3183 l 3.0761,3.0762 -3.0761,3.1055 c -0.3809,0.3515 -0.3809,0.9668 0,1.3183 0.3515,0.3809 0.9668,0.3809 1.3183,0 l 3.1055,-3.0761 3.0762,3.0761 c 0.3515,0.3809 0.9668,0.3809 1.3183,0 0.3809,-0.3515 0.3809,-0.9668 0,-1.3183 l -3.0761,-3.1055 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
69
client/public/themes/olympus/images/buttons/intensity/1.svg
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="1.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
width="30px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="16.808938"
|
||||
inkscape:cx="4.2536893"
|
||||
inkscape:cy="-1.2195892"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<rect
|
||||
style="stroke-width:0.659;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers;fill-opacity:1"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff"
|
||||
id="rect1107"
|
||||
width="2.8299551"
|
||||
height="3.9513376"
|
||||
x="1.7056587"
|
||||
y="9.5718069" />
|
||||
<rect
|
||||
style="fill:none;stroke-width:0.659001;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff"
|
||||
id="rect1107-7"
|
||||
width="2.8299551"
|
||||
height="7.6993432"
|
||||
x="6.0053182"
|
||||
y="5.817802" />
|
||||
<rect
|
||||
style="fill:none;stroke-width:0.659001;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff"
|
||||
id="rect1107-9"
|
||||
width="2.8299551"
|
||||
height="11.89354"
|
||||
x="10.304977"
|
||||
y="1.7128451" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
69
client/public/themes/olympus/images/buttons/intensity/2.svg
Normal file
@@ -0,0 +1,69 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="2.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
width="30px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="16.808938"
|
||||
inkscape:cx="4.2536893"
|
||||
inkscape:cy="-1.2195892"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<rect
|
||||
style="stroke-width:0.659;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers;fill-opacity:1"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff"
|
||||
id="rect1107"
|
||||
width="2.8299551"
|
||||
height="3.9513376"
|
||||
x="1.7056587"
|
||||
y="9.5718069" />
|
||||
<rect
|
||||
style="stroke-width:0.659001;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers;fill-opacity:1"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff"
|
||||
id="rect1107-7"
|
||||
width="2.8299551"
|
||||
height="7.6993432"
|
||||
x="6.0053182"
|
||||
y="5.817802" />
|
||||
<rect
|
||||
style="fill:none;stroke-width:0.659001;stroke-linecap:round;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:5.6;stroke-opacity:1;paint-order:stroke fill markers"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff"
|
||||
id="rect1107-9"
|
||||
width="2.8299551"
|
||||
height="11.89354"
|
||||
x="10.304977"
|
||||
y="1.7128451" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
62
client/public/themes/olympus/images/buttons/intensity/3.svg
Normal file
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
viewBox="0 0 15 15"
|
||||
id="svg8"
|
||||
sodipodi:docname="3.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
id="namedview10"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="55.466667"
|
||||
inkscape:cx="7.4909856"
|
||||
inkscape:cy="7.4909856"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8" />
|
||||
<rect
|
||||
x="1.7057"
|
||||
y="9.5718"
|
||||
width="2.83"
|
||||
height="3.9513"
|
||||
style="paint-order:stroke fill markers;stroke-dashoffset:5.6;stroke-linecap:round;stroke-linejoin:bevel;stroke-width:.659;"
|
||||
id="rect2"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff" />
|
||||
<rect
|
||||
x="6.0053"
|
||||
y="5.8178"
|
||||
width="2.83"
|
||||
height="7.6993"
|
||||
style="paint-order:stroke fill markers;stroke-dashoffset:5.6;stroke-linecap:round;stroke-linejoin:bevel;stroke-width:.659;"
|
||||
id="rect4"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff" />
|
||||
<rect
|
||||
x="10.305"
|
||||
y="1.7128"
|
||||
width="2.83"
|
||||
height="11.894"
|
||||
style="paint-order:stroke fill markers;stroke-dashoffset:5.6;stroke-linecap:round;stroke-linejoin:bevel;stroke-width:.659;"
|
||||
id="rect6"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M352 144c0-44.2 35.8-80 80-80s80 35.8 80 80v48c0 17.7 14.3 32 32 32s32-14.3 32-32V144C576 64.5 511.5 0 432 0S288 64.5 288 144v48H64c-35.3 0-64 28.7-64 64V448c0 35.3 28.7 64 64 64H384c35.3 0 64-28.7 64-64V256c0-35.3-28.7-64-64-64H352V144z"/></svg>
|
||||
|
After Width: | Height: | Size: 485 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M144 144v48H304V144c0-44.2-35.8-80-80-80s-80 35.8-80 80zM80 192V144C80 64.5 144.5 0 224 0s144 64.5 144 144v48h16c35.3 0 64 28.7 64 64V448c0 35.3-28.7 64-64 64H64c-35.3 0-64-28.7-64-64V256c0-35.3 28.7-64 64-64H80z"/></svg>
|
||||
|
After Width: | Height: | Size: 460 B |
@@ -40,5 +40,6 @@
|
||||
<path
|
||||
d="m 7.5000002,0 c 0.498,0 0.9375,0.4395 0.9375,0.9375 V 1.2598 C 11.1621,1.6699 13.3301,3.8379002 13.7402,6.5625002 h 0.3223 c 0.498,0 0.9375,0.4395 0.9375,0.9375 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 H 13.7402 C 13.3301,11.1914 11.1621,13.3594 8.4375002,13.7695 v 0.293 c 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 v -0.293 C 3.8086002,13.3594 1.6406,11.1914 1.2305,8.4375002 h -0.293 c -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 h 0.293 C 1.6406,3.8379002 3.8086002,1.6699 6.5625002,1.2598 V 0.9375 c 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 z m -4.3652,8.4375002 c 0.3515,1.7284998 1.6992,3.0761998 3.4277,3.4276998 V 11.25 c 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 0.498,0 0.9375,0.4395 0.9375,0.9375 v 0.6152 C 10.1367,11.5137 11.4844,10.166 11.8359,8.4375002 H 11.25 c -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 h 0.5859 c -0.3515,-1.6992 -1.6992,-3.0469 -3.3983998,-3.3984 v 0.5859 c 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 v -0.5859 c -1.7285,0.3515 -3.0762,1.6992 -3.4277,3.3984 h 0.6152 c 0.498,0 0.9375,0.4395 0.9375,0.9375 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 z m 4.3652,0 c -0.5273,0 -0.9375,-0.4102 -0.9375,-0.9375 0,-0.498 0.4102,-0.9375 0.9375,-0.9375 0.498,0 0.9375,0.4395 0.9375,0.9375 0,0.5273 -0.4395,0.9375 -0.9375,0.9375 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.6 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 10.796771,3.75 c 0,1.31836 -0.7618,2.46094 -1.8750496,3.13476 v 0.61525 c 0,0.5273 -0.43945,0.9375 -0.9375,0.9375 h -2.8125 c -0.52734,0 -0.9375,-0.4102 -0.9375,-0.9375 V 6.88476 c -1.14258,-0.67382 -1.875,-1.8164 -1.875,-3.13476 0,-2.05078 1.875,-3.75 4.21875,-3.75 2.31445,0 4.2187996,1.69922 4.2187996,3.75 z M 4.9373514,5.15625 c 0.49804,0 0.9375,-0.41016 0.9375,-0.9375 0,-0.49805 -0.43946,-0.9375 -0.9375,-0.9375 -0.52735,0 -0.9375,0.43945 -0.9375,0.9375 0,0.52734 0.41015,0.9375 0.9375,0.9375 z m 4.21872,-0.9375 c 0,-0.49805 -0.43943,-0.9375 -0.93748,-0.9375 -0.52734,0 -0.9375,0.43945 -0.9375,0.9375 0,0.52734 0.41016,0.9375 0.9375,0.9375 0.49805,0 0.93748,-0.41016 0.93748,-0.9375 z M 0.10336144,8.02731 c 0.23438,-0.4687 0.79102,-0.6445 1.25976996,-0.4101 l 5.21484,2.6074 5.1854996,-2.6074 c 0.4688,-0.2344 1.0254,-0.0586 1.2598,0.4101 0.2344,0.4688 0.0586,1.0254 -0.4101,1.2598 l -3.9551196,1.9629 3.9551196,1.9922 c 0.4687,0.2344 0.6445,0.791 0.4101,1.2597 -0.2344,0.4688 -0.791,0.6446 -1.2598,0.4102 l -5.1854996,-2.6074 -5.21484,2.6074 c -0.46874996,0.2344 -1.02538996,0.0586 -1.25976996,-0.4102 -0.234374,-0.4687 -0.058593,-1.0253 0.41016,-1.2597 L 4.4685914,11.25001 0.51352144,9.28711 c -0.468753,-0.2344 -0.644534,-0.791 -0.41016,-1.2598 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 9.103975,1.603975 c 0.3809,-0.3515 0.3809,-0.9668 0,-1.3183 -0.3515,-0.3809 -0.9668,-0.3809 -1.3183,0 l -3.0762,3.0761 -3.1055,-3.0761 c -0.3515,-0.3809 -0.9668,-0.3809 -1.3183,0 -0.3809,0.3515 -0.3809,0.9668 0,1.3183 l 3.0761,3.0762 -3.0761,3.1055 c -0.3809,0.3515 -0.3809,0.9668 0,1.3183 0.3515,0.3809 0.9668,0.3809 1.3183,0 l 3.1055,-3.0761 3.0762,3.0761 c 0.3515,0.3809 0.9668,0.3809 1.3183,0 0.3809,-0.3515 0.3809,-0.9668 0,-1.3183 l -3.0761,-3.1055 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 7.0324294,0 c 0.1172,0 0.2637,0.0293 0.3809,0.0879 l 5.5077996,2.3437 c 0.6445,0.293 1.1425,0.9082 1.1425,1.67 -0.0292,2.9296 -1.2304,8.2324 -6.2694996,10.664 -0.498,0.2344 -1.0547,0.2344 -1.5527,0 -5.0391,-2.4316 -6.24020004,-7.7344 -6.24020004,-10.664 -0.0293,-0.7618 0.4687,-1.377 1.11320004,-1.67 l 5.5078,-2.3437 C 6.7394294,0.0293 6.8859294,0 7.0324294,0 Z m 0,1.9629 V 13.0371 C 11.075429,11.0742 12.159429,6.7676 12.188629,4.1602 Z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
56
client/public/themes/olympus/images/buttons/scatter/1.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="1.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
width="30px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="23.771428"
|
||||
inkscape:cx="2.6712741"
|
||||
inkscape:cy="12.283654"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<path
|
||||
style="opacity:1;fill:none;stroke-width:2.13035;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1;stroke-dashoffset:0"
|
||||
id="path940"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="7.614182"
|
||||
sodipodi:cy="12.730443"
|
||||
sodipodi:rx="11.467682"
|
||||
sodipodi:ry="10.686775"
|
||||
sodipodi:start="4.1887902"
|
||||
sodipodi:end="5.2359878"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 1.880341,3.4754242 a 11.467682,10.686775 0 0 1 11.467682,2e-7 L 7.614182,12.730443 Z"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
56
client/public/themes/olympus/images/buttons/scatter/2.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="2.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
width="30px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="23.771428"
|
||||
inkscape:cx="2.6712741"
|
||||
inkscape:cy="12.283654"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<path
|
||||
style="opacity:1;fill:none;stroke-width:2.13035;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path940"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="7.614182"
|
||||
sodipodi:cy="12.730443"
|
||||
sodipodi:rx="11.467682"
|
||||
sodipodi:ry="10.686775"
|
||||
sodipodi:start="4.3633231"
|
||||
sodipodi:end="5.0614548"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 3.6920035,2.6881593 a 11.467682,10.686775 0 0 1 7.8443565,-2e-7 L 7.614182,12.730443 Z"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
56
client/public/themes/olympus/images/buttons/scatter/3.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="15"
|
||||
height="15"
|
||||
viewBox="0 0 15 15"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="3.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
width="30px"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="23.771428"
|
||||
inkscape:cx="2.6712741"
|
||||
inkscape:cy="12.283654"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
inkscape:window-x="1912"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4"
|
||||
inkscape:showpageshadow="2"
|
||||
inkscape:deskcolor="#d1d1d1" />
|
||||
<path
|
||||
style="opacity:1;fill:none;stroke-width:2.13035;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||
id="path940"
|
||||
sodipodi:type="arc"
|
||||
sodipodi:cx="7.614182"
|
||||
sodipodi:cy="12.730443"
|
||||
sodipodi:rx="11.467682"
|
||||
sodipodi:ry="10.686775"
|
||||
sodipodi:start="4.5378561"
|
||||
sodipodi:end="4.8869219"
|
||||
sodipodi:arc-type="slice"
|
||||
d="m 5.6228404,2.2060238 a 11.467682,10.686775 0 0 1 3.9826836,10e-8 L 7.614182,12.730443 Z"
|
||||
fill="#5ca7ff"
|
||||
stroke="#5ca7ff" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
@@ -39,7 +39,8 @@
|
||||
<path
|
||||
d="m 0.02182384,14.515426 c -0.0453,0.1119 -0.01864,0.2398 0.06662,0.325 0.08526,0.0853 0.21314,0.1119 0.32505,0.0666 l 1.95830996,-0.7833 c 0.15188,-0.0613 0.2891,-0.1505 0.405,-0.2664 l 1.02578,-1.0258 3.03735,0.7993 -0.2504,0.2504 c -0.1772,0.1772 -0.1772,0.4623 0,0.6395 0.1772,0.1772 0.4623,0.1772 0.6394,0 l 0.7461,-0.746 0.4263,-0.4263 0.3197,-0.3198 c 0.1772,-0.1771 0.1772,-0.4622 0,-0.6394 -0.1772,-0.1772 -0.4623,-0.1772 -0.6395,0 l -0.1065,0.1066 -1.9184,-1.9184 0.4356,-0.4356 1.4628,0.0959 c 0.0866,0.0066 0.1718,-0.0253 0.2331,-0.0866 l 0.2132,-0.2130999 c 0.1172,-0.1173 0.1172,-0.3091 0,-0.4263 l -1.2789,-1.2789 -0.8526,0.8526 c -0.1173,0.1172 -0.3091,0.1172 -0.4263,0 -0.1173,-0.1173 -0.1173,-0.3091 0,-0.4263 l 0.8526,-0.8526 -1.2789,-1.2789 c -0.1173,-0.1173 -0.3091,-0.1173 -0.4263,0 l -0.2132,0.2131 c -0.0613,0.0613 -0.0933,0.1465 -0.0866,0.2331 l 0.0959,1.4628 -0.4356,0.4356 -1.91834,-1.9183 0.10657,-0.1066 c 0.17717,-0.1772 0.17717,-0.4623 0,-0.6395 -0.17717,-0.1771 -0.46228,-0.1771 -0.63945,0 l -0.31972,0.3198 -0.4263,0.4263 -0.74602996,0.746 c -0.17717,0.1772 -0.17717,0.4623 0,0.6394 0.17717,0.1772 0.46228,0.1772 0.63944996,0 l 0.25041,-0.2504 0.79936,3.0373999 -1.02578,1.0258 c -0.11590996,0.1159 -0.20516996,0.2531 -0.26644996,0.405 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 9.0916338,5.3111261 c 2.5638002,-2.3307 8.3905002,-6.43275 11.1873002,-4.19528 3.4961,2.79688 4.1953,9.0895799 -2.7968,16.7808799"
|
||||
stroke="#5ca7ff"
|
||||
@@ -50,13 +51,16 @@
|
||||
<path
|
||||
d="m 14.783034,12.805026 -0.1001,0.8985 0.9106,-0.2539 0.0806,0.6152 -0.8301,0.0586 0.5444,0.7251 -0.5542,0.2954 -0.3808,-0.7642 -0.3345,0.7593 -0.5762,-0.2905 0.5396,-0.7251 -0.8252,-0.0635 0.0952,-0.6103 0.8911,0.2539 -0.1001,-0.8985 z"
|
||||
fill="#5ca7ff"
|
||||
id="path6" />
|
||||
id="path6"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 13.384534,7.2113261 -0.1001,0.8984 0.9107,-0.2539 0.0805,0.6152 -0.83,0.0586 0.5444,0.7251 -0.5542,0.2954 -0.3809,-0.7641 -0.3344,0.7593 -0.5762,-0.2906 0.5395,-0.7251 -0.8252,-0.0634 0.0953,-0.6104 0.8911,0.2539 -0.1001,-0.8984 z"
|
||||
fill="#5ca7ff"
|
||||
id="path8" />
|
||||
id="path8"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 18.977834,7.2113261 -0.1001,0.8984 0.9106,-0.2539 0.0806,0.6152 -0.8301,0.0586 0.5445,0.7251 -0.5542,0.2954 -0.3809,-0.7641 -0.3345,0.7593 -0.5761,-0.2906 0.5395,-0.7251 -0.8252,-0.0634 0.0952,-0.6104 0.8911,0.2539 -0.1001,-0.8984 z"
|
||||
fill="#5ca7ff"
|
||||
id="path10" />
|
||||
id="path10"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.6 KiB |
@@ -39,7 +39,8 @@
|
||||
<path
|
||||
d="m 0.02182384,14.515426 c -0.0453,0.1119 -0.01864,0.2398 0.06662,0.325 0.08526,0.0853 0.21314,0.1119 0.32505,0.0666 l 1.95830996,-0.7833 c 0.15188,-0.0613 0.2891,-0.1505 0.405,-0.2664 l 1.02578,-1.0258 3.03735,0.7993 -0.2504,0.2504 c -0.1772,0.1772 -0.1772,0.4623 0,0.6395 0.1772,0.1772 0.4623,0.1772 0.6394,0 l 0.7461,-0.746 0.4263,-0.4263 0.3197,-0.3198 c 0.1772,-0.1771 0.1772,-0.4622 0,-0.6394 -0.1772,-0.1772 -0.4623,-0.1772 -0.6395,0 l -0.1065,0.1066 -1.9184,-1.9184 0.4356,-0.4356 1.4628,0.0959 c 0.0866,0.0066 0.1718,-0.0253 0.2331,-0.0866 l 0.2132,-0.2130999 c 0.1172,-0.1173 0.1172,-0.3091 0,-0.4263 l -1.2789,-1.2789 -0.8526,0.8526 c -0.1173,0.1172 -0.3091,0.1172 -0.4263,0 -0.1173,-0.1173 -0.1173,-0.3091 0,-0.4263 l 0.8526,-0.8526 -1.2789,-1.2789 c -0.1173,-0.1173 -0.3091,-0.1173 -0.4263,0 l -0.2132,0.2131 c -0.0613,0.0613 -0.0933,0.1465 -0.0866,0.2331 l 0.0959,1.4628 -0.4356,0.4356 -1.91834,-1.9183 0.10657,-0.1066 c 0.17717,-0.1772 0.17717,-0.4623 0,-0.6395 -0.17717,-0.1771 -0.46228,-0.1771 -0.63945,0 l -0.31972,0.3198 -0.4263,0.4263 -0.74602996,0.746 c -0.17717,0.1772 -0.17717,0.4623 0,0.6394 0.17717,0.1772 0.46228,0.1772 0.63944996,0 l 0.25041,-0.2504 0.79936,3.0373999 -1.02578,1.0258 c -0.11590996,0.1159 -0.20516996,0.2531 -0.26644996,0.405 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 9.0916338,5.3111261 c 2.5638002,-2.3307 8.3905002,-6.43275 11.1873002,-4.19528 3.4961,2.79688 4.1953,9.0895799 -2.7968,16.7808799"
|
||||
stroke="#5ca7ff"
|
||||
|
||||
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
@@ -39,5 +39,6 @@
|
||||
<path
|
||||
d="m 9.103975,1.603975 c 0.3809,-0.3515 0.3809,-0.9668 0,-1.3183 -0.3515,-0.3809 -0.9668,-0.3809 -1.3183,0 l -3.0762,3.0761 -3.1055,-3.0761 c -0.3515,-0.3809 -0.9668,-0.3809 -1.3183,0 -0.3809,0.3515 -0.3809,0.9668 0,1.3183 l 3.0761,3.0762 -3.0761,3.1055 c -0.3809,0.3515 -0.3809,0.9668 0,1.3183 0.3515,0.3809 0.9668,0.3809 1.3183,0 l 3.1055,-3.0761 3.0762,3.0761 c 0.3515,0.3809 0.9668,0.3809 1.3183,0 0.3809,-0.3515 0.3809,-0.9668 0,-1.3183 l -3.0761,-3.1055 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.6 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -39,7 +39,8 @@
|
||||
<path
|
||||
d="M 0.1977,6.4546 C 0.07745,6.5055 0,6.6237 0,6.7542 0,6.8846 0.07745,7.0028 0.1977,7.0538 l 2.09719,0.8987 c 0.16304,0.0694 0.33629,0.106 0.51361,0.106 h 1.5693 l 1.712,2.9349 H 5.7067 c -0.2711,0 -0.4892,0.2181 -0.4892,0.4891 0,0.2711 0.2181,0.4892 0.4892,0.4892 H 6.848 7.5002 7.9893 c 0.2711,0 0.4892,-0.2181 0.4892,-0.4892 0,-0.271 -0.2181,-0.4891 -0.4892,-0.4891 H 7.8263 V 8.0585 h 0.6664 l 1.0456,1.1923 c 0.0611,0.0713 0.1508,0.1121 0.2445,0.1121 h 0.3261 c 0.1794,0 0.3261,-0.1467 0.3261,-0.3261 V 7.0802 H 9.1306 c -0.1793,0 -0.326,-0.1467 -0.326,-0.326 0,-0.1794 0.1467,-0.3261 0.326,-0.3261 H 10.435 V 4.4715 c 0,-0.1794 -0.1467,-0.3261 -0.3261,-0.3261 H 9.7828 c -0.0937,0 -0.1834,0.0407 -0.2445,0.112 L 8.4927,5.4498 H 7.8263 V 2.5149 h 0.163 c 0.2711,0 0.4892,-0.2181 0.4892,-0.4891 0,-0.2711 -0.2181,-0.4892 -0.4892,-0.4892 H 7.5002 6.848 5.7067 c -0.2711,0 -0.4892,0.2181 -0.4892,0.4892 0,0.271 0.2181,0.4891 0.4892,0.4891 H 6.0898 L 4.3778,5.4498 H 2.8085 c -0.17732,0 -0.35057,0.0367 -0.51361,0.106 z"
|
||||
fill="#5ca7ff"
|
||||
id="path2" />
|
||||
id="path2"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="M 12.8398,6.5498 H 23.2749"
|
||||
stroke="#5ca7ff"
|
||||
@@ -48,17 +49,21 @@
|
||||
<path
|
||||
d="m 16.4116,9 -0.1,0.8984 0.9106,-0.2539 0.0806,0.6152 -0.8301,0.0586 0.5444,0.7251 -0.5542,0.2955 L 16.0821,10.5747 15.7476,11.334 15.1714,11.0434 15.711,10.3183 14.8858,10.2549 14.981,9.6445 15.8721,9.8984 15.772,9 Z"
|
||||
fill="#5ca7ff"
|
||||
id="path6" />
|
||||
id="path6"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 21.4116,10.6582 -0.1,0.8984 0.9106,-0.2539 0.0806,0.6153 -0.8301,0.0585 0.5444,0.7251 -0.5542,0.2955 -0.3808,-0.7642 -0.3345,0.7593 -0.5762,-0.2906 0.5396,-0.7251 -0.8252,-0.0634 0.0952,-0.6104 0.8911,0.2539 -0.1001,-0.8984 z"
|
||||
fill="#5ca7ff"
|
||||
id="path8" />
|
||||
id="path8"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 21.4116,0 -0.1,0.8984 0.9106,-0.2539 0.0806,0.6152 -0.8301,0.0586 0.5444,0.7251 L 21.4629,2.3389 21.0821,1.5747 20.7476,2.334 20.1714,2.0434 20.711,1.3183 19.8858,1.2549 19.981,0.6445 20.8721,0.8984 20.772,0 Z"
|
||||
fill="#5ca7ff"
|
||||
id="path10" />
|
||||
id="path10"
|
||||
style="stroke: none"/>
|
||||
<path
|
||||
d="m 16.4116,1.6582 -0.1,0.8984 0.9106,-0.2539 0.0806,0.6153 -0.8301,0.0585 0.5444,0.7251 L 16.4629,3.9971 16.0821,3.2329 15.7476,3.9922 15.1714,3.7016 15.711,2.9765 14.8858,2.9131 14.981,2.3027 15.8721,2.5566 15.772,1.6582 Z"
|
||||
fill="#5ca7ff"
|
||||
id="path12" />
|
||||
id="path12"
|
||||
style="stroke: none"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M256 512A256 256 0 1 0 256 0a256 256 0 1 0 0 512zM216 336h24V272H216c-13.3 0-24-10.7-24-24s10.7-24 24-24h48c13.3 0 24 10.7 24 24v88h8c13.3 0 24 10.7 24 24s-10.7 24-24 24H216c-13.3 0-24-10.7-24-24s10.7-24 24-24zm40-208a32 32 0 1 1 0 64 32 32 0 1 1 0-64z"/></svg>
|
||||
|
After Width: | Height: | Size: 500 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M464 256A208 208 0 1 0 48 256a208 208 0 1 0 416 0zM0 256a256 256 0 1 1 512 0A256 256 0 1 1 0 256zm169.8-90.7c7.9-22.3 29.1-37.3 52.8-37.3h58.3c34.9 0 63.1 28.3 63.1 63.1c0 22.6-12.1 43.5-31.7 54.8L280 264.4c-.2 13-10.9 23.6-24 23.6c-13.3 0-24-10.7-24-24V250.5c0-8.6 4.6-16.5 12.1-20.8l44.3-25.4c4.7-2.7 7.6-7.7 7.6-13.1c0-8.4-6.8-15.1-15.1-15.1H222.6c-3.4 0-6.4 2.1-7.5 5.3l-.4 1.2c-4.4 12.5-18.2 19-30.6 14.6s-19-18.2-14.6-30.6l.4-1.2zM224 352a32 32 0 1 1 64 0 32 32 0 1 1 -64 0z"/></svg>
|
||||
|
After Width: | Height: | Size: 728 B |
1
client/public/themes/olympus/images/icons/fire-solid.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M159.3 5.4c7.8-7.3 19.9-7.2 27.7 .1c27.6 25.9 53.5 53.8 77.7 84c11-14.4 23.5-30.1 37-42.9c7.9-7.4 20.1-7.4 28 .1c34.6 33 63.9 76.6 84.5 118c20.3 40.8 33.8 82.5 33.8 111.9C448 404.2 348.2 512 224 512C98.4 512 0 404.1 0 276.5c0-38.4 17.8-85.3 45.4-131.7C73.3 97.7 112.7 48.6 159.3 5.4zM225.7 416c25.3 0 47.7-7 68.8-21c42.1-29.4 53.4-88.2 28.1-134.4c-4.5-9-16-9.6-22.5-2l-25.2 29.3c-6.6 7.6-18.5 7.4-24.7-.5c-16.5-21-46-58.5-62.8-79.8c-6.3-8-18.3-8.1-24.7-.1c-33.8 42.5-50.8 69.3-50.8 99.4C112 375.4 162.6 416 225.7 416z"/></svg>
|
||||
|
After Width: | Height: | Size: 765 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M192 64C86 64 0 150 0 256S86 448 192 448H448c106 0 192-86 192-192s-86-192-192-192H192zM496 168a40 40 0 1 1 0 80 40 40 0 1 1 0-80zM392 304a40 40 0 1 1 80 0 40 40 0 1 1 -80 0zM168 200c0-13.3 10.7-24 24-24s24 10.7 24 24v32h32c13.3 0 24 10.7 24 24s-10.7 24-24 24H216v32c0 13.3-10.7 24-24 24s-24-10.7-24-24V280H136c-13.3 0-24-10.7-24-24s10.7-24 24-24h32V200z"/></svg>
|
||||
|
After Width: | Height: | Size: 601 B |
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 |
41
client/public/themes/olympus/images/icons/napalm.svg
Normal file
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 576 512"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="napalm.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1490485"
|
||||
inkscape:cx="251.94759"
|
||||
inkscape:cy="244.11502"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 64,448 v 0 h 448 v 0 h 32 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 32 C 14.3,512 0,497.7 0,480 0,462.3 14.3,448 32,448 Z"
|
||||
id="path2"
|
||||
sodipodi:nodetypes="ccccssssssc" />
|
||||
<path
|
||||
d="m 233.26314,56.434762 c 5.55746,-5.201213 14.17865,-5.129964 19.73611,0.07125 19.66487,18.453622 38.11849,38.332232 55.36087,59.849578 7.83744,-10.25993 16.74363,-21.446096 26.36232,-30.566036 5.62871,-5.27246 14.32115,-5.27246 19.94986,0.0713 24.65233,23.512336 45.52843,54.577126 60.20583,84.074416 14.46365,29.0698 24.08233,58.78084 24.08233,79.7282 0,90.91437 -71.107,167.72133 -159.59889,167.72133 -89.48938,0 -159.59889,-76.87821 -159.59889,-167.79258 0,-27.35981 12.68241,-60.77583 32.34727,-93.8356 19.87862,-33.55852 47.95092,-68.542026 81.15319,-99.321808 z m 47.30967,292.550468 c 18.02613,0 33.98602,-4.98747 49.01966,-14.9624 29.99604,-20.94735 38.04724,-62.84206 20.02111,-95.75933 -3.20623,-6.41246 -11.39992,-6.83996 -16.03114,-1.42499 l -17.95487,20.8761 c -4.70247,5.41496 -13.18116,5.27247 -17.59863,-0.35625 -11.75617,-14.96239 -32.77477,-41.68096 -44.74469,-56.8571 -4.48872,-5.69996 -13.03866,-5.77121 -17.59863,-0.0713 -24.08233,30.28104 -36.19474,49.37591 -36.19474,70.82201 0.0712,48.80591 36.1235,77.73321 81.08193,77.73321 z"
|
||||
id="path1209"
|
||||
style="stroke-width:1" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M246.9 14.1C234 15.2 224 26 224 39c0 13.8 11.2 25 25 25H400c8.8 0 16-7.2 16-16V17.4C416 8 408 .7 398.7 1.4L246.9 14.1zM240 112c0 44.2 35.8 80 80 80s80-35.8 80-80c0-5.5-.6-10.8-1.6-16H241.6c-1 5.2-1.6 10.5-1.6 16zM72 224c-22.1 0-40 17.9-40 40s17.9 40 40 40H224v89.4L386.8 230.5c-13.3-4.3-27.3-6.5-41.6-6.5H240 72zm345.7 20.9L246.6 416H416V369.7l53.6 90.6c11.2 19 35.8 25.3 54.8 14.1s25.3-35.8 14.1-54.8L462.3 290.8c-11.2-18.9-26.6-34.5-44.6-45.9zM224 448v32c0 17.7 14.3 32 32 32H384c17.7 0 32-14.3 32-32V448H224z"/></svg>
|
||||
|
After Width: | Height: | Size: 759 B |
49
client/public/themes/olympus/images/icons/secondaries.svg
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 576 512"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="secondaries.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.1490485"
|
||||
inkscape:cx="228.44988"
|
||||
inkscape:cy="281.53728"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 64,448 v 0 h 448 v 0 h 32 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 32 C 14.3,512 0,497.7 0,480 0,462.3 14.3,448 32,448 Z"
|
||||
id="path2"
|
||||
sodipodi:nodetypes="ccccssssssc" />
|
||||
<path
|
||||
d="m 278.72676,199.54168 c 3.72808,-5.9538 11.40681,-8.06823 17.63883,-4.72965 6.23202,3.33858 8.79159,10.85038 5.89816,17.24933 l -76.28657,169.59989 c 1.22415,1.27979 2.39265,2.61522 3.50551,3.95065 l 54.08501,-30.43672 c 5.84251,-3.28294 13.13175,-1.72494 17.19369,3.56115 4.06194,5.28608 3.50551,12.79789 -1.22415,17.52755 l -48.40942,48.40941 h -39.78475 c -7.34487,-20.75484 -27.09814,-35.61152 -50.35692,-35.61152 -23.25878,0 -43.06769,14.85668 -50.35692,35.61152 H 66.281757 l -42.01048,-29.04565 c -5.39737,-3.72808 -7.28923,-10.90603 -4.39579,-16.85983 2.89343,-5.9538 9.68188,-8.84724 15.96954,-6.89973 l 54.085,16.91547 c 1.66929,-2.17007 3.39422,-4.28451 5.23044,-6.28766 l -34.66559,-57.75744 c -3.39422,-5.61994 -2.17008,-12.85353 2.8378,-17.0824 5.00787,-4.22887 12.35274,-4.17323 17.30497,0.0556 l 56.978443,48.9102 c 0.83464,-0.22257 1.66929,-0.44514 2.50393,-0.61207 l 7.56745,-79.40257 c 0.66772,-6.84409 6.39895,-12.07453 13.29868,-12.07453 6.89973,0 12.63096,5.23044 13.29868,12.07453 l 7.51181,78.95743 z m -117.74061,-6.28766 c 7.40052,0 13.35432,5.9538 13.35432,13.35432 v 26.70865 c 0,7.40052 -5.9538,13.35432 -13.35432,13.35432 -7.40052,0 -13.35432,-5.9538 -13.35432,-13.35432 v -26.70865 c 0,-7.40052 5.9538,-13.35432 13.35432,-13.35432 z"
|
||||
id="path850"
|
||||
style="stroke-width:0.999999" />
|
||||
<path
|
||||
d="m 505.67595,141.18773 c 2.83997,-4.53547 8.68946,-6.1462 13.43688,-3.60294 4.74742,2.54326 6.69725,8.26558 4.49309,13.14017 L 465.49246,279.9225 c 0.93253,0.97491 1.82267,1.99221 2.67042,3.00952 l 41.20079,-23.18604 c 4.4507,-2.50087 10.00349,-1.31402 13.09779,2.71281 3.0943,4.02682 2.67042,9.74915 -0.93253,13.35211 l -36.87726,36.87724 h -30.30716 c -5.59516,-15.81059 -20.64278,-27.12809 -38.36082,-27.12809 -17.71803,0 -32.80803,11.3175 -38.36081,27.12809 h -33.78295 l -32.00268,-22.12635 c -4.1116,-2.83997 -5.55278,-8.30798 -3.34862,-12.84345 2.20416,-4.53548 7.37545,-6.73964 12.16526,-5.25607 l 41.20078,12.88584 c 1.27163,-1.65311 2.58565,-3.26385 3.98444,-4.7898 l -26.4075,-43.99838 c -2.58564,-4.28115 -1.65312,-9.79154 2.16177,-13.013 3.81489,-3.22146 9.41006,-3.17908 13.18256,0.0423 l 43.40494,37.25874 c 0.63582,-0.16955 1.27163,-0.3391 1.90744,-0.46626 l 5.76473,-60.48717 c 0.50865,-5.21368 4.87458,-9.19811 10.13064,-9.19811 5.25607,0 9.622,3.98443 10.13065,9.19811 l 5.72234,60.14807 z m -89.69226,-4.7898 c 5.63756,0 10.17304,4.53548 10.17304,10.17303 v 20.34608 c 0,5.63755 -4.53548,10.17303 -10.17304,10.17303 -5.63755,0 -10.17303,-4.53548 -10.17303,-10.17303 v -20.34608 c 0,-5.63755 4.53548,-10.17303 10.17303,-10.17303 z"
|
||||
id="path850-7"
|
||||
style="stroke-width:1" />
|
||||
<path
|
||||
d="m 265.48894,18.393218 c 2.4073,-3.844498 7.36562,-5.209832 11.38977,-3.054038 4.02416,2.155794 5.67693,7.006327 3.80858,11.138268 l -49.2599,109.514342 c 0.79046,0.82639 1.54498,1.6887 2.26358,2.55102 l 34.92387,-19.65365 c 3.77263,-2.11987 8.47946,-1.11384 11.10234,2.29951 2.62288,3.41333 2.26358,8.26387 -0.79046,11.31792 L 247.6677,163.7656 h -25.68988 c -4.74274,-13.40185 -17.49786,-22.99514 -32.51656,-22.99514 -15.0187,0 -27.80974,9.59329 -32.51656,22.99514 h -28.63613 l -27.12708,-18.75541 c -3.485195,-2.4073 -4.70681,-7.04226 -2.838453,-10.88676 1.868353,-3.8445 6.251803,-5.71285 10.311883,-4.45531 l 34.92386,10.92269 c 1.07789,-1.40126 2.19172,-2.7666 3.37741,-4.06008 L 124.57186,99.235499 c -2.19172,-3.628918 -1.40127,-8.299804 1.83243,-11.030478 3.23369,-2.730673 7.97643,-2.694745 11.1742,0.0359 l 36.79222,31.582379 c 0.53894,-0.14372 1.07789,-0.28743 1.61684,-0.39522 l 4.88646,-51.271971 c 0.43117,-4.419378 4.13195,-7.796787 8.58725,-7.796787 4.45531,0 8.15609,3.377409 8.58725,7.796787 l 4.85054,50.984531 z m -76.02768,-4.060079 c 4.77868,0 8.62318,3.844499 8.62318,8.623175 v 17.246357 c 0,4.778677 -3.8445,8.623176 -8.62318,8.623176 -4.77868,0 -8.62317,-3.844499 -8.62317,-8.623176 V 22.956314 c 0,-4.778676 3.84449,-8.623175 8.62317,-8.623175 z"
|
||||
id="path850-6"
|
||||
style="stroke-width:0.999997" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.2 KiB |
1
client/public/themes/olympus/images/icons/smog-solid.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><!--! Font Awesome Pro 6.4.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M32 144c0 79.5 64.5 144 144 144H299.3c22.6 19.9 52.2 32 84.7 32s62.1-12.1 84.7-32H496c61.9 0 112-50.1 112-112s-50.1-112-112-112c-10.7 0-21 1.5-30.8 4.3C443.8 27.7 401.1 0 352 0c-32.6 0-62.4 12.2-85.1 32.3C242.1 12.1 210.5 0 176 0C96.5 0 32 64.5 32 144zM616 368H280c-13.3 0-24 10.7-24 24s10.7 24 24 24H616c13.3 0 24-10.7 24-24s-10.7-24-24-24zm-64 96H440c-13.3 0-24 10.7-24 24s10.7 24 24 24H552c13.3 0 24-10.7 24-24s-10.7-24-24-24zm-192 0H24c-13.3 0-24 10.7-24 24s10.7 24 24 24H360c13.3 0 24-10.7 24-24s-10.7-24-24-24zM224 392c0-13.3-10.7-24-24-24H96c-13.3 0-24 10.7-24 24s10.7 24 24 24H200c13.3 0 24-10.7 24-24z"/></svg>
|
||||
|
After Width: | Height: | Size: 858 B |
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
viewBox="0 0 576 512"
|
||||
version="1.1"
|
||||
id="svg4"
|
||||
sodipodi:docname="white-phosphorous.svg"
|
||||
inkscape:version="1.1 (c68e22c387, 2021-05-23)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs8" />
|
||||
<sodipodi:namedview
|
||||
id="namedview6"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.625"
|
||||
inkscape:cx="237.84615"
|
||||
inkscape:cy="323.38462"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1017"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg4" />
|
||||
<!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. -->
|
||||
<path
|
||||
d="m 499.6,11.3 c 6.7,-10.7 20.5,-14.5 31.7,-8.5 11.2,6 15.8,19.5 10.6,31 L 404.8,338.6 c 2.2,2.3 4.3,4.7 6.3,7.1 L 508.3,291 c 10.5,-5.9 23.6,-3.1 30.9,6.4 7.3,9.5 6.3,23 -2.2,31.5 l -87,87 h -71.5 c -13.2,-37.3 -48.7,-64 -90.5,-64 -41.8,0 -77.4,26.7 -90.5,64 H 117.8 L 42.3,363.7 C 32.6,357 29.2,344.1 34.4,333.4 39.6,322.7 51.8,317.5 63.1,321 l 97.2,30.4 c 3,-3.9 6.1,-7.7 9.4,-11.3 L 107.4,236.3 c -6.1,-10.1 -3.9,-23.1 5.1,-30.7 9,-7.6 22.2,-7.5 31.1,0.1 L 246,293.6 c 1.5,-0.4 3,-0.8 4.5,-1.1 l 13.6,-142.7 c 1.2,-12.3 11.5,-21.7 23.9,-21.7 12.4,0 22.7,9.4 23.9,21.7 l 13.5,141.9 z M 288,0 c 13.3,0 24,10.7 24,24 v 48 c 0,13.3 -10.7,24 -24,24 -13.3,0 -24,-10.7 -24,-24 V 24 C 264,10.7 274.7,0 288,0 Z"
|
||||
id="path2"
|
||||
sodipodi:nodetypes="csccccssccscccsccccsccccscccsssssss"
|
||||
style="fill:#f9ffff;fill-opacity:1;opacity:0.41025641" />
|
||||
<path
|
||||
d="m 64.847242,449.52266 v 0 H 512.84724 v 0 h 32 c 17.7,0 32,14.3 32,32 0,17.7 -14.3,32 -32,32 H 32.847242 c -17.7,0 -31.99999998,-14.3 -31.99999998,-32 0,-17.7 14.29999998,-32 31.99999998,-32 z"
|
||||
id="path965" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |
BIN
client/public/themes/olympus/images/splash/1.jpg
Normal file
|
After Width: | Height: | Size: 232 KiB |
BIN
client/public/themes/olympus/images/splash/2.jpg
Normal file
|
After Width: | Height: | Size: 520 KiB |
BIN
client/public/themes/olympus/images/splash/3.jpg
Normal file
|
After Width: | Height: | Size: 430 KiB |
BIN
client/public/themes/olympus/images/splash/4.jpg
Normal file
|
After Width: | Height: | Size: 459 KiB |
BIN
client/public/themes/olympus/images/splash/5.jpg
Normal file
|
After Width: | Height: | Size: 364 KiB |
BIN
client/public/themes/olympus/images/splash/6.jpg
Normal file
|
After Width: | Height: | Size: 185 KiB |
BIN
client/public/themes/olympus/images/splash/7.jpg
Normal file
|
After Width: | Height: | Size: 575 KiB |
BIN
client/public/themes/olympus/images/splash/8.jpg
Normal file
|
After Width: | Height: | Size: 379 KiB |
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="50" height="50" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="m45.773 41.342-19.825-33.703c-0.4253-0.72303-1.4709-0.72305-1.8962 0l-19.825 33.703c-0.43135 0.7333 0.09738 1.6577 0.94813 1.6577h39.65c0.8507 0 1.3794-0.9244 0.9481-1.6577z" fill="#3BB9FF" stroke-width="2"/>
|
||||
<text x="21.590775" y="28.910091" fill="#082e44" font-family="sans-serif" font-size="8.838px" font-weight="bold" stroke="#082e44" stroke-width=".514" style="line-height:1.25" xml:space="preserve"><tspan x="21.590775" y="28.910091" font-family="sans-serif" font-size="8.838px" font-weight="bold" stroke="#082e44" stroke-width=".514">A</tspan></text>
|
||||
<path d="M6.74842 41L25 9.97231L43.2516 41H6.74842Z" fill="none" stroke="#082E44" stroke-width="2"/>
|
||||
<text x="16.189293" y="36.063168" fill="#082e44" font-family="sans-serif" font-size="8.838px" font-weight="bold" stroke="#082e44" stroke-width=".514" style="line-height:1.25" xml:space="preserve"><tspan x="16.189293" y="36.063168" font-family="sans-serif" font-size="8.838px" font-weight="bold" stroke="#082e44" stroke-width=".514">A</tspan></text>
|
||||
<text x="27.098772" y="36.063168" fill="#082e44" font-family="sans-serif" font-size="8.838px" font-weight="bold" stroke="#082e44" stroke-width=".514" style="line-height:1.25" xml:space="preserve"><tspan x="27.098772" y="36.063168" font-family="sans-serif" font-size="8.838px" font-weight="bold" stroke="#082e44" stroke-width=".514">A</tspan></text>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 6.7 KiB |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="50" height="50" version="1.1" viewBox="0 0 50 50" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect transform="rotate(45 25 2.3724)" x="25" y="2.3724" width="32" height="32" rx="1.1" fill="white" stroke-width="2"/><rect transform="rotate(45 25 5.2008)" x="25" y="5.2008" width="28" height="28" fill="none" stroke="#082e44" stroke-width="2"/><path d="m25 14.598c0.71918 0 1.3002 0.58104 1.3002 1.3002v0.42257c3.8072 0.56478 6.814 3.5756 7.3787 7.3787h0.42257c0.71918 0 1.3002 0.58104 1.3002 1.3002s-0.58104 1.3002-1.3002 1.3002h-0.42257c-0.56478 3.8072-3.5756 6.814-7.3787 7.3787v0.42257c0 0.71918-0.58104 1.3002-1.3002 1.3002s-1.3002-0.58104-1.3002-1.3002v-0.42257c-3.8072-0.56478-6.814-3.5715-7.3787-7.3787h-0.42257c-0.71918 0-1.3002-0.58104-1.3002-1.3002s0.58104-1.3002 1.3002-1.3002h0.42257c0.56478-3.8072 3.5715-6.814 7.3787-7.3787v-0.42257c0-0.71918 0.58104-1.3002 1.3002-1.3002zm-6.0379 11.702c0.5079 2.3688 2.3729 4.2298 4.7377 4.7377v-0.83702c0-0.71918 0.58104-1.3002 1.3002-1.3002s1.3002 0.58104 1.3002 1.3002v0.83702c2.3688-0.5079 4.2298-2.3729 4.7377-4.7377h-0.83702c-0.71918 0-1.3002-0.58104-1.3002-1.3002s0.58104-1.3002 1.3002-1.3002h0.83702c-0.5079-2.3688-2.3688-4.2298-4.7377-4.7377v0.83702c0 0.71918-0.58104 1.3002-1.3002 1.3002s-1.3002-0.58104-1.3002-1.3002v-0.83702c-2.3688 0.5079-4.2298 2.3688-4.7377 4.7377h0.83702c0.71918 0 1.3002 0.58104 1.3002 1.3002s-0.58104 1.3002-1.3002 1.3002zm6.0379-2.6004a1.3002 1.3002 0 1 1 0 2.6004 1.3002 1.3002 0 1 1 0-2.6004z" fill="#082e44" stroke="#082e44" stroke-width=".040632"/></svg>
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="50" height="50" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect transform="rotate(45 25 2.3724)" x="25" y="2.3724" width="32" height="32" rx="1.1" fill="white" stroke-width="2"/>
|
||||
<rect transform="rotate(45 25 5.2008)" x="25" y="5.2008" width="28" height="28" fill="none" stroke="#082E44" stroke-width="2"/>
|
||||
<path d="m24.581 23.186c0.72013 0 1.4119 0.2013 2.0073 0.56419v8.5083h-5.4435v-4.9416l-1.5196 2.5686c-0.31753 0.53868-1.015 0.71729-1.5537 0.39976-0.53868-0.31754-0.71729-1.015-0.39975-1.5537l2.1604-3.6517c0.69461-1.1737 1.9562-1.8939 3.3199-1.8939zm-2.9826-3.1754a2.2681 2.2681 0 1 1 4.5362 0 2.2681 2.2681 0 1 1-4.5362 0zm8.1652-2.2681c0.24949 0 0.45362 0.20413 0.45362 0.45362v3.2973c0.27218 0.15594 0.45362 0.45079 0.45362 0.78533v3.0988l0.45362-0.15026v-1.5877c0-0.24949 0.20413-0.45362 0.45362-0.45362h0.45362c0.24949 0 0.45362 0.20413 0.45362 0.45362v2.3957c0 0.19562-0.12474 0.36857-0.30903 0.43094l-1.5055 0.49898v0.75698h1.3609c0.24949 0 0.45362 0.20413 0.45362 0.45362v0.45362c0 0.24949-0.20413 0.45362-0.45362 0.45362h-1.2475l0.65208 2.6112c0.07088 0.28635-0.1446 0.56419-0.43945 0.56419h-1.6869c-0.24949 0-0.45362-0.20413-0.45362-0.45362v-2.7217h-0.45362c-0.50182 0-0.90724-0.40542-0.90724-0.90724v-4.0826c0-0.50182 0.40542-0.90724 0.90724-0.90724v-0.90725c0-0.33454 0.18145-0.6294 0.45362-0.78533v-2.8436c-0.24949 0-0.45362-0.20413-0.45362-0.45362 0-0.2495 0.20413-0.45362 0.45362-0.45362h0.45362z" fill="none" stroke="#082e44"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
@@ -0,0 +1,2 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="50" height="50" version="1.1" viewBox="0 0 50 50" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect transform="rotate(45 25 2.3724)" x="25" y="2.3724" width="32" height="32" rx="1.1" fill="white" stroke-width="2"/><rect transform="rotate(45 25 5.2008)" x="25" y="5.2008" width="28" height="28" fill="none" stroke="#082E44" stroke-width="2"/><path d="m22.431 22.053-0.55497 1.5863h6.2472l-0.55497-1.5863c-0.09568-0.27217-0.35297-0.45504-0.64216-0.45504h-3.8529c-0.28918 0-0.54647 0.18287-0.64216 0.45504zm-2.0328 1.6883 0.74847-2.137c0.28706-0.81864 1.0589-1.3672 1.9265-1.3672h3.8529c0.86754 0 1.6394 0.5486 1.9265 1.3672l0.74847 2.137c0.49331 0.20412 0.84203 0.69106 0.84203 1.2588v4.0826c0 0.37636-0.30407 0.68042-0.68043 0.68042h-0.68042c-0.37636 0-0.68043-0.30407-0.68043-0.68042v-1.0206h-6.8043v1.0206c0 0.37636-0.30407 0.68042-0.68043 0.68042h-0.68042c-0.37636 0-0.68043-0.30407-0.68043-0.68042v-4.0826c0-0.56773 0.34872-1.0547 0.84203-1.2588zm1.8797 1.9392a0.68043 0.68043 0 1 0-1.3609 0 0.68043 0.68043 0 1 0 1.3609 0zm6.1239 0.68043a0.68043 0.68043 0 1 0 0-1.3609 0.68043 0.68043 0 1 0 0 1.3609z" fill="none" stroke="#082e44"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 7.5 KiB |
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="50" height="50" version="1.1" viewBox="0 0 50 50" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect transform="rotate(45 25 2.3724)" x="25" y="2.3724" width="32" height="32" rx="1.1" fill="white" stroke-width="2"/>
|
||||
<rect transform="rotate(45 25 5.2008)" x="25" y="5.2008" width="28" height="28" fill="none" stroke="#082E44" stroke-width="2"/>
|
||||
<path d="m19.209 19.55c-0.56415 0-1.0219 0.45771-1.0219 1.0219v6.8124c0 0.56415 0.45771 1.0219 1.0219 1.0219h0.34062c0 1.1283 0.91541 2.0437 2.0437 2.0437 1.1283 0 2.0437-0.91541 2.0437-2.0437h2.725c0 1.1283 0.91542 2.0437 2.0437 2.0437 1.1283 0 2.0437-0.91541 2.0437-2.0437h0.68124c0.37681 0 0.68124-0.30443 0.68124-0.68124s-0.30443-0.68124-0.68124-0.68124v-2.4418c0-0.36191-0.14264-0.70892-0.3981-0.96438l-1.6456-1.6456c-0.25546-0.25546-0.60247-0.3981-0.96438-0.3981h-1.0793v-1.0219c0-0.56415-0.45771-1.0219-1.0219-1.0219zm7.8342 3.4062h1.0793l1.6456 1.6456v0.3981h-2.725zm-6.4718 5.4499a1.0219 1.0219 0 1 1 2.0437 0 1.0219 1.0219 0 1 1-2.0437 0zm7.8342-1.0219a1.0219 1.0219 0 1 1 0 2.0437 1.0219 1.0219 0 1 1 0-2.0437z" fill="none" stroke="#082e44"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 447 B After Width: | Height: | Size: 447 B |
@@ -23,6 +23,7 @@
|
||||
--accent-amber: #ffd828;
|
||||
--accent-green: #8bff63;
|
||||
--accent-light-blue: #5ca7ff;
|
||||
--accent-dark-blue: #017DC1;
|
||||
--transparent-accent-light-blue: rgba(92, 167, 255, .33);
|
||||
--accent-light-red: #F5B6B6;
|
||||
|
||||
@@ -66,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%;
|
||||
@@ -80,4 +87,4 @@
|
||||
--unit-fuel-x: 0px;
|
||||
--unit-fuel-y: 22px;
|
||||
--unit-vvi-width: 4px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { LatLng, LatLngBounds } from "leaflet";
|
||||
import { MapMarkerControl } from "../map/map";
|
||||
|
||||
export const UNITS_URI = "units";
|
||||
export const WEAPONS_URI = "weapons";
|
||||
@@ -14,11 +15,11 @@ export const BLUE_COMMANDER = "Blue commander";
|
||||
export const RED_COMMANDER = "Red commander";
|
||||
|
||||
export const VISUAL = 1;
|
||||
export const OPTIC = 2;
|
||||
export const RADAR = 4;
|
||||
export const IRST = 8;
|
||||
export const RWR = 16;
|
||||
export const DLINK = 32;
|
||||
export const OPTIC = 2;
|
||||
export const RADAR = 4;
|
||||
export const IRST = 8;
|
||||
export const RWR = 16;
|
||||
export const DLINK = 32;
|
||||
|
||||
export const states: string[] = ["none", "idle", "reach-destination", "attack", "follow", "land", "refuel", "AWACS", "tanker", "bomb-point", "carpet-bomb", "bomb-building", "fire-at-area", "simulate-fire-fight", "scenic-aaa", "miss-on-purpose", "land-at-point"];
|
||||
export const ROEs: string[] = ["free", "designated", "", "return", "hold"];
|
||||
@@ -34,19 +35,31 @@ export const ROEDescriptions: string[] = [
|
||||
];
|
||||
|
||||
export const reactionsToThreatDescriptions: string[] = [
|
||||
"None (No reaction)",
|
||||
"Manoeuvre (no countermeasures)",
|
||||
"Passive (Countermeasures only, no manoeuvre)",
|
||||
"None (No reaction)",
|
||||
"Manoeuvre (no countermeasures)",
|
||||
"Passive (Countermeasures only, no manoeuvre)",
|
||||
"Evade (Countermeasures and manoeuvers)"
|
||||
];
|
||||
|
||||
export const emissionsCountermeasuresDescriptions: string[] = [
|
||||
"Silent (Radar OFF, no ECM)",
|
||||
"Attack (Radar only for targeting, ECM only if locked)",
|
||||
"Defend (Radar for searching, ECM if locked)",
|
||||
"Silent (Radar OFF, no ECM)",
|
||||
"Attack (Radar only for targeting, ECM only if locked)",
|
||||
"Defend (Radar for searching, ECM if locked)",
|
||||
"Always on (Radar and ECM always on)"
|
||||
];
|
||||
|
||||
export const shotsScatterDescriptions: string[] = [
|
||||
"When performing scenic shooting tasks like simulated firefights, will shoot with a large scatter",
|
||||
"When performing scenic shooting tasks like simulated firefights, will shoot with a medium scatter",
|
||||
"When performing scenic shooting tasks like simulated firefights, will shoot with a small scatter (Radar guided units will track shots when the enemy unit is close)"
|
||||
];
|
||||
|
||||
export const shotsIntensityDescriptions: string[] = [
|
||||
"When performing scenic shooting tasks like simulated firefights, will shoot with a low rate of fire",
|
||||
"When performing scenic shooting tasks like simulated firefights, will shoot with a medium rate of fire",
|
||||
"When performing scenic shooting tasks like simulated firefights, will shoot with a high rate of fire"
|
||||
];
|
||||
|
||||
export const minSpeedValues: { [key: string]: number } = { Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0 };
|
||||
export const maxSpeedValues: { [key: string]: number } = { Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60 };
|
||||
export const speedIncrements: { [key: string]: number } = { Aircraft: 25, Helicopter: 10, NavyUnit: 5, GroundUnit: 5 };
|
||||
@@ -105,25 +118,25 @@ export const mapLayers = {
|
||||
"ArcGIS Satellite": {
|
||||
urlTemplate: "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}",
|
||||
minZoom: 1,
|
||||
maxZoom: 16,
|
||||
maxZoom: 19,
|
||||
attribution: "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, GetApp().getMap()ping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
|
||||
},
|
||||
"USGS Topo": {
|
||||
urlTemplate: 'https://basemap.nationalmap.gov/arcgis/rest/services/USGSTopo/MapServer/tile/{z}/{y}/{x}',
|
||||
minZoom: 1,
|
||||
maxZoom: 16,
|
||||
maxZoom: 14,
|
||||
attribution: 'Tiles courtesy of the <a href="https://usgs.gov/">U.S. Geological Survey</a>'
|
||||
},
|
||||
"OpenStreetMap Mapnik": {
|
||||
urlTemplate: 'https://tile.openstreetmap.org/{z}/{x}/{y}.png',
|
||||
minZoom: 1,
|
||||
maxZoom: 16,
|
||||
maxZoom: 20,
|
||||
attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
},
|
||||
"OPENVKarte": {
|
||||
urlTemplate: 'https://tileserver.memomaps.de/tilegen/{z}/{x}/{y}.png',
|
||||
minZoom: 1,
|
||||
maxZoom: 16,
|
||||
maxZoom: 20,
|
||||
attribution: 'Map <a href="https://memomaps.de/">memomaps.de</a> <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, map data © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
},
|
||||
"Esri.DeLorme": {
|
||||
@@ -135,7 +148,7 @@ export const mapLayers = {
|
||||
"CyclOSM": {
|
||||
urlTemplate: 'https://{s}.tile-cyclosm.openstreetmap.fr/cyclosm/{z}/{x}/{y}.png',
|
||||
minZoom: 1,
|
||||
maxZoom: 16,
|
||||
maxZoom: 20,
|
||||
attribution: '<a href="https://github.com/cyclosm/cyclosm-cartocss-style/releases" title="CyclOSM - Open Bicycle render">CyclOSM</a> | Map data: © <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
|
||||
}
|
||||
}
|
||||
@@ -147,19 +160,62 @@ export const COALITIONAREA_DRAW_POLYGON = "Draw Coalition Area";
|
||||
export const visibilityControls: string[] = ["human", "dcs", "aircraft", "helicopter", "groundunit-sam", "groundunit-other", "navyunit", "airbase"];
|
||||
export const visibilityControlsTypes: string[][] = [["human"], ["dcs"], ["aircraft"], ["helicopter"], ["groundunit-sam", "groundunit-sam-radar", "groundunit-sam-launcher"], ["groundunit-other", "groundunit-ewr"], ["navyunit"], ["airbase"]];
|
||||
export const visibilityControlsTooltips: string[] = ["Toggle human players visibility", "Toggle DCS controlled units visibility", "Toggle aircrafts visibility", "Toggle helicopter visibility", "Toggle SAM units visibility", "Toggle ground units (not SAM) visibility", "Toggle navy units visibility", "Toggle airbases visibility"];
|
||||
export const MAP_MARKER_CONTROLS: MapMarkerControl[] = [{
|
||||
"name": "Human",
|
||||
"image": "visibility/human.svg",
|
||||
"toggles": ["human"],
|
||||
"tooltip": "Toggle human players' visibility"
|
||||
}, {
|
||||
"image": "visibility/dcs.svg",
|
||||
"isProtected": true,
|
||||
"name": "DCS",
|
||||
"protectable": true,
|
||||
"toggles": ["dcs"],
|
||||
"tooltip": "Toggle DCS-controlled units' visibility"
|
||||
}, {
|
||||
"image": "visibility/aircraft.svg",
|
||||
"name": "Aircraft",
|
||||
"toggles": ["aircraft"],
|
||||
"tooltip": "Toggle aircraft's visibility"
|
||||
}, {
|
||||
"image": "visibility/helicopter.svg",
|
||||
"name": "Helicopter",
|
||||
"toggles": ["helicopter"],
|
||||
"tooltip": "Toggle helicopters' visibility"
|
||||
}, {
|
||||
"image": "visibility/groundunit-sam.svg",
|
||||
"name": "Air defence",
|
||||
"toggles": ["groundunit-sam"],
|
||||
"tooltip": "Toggle air defence units' visibility"
|
||||
}, {
|
||||
"image": "visibility/groundunit-other.svg",
|
||||
"name": "Ground units",
|
||||
"toggles": ["groundunit-other"],
|
||||
"tooltip": "Toggle ground units' visibility"
|
||||
}, {
|
||||
"image": "visibility/navyunit.svg",
|
||||
"name": "Naval",
|
||||
"toggles": ["navyunit"],
|
||||
"tooltip": "Toggle naval units' visibility"
|
||||
}, {
|
||||
"image": "visibility/airbase.svg",
|
||||
"name": "Airbase",
|
||||
"toggles": ["airbase"],
|
||||
"tooltip": "Toggle airbase' visibility"
|
||||
}];
|
||||
|
||||
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 IADSDensities: { [key: string]: number } = { "AAA": 0.8, "MANPADS": 0.3, "SAM Site": 0.1, "Radar": 0.05 };
|
||||
|
||||
export const HIDE_GROUP_MEMBERS = "Hide group members when zoomed out";
|
||||
export const SHOW_UNIT_LABELS = "Show unit labels (L)";
|
||||
export const SHOW_UNITS_ENGAGEMENT_RINGS = "Show units threat range rings (Q)";
|
||||
export const HIDE_UNITS_SHORT_RANGE_RINGS = "Hide short range units threat range rings (R)";
|
||||
export const SHOW_UNITS_ACQUISITION_RINGS = "Show units detection range rings (E)";
|
||||
export const FILL_SELECTED_RING = "Fill the threat range rings of selected units (F)";
|
||||
export const SHOW_UNIT_CONTACTS = "Show selected units contact lines";
|
||||
export const SHOW_UNIT_PATHS = "Show selected unit paths";
|
||||
export const SHOW_UNIT_TARGETS = "Show selected unit targets";
|
||||
export const HIDE_GROUP_MEMBERS = "Hide group members when zoomed out";
|
||||
export const SHOW_UNIT_LABELS = "Show unit labels (L)";
|
||||
export const SHOW_UNITS_ENGAGEMENT_RINGS = "Show units threat range rings (Q)";
|
||||
export const HIDE_UNITS_SHORT_RANGE_RINGS = "Hide short range units threat range rings (R)";
|
||||
export const SHOW_UNITS_ACQUISITION_RINGS = "Show units detection range rings (E)";
|
||||
export const FILL_SELECTED_RING = "Fill the threat range rings of selected units (F)";
|
||||
export const SHOW_UNIT_CONTACTS = "Show selected units contact lines";
|
||||
export const SHOW_UNIT_PATHS = "Show selected unit paths";
|
||||
export const SHOW_UNIT_TARGETS = "Show selected unit targets";
|
||||
|
||||
export enum DataIndexes {
|
||||
startOfData = 0,
|
||||
@@ -177,6 +233,8 @@ export enum DataIndexes {
|
||||
hasTask,
|
||||
position,
|
||||
speed,
|
||||
horizontalVelocity,
|
||||
verticalVelocity,
|
||||
heading,
|
||||
isActiveTanker,
|
||||
isActiveAWACS,
|
||||
@@ -202,11 +260,19 @@ export enum DataIndexes {
|
||||
activePath,
|
||||
isLeader,
|
||||
operateAs,
|
||||
shotsScatter,
|
||||
shotsIntensity,
|
||||
health,
|
||||
endOfData = 255
|
||||
};
|
||||
|
||||
export const MGRS_PRECISION_10KM = 2;
|
||||
export const MGRS_PRECISION_1KM = 3;
|
||||
export const MGRS_PRECISION_1KM = 3;
|
||||
export const MGRS_PRECISION_100M = 4;
|
||||
export const MGRS_PRECISION_10M = 5;
|
||||
export const MGRS_PRECISION_1M = 6;
|
||||
export const MGRS_PRECISION_10M = 5;
|
||||
export const MGRS_PRECISION_1M = 6;
|
||||
|
||||
export const DELETE_CYCLE_TIME = 0.05;
|
||||
export const DELETE_SLOW_THRESHOLD = 50;
|
||||
|
||||
export const GROUPING_ZOOM_TRANSITION = 13;
|
||||
31
client/src/context/context.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
export interface ContextInterface {
|
||||
useSpawnMenu?: boolean;
|
||||
useUnitControlPanel?: boolean;
|
||||
useUnitInfoPanel?: boolean;
|
||||
}
|
||||
|
||||
export class Context {
|
||||
|
||||
#useSpawnMenu:boolean;
|
||||
#useUnitControlPanel:boolean;
|
||||
#useUnitInfoPanel:boolean;
|
||||
|
||||
constructor( config:ContextInterface ) {
|
||||
this.#useSpawnMenu = ( config.useSpawnMenu !== false );
|
||||
this.#useUnitControlPanel = ( config.useUnitControlPanel !== false );
|
||||
this.#useUnitInfoPanel = ( config.useUnitInfoPanel !== false );
|
||||
}
|
||||
|
||||
getUseSpawnMenu() {
|
||||
return this.#useSpawnMenu;
|
||||
}
|
||||
|
||||
getUseUnitControlPanel() {
|
||||
return this.#useUnitControlPanel;
|
||||
}
|
||||
|
||||
getUseUnitInfoPanel() {
|
||||
return this.#useUnitInfoPanel;
|
||||
}
|
||||
|
||||
}
|
||||
43
client/src/context/contextmanager.ts
Normal file
@@ -0,0 +1,43 @@
|
||||
import { Manager } from "../other/manager";
|
||||
import { Context, ContextInterface } from "./context";
|
||||
|
||||
export class ContextManager extends Manager {
|
||||
|
||||
#currentContext!:string;
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
add( name:string, contextConfig:ContextInterface ) {
|
||||
super.add( name, new Context( contextConfig ) );
|
||||
|
||||
if ( Object.values( this.getAll() ).length === 1 ) {
|
||||
this.#currentContext = name;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
currentContextIs( contextName:string ) {
|
||||
return contextName === this.#currentContext;
|
||||
}
|
||||
|
||||
getCurrentContext() {
|
||||
const contexts = this.getAll();
|
||||
|
||||
return ( contexts.hasOwnProperty( this.#currentContext ) ) ? contexts[this.#currentContext] : false;
|
||||
}
|
||||
|
||||
setContext( contextName:string ) {
|
||||
|
||||
if ( !this.get( contextName ) ) {
|
||||
console.error( `setContext(): context name "${contextName}" does not exist.` );
|
||||
return false;
|
||||
}
|
||||
this.#currentContext = contextName;
|
||||
|
||||
console.log( `Setting context to "${this.#currentContext}".` );
|
||||
}
|
||||
|
||||
}
|
||||
15
client/src/context/contextmenumanager.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { ContextMenu } from "../contextmenus/contextmenu";
|
||||
import { Manager } from "../other/manager";
|
||||
|
||||
export class ContextMenuManager extends Manager {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
add( name:string, contextMenu:ContextMenu ) {
|
||||
super.add( name, contextMenu );
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,7 @@ export class AirbaseContextMenu extends ContextMenu {
|
||||
|
||||
document.addEventListener("contextMenuLandAirbase", (e: any) => {
|
||||
if (this.#airbase)
|
||||
getApp().getUnitsManager().selectedUnitsLandAt(this.#airbase.getLatLng());
|
||||
getApp().getUnitsManager().landAt(this.#airbase.getLatLng());
|
||||
this.hide();
|
||||
})
|
||||
}
|
||||
@@ -111,7 +111,7 @@ export class AirbaseContextMenu extends ContextMenu {
|
||||
#showSpawnMenu() {
|
||||
if (this.#airbase != null) {
|
||||
getApp().setActiveCoalition(this.#airbase.getCoalition());
|
||||
getApp().getMap().showAirbaseSpawnMenu(this.getX(), this.getY(), this.getLatLng(), this.#airbase);
|
||||
getApp().getMap().showAirbaseSpawnMenu(this.#airbase, this.getX(), this.getY(), this.getLatLng());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ export class AirbaseSpawnContextMenu extends ContextMenu {
|
||||
* @param x X screen coordinate of the top left corner of the context menu
|
||||
* @param y Y screen coordinate of the top left corner of the context menu
|
||||
*/
|
||||
show(x: number, y: number) {
|
||||
show(x: number | undefined, y: number | undefined) {
|
||||
super.show(x, y, new LatLng(0, 0));
|
||||
|
||||
this.#aircraftSpawnMenu.setAirbase(undefined);
|
||||
|
||||
@@ -19,15 +19,15 @@ export class ContextMenu {
|
||||
|
||||
/** Show the contextmenu on top of the map, usually at the location where the user has clicked on it.
|
||||
*
|
||||
* @param x X screen coordinate of the top left corner of the context menu
|
||||
* @param y Y screen coordinate of the top left corner of the context menu
|
||||
* @param latlng Leaflet latlng object of the mouse click
|
||||
* @param x X screen coordinate of the top left corner of the context menu. If undefined, use the old value
|
||||
* @param y Y screen coordinate of the top left corner of the context menu. If undefined, use the old value
|
||||
* @param latlng Leaflet latlng object of the mouse click. If undefined, use the old value
|
||||
*/
|
||||
show(x: number, y: number, latlng: LatLng) {
|
||||
this.#latlng = latlng;
|
||||
show(x: number | undefined = undefined, y: number | undefined = undefined, latlng: LatLng | undefined = undefined) {
|
||||
this.#latlng = latlng ?? this.#latlng;
|
||||
this.#container?.classList.toggle("hide", false);
|
||||
this.#x = x;
|
||||
this.#y = y;
|
||||
this.#x = x ?? this.#x;
|
||||
this.#y = y ?? this.#y;
|
||||
this.clip();
|
||||
this.getContainer()?.dispatchEvent(new Event("show"));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import { ContextMenu } from "./contextmenu";
|
||||
import { Switch } from "../controls/switch";
|
||||
import { GAME_MASTER } from "../constants/constants";
|
||||
import { CoalitionArea } from "../map/coalitionarea/coalitionarea";
|
||||
import { AircraftSpawnMenu, GroundUnitSpawnMenu, HelicopterSpawnMenu, NavyUnitSpawnMenu } from "../controls/unitspawnmenu";
|
||||
import { AirDefenceUnitSpawnMenu, AircraftSpawnMenu, GroundUnitSpawnMenu, HelicopterSpawnMenu, NavyUnitSpawnMenu } from "../controls/unitspawnmenu";
|
||||
import { Airbase } from "../mission/airbase";
|
||||
import { SmokeMarker } from "../map/markers/smokemarker";
|
||||
|
||||
@@ -15,9 +15,11 @@ export class MapContextMenu extends ContextMenu {
|
||||
#coalitionSwitch: Switch;
|
||||
#aircraftSpawnMenu: AircraftSpawnMenu;
|
||||
#helicopterSpawnMenu: HelicopterSpawnMenu;
|
||||
#airDefenceUnitSpawnMenu: AirDefenceUnitSpawnMenu;
|
||||
#groundUnitSpawnMenu: GroundUnitSpawnMenu;
|
||||
#navyUnitSpawnMenu: NavyUnitSpawnMenu;
|
||||
#coalitionArea: CoalitionArea | null = null;
|
||||
#selectedUnitCategory: string = "";
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -34,14 +36,16 @@ export class MapContextMenu extends ContextMenu {
|
||||
/* Create the spawn menus for the different unit types */
|
||||
this.#aircraftSpawnMenu = new AircraftSpawnMenu("aircraft-spawn-menu");
|
||||
this.#helicopterSpawnMenu = new HelicopterSpawnMenu("helicopter-spawn-menu");
|
||||
this.#airDefenceUnitSpawnMenu = new AirDefenceUnitSpawnMenu("air-defence-spawn-menu");
|
||||
this.#groundUnitSpawnMenu = new GroundUnitSpawnMenu("groundunit-spawn-menu");
|
||||
this.#navyUnitSpawnMenu = new NavyUnitSpawnMenu("navyunit-spawn-menu");
|
||||
|
||||
/* Event listeners */
|
||||
document.addEventListener("mapContextMenuShow", (e: any) => {
|
||||
if (this.getVisibleSubMenu() !== e.detail.type)
|
||||
if (this.getVisibleSubMenu() !== e.detail.type) {
|
||||
this.#showSubMenu(e.detail.type);
|
||||
else
|
||||
this.#selectedUnitCategory = e.detail.type;
|
||||
} else
|
||||
this.#hideSubMenus(e.detail.type);
|
||||
});
|
||||
|
||||
@@ -54,7 +58,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
|
||||
document.addEventListener("contextMenuExplosion", (e: any) => {
|
||||
this.hide();
|
||||
getApp().getServerManager().spawnExplosion(e.detail.strength, this.getLatLng());
|
||||
getApp().getServerManager().spawnExplosion(e.detail.strength ?? 0, e.detail.explosionType, this.getLatLng());
|
||||
});
|
||||
|
||||
document.addEventListener("editCoalitionArea", (e: any) => {
|
||||
@@ -65,27 +69,31 @@ export class MapContextMenu extends ContextMenu {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener("commandModeOptionsChanged", (e: any) => {
|
||||
//this.#refreshOptions();
|
||||
});
|
||||
// document.addEventListener("commandModeOptionsChanged", (e: any) => {
|
||||
// //this.#refreshOptions();
|
||||
// });
|
||||
|
||||
this.#aircraftSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
|
||||
this.#helicopterSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
|
||||
this.#airDefenceUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
|
||||
this.#groundUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
|
||||
this.#navyUnitSpawnMenu.getContainer().addEventListener("resize", () => this.clip());
|
||||
|
||||
this.#aircraftSpawnMenu.getContainer().addEventListener("hide", () => this.hide());
|
||||
this.#helicopterSpawnMenu.getContainer().addEventListener("hide", () => this.hide());
|
||||
this.#airDefenceUnitSpawnMenu.getContainer().addEventListener("hide", () => this.hide());
|
||||
this.#groundUnitSpawnMenu.getContainer().addEventListener("hide", () => this.hide());
|
||||
this.#navyUnitSpawnMenu.getContainer().addEventListener("hide", () => this.hide());
|
||||
|
||||
this.getContainer()?.addEventListener("show", () => this.#aircraftSpawnMenu.showCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("show", () => this.#helicopterSpawnMenu.showCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("show", () => this.#airDefenceUnitSpawnMenu.showCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("show", () => this.#groundUnitSpawnMenu.showCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("show", () => this.#navyUnitSpawnMenu.showCirclesPreviews());
|
||||
|
||||
this.getContainer()?.addEventListener("hide", () => this.#aircraftSpawnMenu.clearCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("hide", () => this.#helicopterSpawnMenu.clearCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("hide", () => this.#airDefenceUnitSpawnMenu.clearCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("hide", () => this.#groundUnitSpawnMenu.clearCirclesPreviews());
|
||||
this.getContainer()?.addEventListener("hide", () => this.#navyUnitSpawnMenu.clearCirclesPreviews());
|
||||
}
|
||||
@@ -97,15 +105,20 @@ export class MapContextMenu extends ContextMenu {
|
||||
* @param latlng Leaflet latlng object of the mouse click
|
||||
*/
|
||||
show(x: number, y: number, latlng: LatLng) {
|
||||
if (!getApp().getCurrentContext().getUseSpawnMenu())
|
||||
return false;
|
||||
|
||||
super.show(x, y, latlng);
|
||||
|
||||
this.#aircraftSpawnMenu.setLatLng(latlng);
|
||||
this.#helicopterSpawnMenu.setLatLng(latlng);
|
||||
this.#airDefenceUnitSpawnMenu.setLatLng(latlng);
|
||||
this.#groundUnitSpawnMenu.setLatLng(latlng);
|
||||
this.#navyUnitSpawnMenu.setLatLng(latlng);
|
||||
|
||||
this.#aircraftSpawnMenu.setCountries();
|
||||
this.#helicopterSpawnMenu.setCountries();
|
||||
this.#airDefenceUnitSpawnMenu.setCountries();
|
||||
this.#groundUnitSpawnMenu.setCountries();
|
||||
this.#navyUnitSpawnMenu.setCountries();
|
||||
|
||||
@@ -141,7 +154,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
#showSubMenu(type: string) {
|
||||
if (type === "more")
|
||||
this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide");
|
||||
else if (["aircraft", "helicopter", "groundunit"].includes(type))
|
||||
else if (["aircraft", "helicopter", "air-defence", "groundunit"].includes(type))
|
||||
this.getContainer()?.querySelector("#more-options-button-bar")?.classList.toggle("hide", true);
|
||||
|
||||
this.getContainer()?.querySelector("#aircraft-spawn-menu")?.classList.toggle("hide", type !== "aircraft");
|
||||
@@ -150,6 +163,8 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.getContainer()?.querySelector("#helicopter-spawn-button")?.classList.toggle("is-open", type === "helicopter");
|
||||
this.getContainer()?.querySelector("#groundunit-spawn-menu")?.classList.toggle("hide", type !== "groundunit");
|
||||
this.getContainer()?.querySelector("#groundunit-spawn-button")?.classList.toggle("is-open", type === "groundunit");
|
||||
this.getContainer()?.querySelector("#air-defence-spawn-menu")?.classList.toggle("hide", type !== "air-defence");
|
||||
this.getContainer()?.querySelector("#air-defence-spawn-button")?.classList.toggle("is-open", type === "air-defence");
|
||||
this.getContainer()?.querySelector("#navyunit-spawn-menu")?.classList.toggle("hide", type !== "navyunit");
|
||||
this.getContainer()?.querySelector("#navyunit-spawn-button")?.classList.toggle("is-open", type === "navyunit");
|
||||
this.getContainer()?.querySelector("#smoke-spawn-menu")?.classList.toggle("hide", type !== "smoke");
|
||||
@@ -165,6 +180,9 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.#helicopterSpawnMenu.reset();
|
||||
this.#helicopterSpawnMenu.setCountries();
|
||||
this.#helicopterSpawnMenu.clearCirclesPreviews();
|
||||
this.#airDefenceUnitSpawnMenu.reset();
|
||||
this.#airDefenceUnitSpawnMenu.setCountries();
|
||||
this.#airDefenceUnitSpawnMenu.clearCirclesPreviews();
|
||||
this.#groundUnitSpawnMenu.reset();
|
||||
this.#groundUnitSpawnMenu.setCountries();
|
||||
this.#groundUnitSpawnMenu.clearCirclesPreviews();
|
||||
@@ -198,11 +216,13 @@ export class MapContextMenu extends ContextMenu {
|
||||
|
||||
this.#aircraftSpawnMenu.reset();
|
||||
this.#helicopterSpawnMenu.reset();
|
||||
this.#airDefenceUnitSpawnMenu.reset();
|
||||
this.#groundUnitSpawnMenu.reset();
|
||||
this.#navyUnitSpawnMenu.reset();
|
||||
|
||||
this.#aircraftSpawnMenu.clearCirclesPreviews();
|
||||
this.#helicopterSpawnMenu.clearCirclesPreviews();
|
||||
this.#airDefenceUnitSpawnMenu.clearCirclesPreviews();
|
||||
this.#groundUnitSpawnMenu.clearCirclesPreviews();
|
||||
this.#navyUnitSpawnMenu.clearCirclesPreviews();
|
||||
|
||||
@@ -219,6 +239,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getApp().getActiveCoalition()) });
|
||||
this.#aircraftSpawnMenu.setCountries();
|
||||
this.#helicopterSpawnMenu.setCountries();
|
||||
this.#airDefenceUnitSpawnMenu.setCountries();
|
||||
this.#groundUnitSpawnMenu.setCountries();
|
||||
this.#navyUnitSpawnMenu.setCountries();
|
||||
}
|
||||
@@ -232,6 +253,7 @@ export class MapContextMenu extends ContextMenu {
|
||||
this.getContainer()?.querySelectorAll('[data-coalition]').forEach((element: any) => { element.setAttribute("data-coalition", getApp().getActiveCoalition()) });
|
||||
this.#aircraftSpawnMenu.setCountries();
|
||||
this.#helicopterSpawnMenu.setCountries();
|
||||
this.#airDefenceUnitSpawnMenu.setCountries();
|
||||
this.#groundUnitSpawnMenu.setCountries();
|
||||
this.#navyUnitSpawnMenu.setCountries();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { deg2rad, ftToM } from "../other/utils";
|
||||
import { ContextActionSet } from "../unit/contextactionset";
|
||||
import { ContextMenu } from "./contextmenu";
|
||||
|
||||
/** The UnitContextMenu is shown when the user rightclicks on a unit. It dynamically presents the user with possible actions to perform on the unit. */
|
||||
@@ -16,15 +16,19 @@ export class UnitContextMenu extends ContextMenu {
|
||||
* @param options Dictionary element containing the text and tooltip of the options shown in the menu
|
||||
* @param callback Callback that will be called when the user clicks on one of the options
|
||||
*/
|
||||
setOptions(options: { [key: string]: {text: string, tooltip: string }}, callback: CallableFunction) {
|
||||
this.getContainer()?.replaceChildren(...Object.keys(options).map((key: string, idx: number) => {
|
||||
const option = options[key];
|
||||
setContextActions(contextActionSet: ContextActionSet) {
|
||||
this.getContainer()?.replaceChildren(...Object.keys(contextActionSet.getContextActions()).map((key: string, idx: number) => {
|
||||
const contextAction = contextActionSet.getContextActions()[key];
|
||||
var button = document.createElement("button");
|
||||
var el = document.createElement("div");
|
||||
el.title = option.tooltip;
|
||||
el.innerText = option.text;
|
||||
el.title = contextAction.getDescription();
|
||||
el.innerText = contextAction.getLabel();
|
||||
el.id = key;
|
||||
button.addEventListener("click", () => callback(key));
|
||||
button.addEventListener("click", () => {
|
||||
contextAction.executeCallback();
|
||||
if (contextAction.getHideContextAfterExecution())
|
||||
this.hide();
|
||||
});
|
||||
button.appendChild(el);
|
||||
return (button);
|
||||
}));
|
||||
|
||||
@@ -36,8 +36,40 @@ export class Dropdown {
|
||||
return this.#container;
|
||||
}
|
||||
|
||||
setOptions(optionsList: string[], sortAlphabetically: boolean = true) {
|
||||
this.#optionsList = optionsList.sort();
|
||||
setOptions(optionsList: string[], sort: "" | "string" | "number" | "string+number" = "string") {
|
||||
if (sort === "number") {
|
||||
this.#optionsList = optionsList.sort((optionA: string, optionB: string) => {
|
||||
const a = parseInt(optionA);
|
||||
const b = parseInt(optionB);
|
||||
if (a > b)
|
||||
return 1;
|
||||
else
|
||||
return (b > a) ? -1 : 0;
|
||||
});
|
||||
} else if (sort === "string+number") {
|
||||
this.#optionsList = optionsList.sort((optionA: string, optionB: string) => {
|
||||
var regex = /\d+/g;
|
||||
var matchesA = optionA.match(regex);
|
||||
var matchesB = optionB.match(regex);
|
||||
if ((matchesA != null && matchesA?.length > 0) && (matchesB != null && matchesB?.length > 0) && optionA[0] == optionB[0]) {
|
||||
const a = parseInt(matchesA[0] ?? 0);
|
||||
const b = parseInt(matchesB[0] ?? 0);
|
||||
if (a > b)
|
||||
return 1;
|
||||
else
|
||||
return (b > a) ? -1 : 0;
|
||||
} else {
|
||||
if (optionA > optionB)
|
||||
return 1;
|
||||
else
|
||||
return (optionB > optionA) ? -1 : 0;
|
||||
}
|
||||
|
||||
});
|
||||
} else if (sort === "string") {
|
||||
this.#optionsList = optionsList.sort();
|
||||
}
|
||||
|
||||
if (this.#optionsList.length == 0) {
|
||||
optionsList = ["No options available"]
|
||||
this.#value.innerText = "No options available";
|
||||
@@ -156,17 +188,17 @@ export class Dropdown {
|
||||
}
|
||||
|
||||
#toggle() {
|
||||
this.#container.classList.contains("is-open")? this.close(): this.open();
|
||||
this.#container.classList.contains("is-open") ? this.close() : this.open();
|
||||
}
|
||||
|
||||
#createElement(defaultText: string | undefined) {
|
||||
var div = document.createElement("div");
|
||||
div.classList.add("ol-select");
|
||||
|
||||
|
||||
var value = document.createElement("div");
|
||||
value.classList.add("ol-select-value");
|
||||
value.innerText = defaultText? defaultText: "";
|
||||
|
||||
value.innerText = defaultText ? defaultText : "";
|
||||
|
||||
var options = document.createElement("div");
|
||||
options.classList.add("ol-select-options");
|
||||
|
||||
|
||||
@@ -13,11 +13,8 @@ import { navyUnitDatabase } from "../unit/databases/navyunitdatabase";
|
||||
import { UnitSpawnOptions, UnitSpawnTable } from "../interfaces";
|
||||
|
||||
export class UnitSpawnMenu {
|
||||
#container: HTMLElement;
|
||||
#unitDatabase: UnitDatabase;
|
||||
#countryCodes: any;
|
||||
#orderByRole: boolean;
|
||||
spawnOptions: UnitSpawnOptions = {
|
||||
protected showRangeCircles: boolean = false;
|
||||
protected spawnOptions: UnitSpawnOptions = {
|
||||
roleType: "",
|
||||
name: "",
|
||||
latlng: new LatLng(0, 0),
|
||||
@@ -30,6 +27,12 @@ export class UnitSpawnMenu {
|
||||
altitude: undefined
|
||||
};
|
||||
|
||||
#container: HTMLElement;
|
||||
#unitDatabase: UnitDatabase;
|
||||
#countryCodes: any;
|
||||
#orderByRole: boolean;
|
||||
protected unitTypeFilter = (unit:any) => { return true; };
|
||||
|
||||
/* Controls */
|
||||
#unitRoleTypeDropdown: Dropdown;
|
||||
#unitLabelDropdown: Dropdown;
|
||||
@@ -151,9 +154,28 @@ export class UnitSpawnMenu {
|
||||
this.#unitLiveryDropdown.reset();
|
||||
|
||||
if (this.#orderByRole)
|
||||
this.#unitLabelDropdown.setOptions(this.#unitDatabase.getByRole(this.spawnOptions.roleType).map((blueprint) => { return blueprint.label }));
|
||||
this.#unitLabelDropdown.setOptions(this.#unitDatabase.getByRole(this.spawnOptions.roleType).map((blueprint) => { return blueprint.label }), "string+number");
|
||||
else
|
||||
this.#unitLabelDropdown.setOptions(this.#unitDatabase.getByType(this.spawnOptions.roleType).map((blueprint) => { return blueprint.label }));
|
||||
this.#unitLabelDropdown.setOptions(this.#unitDatabase.getByType(this.spawnOptions.roleType).map((blueprint) => { return blueprint.label }), "string+number");
|
||||
|
||||
/* Add the tags to the options */
|
||||
var elements: HTMLElement[] = [];
|
||||
for (let idx = 0; idx < this.#unitLabelDropdown.getOptionElements().length; idx++) {
|
||||
let element = this.#unitLabelDropdown.getOptionElements()[idx] as HTMLElement;
|
||||
let entry = this.#unitDatabase.getByLabel(element.textContent ?? "");
|
||||
if (entry) {
|
||||
element.querySelectorAll("button")[0]?.append(...(entry.tags?.split(",").map((tag: string) => {
|
||||
tag = tag.trim();
|
||||
let el = document.createElement("div");
|
||||
el.classList.add("pill", `ol-tag`, `ol-tag-${tag.replace(/[\W_]+/g,"-")}`);
|
||||
el.textContent = tag;
|
||||
element.appendChild(el);
|
||||
return el;
|
||||
}) ?? []));
|
||||
elements.push(element);
|
||||
}
|
||||
}
|
||||
|
||||
this.#container.dispatchEvent(new Event("resize"));
|
||||
|
||||
this.spawnOptions.name = "";
|
||||
@@ -244,6 +266,10 @@ export class UnitSpawnMenu {
|
||||
return this.#container;
|
||||
}
|
||||
|
||||
getVisible() {
|
||||
return !this.getContainer().classList.contains( "hide" );
|
||||
}
|
||||
|
||||
reset() {
|
||||
this.#deployUnitButtonEl.disabled = true;
|
||||
this.#unitRoleTypeDropdown.reset();
|
||||
@@ -252,7 +278,7 @@ export class UnitSpawnMenu {
|
||||
if (this.#orderByRole)
|
||||
this.#unitRoleTypeDropdown.setOptions(this.#unitDatabase.getRoles());
|
||||
else
|
||||
this.#unitRoleTypeDropdown.setOptions(this.#unitDatabase.getTypes());
|
||||
this.#unitRoleTypeDropdown.setOptions(this.#unitDatabase.getTypes(this.unitTypeFilter));
|
||||
|
||||
this.#unitLoadoutListEl.replaceChildren();
|
||||
this.#unitLoadoutDropdown.reset();
|
||||
@@ -286,9 +312,17 @@ export class UnitSpawnMenu {
|
||||
|
||||
showCirclesPreviews() {
|
||||
this.clearCirclesPreviews();
|
||||
|
||||
if ( !this.showRangeCircles || this.spawnOptions.name === "" || !this.getVisible() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
var acquisitionRange = this.#unitDatabase.getByName(this.spawnOptions.name)?.acquisitionRange ?? 0;
|
||||
var engagementRange = this.#unitDatabase.getByName(this.spawnOptions.name)?.engagementRange ?? 0;
|
||||
let acquisitionRange = this.#unitDatabase.getByName(this.spawnOptions.name)?.acquisitionRange ?? 0;
|
||||
let engagementRange = this.#unitDatabase.getByName(this.spawnOptions.name)?.engagementRange ?? 0;
|
||||
|
||||
if ( acquisitionRange === 0 && engagementRange === 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.#acquisitionCircle.setRadius(acquisitionRange);
|
||||
this.#engagementCircle.setRadius(engagementRange);
|
||||
@@ -343,10 +377,7 @@ export class UnitSpawnMenu {
|
||||
|
||||
setMaxUnitCount(maxUnitCount: number) {
|
||||
/* Create the unit count options */
|
||||
var countOptions: string[] = [];
|
||||
for (let i = 1; i <= maxUnitCount; i++)
|
||||
countOptions.push(i.toString());
|
||||
this.#unitCountDropdown.setOptions(countOptions);
|
||||
this.#unitCountDropdown.setOptions( [...Array(maxUnitCount).keys()].map( n => (n+1).toString() ), "number");
|
||||
this.#unitCountDropdown.selectValue(0);
|
||||
}
|
||||
|
||||
@@ -572,6 +603,10 @@ export class HelicopterSpawnMenu extends UnitSpawnMenu {
|
||||
}
|
||||
|
||||
export class GroundUnitSpawnMenu extends UnitSpawnMenu {
|
||||
|
||||
protected showRangeCircles: boolean = true;
|
||||
protected unitTypeFilter = (unit:any) => {return !(/\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type))};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ID - the ID of the HTML element which will contain the context menu
|
||||
@@ -609,6 +644,20 @@ export class GroundUnitSpawnMenu extends UnitSpawnMenu {
|
||||
}
|
||||
}
|
||||
|
||||
export class AirDefenceUnitSpawnMenu extends GroundUnitSpawnMenu {
|
||||
|
||||
protected unitTypeFilter = (unit:any) => {return /\bAAA|SAM\b/.test(unit.type) || /\bmanpad|stinger\b/i.test(unit.type)};
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ID - the ID of the HTML element which will contain the context menu
|
||||
*/
|
||||
constructor(ID: string){
|
||||
super(ID);
|
||||
this.setMaxUnitCount(4);
|
||||
}
|
||||
}
|
||||
|
||||
export class NavyUnitSpawnMenu extends UnitSpawnMenu {
|
||||
/**
|
||||
*
|
||||
|
||||
19
client/src/dialog/dialog.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { Panel } from "../panels/panel";
|
||||
|
||||
export class Dialog extends Panel {
|
||||
|
||||
constructor( element:string ) {
|
||||
super( element );
|
||||
}
|
||||
|
||||
hide() {
|
||||
super.hide();
|
||||
document.getElementById( "gray-out" )?.classList.toggle("hide", true);
|
||||
}
|
||||
|
||||
show() {
|
||||
super.show();
|
||||
document.getElementById( "gray-out" )?.classList.toggle("hide", false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -86,6 +86,7 @@ export interface UnitSpawnTable {
|
||||
export interface ObjectIconOptions {
|
||||
showState: boolean,
|
||||
showVvi: boolean,
|
||||
showHealth: boolean,
|
||||
showHotgroup: boolean,
|
||||
showUnitIcon: boolean,
|
||||
showShortLabel: boolean,
|
||||
@@ -152,6 +153,8 @@ export interface UnitData {
|
||||
hasTask: boolean;
|
||||
position: LatLng;
|
||||
speed: number;
|
||||
horizontalVelocity: number;
|
||||
verticalVelocity: number;
|
||||
heading: number;
|
||||
isActiveTanker: boolean;
|
||||
isActiveAWACS: boolean;
|
||||
@@ -177,6 +180,9 @@ export interface UnitData {
|
||||
activePath: LatLng[];
|
||||
isLeader: boolean;
|
||||
operateAs: string;
|
||||
shotsScatter: number;
|
||||
shotsIntensity: number;
|
||||
health: number;
|
||||
}
|
||||
|
||||
export interface LoadoutItemBlueprint {
|
||||
@@ -210,12 +216,22 @@ export interface UnitBlueprint {
|
||||
muzzleVelocity?: number;
|
||||
aimTime?: number;
|
||||
shotsToFire?: number;
|
||||
shotsBaseInterval?: number;
|
||||
shotsBaseScatter?: number;
|
||||
description?: string;
|
||||
abilities?: string;
|
||||
tags?: string;
|
||||
acquisitionRange?: number;
|
||||
engagementRange?: number;
|
||||
targetingRange?: number;
|
||||
aimMethodRange?: number;
|
||||
alertnessTimeConstant?: number;
|
||||
canTargetPoint?: boolean;
|
||||
canRearm?: boolean;
|
||||
canAAA?: boolean;
|
||||
indirectFire?: boolean;
|
||||
markerFile?: string;
|
||||
unitWhenGrouped?: string;
|
||||
}
|
||||
|
||||
export interface UnitSpawnOptions {
|
||||
@@ -263,6 +279,7 @@ export interface Listener {
|
||||
export interface ShortcutOptions {
|
||||
altKey?: boolean;
|
||||
callback: CallableFunction;
|
||||
context?: string;
|
||||
ctrlKey?: boolean;
|
||||
name?: string;
|
||||
shiftKey?: boolean;
|
||||
|
||||
@@ -12,16 +12,16 @@ import { DestinationPreviewMarker } from "./markers/destinationpreviewmarker";
|
||||
import { TemporaryUnitMarker } from "./markers/temporaryunitmarker";
|
||||
import { ClickableMiniMap } from "./clickableminimap";
|
||||
import { SVGInjector } from '@tanem/svg-injector'
|
||||
import { mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, visibilityControls, visibilityControlsTooltips, MOVE_UNIT, SHOW_UNIT_CONTACTS, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, visibilityControlsTypes, SHOW_UNIT_LABELS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING } from "../constants/constants";
|
||||
import { mapLayers, mapBounds, minimapBoundaries, IDLE, COALITIONAREA_DRAW_POLYGON, MOVE_UNIT, SHOW_UNIT_CONTACTS, HIDE_GROUP_MEMBERS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, SHOW_UNIT_LABELS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, MAP_MARKER_CONTROLS } from "../constants/constants";
|
||||
import { TargetMarker } from "./markers/targetmarker";
|
||||
import { CoalitionArea } from "./coalitionarea/coalitionarea";
|
||||
import { CoalitionAreaContextMenu } from "../contextmenus/coalitionareacontextmenu";
|
||||
import { DrawingCursor } from "./coalitionarea/drawingcursor";
|
||||
import { AirbaseSpawnContextMenu } from "../contextmenus/airbasespawnmenu";
|
||||
import { Popup } from "../popups/popup";
|
||||
import { GestureHandling } from "leaflet-gesture-handling";
|
||||
import { TouchBoxSelect } from "./touchboxselect";
|
||||
import { DestinationPreviewHandle } from "./markers/destinationpreviewHandle";
|
||||
import { ContextActionSet } from "../unit/contextactionset";
|
||||
|
||||
var hasTouchScreen = false;
|
||||
//if ("maxTouchPoints" in navigator)
|
||||
@@ -38,6 +38,15 @@ L.Map.addInitHook("addHandler", "gestureHandling", GestureHandling);
|
||||
require("../../public/javascripts/leaflet.nauticscale.js")
|
||||
require("../../public/javascripts/L.Path.Drag.js")
|
||||
|
||||
export type MapMarkerControl = {
|
||||
"image": string;
|
||||
"isProtected"?: boolean,
|
||||
"name":string,
|
||||
"protectable"?: boolean,
|
||||
"toggles": string[],
|
||||
"tooltip": string
|
||||
}
|
||||
|
||||
export class Map extends L.Map {
|
||||
#ID: string;
|
||||
#state: string;
|
||||
@@ -59,6 +68,7 @@ export class Map extends L.Map {
|
||||
#temporaryMarkers: TemporaryUnitMarker[] = [];
|
||||
#selecting: boolean = false;
|
||||
#isZooming: boolean = false;
|
||||
#previousZoom: number = 0;
|
||||
|
||||
#destinationGroupRotation: number = 0;
|
||||
#computeDestinationRotation: boolean = false;
|
||||
@@ -80,6 +90,7 @@ export class Map extends L.Map {
|
||||
#coalitionAreaContextMenu: CoalitionAreaContextMenu = new CoalitionAreaContextMenu("coalition-area-contextmenu");
|
||||
|
||||
#mapSourceDropdown: Dropdown;
|
||||
#mapMarkerControls:MapMarkerControl[] = MAP_MARKER_CONTROLS;
|
||||
#mapVisibilityOptionsDropdown: Dropdown;
|
||||
#optionButtons: { [key: string]: HTMLButtonElement[] } = {}
|
||||
#visibilityOptions: { [key: string]: boolean } = {}
|
||||
@@ -92,8 +103,6 @@ export class Map extends L.Map {
|
||||
constructor(ID: string){
|
||||
/* Init the leaflet map */
|
||||
super(ID, {
|
||||
zoomSnap: 0,
|
||||
zoomDelta: 0.25,
|
||||
preferCanvas: true,
|
||||
doubleClickZoom: false,
|
||||
zoomControl: false,
|
||||
@@ -201,12 +210,7 @@ export class Map extends L.Map {
|
||||
}, 20);
|
||||
|
||||
/* Option buttons */
|
||||
this.#optionButtons["visibility"] = visibilityControls.map((option: string, index: number) => {
|
||||
var typesArrayString = `"${visibilityControlsTypes[index][0]}"`;
|
||||
visibilityControlsTypes[index].forEach((type: string, idx: number) => { if (idx > 0) typesArrayString = `${typesArrayString}, "${type}"` });
|
||||
return this.#createOptionButton(option, `visibility/${option.toLowerCase()}.svg`, visibilityControlsTooltips[index], "toggleMarkerVisibility", `{"types": [${typesArrayString}]}`);
|
||||
});
|
||||
document.querySelector("#unit-visibility-control")?.append(...this.#optionButtons["visibility"]);
|
||||
this.#createUnitMarkerControlButtons();
|
||||
|
||||
/* Create the checkboxes to select the advanced visibility options */
|
||||
this.addVisibilityOption(SHOW_UNIT_CONTACTS, false);
|
||||
@@ -318,7 +322,7 @@ export class Map extends L.Map {
|
||||
return this.#mapContextMenu;
|
||||
}
|
||||
|
||||
showUnitContextMenu(x: number, y: number, latlng: L.LatLng) {
|
||||
showUnitContextMenu(x: number | undefined = undefined, y: number | undefined = undefined, latlng: L.LatLng | undefined = undefined) {
|
||||
this.hideAllContextMenus();
|
||||
this.#unitContextMenu.show(x, y, latlng);
|
||||
}
|
||||
@@ -331,7 +335,7 @@ export class Map extends L.Map {
|
||||
this.#unitContextMenu.hide();
|
||||
}
|
||||
|
||||
showAirbaseContextMenu(x: number, y: number, latlng: L.LatLng, airbase: Airbase) {
|
||||
showAirbaseContextMenu(airbase: Airbase, x: number | undefined = undefined, y: number | undefined = undefined, latlng: L.LatLng | undefined = undefined) {
|
||||
this.hideAllContextMenus();
|
||||
this.#airbaseContextMenu.show(x, y, latlng);
|
||||
this.#airbaseContextMenu.setAirbase(airbase);
|
||||
@@ -345,7 +349,7 @@ export class Map extends L.Map {
|
||||
this.#airbaseContextMenu.hide();
|
||||
}
|
||||
|
||||
showAirbaseSpawnMenu(x: number, y: number, latlng: L.LatLng, airbase: Airbase) {
|
||||
showAirbaseSpawnMenu(airbase: Airbase, x: number | undefined = undefined, y: number | undefined = undefined, latlng: L.LatLng | undefined = undefined) {
|
||||
this.hideAllContextMenus();
|
||||
this.#airbaseSpawnMenu.show(x, y);
|
||||
this.#airbaseSpawnMenu.setAirbase(airbase);
|
||||
@@ -498,6 +502,10 @@ export class Map extends L.Map {
|
||||
return this.#visibilityOptions;
|
||||
}
|
||||
|
||||
getPreviousZoom() {
|
||||
return this.#previousZoom;
|
||||
}
|
||||
|
||||
/* Event handlers */
|
||||
#onClick(e: any) {
|
||||
if (!this.#preventLeftClick) {
|
||||
@@ -553,9 +561,9 @@ export class Map extends L.Map {
|
||||
}
|
||||
else if (this.#state === MOVE_UNIT) {
|
||||
if (!e.originalEvent.ctrlKey) {
|
||||
getApp().getUnitsManager().selectedUnitsClearDestinations();
|
||||
getApp().getUnitsManager().clearDestinations();
|
||||
}
|
||||
getApp().getUnitsManager().selectedUnitsAddDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : e.latlng, this.#shiftKey, this.#destinationGroupRotation)
|
||||
getApp().getUnitsManager().addDestination(this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : e.latlng, this.#shiftKey, this.#destinationGroupRotation)
|
||||
|
||||
this.#destinationGroupRotation = 0;
|
||||
this.#destinationRotationCenter = null;
|
||||
@@ -603,59 +611,15 @@ export class Map extends L.Map {
|
||||
if (e.originalEvent.button != 2 || e.originalEvent.ctrlKey || e.originalEvent.shiftKey)
|
||||
return;
|
||||
|
||||
var options: { [key: string]: { text: string, tooltip: string } } = {};
|
||||
const selectedUnits = getApp().getUnitsManager().getSelectedUnits();
|
||||
const selectedUnitTypes = getApp().getUnitsManager().getSelectedUnitsCategories();
|
||||
|
||||
if (selectedUnitTypes.length === 1 && ["Aircraft", "Helicopter"].includes(selectedUnitTypes[0])) {
|
||||
if (selectedUnitTypes[0] === "Helicopter") {
|
||||
options["land-at-point"] = { text: "Land here", tooltip: "Land at this precise location" };
|
||||
}
|
||||
|
||||
if (selectedUnits.every((unit: Unit) => { return unit.canTargetPoint()})) {
|
||||
options["bomb"] = { text: "Precision bombing", tooltip: "Precision bombing of a specific point" };
|
||||
options["carpet-bomb"] = { text: "Carpet bombing", tooltip: "Carpet bombing close to a point" };
|
||||
} else {
|
||||
(getApp().getPopupsManager().get("infoPopup") as Popup).setText(`Selected units can not perform point actions.`);
|
||||
}
|
||||
}
|
||||
else if (selectedUnitTypes.length === 1 && ["GroundUnit", "NavyUnit"].includes(selectedUnitTypes[0])) {
|
||||
if (selectedUnits.every((unit: Unit) => { return unit.canTargetPoint() })) {
|
||||
options["fire-at-area"] = { text: "Fire at area", tooltip: "Fire at a large area" };
|
||||
options["simulate-fire-fight"] = { text: "Simulate fire fight", tooltip: "Simulate a fire fight by shooting randomly in a certain large area" };
|
||||
}
|
||||
else
|
||||
(getApp().getPopupsManager().get("infoPopup") as Popup).setText(`Selected units can not perform point actions.`);
|
||||
}
|
||||
else if(selectedUnitTypes.length > 1) {
|
||||
(getApp().getPopupsManager().get("infoPopup") as Popup).setText(`Multiple unit types selected, no common actions available.`);
|
||||
}
|
||||
|
||||
if (Object.keys(options).length > 0) {
|
||||
this.showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
|
||||
this.getUnitContextMenu().setOptions(options, (option: string) => {
|
||||
this.hideUnitContextMenu();
|
||||
if (option === "bomb") {
|
||||
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getApp().getUnitsManager().selectedUnitsBombPoint(this.getMouseCoordinates());
|
||||
}
|
||||
else if (option === "carpet-bomb") {
|
||||
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getApp().getUnitsManager().selectedUnitsCarpetBomb(this.getMouseCoordinates());
|
||||
}
|
||||
else if (option === "fire-at-area") {
|
||||
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getApp().getUnitsManager().selectedUnitsFireAtArea(this.getMouseCoordinates());
|
||||
}
|
||||
else if (option === "simulate-fire-fight") {
|
||||
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getApp().getUnitsManager().selectedUnitsSimulateFireFight(this.getMouseCoordinates());
|
||||
}
|
||||
else if (option === "land-at-point") {
|
||||
getApp().getUnitsManager().getSelectedUnits().length > 0 ? this.setState(MOVE_UNIT) : this.setState(IDLE);
|
||||
getApp().getUnitsManager().selectedUnitsLandAtPoint(this.getMouseCoordinates());
|
||||
}
|
||||
});
|
||||
var contextActionSet = new ContextActionSet();
|
||||
var units = getApp().getUnitsManager().getSelectedUnits();
|
||||
units.forEach((unit: Unit) => {
|
||||
unit.appendContextActions(contextActionSet, null, e.latlng);
|
||||
})
|
||||
|
||||
if (Object.keys(contextActionSet.getContextActions()).length > 0) {
|
||||
getApp().getMap().showUnitContextMenu(e.originalEvent.x, e.originalEvent.y, e.latlng);
|
||||
getApp().getMap().getUnitContextMenu().setContextActions(contextActionSet);
|
||||
}
|
||||
}, 150);
|
||||
this.#longPressHandled = false;
|
||||
@@ -698,6 +662,7 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#onZoomStart(e: any) {
|
||||
this.#previousZoom = this.getZoom();
|
||||
if (this.#centerUnit != null)
|
||||
this.#panToUnit(this.#centerUnit);
|
||||
this.#isZooming = true;
|
||||
@@ -724,17 +689,64 @@ export class Map extends L.Map {
|
||||
return minimapBoundaries;
|
||||
}
|
||||
|
||||
#createOptionButton(value: string, url: string, title: string, callback: string, argument: string) {
|
||||
var button = document.createElement("button");
|
||||
const img = document.createElement("img");
|
||||
img.src = `/resources/theme/images/buttons/${url}`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
button.title = title;
|
||||
button.value = value;
|
||||
button.appendChild(img);
|
||||
button.setAttribute("data-on-click", callback);
|
||||
button.setAttribute("data-on-click-params", argument);
|
||||
return button;
|
||||
#createUnitMarkerControlButtons() {
|
||||
const unitVisibilityControls = <HTMLElement>document.getElementById("unit-visibility-control");
|
||||
const makeTitle = (isProtected:boolean) => {
|
||||
return ( isProtected ) ? "Unit type is protected and will ignore orders" : "Unit is NOT protected and will respond to orders";
|
||||
}
|
||||
this.getMapMarkerControls().forEach( (control:MapMarkerControl) => {
|
||||
const toggles = `["${control.toggles.join('","')}"]`;
|
||||
const div = document.createElement("div");
|
||||
div.className = control.protectable === true ? "protectable" : "";
|
||||
|
||||
// TODO: for consistency let's avoid using innerHTML. Let's create elements.
|
||||
div.innerHTML = `
|
||||
<button data-on-click="toggleMarkerVisibility" title="${control.tooltip}" data-on-click-params='{"types":${toggles}}'>
|
||||
<img src="/resources/theme/images/buttons/${control.image}" />
|
||||
</button>
|
||||
`;
|
||||
unitVisibilityControls.appendChild(div);
|
||||
|
||||
if ( control.protectable ) {
|
||||
div.innerHTML += `
|
||||
<button class="lock" ${control.isProtected ? "data-protected" : ""} title="${makeTitle(control.isProtected || false)}">
|
||||
<img src="/resources/theme/images/buttons/other/lock-solid.svg" class="locked" />
|
||||
<img src="/resources/theme/images/buttons/other/lock-open-solid.svg" class="unlocked" />
|
||||
</button>`;
|
||||
|
||||
const btn = <HTMLButtonElement>div.querySelector("button.lock");
|
||||
btn.addEventListener("click", (ev:MouseEventInit) => {
|
||||
control.isProtected = !control.isProtected;
|
||||
btn.toggleAttribute("data-protected", control.isProtected);
|
||||
btn.title = makeTitle( control.isProtected );
|
||||
document.dispatchEvent(new CustomEvent("toggleMarkerProtection", {
|
||||
detail: {
|
||||
"_element": btn,
|
||||
"control": control
|
||||
}
|
||||
}));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
unitVisibilityControls.querySelectorAll(`img[src$=".svg"]`).forEach(img => SVGInjector(img));
|
||||
}
|
||||
|
||||
unitIsProtected(unit:Unit) {
|
||||
const toggles = this.#mapMarkerControls.reduce((list, control:MapMarkerControl) => {
|
||||
if (control.isProtected) {
|
||||
list = list.concat(control.toggles);
|
||||
}
|
||||
return list;
|
||||
}, [] as string[]);
|
||||
|
||||
if (toggles.length === 0)
|
||||
return false;
|
||||
|
||||
return toggles.some((toggle:string) => {
|
||||
// Specific coding for robots - extend later if needed
|
||||
return (toggle === "dcs" && !unit.getControlled() && !unit.getHuman());
|
||||
});
|
||||
}
|
||||
|
||||
#deselectCoalitionAreas() {
|
||||
@@ -753,44 +765,42 @@ export class Map extends L.Map {
|
||||
#showDestinationCursors() {
|
||||
const singleCursor = !this.#shiftKey;
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).length;
|
||||
if (selectedUnitsCount > 0) {
|
||||
if (singleCursor) {
|
||||
if ( this.#destinationPreviewCursors.length != 1) {
|
||||
this.#hideDestinationCursors();
|
||||
var marker = new DestinationPreviewMarker(this.getMouseCoordinates(), { interactive: false });
|
||||
marker.addTo(this);
|
||||
this.#destinationPreviewCursors = [marker];
|
||||
}
|
||||
|
||||
this.#destinationPreviewHandleLine.removeFrom(this);
|
||||
this.#destinationPreviewHandle.removeFrom(this);
|
||||
if (singleCursor) {
|
||||
if ( this.#destinationPreviewCursors.length != 1) {
|
||||
this.#hideDestinationCursors();
|
||||
var marker = new DestinationPreviewMarker(this.getMouseCoordinates(), { interactive: false });
|
||||
marker.addTo(this);
|
||||
this.#destinationPreviewCursors = [marker];
|
||||
}
|
||||
else if (!singleCursor) {
|
||||
while (this.#destinationPreviewCursors.length > selectedUnitsCount) {
|
||||
this.removeLayer(this.#destinationPreviewCursors[0]);
|
||||
this.#destinationPreviewCursors.splice(0, 1);
|
||||
}
|
||||
|
||||
this.#destinationPreviewHandleLine.addTo(this);
|
||||
this.#destinationPreviewHandle.addTo(this);
|
||||
|
||||
while (this.#destinationPreviewCursors.length < selectedUnitsCount) {
|
||||
var cursor = new DestinationPreviewMarker(this.getMouseCoordinates(), { interactive: false });
|
||||
cursor.addTo(this);
|
||||
this.#destinationPreviewCursors.push(cursor);
|
||||
}
|
||||
|
||||
this.#updateDestinationCursors();
|
||||
}
|
||||
this.#destinationPreviewHandleLine.removeFrom(this);
|
||||
this.#destinationPreviewHandle.removeFrom(this);
|
||||
}
|
||||
}
|
||||
else if (!singleCursor) {
|
||||
while (this.#destinationPreviewCursors.length > selectedUnitsCount) {
|
||||
this.removeLayer(this.#destinationPreviewCursors[0]);
|
||||
this.#destinationPreviewCursors.splice(0, 1);
|
||||
}
|
||||
|
||||
this.#destinationPreviewHandleLine.addTo(this);
|
||||
this.#destinationPreviewHandle.addTo(this);
|
||||
|
||||
while (this.#destinationPreviewCursors.length < selectedUnitsCount) {
|
||||
var cursor = new DestinationPreviewMarker(this.getMouseCoordinates(), { interactive: false });
|
||||
cursor.addTo(this);
|
||||
this.#destinationPreviewCursors.push(cursor);
|
||||
}
|
||||
|
||||
this.#updateDestinationCursors();
|
||||
}
|
||||
}
|
||||
|
||||
#updateDestinationCursors() {
|
||||
const groupLatLng = this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : this.getMouseCoordinates();
|
||||
if (this.#destinationPreviewCursors.length == 1)
|
||||
this.#destinationPreviewCursors[0].setLatLng(this.getMouseCoordinates());
|
||||
else {
|
||||
Object.values(getApp().getUnitsManager().selectedUnitsComputeGroupDestination(groupLatLng, this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => {
|
||||
Object.values(getApp().getUnitsManager().computeGroupDestination(groupLatLng, this.#destinationGroupRotation)).forEach((latlng: L.LatLng, idx: number) => {
|
||||
if (idx < this.#destinationPreviewCursors.length)
|
||||
this.#destinationPreviewCursors[idx].setLatLng(this.#shiftKey ? latlng : this.getMouseCoordinates());
|
||||
})
|
||||
@@ -853,5 +863,9 @@ export class Map extends L.Map {
|
||||
this.#visibilityOptions[option] = ev.currentTarget.checked;
|
||||
document.dispatchEvent(new CustomEvent("mapVisibilityOptionsChanged"));
|
||||
}
|
||||
|
||||
getMapMarkerControls() {
|
||||
return this.#mapMarkerControls;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -36,6 +36,7 @@ export class TemporaryUnitMarker extends CustomMarker {
|
||||
|
||||
createIcon() {
|
||||
const category = getMarkerCategoryByName(this.#name);
|
||||
const databaseEntry = getUnitDatabaseByCategory(category)?.getByName(this.#name);
|
||||
|
||||
/* Set the icon */
|
||||
var icon = new DivIcon({
|
||||
@@ -54,7 +55,8 @@ export class TemporaryUnitMarker extends CustomMarker {
|
||||
var unitIcon = document.createElement("div");
|
||||
unitIcon.classList.add("unit-icon");
|
||||
var img = document.createElement("img");
|
||||
img.src = `/resources/theme/images/units/${category}.svg`;
|
||||
|
||||
img.src = `/resources/theme/images/units/${databaseEntry?.markerFile ?? category}.svg`;
|
||||
img.onload = () => SVGInjector(img);
|
||||
unitIcon.appendChild(img);
|
||||
unitIcon.toggleAttribute("data-rotate-to-heading", false);
|
||||
@@ -64,7 +66,7 @@ export class TemporaryUnitMarker extends CustomMarker {
|
||||
if (category == "aircraft" || category == "helicopter") {
|
||||
var shortLabel = document.createElement("div");
|
||||
shortLabel.classList.add("unit-short-label");
|
||||
shortLabel.innerText = getUnitDatabaseByCategory(category)?.getByName(this.#name)?.shortLabel || "";
|
||||
shortLabel.innerText = databaseEntry?.shortLabel || "";
|
||||
el.append(shortLabel);
|
||||
}
|
||||
|
||||
|
||||