diff --git a/client/@types/olympus/index.d.ts b/client/@types/olympus/index.d.ts
index c5666bb1..6d698502 100644
--- a/client/@types/olympus/index.d.ts
+++ b/client/@types/olympus/index.d.ts
@@ -590,6 +590,7 @@ declare module "interfaces" {
canAAA?: boolean;
indirectFire?: boolean;
markerFile?: string;
+ unitWhenGrouped?: string;
}
export interface UnitSpawnOptions {
roleType: string;
@@ -773,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;
diff --git a/client/demo.js b/client/demo.js
index 751fab2d..9e560bee 100644
--- a/client/demo.js
+++ b/client/demo.js
@@ -10,7 +10,7 @@ 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 {
@@ -52,6 +52,10 @@ class DemoDataGenerator {
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));
@@ -60,28 +64,57 @@ class DemoDataGenerator {
let idx = 1;
console.log(l)
for (let name in databases) {
- 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 (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;
+ 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;
+
this.startTime = Date.now();
}
diff --git a/client/plugins/databasemanager/index.js b/client/plugins/databasemanager/index.js
index 5c5781b5..2e282c1a 100644
--- a/client/plugins/databasemanager/index.js
+++ b/client/plugins/databasemanager/index.js
@@ -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, _o, _p, _q, _r, _s, _t, _u, _v;
+ 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,28 +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, "Targeting range [m]", (_e = String(blueprint.targetingRange)) !== null && _e !== void 0 ? _e : "", "number", (value) => { blueprint.targetingRange = parseFloat(value); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Aim method range [m]", (_f = String(blueprint.aimMethodRange)) !== null && _f !== void 0 ? _f : "", "number", (value) => { blueprint.aimMethodRange = parseFloat(value); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Barrel height [m]", (_g = String(blueprint.barrelHeight)) !== null && _g !== void 0 ? _g : "", "number", (value) => { blueprint.barrelHeight = parseFloat(value); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Muzzle velocity [m/s]", (_h = String(blueprint.muzzleVelocity)) !== null && _h !== void 0 ? _h : "", "number", (value) => { blueprint.muzzleVelocity = parseFloat(value); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Aim time [s]", (_j = String(blueprint.aimTime)) !== null && _j !== void 0 ? _j : "", "number", (value) => { blueprint.aimTime = parseFloat(value); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Shots to fire", (_k = String(blueprint.shotsToFire)) !== null && _k !== void 0 ? _k : "", "number", (value) => { blueprint.shotsToFire = Math.round(parseFloat(value)); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Shots base interval [s]", (_l = String(blueprint.shotsBaseInterval)) !== null && _l !== void 0 ? _l : "", "number", (value) => { blueprint.shotsBaseInterval = Math.round(parseFloat(value)); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Shots base scatter [°]", (_m = String(blueprint.shotsBaseScatter)) !== null && _m !== void 0 ? _m : "", "number", (value) => { blueprint.shotsBaseScatter = Math.round(parseFloat(value)); });
- (0, utils_1.addStringInput)(this.contentDiv2, "Alertness time constant [s]", (_o = String(blueprint.alertnessTimeConstant)) !== null && _o !== void 0 ? _o : "", "number", (value) => { blueprint.alertnessTimeConstant = Math.round(parseFloat(value)); });
- (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can target point", (_p = blueprint.canTargetPoint) !== null && _p !== void 0 ? _p : false, (value) => { blueprint.canTargetPoint = value; });
- (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can rearm", (_q = blueprint.canRearm) !== null && _q !== void 0 ? _q : false, (value) => { blueprint.canRearm = value; });
- (0, utils_1.addCheckboxInput)(this.contentDiv2, "Can operate as AAA", (_r = blueprint.canAAA) !== null && _r !== void 0 ? _r : false, (value) => { blueprint.canAAA = value; });
- (0, utils_1.addCheckboxInput)(this.contentDiv2, "Indirect fire (e.g. mortar)", (_s = blueprint.indirectFire) !== null && _s !== void 0 ? _s : false, (value) => { blueprint.indirectFire = value; });
- (0, utils_1.addStringInput)(this.contentDiv2, "Description", (_t = blueprint.description) !== null && _t !== void 0 ? _t : "", "text", (value) => { blueprint.description = value; });
- (0, utils_1.addStringInput)(this.contentDiv2, "Tags", (_u = blueprint.tags) !== null && _u !== void 0 ? _u : "", "text", (value) => { blueprint.tags = value; });
- (0, utils_1.addStringInput)(this.contentDiv2, "Marker file", (_v = blueprint.markerFile) !== null && _v !== void 0 ? _v : "", "text", (value) => { blueprint.markerFile = 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
@@ -998,8 +999,8 @@ function addBlueprintsScroll(div, database, filter, callback) {
if (addKey) {
var rowDiv = document.createElement("div");
scrollDiv.appendChild(rowDiv);
- let text = document.createElement("label");
- text.textContent = key;
+ let text = document.createElement("div");
+ text.innerHTML = `
${key}
${blueprints[key].label}
`;
text.onclick = () => {
callback(key);
const collection = document.getElementsByClassName("blueprint-selected");
diff --git a/client/plugins/databasemanager/src/grounduniteditor.ts b/client/plugins/databasemanager/src/grounduniteditor.ts
index ef5c61ae..41d68345 100644
--- a/client/plugins/databasemanager/src/grounduniteditor.ts
+++ b/client/plugins/databasemanager/src/grounduniteditor.ts
@@ -30,6 +30,7 @@ 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; });
diff --git a/client/plugins/databasemanager/src/utils.ts b/client/plugins/databasemanager/src/utils.ts
index 18639612..ba166dec 100644
--- a/client/plugins/databasemanager/src/utils.ts
+++ b/client/plugins/databasemanager/src/utils.ts
@@ -198,8 +198,8 @@ export function addBlueprintsScroll(div: HTMLElement, database: {blueprints: {[k
var rowDiv = document.createElement("div");
scrollDiv.appendChild(rowDiv);
- let text = document.createElement("label");
- text.textContent = key;
+ let text = document.createElement("div");
+ text.innerHTML = `${key}
${blueprints[key].label}
`;
text.onclick = () => {
callback(key);
const collection = document.getElementsByClassName("blueprint-selected");
diff --git a/client/plugins/databasemanager/style.css b/client/plugins/databasemanager/style.css
index 0dfd2647..f8c80213 100644
--- a/client/plugins/databasemanager/style.css
+++ b/client/plugins/databasemanager/style.css
@@ -73,7 +73,7 @@
}
.dm-content-container:nth-of-type(1) {
- width: 300px;
+ width: 400px;
}
.dm-content-container:nth-of-type(2) {
@@ -153,12 +153,29 @@
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;
diff --git a/client/public/databases/units/groundunitdatabase.json b/client/public/databases/units/groundunitdatabase.json
index ca48fbd4..5c980d7a 100644
--- a/client/public/databases/units/groundunitdatabase.json
+++ b/client/public/databases/units/groundunitdatabase.json
@@ -26,7 +26,7 @@
"name": "2B11 mortar",
"coalition": "red",
"era": "Late Cold War",
- "label": "2B11 mortar (120mm)",
+ "label": "2B11 mortar",
"shortLabel": "2B11 mortar",
"filename": "",
"type": "Artillery",
@@ -62,14 +62,16 @@
"barrelHeight": 1,
"muzzleVelocity": 325,
"aimTime": 5,
- "shotsToFire": 100
+ "shotsToFire": 100,
+ "markerFile": "groundunit-artillery",
+ "tags": "120mm"
},
"2S6 Tunguska": {
"name": "2S6 Tunguska",
"coalition": "red",
"era": "Late Cold War",
"label": "SA-19 Tunguska",
- "shortLabel": "SA-19",
+ "shortLabel": "19",
"range": "Short",
"filename": "",
"type": "SAM Site",
@@ -123,7 +125,8 @@
"aimTime": 5,
"shotsToFire": 10,
"cost": null,
- "tags": "Optical, Radar, CA"
+ "tags": "Optical, Radar, CA",
+ "markerFile": "groundunit-sam"
},
"55G6 EWR": {
"name": "55G6 EWR",
@@ -152,7 +155,7 @@
"name": "5p73 s-125 ln",
"coalition": "red",
"era": "Mid Cold War",
- "label": "SA-3",
+ "label": "SA-3 Launcher",
"shortLabel": "5p73 s-125 ln",
"range": "Medium",
"filename": "",
@@ -202,7 +205,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Launcher"
+ "tags": "",
+ "markerFile": "groundunit-sam-launcher"
},
"AAV7": {
"name": "AAV7",
@@ -245,7 +249,8 @@
"muzzleVelocity": 900,
"aimTime": 10,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"ATMZ-5": {
"name": "ATMZ-5",
@@ -268,7 +273,8 @@
"abilities": "Refuel",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Fuel Truck"
+ "tags": "Fuel Truck",
+ "markerFile": "groundunit-truck"
},
"ATZ-10": {
"name": "ATZ-10",
@@ -291,7 +297,8 @@
"abilities": "Refuel",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Fuel Truck"
+ "tags": "Fuel Truck",
+ "markerFile": "groundunit-truck"
},
"BMD-1": {
"name": "BMD-1",
@@ -354,7 +361,8 @@
"canRearm": false,
"shotsToFire": 100,
"aimTime": 5,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"BMP-1": {
"name": "BMP-1",
@@ -461,7 +469,8 @@
"muzzleVelocity": 665,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"BMP-2": {
"name": "BMP-2",
@@ -552,7 +561,8 @@
"canRearm": false,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"BMP-3": {
"name": "BMP-3",
@@ -611,7 +621,8 @@
"muzzleVelocity": 1080,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"BRDM-2": {
"name": "BRDM-2",
@@ -670,7 +681,8 @@
"barrelHeight": 2.25,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"BTR-80": {
"name": "BTR-80",
@@ -761,7 +773,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"BTR_D": {
"name": "BTR_D",
@@ -816,7 +829,8 @@
"abilities": "Combined arms, Amphibious, Transport",
"canTargetPoint": false,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"Bunker": {
"name": "Bunker",
@@ -863,7 +877,8 @@
"muzzleVelocity": 800,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tank"
},
"Cobra": {
"name": "Cobra",
@@ -884,7 +899,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"Dog Ear radar": {
"name": "Dog Ear radar",
@@ -955,7 +971,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Search Radar"
+ "tags": "Search Radar",
+ "markerFile": "groundunit-sam-radar"
},
"GAZ-3307": {
"name": "GAZ-3307",
@@ -977,7 +994,8 @@
"description": "Civilian truck, single axle, wheeled",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"GAZ-3308": {
"name": "GAZ-3308",
@@ -999,7 +1017,8 @@
"description": "Military truck, single axle, canvas covered cargo bay. wheeled",
"abilities": "Rearm",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"GAZ-66": {
"name": "GAZ-66",
@@ -1053,7 +1072,8 @@
"description": "Military truck, single axle, open cargo bay. wheeled",
"abilities": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"Gepard": {
"name": "Gepard",
@@ -1097,7 +1117,8 @@
"aimTime": 5,
"shotsToFire": 100,
"cost": 15000000,
- "tags": "Radar, CA"
+ "tags": "Radar, CA",
+ "markerFile": "groundunit-aaa"
},
"Grad-URAL": {
"name": "Grad-URAL",
@@ -1113,7 +1134,8 @@
"description": "Military truck, single axle, open cargo bay. wheeled",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"HEMTT TFFT": {
"name": "HEMTT TFFT",
@@ -1135,14 +1157,15 @@
"description": "Military truck, 2 axle, firefigther. wheeled",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Hawk SAM Battery": {
"name": "Hawk SAM Battery",
"coalition": "blue",
"era": "Early Cold War",
"label": "Hawk SAM Battery",
- "shortLabel": "Hawk SAM Battery",
+ "shortLabel": "HA",
"range": "Medium",
"filename": "",
"type": "SAM Site",
@@ -1153,7 +1176,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"Hawk cwar": {
"name": "Hawk cwar",
@@ -1184,7 +1208,8 @@
"description": "Hawk site Aquisition Radar",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"Hawk ln": {
"name": "Hawk ln",
@@ -1888,7 +1913,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam-radar"
},
"Hawk tr": {
"name": "Hawk tr",
@@ -2224,7 +2250,8 @@
"description": "Hawk site track Radar. Medium sized trailer",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"Hummer": {
"name": "Hummer",
@@ -2279,7 +2306,8 @@
"abilities": "Combined arms, Transport",
"canTargetPoint": false,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"IKARUS Bus": {
"name": "IKARUS Bus",
@@ -2295,14 +2323,15 @@
"description": "Civilian Bus. Yellow. Bendy bus",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Igla manpad INS": {
"name": "Igla manpad INS",
"coalition": "red",
"era": "Late Cold War",
"label": "SA-18",
- "shortLabel": "SA-18 Igla",
+ "shortLabel": "18",
"range": "Short",
"filename": "",
"type": "SAM Site",
@@ -2331,7 +2360,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "IR, CA, MANPADS"
+ "tags": "IR, CA, MANPADS",
+ "markerFile": "groundunit-sam"
},
"Infantry AK": {
"name": "Infantry AK",
@@ -2352,7 +2382,8 @@
"canRearm": false,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian type 1"
+ "tags": "Russian type 1",
+ "markerFile": "groundunit-infantry"
},
"KAMAZ Truck": {
"name": "KAMAZ Truck",
@@ -2406,7 +2437,8 @@
"description": "Military truck, 2 axle, wheeled",
"abilities": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"Kub 1S91 str": {
"name": "Kub 1S91 str",
@@ -2445,7 +2477,8 @@
"description": "SA-6/Kub search and track Radar, tracked.",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"Kub 2P25 ln": {
"name": "Kub 2P25 ln",
@@ -2544,7 +2577,8 @@
"muzzleVelocity": 1100,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"LAZ Bus": {
"name": "LAZ Bus",
@@ -2560,7 +2594,8 @@
"description": "Civilian bus. Single Axle. Wheeled",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Leclerc": {
"name": "Leclerc",
@@ -2582,7 +2617,8 @@
"description": "Main battle tank. Tracked. Modern and heavily armoured.",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Leopard-2": {
"name": "Leopard-2",
@@ -2748,7 +2784,8 @@
"description": "Main battle tank. Tracked. Modern and heavily armoured.",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Leopard1A3": {
"name": "Leopard1A3",
@@ -2802,7 +2839,8 @@
"description": "Main battle tank. Tracked. Heavily armoured.",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"M 818": {
"name": "M 818",
@@ -2836,7 +2874,8 @@
"description": "???",
"abilities": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"M-1 Abrams": {
"name": "M-1 Abrams",
@@ -2875,7 +2914,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tank"
},
"M-109": {
"name": "M-109",
@@ -2930,7 +2970,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "155mm, CA"
+ "tags": "155mm, CA",
+ "markerFile": "groundunit-artillery"
},
"M-113": {
"name": "M-113",
@@ -3033,7 +3074,8 @@
"muzzleVelocity": 950,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"M-2 Bradley": {
"name": "M-2 Bradley",
@@ -3076,7 +3118,8 @@
"muzzleVelocity": 1000,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"M-60": {
"name": "M-60",
@@ -3114,7 +3157,8 @@
"description": "Main battle tank. Tracked. Heavily armoured.",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"M1043 HMMWV Armament": {
"name": "M1043 HMMWV Armament",
@@ -3169,7 +3213,8 @@
"abilities": "Combined arms, Transport",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"M1045 HMMWV TOW": {
"name": "M1045 HMMWV TOW",
@@ -3224,14 +3269,15 @@
"abilities": "Combined arms, Transport",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"M1097 Avenger": {
"name": "M1097 Avenger",
"coalition": "blue",
"era": "Modern",
"label": "M1097 Avenger",
- "shortLabel": "M1097 Avenger",
+ "shortLabel": "97",
"filename": "",
"type": "SAM Site",
"enabled": true,
@@ -3241,7 +3287,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "IR, CA"
+ "tags": "IR, CA",
+ "markerFile": "groundunit-sam"
},
"M1126 Stryker ICV": {
"name": "M1126 Stryker ICV",
@@ -3262,7 +3309,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"M1128 Stryker MGS": {
"name": "M1128 Stryker MGS",
@@ -3283,7 +3331,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"M1134 Stryker ATGM": {
"name": "M1134 Stryker ATGM",
@@ -3304,14 +3353,15 @@
"muzzleVelocity": 900,
"barrelHeight": 2.8,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"M48 Chaparral": {
"name": "M48 Chaparral",
"coalition": "blue",
"era": "Mid Cold War",
"label": "M48 Chaparral",
- "shortLabel": "M48 Chaparral",
+ "shortLabel": "48",
"filename": "",
"type": "SAM Site",
"enabled": true,
@@ -3375,14 +3425,15 @@
"abilities": "Combined arms,",
"canTargetPoint": false,
"canRearm": false,
- "tags": "IR, CA"
+ "tags": "IR, CA",
+ "markerFile": "groundunit-sam"
},
"M6 Linebacker": {
"name": "M6 Linebacker",
"coalition": "blue",
"era": "Late Cold War",
"label": "M6 Linebacker",
- "shortLabel": "M6 Linebacker",
+ "shortLabel": "M6",
"filename": "",
"type": "SAM Site",
"enabled": true,
@@ -3414,7 +3465,8 @@
"abilities": "Combined arms,",
"canTargetPoint": false,
"canRearm": false,
- "tags": "IR, CA"
+ "tags": "IR, CA",
+ "markerFile": "groundunit-sam"
},
"M978 HEMTT Tanker": {
"name": "M978 HEMTT Tanker",
@@ -3452,7 +3504,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"MAZ-6303": {
"name": "MAZ-6303",
@@ -3490,7 +3543,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"MCV-80": {
"name": "MCV-80",
@@ -3533,7 +3587,8 @@
"muzzleVelocity": 1100,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"MLRS": {
"name": "MLRS",
@@ -3588,7 +3643,8 @@
"abilities": "Combined arms, Indirect Fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "270mm, MLRS, CA"
+ "tags": "270mm, MLRS, CA",
+ "markerFile": "groundunit-artillery"
},
"MTLB": {
"name": "MTLB",
@@ -3647,7 +3703,8 @@
"muzzleVelocity": 800,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"Marder": {
"name": "Marder",
@@ -3690,7 +3747,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"Osa 9A33 ln": {
"name": "Osa 9A33 ln",
@@ -3751,7 +3809,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian Para"
+ "tags": "Russian Para",
+ "markerFile": "groundunit-infantry"
},
"Paratrooper RPG-16": {
"name": "Paratrooper RPG-16",
@@ -3772,7 +3831,8 @@
"muzzleVelocity": 295,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian Para"
+ "tags": "Russian Para",
+ "markerFile": "groundunit-infantry"
},
"Patriot AMG": {
"name": "Patriot AMG",
@@ -4046,7 +4106,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"Predator GCS": {
"name": "Predator GCS",
@@ -4070,7 +4131,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Predator TrojanSpirit": {
"name": "Predator TrojanSpirit",
@@ -4086,7 +4148,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"RLS_19J6": {
"name": "RLS_19J6",
@@ -4121,7 +4184,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"RPC_5N62V": {
"name": "RPC_5N62V",
@@ -4211,7 +4275,7 @@
"coalition": "blue",
"era": "Late Cold War",
"label": "Roland ADS",
- "shortLabel": "Roland ADS",
+ "shortLabel": "RO",
"filename": "",
"type": "SAM Site",
"enabled": true,
@@ -4227,7 +4291,8 @@
"abilities": "Combined arms,",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar, Optical, CA"
+ "tags": "Radar, Optical, CA",
+ "markerFile": "groundunit-sam"
},
"Roland Radar": {
"name": "Roland Radar",
@@ -4249,7 +4314,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"S-200_Launcher": {
"name": "S-200_Launcher",
@@ -4372,7 +4438,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"S-300PS 40B6MD sr": {
"name": "S-300PS 40B6MD sr",
@@ -4411,7 +4478,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"S-300PS 54K6 cp": {
"name": "S-300PS 54K6 cp",
@@ -4571,14 +4639,15 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"SA-10 SAM Battery": {
"name": "SA-10 SAM Battery",
"coalition": "red",
"era": "Late Cold War",
"label": "SA-10 SAM Battery",
- "shortLabel": "SA-10",
+ "shortLabel": "10",
"range": "Long",
"filename": "",
"type": "SAM Site",
@@ -4589,7 +4658,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"SA-11 Buk CC 9S470M1": {
"name": "SA-11 Buk CC 9S470M1",
@@ -4762,7 +4832,7 @@
"coalition": "red",
"era": "Late Cold War",
"label": "SA-11 SAM Battery",
- "shortLabel": "SA-11 SAM Battery",
+ "shortLabel": "11",
"range": "Medium",
"filename": "",
"type": "SAM Site",
@@ -4773,14 +4843,15 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"SA-18 Igla manpad": {
"name": "SA-18 Igla manpad",
"coalition": "red",
"era": "Late Cold War",
"label": "SA-18 Igla \"Grouse\" C2",
- "shortLabel": "SA-18 Igla manpad",
+ "shortLabel": "18",
"range": "Short",
"filename": "",
"type": "SAM Site",
@@ -4798,7 +4869,7 @@
"coalition": "red",
"era": "Late Cold War",
"label": "SA-18 Igla \"Grouse\" C2",
- "shortLabel": "SA-18 Igla \"Grouse\"",
+ "shortLabel": "18",
"range": "Short",
"filename": "",
"type": "SAM Site",
@@ -4816,7 +4887,7 @@
"coalition": "red",
"era": "Early Cold War",
"label": "SA-2 SAM Battery",
- "shortLabel": "SA-2",
+ "shortLabel": "2",
"range": "Long",
"filename": "",
"type": "SAM Site",
@@ -4827,14 +4898,15 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"SA-3 SAM Battery": {
"name": "SA-3 SAM Battery",
"coalition": "red",
"era": "Early Cold War",
"label": "SA-3 SAM Battery",
- "shortLabel": "SA-3",
+ "shortLabel": "3",
"range": "Medium",
"filename": "",
"type": "SAM Site",
@@ -4845,14 +4917,15 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"SA-5 SAM Battery": {
"name": "SA-5 SAM Battery",
"coalition": "red",
"era": "Mid Cold War",
"label": "SA-5 SAM Battery",
- "shortLabel": "SA-5",
+ "shortLabel": "5",
"range": "Long",
"filename": "",
"type": "SAM Site",
@@ -4863,14 +4936,15 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"SA-6 SAM Battery": {
"name": "SA-6 SAM Battery",
"coalition": "red",
"era": "Mid Cold War",
"label": "SA-6 SAM Battery",
- "shortLabel": "SA-6",
+ "shortLabel": "6",
"range": "Medium",
"filename": "",
"type": "SAM Site",
@@ -4881,7 +4955,8 @@
"engagementRange": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-sam"
},
"SAU 2-C9": {
"name": "SAU 2-C9",
@@ -4936,7 +5011,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "120mm, CA"
+ "tags": "120mm, CA",
+ "markerFile": "groundunit-artillery"
},
"SAU Akatsia": {
"name": "SAU Akatsia",
@@ -4991,7 +5067,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "152mm, CA"
+ "tags": "152mm, CA",
+ "markerFile": "groundunit-artillery"
},
"SAU Gvozdika": {
"name": "SAU Gvozdika",
@@ -5046,7 +5123,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "122mm, CA"
+ "tags": "122mm, CA",
+ "markerFile": "groundunit-artillery"
},
"SAU Msta": {
"name": "SAU Msta",
@@ -5101,7 +5179,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "152mm, CA"
+ "tags": "152mm, CA",
+ "markerFile": "groundunit-artillery"
},
"SKP-11": {
"name": "SKP-11",
@@ -5123,7 +5202,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"SNR_75V": {
"name": "SNR_75V",
@@ -5161,7 +5241,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"S_75M_Volhov": {
"name": "S_75M_Volhov",
@@ -5200,7 +5281,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "markerFile": "groundunit-sam-launcher"
+ "markerFile": "groundunit-sam-launcher",
+ "unitWhenGrouped": "SA-2 SAM Battery"
},
"Sandbox": {
"name": "Sandbox",
@@ -5255,7 +5337,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Rocket, CA"
+ "tags": "Rocket, CA",
+ "markerFile": "groundunit-artillery"
},
"Soldier AK": {
"name": "Soldier AK",
@@ -5310,7 +5393,8 @@
"canRearm": false,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian type 4"
+ "tags": "Russian type 4",
+ "markerFile": "groundunit-infantry"
},
"Soldier M249": {
"name": "Soldier M249",
@@ -5365,7 +5449,8 @@
"aimTime": 5,
"shotsToFire": 100,
"barrelHeight": 0.2,
- "tags": "US"
+ "tags": "US",
+ "markerFile": "groundunit-infantry"
},
"Soldier M4 GRG": {
"name": "Soldier M4 GRG",
@@ -5420,7 +5505,8 @@
"muzzleVelocity": 910,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Georgia"
+ "tags": "Georgia",
+ "markerFile": "groundunit-infantry"
},
"Soldier M4": {
"name": "Soldier M4",
@@ -5475,7 +5561,8 @@
"muzzleVelocity": 910,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "US"
+ "tags": "US",
+ "markerFile": "groundunit-infantry"
},
"Soldier RPG": {
"name": "Soldier RPG",
@@ -5530,7 +5617,8 @@
"muzzleVelocity": 295,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian"
+ "tags": "Russian",
+ "markerFile": "groundunit-infantry"
},
"Stinger comm dsr": {
"name": "Stinger comm dsr",
@@ -5570,7 +5658,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "MANPADS, IR"
+ "tags": "MANPADS, IR",
+ "markerFile": "groundunit-sam"
},
"Stinger comm": {
"name": "Stinger comm",
@@ -5610,14 +5699,15 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "MANPADS, IR"
+ "tags": "MANPADS, IR",
+ "markerFile": "groundunit-sam"
},
"Strela-1 9P31": {
"name": "Strela-1 9P31",
"coalition": "red",
"era": "Mid Cold War",
"label": "SA-9 SAM Battery",
- "shortLabel": "SA-9 Strela 1",
+ "shortLabel": "9",
"range": "Short",
"filename": "",
"type": "SAM Site",
@@ -5666,14 +5756,15 @@
"abilities": "Combined arms, Amphibious",
"canTargetPoint": false,
"canRearm": false,
- "tags": "IR, CA"
+ "tags": "IR, CA",
+ "markerFile": "groundunit-sam"
},
"Strela-10M3": {
"name": "Strela-10M3",
"coalition": "red",
"era": "Late Cold War",
"label": "SA-13 SAM Battery",
- "shortLabel": "SA-13 Strela 10",
+ "shortLabel": "13",
"range": "Short",
"filename": "",
"type": "SAM Site",
@@ -5722,7 +5813,8 @@
"abilities": "Combined arms, Amphibious",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Optical, Radar, CA"
+ "tags": "Optical, Radar, CA",
+ "markerFile": "groundunit-sam"
},
"Suidae": {
"name": "Suidae",
@@ -5738,7 +5830,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"T-55": {
"name": "T-55",
@@ -5792,7 +5885,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"T-72B": {
"name": "T-72B",
@@ -5814,7 +5908,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"T-80UD": {
"name": "T-80UD",
@@ -5876,7 +5971,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"T-90": {
"name": "T-90",
@@ -5930,7 +6026,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"TPZ": {
"name": "TPZ",
@@ -5951,7 +6048,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"Tigr_233036": {
"name": "Tigr_233036",
@@ -5973,14 +6071,15 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Tor 9A331": {
"name": "Tor 9A331",
"coalition": "red",
"era": "Late Cold War",
"label": "SA-15 SAM Battery",
- "shortLabel": "SA-15 Tor",
+ "shortLabel": "15",
"range": "Medium",
"filename": "",
"type": "SAM Site",
@@ -6045,7 +6144,8 @@
"abilities": "Combined arms,",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Radar, CA"
+ "tags": "Radar, CA",
+ "markerFile": "groundunit-sam"
},
"Trolley bus": {
"name": "Trolley bus",
@@ -6061,7 +6161,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"UAZ-469": {
"name": "UAZ-469",
@@ -6127,7 +6228,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Uragan_BM-27": {
"name": "Uragan_BM-27",
@@ -6198,7 +6300,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Rocket, CA"
+ "tags": "Rocket, CA",
+ "markerFile": "groundunit-artillery"
},
"Ural ATsP-6": {
"name": "Ural ATsP-6",
@@ -6214,7 +6317,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Ural-375 PBU": {
"name": "Ural-375 PBU",
@@ -6236,7 +6340,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Ural-375 ZU-23 Insurgent": {
"name": "Ural-375 ZU-23 Insurgent",
@@ -6264,7 +6369,8 @@
"muzzleVelocity": 1000,
"barrelHeight": 3,
"cost": 90000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"Ural-375 ZU-23": {
"name": "Ural-375 ZU-23",
@@ -6292,7 +6398,8 @@
"muzzleVelocity": 1000,
"aimTime": 8,
"shotsToFire": 1000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"Ural-375": {
"name": "Ural-375",
@@ -6314,7 +6421,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"Ural-4320 APA-5D": {
"name": "Ural-4320 APA-5D",
@@ -6336,7 +6444,8 @@
"description": "Lightly armoured",
"abilities": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"Ural-4320-31": {
"name": "Ural-4320-31",
@@ -6358,7 +6467,8 @@
"abilities": "",
"description": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"Ural-4320T": {
"name": "Ural-4320T",
@@ -6380,7 +6490,8 @@
"abilities": "",
"description": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"VAZ Car": {
"name": "VAZ Car",
@@ -6396,7 +6507,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Vulcan": {
"name": "Vulcan",
@@ -6472,7 +6584,8 @@
"muzzleVelocity": 900,
"aimTime": 10,
"shotsToFire": 100,
- "tags": "Radar, CA"
+ "tags": "Radar, CA",
+ "markerFile": "groundunit-aaa"
},
"ZIL-131 KUNG": {
"name": "ZIL-131 KUNG",
@@ -6526,7 +6639,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"ZIL-4331": {
"name": "ZIL-4331",
@@ -6580,7 +6694,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"ZSU-23-4 Shilka": {
"name": "ZSU-23-4 Shilka",
@@ -6672,7 +6787,8 @@
"aimTime": 9,
"shotsToFire": 100,
"cost": 2500000,
- "tags": "Radar, CA"
+ "tags": "Radar, CA",
+ "markerFile": "groundunit-aaa"
},
"ZU-23 Closed Insurgent": {
"name": "ZU-23 Closed Insurgent",
@@ -6700,7 +6816,8 @@
"aimTime": 9,
"shotsToFire": 100,
"cost": 50000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"ZU-23 Emplacement Closed": {
"name": "ZU-23 Emplacement Closed",
@@ -6744,7 +6861,8 @@
"muzzleVelocity": 1000,
"barrelHeight": 1.5,
"cost": 50000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"ZU-23 Emplacement": {
"name": "ZU-23 Emplacement",
@@ -6788,7 +6906,8 @@
"muzzleVelocity": 1000,
"barrelHeight": 1.5,
"cost": 50000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"ZU-23 Insurgent": {
"name": "ZU-23 Insurgent",
@@ -6816,7 +6935,8 @@
"muzzleVelocity": 1000,
"barrelHeight": 1.5,
"cost": 50000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"ZiL-131 APA-80": {
"name": "ZiL-131 APA-80",
@@ -6838,7 +6958,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"house1arm": {
"name": "house1arm",
@@ -6972,7 +7093,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"snr s-125 tr": {
"name": "snr s-125 tr",
@@ -7027,7 +7149,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"SpGH_Dana": {
"name": "SpGH_Dana",
@@ -7043,7 +7166,8 @@
"description": "SpGH Dana 77. Wheeled. Self propelled 152mm howitzer. 1km min range, 18km max.",
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-artillery"
},
"Grad_FDDM": {
"name": "Grad_FDDM",
@@ -7064,7 +7188,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Arty Command/Recon, CA"
+ "tags": "Arty Command/Recon, CA",
+ "markerFile": "groundunit-artillery"
},
"Infantry AK Ins": {
"name": "Infantry AK Ins",
@@ -7085,7 +7210,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Insurgent"
+ "tags": "Insurgent",
+ "markerFile": "groundunit-infantry"
},
"MLRS FDDM": {
"name": "MLRS FDDM",
@@ -7106,7 +7232,8 @@
"aimTime": 5,
"shotsToFire": 100,
"barrelHeight": 2.49,
- "tags": "Arty Command/Recon, CA"
+ "tags": "Arty Command/Recon, CA",
+ "markerFile": "groundunit-artillery"
},
"Infantry AK ver2": {
"name": "Infantry AK ver2",
@@ -7127,7 +7254,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian type 2"
+ "tags": "Russian type 2",
+ "markerFile": "groundunit-infantry"
},
"Infantry AK ver3": {
"name": "Infantry AK ver3",
@@ -7148,7 +7276,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "Russian type 3"
+ "tags": "Russian type 3",
+ "markerFile": "groundunit-infantry"
},
"Smerch_HE": {
"name": "Smerch_HE",
@@ -7165,14 +7294,15 @@
"abilities": "Combined Arms, Indirect Fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "300mm, MLRS, CA"
+ "tags": "300mm, MLRS, CA",
+ "markerFile": "groundunit-artillery"
},
"Soldier stinger": {
"name": "Soldier stinger",
"coalition": "",
"era": "",
"label": "Stinger",
- "shortLabel": "Stinger",
+ "shortLabel": "ST",
"type": "SAM Site",
"enabled": true,
"liveries": {},
@@ -7182,14 +7312,15 @@
"abilities": "Combined arms,",
"canTargetPoint": false,
"canRearm": false,
- "tags": "IR, CA, MANPADS"
+ "tags": "IR, CA, MANPADS",
+ "markerFile": "groundunit-sam"
},
"SA-18 Igla comm": {
"name": "SA-18 Igla comm",
"coalition": "",
"era": "",
"label": "SA-18 Igla \"Grouse\" C2",
- "shortLabel": "SA-18 Igla \"Grouse\" C2",
+ "shortLabel": "18",
"type": "SAM Site",
"enabled": false,
"liveries": {},
@@ -7206,7 +7337,7 @@
"coalition": "",
"era": "",
"label": "SA-18 Igla \"Grouse\" C2",
- "shortLabel": "SA-18 Igla \"Grouse\"",
+ "shortLabel": "18",
"type": "SAM Site",
"enabled": false,
"liveries": {},
@@ -7248,7 +7379,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"LiAZ Bus": {
"name": "LiAZ Bus",
@@ -7264,7 +7396,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"KrAZ6322": {
"name": "KrAZ6322",
@@ -7280,7 +7413,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": true
+ "canRearm": true,
+ "markerFile": "groundunit-truck"
},
"JTAC": {
"name": "JTAC",
@@ -7296,7 +7430,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-infantry"
},
"Electric locomotive": {
"name": "Electric locomotive",
@@ -7448,7 +7583,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"LARC-V": {
"name": "LARC-V",
@@ -7464,7 +7600,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"KS-19": {
"name": "KS-19",
@@ -7485,7 +7622,8 @@
"aimTime": 25,
"shotsToFire": 100,
"barrelHeight": 5,
- "cost": 8000
+ "cost": 8000,
+ "markerFile": "groundunit-aaa"
},
"SON_9": {
"name": "SON_9",
@@ -7503,7 +7641,8 @@
"canTargetPoint": false,
"canRearm": false,
"cost": 750000,
- "tags": "Radar"
+ "tags": "Radar",
+ "markerFile": "groundunit-aaa"
},
"Scud_B": {
"name": "Scud_B",
@@ -7520,7 +7659,8 @@
"abilities": "",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Missile"
+ "tags": "Missile",
+ "markerFile": "groundunit-artillery"
},
"HL_DSHK": {
"name": "HL_DSHK",
@@ -7537,7 +7677,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"HL_KORD": {
"name": "HL_KORD",
@@ -7554,7 +7695,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"tt_DSHK": {
"name": "tt_DSHK",
@@ -7571,7 +7713,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"tt_KORD": {
"name": "tt_KORD",
@@ -7588,7 +7731,8 @@
"abilities": "Combined arms,",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"HL_ZU-23": {
"name": "HL_ZU-23",
@@ -7610,7 +7754,8 @@
"muzzleVelocity": 1000,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"tt_ZU-23": {
"name": "tt_ZU-23",
@@ -7632,7 +7777,8 @@
"muzzleVelocity": 1000,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"HL_B8M1": {
"name": "HL_B8M1",
@@ -7649,7 +7795,8 @@
"abilities": "Combined Arms, Indirect Fire.",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Rocket, CA"
+ "tags": "Rocket, CA",
+ "markerFile": "groundunit-artillery"
},
"tt_B8M1": {
"name": "tt_B8M1",
@@ -7666,7 +7813,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "80mm, CA"
+ "tags": "80mm, CA",
+ "markerFile": "groundunit-artillery"
},
"NASAMS_Radar_MPQ64F1": {
"name": "NASAMS_Radar_MPQ64F1",
@@ -7682,7 +7830,8 @@
"description": "",
"abilities": "",
"canTargetPoint": "no",
- "canRearm": "no"
+ "canRearm": "no",
+ "markerFile": "groundunit-sam-radar"
},
"NASAMS_Command_Post": {
"name": "NASAMS_Command_Post",
@@ -7746,7 +7895,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"M2A1_halftrack": {
"name": "M2A1_halftrack",
@@ -7767,7 +7917,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"FPS-117 Dome": {
"name": "FPS-117 Dome",
@@ -7826,7 +7977,7 @@
"name": "RD_75",
"coalition": "",
"era": "",
- "label": "SAM SA-2 S-75 RD-75 Amazonka RF",
+ "label": "SA-2 S-75 RD-75 Amazonka RF",
"shortLabel": "SAM SA-2 S-75 RD-75 Amazonka RF",
"type": "SAM Site Parts",
"enabled": true,
@@ -7858,7 +8009,8 @@
"aimTime": 11,
"shotsToFire": 100,
"cost": 750000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"S-60_Type59_Artillery": {
"name": "S-60_Type59_Artillery",
@@ -7880,7 +8032,8 @@
"shotsToFire": 100,
"barrelHeight": 2,
"cost": 500000,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"generator_5i57": {
"name": "generator_5i57",
@@ -7896,7 +8049,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"T-72B3": {
"name": "T-72B3",
@@ -7912,7 +8066,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"PT_76": {
"name": "PT_76",
@@ -7928,7 +8083,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"BTR-82A": {
"name": "BTR-82A",
@@ -7949,7 +8105,8 @@
"muzzleVelocity": 900,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"ATZ-5": {
"name": "ATZ-5",
@@ -7966,7 +8123,8 @@
"abilities": "Combined arms, Refuel",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Fuel Truck, CA"
+ "tags": "Fuel Truck, CA",
+ "markerFile": "groundunit-truck"
},
"AA8": {
"name": "AA8",
@@ -7983,7 +8141,8 @@
"abilities": "Combined Arms",
"canTargetPoint": false,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-truck"
},
"TZ-22_KrAZ": {
"name": "TZ-22_KrAZ",
@@ -8000,7 +8159,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "KrAZ-258B1"
+ "tags": "KrAZ-258B1",
+ "markerFile": "groundunit-truck"
},
"ATZ-60_Maz": {
"name": "ATZ-60_Maz",
@@ -8017,7 +8177,8 @@
"abilities": "Combined arms",
"canTargetPoint": false,
"canRearm": false,
- "tags": "Cab only, CA"
+ "tags": "Cab only, CA",
+ "markerFile": "groundunit-truck"
},
"ZIL-135": {
"name": "ZIL-135",
@@ -8026,14 +8187,15 @@
"label": "Truck ZIL-135",
"shortLabel": "Truck ZIL-135",
"type": "Unarmed",
- "enabled": true,
+ "enabled": false,
"liveries": {},
"acquisitionRange": 0,
"engagementRange": 0,
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"S_75_ZIL": {
"name": "S_75_ZIL",
@@ -8050,7 +8212,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "ZIL-131"
+ "tags": "ZIL-131",
+ "markerFile": "groundunit-truck"
},
"rapier_fsa_launcher": {
"name": "rapier_fsa_launcher",
@@ -8098,7 +8261,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"bofors40": {
"name": "bofors40",
@@ -8120,7 +8284,8 @@
"aimTime": 8,
"shotsToFire": 100,
"cost": null,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-aaa"
},
"Chieftain_mk3": {
"name": "Chieftain_mk3",
@@ -8141,7 +8306,8 @@
"muzzleVelocity": 800,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tank"
},
"Bedford_MWD": {
"name": "Bedford_MWD",
@@ -8158,7 +8324,8 @@
"abilities": "Combined arms, Rearm",
"canTargetPoint": false,
"canRearm": true,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-truck"
},
"Land_Rover_101_FC": {
"name": "Land_Rover_101_FC",
@@ -8174,7 +8341,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Land_Rover_109_S3": {
"name": "Land_Rover_109_S3",
@@ -8190,7 +8358,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"hy_launcher": {
"name": "hy_launcher",
@@ -8207,7 +8376,8 @@
"abilities": "",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Missile Launcher"
+ "tags": "Missile Launcher",
+ "markerFile": "groundunit-artillery"
},
"Silkworm_SR": {
"name": "Silkworm_SR",
@@ -8224,7 +8394,8 @@
"abilities": "",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Missile Search Radar"
+ "tags": "Missile Search Radar",
+ "markerFile": "groundunit-artillery"
},
"ES44AH": {
"name": "ES44AH",
@@ -8313,7 +8484,8 @@
"canRearm": false,
"muzzleVelocity": 1000,
"barrelHeight": 2.1,
- "cost": 40000
+ "cost": 40000,
+ "markerFile": "groundunit-aaa"
},
"Pz_IV_H": {
"name": "Pz_IV_H",
@@ -8329,7 +8501,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Leopard-2A5": {
"name": "Leopard-2A5",
@@ -8345,7 +8518,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"leopard-2A4": {
"name": "leopard-2A4",
@@ -8361,7 +8535,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"leopard-2A4_trs": {
"name": "leopard-2A4_trs",
@@ -8377,7 +8552,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Sd_Kfz_251": {
"name": "Sd_Kfz_251",
@@ -8398,7 +8574,8 @@
"muzzleVelocity": 765,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"Blitz_36-6700A": {
"name": "Blitz_36-6700A",
@@ -8415,7 +8592,8 @@
"abilities": "Combined arms, Rearm",
"canTargetPoint": false,
"canRearm": true,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-truck"
},
"T155_Firtina": {
"name": "T155_Firtina",
@@ -8432,7 +8610,8 @@
"abilities": "Combined arms, Indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "155mm, CA"
+ "tags": "155mm, CA",
+ "markerFile": "groundunit-artillery"
},
"VAB_Mephisto": {
"name": "VAB_Mephisto",
@@ -8449,7 +8628,8 @@
"abilities": "",
"canTargetPoint": true,
"canRearm": false,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-tactical"
},
"ZTZ96B": {
"name": "ZTZ96B",
@@ -8469,7 +8649,8 @@
"barrelHeight": 2.2,
"muzzleVelocity": 1100,
"aimTime": 5,
- "shotsToFire": 100
+ "shotsToFire": 100,
+ "markerFile": "groundunit-tank"
},
"ZBD04A": {
"name": "ZBD04A",
@@ -8490,7 +8671,8 @@
"muzzleVelocity": 1000,
"aimTime": 5,
"shotsToFire": 100,
- "tags": "CA"
+ "tags": "CA",
+ "markerFile": "groundunit-apc"
},
"HQ-7_LN_SP": {
"name": "HQ-7_LN_SP",
@@ -8538,7 +8720,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-sam-radar"
},
"PLZ05": {
"name": "PLZ05",
@@ -8555,7 +8738,8 @@
"abilities": "Combined arms, indirect fire",
"canTargetPoint": true,
"canRearm": false,
- "tags": "155mm, CA"
+ "tags": "155mm, CA",
+ "markerFile": "groundunit-artillery"
},
"TYPE-59": {
"name": "TYPE-59",
@@ -8571,7 +8755,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Kubelwagen_82": {
"name": "Kubelwagen_82",
@@ -8587,7 +8772,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Sd_Kfz_2": {
"name": "Sd_Kfz_2",
@@ -8603,7 +8789,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Sd_Kfz_7": {
"name": "Sd_Kfz_7",
@@ -8619,7 +8806,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Horch_901_typ_40_kfz_21": {
"name": "Horch_901_typ_40_kfz_21",
@@ -8635,7 +8823,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"Tiger_I": {
"name": "Tiger_I",
@@ -8651,7 +8840,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Tiger_II_H": {
"name": "Tiger_II_H",
@@ -8667,7 +8857,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Pz_V_Panther_G": {
"name": "Pz_V_Panther_G",
@@ -8684,7 +8875,8 @@
"abilities": "",
"canTargetPoint": true,
"canRearm": false,
- "tags": "Pz V"
+ "tags": "Pz V",
+ "markerFile": "groundunit-tank"
},
"Jagdpanther_G1": {
"name": "Jagdpanther_G1",
@@ -8700,7 +8892,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"JagdPz_IV": {
"name": "JagdPz_IV",
@@ -8716,7 +8909,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Stug_IV": {
"name": "Stug_IV",
@@ -8732,7 +8926,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"SturmPzIV": {
"name": "SturmPzIV",
@@ -8748,7 +8943,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Wespe124": {
"name": "Wespe124",
@@ -8764,7 +8960,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-artillery"
},
"Sd_Kfz_234_2_Puma": {
"name": "Sd_Kfz_234_2_Puma",
@@ -8796,7 +8993,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-aaa"
},
"Flakscheinwerfer_37": {
"name": "Flakscheinwerfer_37",
@@ -8812,7 +9010,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-aaa"
},
"Maschinensatz_33": {
"name": "Maschinensatz_33",
@@ -8828,7 +9027,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-aaa"
},
"soldier_mauser98": {
"name": "soldier_mauser98",
@@ -8844,7 +9044,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-infantry"
},
"SK_C_28_naval_gun": {
"name": "SK_C_28_naval_gun",
@@ -8860,7 +9061,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-artillery"
},
"fire_control": {
"name": "fire_control",
@@ -8892,7 +9094,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Elefant_SdKfz_184": {
"name": "Elefant_SdKfz_184",
@@ -8908,7 +9111,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"v1_launcher": {
"name": "v1_launcher",
@@ -8972,7 +9176,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-artillery"
},
"LeFH_18-40-105": {
"name": "LeFH_18-40-105",
@@ -8988,7 +9193,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-artillery"
},
"Cromwell_IV": {
"name": "Cromwell_IV",
@@ -9004,7 +9210,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"M4A4_Sherman_FF": {
"name": "M4A4_Sherman_FF",
@@ -9020,7 +9227,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"soldier_wwii_br_01": {
"name": "soldier_wwii_br_01",
@@ -9036,7 +9244,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-infantry"
},
"Centaur_IV": {
"name": "Centaur_IV",
@@ -9052,7 +9261,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"Churchill_VII": {
"name": "Churchill_VII",
@@ -9072,7 +9282,8 @@
"barrelHeight": 2,
"muzzleVelocity": 800,
"aimTime": 5,
- "shotsToFire": 100
+ "shotsToFire": 100,
+ "markerFile": "groundunit-tank"
},
"Daimler_AC": {
"name": "Daimler_AC",
@@ -9120,7 +9331,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-aaa"
},
"Allies_Director": {
"name": "Allies_Director",
@@ -9137,7 +9349,8 @@
"abilities": "",
"canTargetPoint": false,
"canRearm": false,
- "tags": "DRT"
+ "tags": "DRT",
+ "markerFile": "groundunit-truck"
},
"CCKW_353": {
"name": "CCKW_353",
@@ -9154,7 +9367,8 @@
"abilities": "Rearm,",
"canTargetPoint": false,
"canRearm": true,
- "tags": "Rearm"
+ "tags": "Rearm",
+ "markerFile": "groundunit-truck"
},
"Willys_MB": {
"name": "Willys_MB",
@@ -9170,7 +9384,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"M12_GMC": {
"name": "M12_GMC",
@@ -9186,7 +9401,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-artillery"
},
"M30_CC": {
"name": "M30_CC",
@@ -9202,7 +9418,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"soldier_wwii_us": {
"name": "soldier_wwii_us",
@@ -9218,7 +9435,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-infantry"
},
"M10_GMC": {
"name": "M10_GMC",
@@ -9234,7 +9452,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-tank"
},
"M8_Greyhound": {
"name": "M8_Greyhound",
@@ -9266,7 +9485,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-artillery"
},
"M4_Tractor": {
"name": "M4_Tractor",
@@ -9282,7 +9502,8 @@
"description": "",
"abilities": "",
"canTargetPoint": false,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-truck"
},
"M45_Quadmount": {
"name": "M45_Quadmount",
@@ -9298,7 +9519,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-aaa"
},
"M1_37mm": {
"name": "M1_37mm",
@@ -9314,7 +9536,8 @@
"description": "",
"abilities": "",
"canTargetPoint": true,
- "canRearm": false
+ "canRearm": false,
+ "markerFile": "groundunit-aaa"
},
"DR_50Ton_Flat_Wagon": {
"name": "DR_50Ton_Flat_Wagon",
diff --git a/client/public/stylesheets/markers/units.css b/client/public/stylesheets/markers/units.css
index 09f02d65..7038f26f 100644
--- a/client/public/stylesheets/markers/units.css
+++ b/client/public/stylesheets/markers/units.css
@@ -97,6 +97,10 @@
position: absolute;
}
+[data-object|="unit-groundunit"] .unit-short-label {
+ transform: translateY(7px);
+}
+
/*** Health indicator ***/
[data-object|="unit"] .unit-health {
background: white;
@@ -277,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 */
}
diff --git a/client/public/themes/olympus/images/units/groundunit-aaa.svg b/client/public/themes/olympus/images/units/groundunit-aaa.svg
index 64a99efd..1174f3bb 100644
--- a/client/public/themes/olympus/images/units/groundunit-aaa.svg
+++ b/client/public/themes/olympus/images/units/groundunit-aaa.svg
@@ -1,6 +1,8 @@
diff --git a/client/public/themes/olympus/images/units/groundunit-apc.svg b/client/public/themes/olympus/images/units/groundunit-apc.svg
new file mode 100644
index 00000000..bb70f4be
--- /dev/null
+++ b/client/public/themes/olympus/images/units/groundunit-apc.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/client/public/themes/olympus/images/units/groundunit-artillery.svg b/client/public/themes/olympus/images/units/groundunit-artillery.svg
new file mode 100644
index 00000000..66fb468d
--- /dev/null
+++ b/client/public/themes/olympus/images/units/groundunit-artillery.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/client/public/themes/olympus/images/units/groundunit-infantry.svg b/client/public/themes/olympus/images/units/groundunit-infantry.svg
new file mode 100644
index 00000000..459b7de0
--- /dev/null
+++ b/client/public/themes/olympus/images/units/groundunit-infantry.svg
@@ -0,0 +1,6 @@
+
+
diff --git a/client/public/themes/olympus/images/units/groundunit-tactical.svg b/client/public/themes/olympus/images/units/groundunit-tactical.svg
new file mode 100644
index 00000000..95292f22
--- /dev/null
+++ b/client/public/themes/olympus/images/units/groundunit-tactical.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/client/public/themes/olympus/images/units/groundunit-tank.svg b/client/public/themes/olympus/images/units/groundunit-tank.svg
new file mode 100644
index 00000000..48ae29d1
--- /dev/null
+++ b/client/public/themes/olympus/images/units/groundunit-tank.svg
@@ -0,0 +1,9 @@
+
+
diff --git a/client/public/themes/olympus/images/units/groundunit-truck.svg b/client/public/themes/olympus/images/units/groundunit-truck.svg
new file mode 100644
index 00000000..9152ad3c
--- /dev/null
+++ b/client/public/themes/olympus/images/units/groundunit-truck.svg
@@ -0,0 +1,6 @@
+
+
diff --git a/client/public/themes/olympus/images/units/groundunit-other.svg b/client/public/themes/olympus/images/units/groundunit.svg
similarity index 100%
rename from client/public/themes/olympus/images/units/groundunit-other.svg
rename to client/public/themes/olympus/images/units/groundunit.svg
diff --git a/client/src/constants/constants.ts b/client/src/constants/constants.ts
index fe1a07fc..7ec229c5 100644
--- a/client/src/constants/constants.ts
+++ b/client/src/constants/constants.ts
@@ -273,4 +273,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;
\ No newline at end of file
+export const DELETE_SLOW_THRESHOLD = 50;
+
+export const GROUPING_ZOOM_TRANSITION = 13;
\ No newline at end of file
diff --git a/client/src/interfaces.ts b/client/src/interfaces.ts
index f4251bf6..c12e5c5f 100644
--- a/client/src/interfaces.ts
+++ b/client/src/interfaces.ts
@@ -231,6 +231,7 @@ export interface UnitBlueprint {
canAAA?: boolean;
indirectFire?: boolean;
markerFile?: string;
+ unitWhenGrouped?: string;
}
export interface UnitSpawnOptions {
diff --git a/client/src/map/map.ts b/client/src/map/map.ts
index 7f4d641d..b176e137 100644
--- a/client/src/map/map.ts
+++ b/client/src/map/map.ts
@@ -68,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;
@@ -501,6 +502,10 @@ export class Map extends L.Map {
return this.#visibilityOptions;
}
+ getPreviousZoom() {
+ return this.#previousZoom;
+ }
+
/* Event handlers */
#onClick(e: any) {
if (!this.#preventLeftClick) {
@@ -701,6 +706,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;
diff --git a/client/src/unit/unit.ts b/client/src/unit/unit.ts
index 237d919e..9b84b072 100644
--- a/client/src/unit/unit.ts
+++ b/client/src/unit/unit.ts
@@ -5,7 +5,7 @@ import { CustomMarker } from '../map/markers/custommarker';
import { SVGInjector } from '@tanem/svg-injector';
import { UnitDatabase } from './databases/unitdatabase';
import { TargetMarker } from '../map/markers/targetmarker';
-import { DLINK, DataIndexes, GAME_MASTER, HIDE_GROUP_MEMBERS, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, ROEs, RWR, SHOW_UNIT_CONTACTS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, VISUAL, emissionsCountermeasures, reactionsToThreat, states, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING } from '../constants/constants';
+import { DLINK, DataIndexes, GAME_MASTER, HIDE_GROUP_MEMBERS, IDLE, IRST, MOVE_UNIT, OPTIC, RADAR, ROEs, RWR, SHOW_UNIT_CONTACTS, SHOW_UNITS_ENGAGEMENT_RINGS, SHOW_UNIT_PATHS, SHOW_UNIT_TARGETS, VISUAL, emissionsCountermeasures, reactionsToThreat, states, SHOW_UNITS_ACQUISITION_RINGS, HIDE_UNITS_SHORT_RANGE_RINGS, FILL_SELECTED_RING, GROUPING_ZOOM_TRANSITION } from '../constants/constants';
import { DataExtractor } from '../server/dataextractor';
import { groundUnitDatabase } from './databases/groundunitdatabase';
import { navyUnitDatabase } from './databases/navyunitdatabase';
@@ -21,12 +21,11 @@ var pathIcon = new Icon({
/**
* Unit class which controls unit behaviour
- *
- * Just about everything is a unit - even missiles!
*/
-export class Unit extends CustomMarker {
+export abstract class Unit extends CustomMarker {
ID: number;
+ /* Data controlled directly by the backend. No setters are provided to avoid misalignments */
#alive: boolean = false;
#human: boolean = false;
#controlled: boolean = false;
@@ -90,6 +89,7 @@ export class Unit extends CustomMarker {
#shotsIntensity: number = 2;
#health: number = 100;
+ /* Other members used to draw the unit, mostly ancillary stuff like targets, ranges and so on */
#selectable: boolean;
#selected: boolean = false;
#hidden: boolean = false;
@@ -107,6 +107,7 @@ export class Unit extends CustomMarker {
#hotgroup: number | null = null;
#detectionMethods: number[] = [];
+ /* Getters for backend driven data */
getAlive() { return this.#alive };
getHuman() { return this.#human };
getControlled() { return this.#controlled };
@@ -171,6 +172,7 @@ export class Unit extends CustomMarker {
this.#engagementCircle = new RangeCircle(this.getPosition(), { radius: 0, weight: 4, opacity: 1, fillOpacity: 0, dashArray: "4 8", interactive: false, bubblingMouseEvents: false });
this.#acquisitionCircle = new RangeCircle(this.getPosition(), { radius: 0, weight: 2, opacity: 1, fillOpacity: 0, dashArray: "8 12", interactive: false, bubblingMouseEvents: false });
+ /* Leaflet events listeners */
this.on('click', (e) => this.#onClick(e));
this.on('dblclick', (e) => this.#onDoubleClick(e));
this.on('contextmenu', (e) => this.#onContextMenu(e));
@@ -184,7 +186,7 @@ export class Unit extends CustomMarker {
this.setHighlighted(false);
document.dispatchEvent(new CustomEvent("unitMouseout", { detail: this }));
});
- getApp().getMap().on("zoomend", () => { this.#onZoom(); })
+ getApp().getMap().on("zoomend", (e: any) => { this.#onZoom(e); })
/* Deselect units if they are hidden */
document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => {
@@ -195,6 +197,7 @@ export class Unit extends CustomMarker {
window.setTimeout(() => { this.setSelected(this.getSelected() && !this.getHidden()) }, 300);
});
+ /* Update the marker when the visibility options change */
document.addEventListener("mapVisibilityOptionsChanged", (ev: CustomEventInit) => {
this.#updateMarker();
@@ -209,13 +212,33 @@ export class Unit extends CustomMarker {
});
}
- getCategory() {
- // Overloaded by child classes
- return "";
- }
+ /********************** Abstract methods *************************/
+ /** Get the unit category string
+ *
+ * @returns string The unit category
+ */
+ abstract getCategory(): string;
+
+ /** Get the icon options
+ * Used to configure how the marker appears on the map
+ *
+ * @returns ObjectIconOptions
+ */
+ abstract getIconOptions(): ObjectIconOptions;
+
+ /** Get the actions that this unit can perform
+ *
+ * @returns Object containing the available actions
+ */
+ abstract getActions(): {[key: string]: { text: string, tooltip: string, type: string}};
/********************** Unit data *************************/
+ /** This function is called by the units manager to update all the data coming from the backend. It reads the binary raw data using a DataExtractor
+ *
+ * @param dataExtractor The DataExtractor object pointing to the binary buffer which contains the raw data coming from the backend
+ */
setData(dataExtractor: DataExtractor) {
+ /* This variable controls if the marker must be updated. This is not always true since not all variables have an effect on the marker*/
var updateMarker = !getApp().getMap().hasLayer(this);
var datumIndex = 0;
@@ -226,7 +249,7 @@ export class Unit extends CustomMarker {
case DataIndexes.alive: this.setAlive(dataExtractor.extractBool()); updateMarker = true; break;
case DataIndexes.human: this.#human = dataExtractor.extractBool(); break;
case DataIndexes.controlled: this.#controlled = dataExtractor.extractBool(); updateMarker = true; break;
- case DataIndexes.coalition: let newCoalition = enumToCoalition(dataExtractor.extractUInt8()); updateMarker = true; if (newCoalition != this.#coalition) this.#clearRanges(); this.#coalition = newCoalition; break;
+ case DataIndexes.coalition: let newCoalition = enumToCoalition(dataExtractor.extractUInt8()); updateMarker = true; if (newCoalition != this.#coalition) this.#clearRanges(); this.#coalition = newCoalition; break; // If the coalition has changed, redraw the range circles to update the colour
case DataIndexes.country: this.#country = dataExtractor.extractUInt8(); break;
case DataIndexes.name: this.#name = dataExtractor.extractString(); break;
case DataIndexes.unitName: this.#unitName = dataExtractor.extractString(); break;
@@ -269,25 +292,18 @@ export class Unit extends CustomMarker {
}
}
- /* Dead units can't be selected */
+ /* Dead and hidden units can't be selected */
this.setSelected(this.getSelected() && this.#alive && !this.getHidden())
+ /* Update the marker if required */
if (updateMarker)
this.#updateMarker();
+ /* If the unit is selected or if the view is centered on this unit, sent the update signal so that other elements like the UnitControlPanel can be updated. */
if (this.getSelected() || getApp().getMap().getCenterUnit() === this)
document.dispatchEvent(new CustomEvent("unitUpdated", { detail: this }));
}
- drawLines() {
- /* Leaflet does not like it when you change coordinates when the map is zooming */
- if (!getApp().getMap().isZooming()) {
- this.#drawPath();
- this.#drawContacts();
- this.#drawTarget();
- }
- }
-
/** Get unit data collated into an object
*
* @returns object populated by unit information which can also be retrieved using getters
@@ -358,28 +374,6 @@ export class Unit extends CustomMarker {
return getUnitDatabaseByCategory(this.getMarkerCategory());
}
- /** Get the icon options
- * Used to configure how the marker appears on the map
- *
- * @returns ObjectIconOptions
- */
- getIconOptions(): ObjectIconOptions {
- // Default values, overloaded by child classes if needed
- return {
- showState: false,
- showVvi: false,
- showHealth: true,
- showHotgroup: false,
- showUnitIcon: true,
- showShortLabel: false,
- showFuel: false,
- showAmmo: false,
- showSummary: true,
- showCallsign: true,
- rotateToHeading: false
- }
- }
-
/** Set the unit as alive or dead
*
* @param newAlive (boolean) true = alive, false = dead
@@ -395,16 +389,11 @@ export class Unit extends CustomMarker {
* @param selected (boolean)
*/
setSelected(selected: boolean) {
- /* Only alive units can be selected. Some units are not selectable (weapons) */
- if ((this.#alive || !selected) && this.getSelectable() && this.getSelected() != selected && this.belongsToCommandedCoalition()) {
+ /* Only alive units can be selected that belong to the commanded coalition can be selected */
+ if ((this.#alive || !selected) && this.belongsToCommandedCoalition() && this.getSelected() != selected) {
this.#selected = selected;
- /* Circles don't like to be updated when the map is zooming */
- if (!getApp().getMap().isZooming())
- this.#drawRanges();
- else
- this.once("zoomend", () => { this.#drawRanges(); })
-
+ /* If selected, update the marker to show the selected effects, else clear all the drawings that are only shown for selected units. */
if (selected) {
this.#updateMarker();
}
@@ -414,21 +403,27 @@ export class Unit extends CustomMarker {
this.#clearTarget();
}
- this.getElement()?.querySelector(`.unit`)?.toggleAttribute("data-is-selected", selected);
- if (this.getCategory() === "GroundUnit" && getApp().getMap().getZoom() < 13) {
- if (this.#isLeader)
+ /* When the group leader is selected, if grouping is active, all the other group members are also selected */
+ if (this.getCategory() === "GroundUnit" && getApp().getMap().getZoom() < GROUPING_ZOOM_TRANSITION) {
+ if (this.#isLeader) {
+ /* Redraw the marker in case the leader unit was replaced by a group marker, like for SAM Sites */
+ this.#redrawMarker();
this.getGroupMembers().forEach((unit: Unit) => unit.setSelected(selected));
- else
+ }
+ else {
this.#updateMarker();
+ }
}
- // Trigger events after all (de-)selecting has been done
+ /* Activate the selection effects on the marker */
+ this.getElement()?.querySelector(`.unit`)?.toggleAttribute("data-is-selected", selected);
+
+ /* Trigger events after all (de-)selecting has been done */
if (selected) {
document.dispatchEvent(new CustomEvent("unitSelection", { detail: this }));
} else {
document.dispatchEvent(new CustomEvent("unitDeselection", { detail: this }));
}
-
}
}
@@ -440,22 +435,6 @@ export class Unit extends CustomMarker {
return this.#selected;
}
- /** Set whether this unit is selectable
- *
- * @param selectable (boolean)
- */
- setSelectable(selectable: boolean) {
- this.#selectable = selectable;
- }
-
- /** Get whether this unit is selectable
- *
- * @returns boolean
- */
- getSelectable() {
- return this.#selectable;
- }
-
/** Set the number of the hotgroup to which the unit belongs
*
* @param hotgroup (number)
@@ -478,9 +457,9 @@ export class Unit extends CustomMarker {
* @param highlighted (boolean)
*/
setHighlighted(highlighted: boolean) {
- if (this.getSelectable() && this.#highlighted != highlighted) {
- this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted);
+ if (this.#highlighted != highlighted) {
this.#highlighted = highlighted;
+ this.getElement()?.querySelector(`[data-object|="unit"]`)?.toggleAttribute("data-is-highlighted", highlighted);
this.getGroupMembers().forEach((unit: Unit) => unit.setHighlighted(highlighted));
}
}
@@ -517,10 +496,25 @@ export class Unit extends CustomMarker {
return this.getDatabase()?.getSpawnPointsByName(this.getName());
}
+ getDatabaseEntry() {
+ return this.getDatabase()?.getByName(this.#name);
+ }
+
+ drawLines() {
+ /* Leaflet does not like it when you change coordinates when the map is zooming */
+ if (!getApp().getMap().isZooming()) {
+ this.#drawPath();
+ this.#drawContacts();
+ this.#drawTarget();
+ }
+ }
+
+ checkRedraw() {
+ return false;
+ }
+
/********************** Icon *************************/
createIcon(): void {
- const databaseEntry = this.getDatabase()?.getByName(this.#name);
-
/* Set the icon */
var icon = new DivIcon({
className: 'leaflet-unit-icon',
@@ -529,6 +523,7 @@ export class Unit extends CustomMarker {
});
this.setIcon(icon);
+ /* Create the base element */
var el = document.createElement("div");
el.classList.add("unit");
el.setAttribute("data-object", `unit-${this.getMarkerCategory()}`);
@@ -536,8 +531,8 @@ export class Unit extends CustomMarker {
var iconOptions = this.getIconOptions();
- // Generate and append elements depending on active options
- // Velocity vector
+ /* Generate and append elements depending on active options */
+ /* Velocity vector */
if (iconOptions.showVvi) {
var vvi = document.createElement("div");
vvi.classList.add("unit-vvi");
@@ -545,7 +540,7 @@ export class Unit extends CustomMarker {
el.append(vvi);
}
- // Hotgroup indicator
+ /* Hotgroup indicator */
if (iconOptions.showHotgroup) {
var hotgroup = document.createElement("div");
hotgroup.classList.add("unit-hotgroup");
@@ -555,42 +550,42 @@ export class Unit extends CustomMarker {
el.append(hotgroup);
}
- // Main icon
+ /* Main icon */
if (iconOptions.showUnitIcon) {
var unitIcon = document.createElement("div");
unitIcon.classList.add("unit-icon");
var img = document.createElement("img");
- var marker;
/* If a unit does not belong to the commanded coalition or it is not visually detected, show it with the generic aircraft square */
- if (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)))
- marker = databaseEntry?.markerFile ?? this.getMarkerCategory();
+ var marker;
+ if (this.belongsToCommandedCoalition() || this.getDetectionMethods().some(value => [VISUAL, OPTIC].includes(value)))
+ marker = this.getDatabaseEntry()?.markerFile ?? this.getMarkerCategory();
else
marker = "aircraft";
-
img.src = `/resources/theme/images/units/${marker}.svg`;
img.onload = () => SVGInjector(img);
unitIcon.appendChild(img);
+
unitIcon.toggleAttribute("data-rotate-to-heading", iconOptions.rotateToHeading);
el.append(unitIcon);
}
- // State icon
+ /* State icon */
if (iconOptions.showState) {
var state = document.createElement("div");
state.classList.add("unit-state");
el.appendChild(state);
}
- // Short label
+ /* Short label */
if (iconOptions.showShortLabel) {
var shortLabel = document.createElement("div");
shortLabel.classList.add("unit-short-label");
- shortLabel.innerText = databaseEntry?.shortLabel || "";
+ shortLabel.innerText = this.getDatabaseEntry()?.shortLabel || "";
el.append(shortLabel);
}
- // Fuel indicator
+ /* Fuel indicator */
if (iconOptions.showFuel) {
var fuelIndicator = document.createElement("div");
fuelIndicator.classList.add("unit-fuel");
@@ -600,7 +595,7 @@ export class Unit extends CustomMarker {
el.append(fuelIndicator);
}
- // Health indicator
+ /* Health indicator */
if (iconOptions.showHealth) {
var healthIndicator = document.createElement("div");
healthIndicator.classList.add("unit-health");
@@ -610,7 +605,7 @@ export class Unit extends CustomMarker {
el.append(healthIndicator);
}
- // Ammo indicator
+ /* Ammo indicator */
if (iconOptions.showAmmo) {
var ammoIndicator = document.createElement("div");
ammoIndicator.classList.add("unit-ammo");
@@ -619,7 +614,7 @@ export class Unit extends CustomMarker {
el.append(ammoIndicator);
}
- // Unit summary
+ /* Unit summary */
if (iconOptions.showSummary) {
var summary = document.createElement("div");
summary.classList.add("unit-summary");
@@ -637,25 +632,29 @@ export class Unit extends CustomMarker {
}
this.getElement()?.appendChild(el);
-
- /* Circles don't like to be updated when the map is zooming */
- if (!getApp().getMap().isZooming())
- this.#drawRanges();
- else
- this.once("zoomend", () => { this.#drawRanges(); })
}
/********************** Visibility *************************/
updateVisibility() {
- const hiddenUnits = getApp().getMap().getHiddenTypes();
- var hidden = ((this.#human && hiddenUnits.includes("human")) ||
- (this.#controlled == false && hiddenUnits.includes("dcs")) ||
- (hiddenUnits.includes(this.getMarkerCategory())) ||
- (hiddenUnits.includes(this.#coalition)) ||
+ const hiddenTypes = getApp().getMap().getHiddenTypes();
+ var hidden = (
+ /* Hide the unit if it is a human and humans are hidden */
+ (this.#human && hiddenTypes.includes("human")) ||
+ /* Hide the unit if it is DCS controlled and DCS controlled units are hidden */
+ (this.#controlled == false && hiddenTypes.includes("dcs")) ||
+ /* Hide the unit if this specific category is hidden */
+ (hiddenTypes.includes(this.getMarkerCategory())) ||
+ /* Hide the unit if this coalition is hidden */
+ (hiddenTypes.includes(this.#coalition)) ||
+ /* Hide the unit if it does not belong to the commanded coalition and it is not detected by a method that can pinpoint its location (RWR does not count) */
(!this.belongsToCommandedCoalition() && (this.#detectionMethods.length == 0 || (this.#detectionMethods.length == 1 && this.#detectionMethods[0] === RWR))) ||
- (getApp().getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getApp().getMap().getZoom() < 13 && (this.belongsToCommandedCoalition() || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0)))) &&
- !(this.getSelected());
+ /* Hide the unit if grouping is activated, the unit is not the group leader, it is not selected, and the zoom is higher than the grouping threshold */
+ (getApp().getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && !this.#isLeader && this.getCategory() == "GroundUnit" && getApp().getMap().getZoom() < GROUPING_ZOOM_TRANSITION &&
+ (this.belongsToCommandedCoalition() || (!this.belongsToCommandedCoalition() && this.#detectionMethods.length == 0)))) &&
+ !(this.getSelected()
+ );
+ /* Force dead units to be hidden */
this.setHidden(hidden || !this.#alive);
}
@@ -675,6 +674,7 @@ export class Unit extends CustomMarker {
getApp().getMap().removeLayer(this);
}
+ /* Draw the range circles if the unit is not hidden */
if (!this.getHidden()) {
/* Circles don't like to be updated when the map is zooming */
if (!getApp().getMap().isZooming())
@@ -714,7 +714,7 @@ export class Unit extends CustomMarker {
if (typeof (roles) === "string")
roles = [roles];
- var loadouts = this.getDatabase()?.getByName(this.#name)?.loadouts;
+ var loadouts = this.getDatabaseEntry()?.loadouts;
if (loadouts) {
return loadouts.some((loadout: LoadoutBlueprint) => {
return (roles as string[]).some((role: string) => { return loadout.roles.includes(role) });
@@ -728,11 +728,11 @@ export class Unit extends CustomMarker {
}
canTargetPoint() {
- return this.getDatabase()?.getByName(this.#name)?.canTargetPoint === true;
+ return this.getDatabaseEntry()?.canTargetPoint === true;
}
canRearm() {
- return this.getDatabase()?.getByName(this.#name)?.canRearm === true;
+ return this.getDatabaseEntry()?.canRearm === true;
}
canLandAtPoint() {
@@ -740,11 +740,11 @@ export class Unit extends CustomMarker {
}
canAAA() {
- return this.getDatabase()?.getByName(this.#name)?.canAAA === true;
+ return this.getDatabaseEntry()?.canAAA === true;
}
indirectFire() {
- return this.getDatabase()?.getByName(this.#name)?.indirectFire === true;
+ return this.getDatabaseEntry()?.indirectFire === true;
}
isTanker() {
@@ -933,11 +933,6 @@ export class Unit extends CustomMarker {
}
/***********************************************/
- getActions(): { [key: string]: { text: string, tooltip: string, type: string } } {
- /* To be implemented by child classes */ // TODO make Unit an abstract class
- return {};
- }
-
executeAction(e: any, action: string) {
if (action === "center-map")
getApp().getMap().centerOnUnit(this.ID);
@@ -963,18 +958,15 @@ export class Unit extends CustomMarker {
/***********************************************/
#onClick(e: any) {
-
- // Exit if we were waiting for a doubleclick
+ /* Exit if we were waiting for a doubleclick */
if (this.#waitingForDoubleClick) {
return;
}
- // We'll wait for a doubleclick
+ /* We'll wait for a doubleclick */
this.#waitingForDoubleClick = true;
-
this.#doubleClickTimer = window.setTimeout(() => {
-
- // Still waiting so no doubleclick; do the click action
+ /* Still waiting so no doubleclick; do the click action */
if (this.#waitingForDoubleClick) {
if (getApp().getMap().getState() === IDLE || getApp().getMap().getState() === MOVE_UNIT || e.originalEvent.ctrlKey) {
if (!e.originalEvent.ctrlKey)
@@ -984,17 +976,17 @@ export class Unit extends CustomMarker {
}
}
- // No longer waiting for a doubleclick
+ /* No longer waiting for a doubleclick */
this.#waitingForDoubleClick = false;
}, 200);
}
#onDoubleClick(e: any) {
- // Let single clicks work again
+ /* Let single clicks work again */
this.#waitingForDoubleClick = false;
clearTimeout(this.#doubleClickTimer);
- // Select all matching units in the viewport
+ /* Select all matching units in the viewport */
const unitsManager = getApp().getUnitsManager();
Object.values(unitsManager.getUnits()).forEach((unit: Unit) => {
if (unit.getAlive() === true && unit.getName() === this.getName() && unit.isInViewport())
@@ -1226,6 +1218,11 @@ export class Unit extends CustomMarker {
if (hotgroupEl)
hotgroupEl.innerText = String(this.#hotgroup);
}
+
+ /* If the unit is a leader of a SAM Site, show the group as a SAM with the appropriate short label */
+ if (this.#isLeader) {
+
+ }
}
/* Set vertical offset for altitude stacking */
@@ -1234,6 +1231,11 @@ export class Unit extends CustomMarker {
}
}
+ #redrawMarker() {
+ this.removeFrom(getApp().getMap());
+ this.#updateMarker();
+ }
+
#drawPath() {
if (this.#activePath != undefined && getApp().getMap().getVisibilityOptions()[SHOW_UNIT_PATHS]) {
var points = [];
@@ -1446,12 +1448,21 @@ export class Unit extends CustomMarker {
this.#targetPositionPolyline.removeFrom(getApp().getMap());
}
- #onZoom() {
+ #onZoom(e: any) {
+ if (this.checkRedraw()) {
+ this.#redrawMarker();
+
+ /* If the marker has been redrawn, reapply selection */
+ if (this.getSelected()) {
+ this.setSelected(false);
+ this.setSelected(true);
+ }
+ }
this.#updateMarker();
}
}
-export class AirUnit extends Unit {
+export abstract class AirUnit extends Unit {
getIconOptions() {
var belongsToCommandedCoalition = this.belongsToCommandedCoalition();
return {
@@ -1534,7 +1545,7 @@ export class GroundUnit extends Unit {
showHealth: true,
showHotgroup: belongsToCommandedCoalition,
showUnitIcon: (belongsToCommandedCoalition || this.getDetectionMethods().some(value => [VISUAL, OPTIC, RADAR, IRST, DLINK].includes(value))),
- showShortLabel: false,
+ showShortLabel: this.getDatabaseEntry()?.type === "SAM Site",
showFuel: false,
showAmmo: false,
showSummary: false,
@@ -1584,6 +1595,31 @@ export class GroundUnit extends Unit {
var blueprint = groundUnitDatabase.getByName(this.getName());
return blueprint?.type ? blueprint.type : "";
}
+
+ /* When a unit is a leader of a group, the map is zoomed out and grouping when zoomed out is enabled, check if the unit should be shown as a specific group. This is used to show a SAM battery instead of the group leader */
+ getDatabaseEntry() {
+ let unitWhenGrouped = null;
+ if (!this.getSelected() && this.getIsLeader() && getApp().getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] && getApp().getMap().getZoom() < GROUPING_ZOOM_TRANSITION) {
+ unitWhenGrouped = this.getDatabase()?.getByName(this.getName())?.unitWhenGrouped ?? null;
+ let member = this.getGroupMembers().reduce((prev: Unit | null, unit: Unit, index: number) => {
+ if (unit.getDatabaseEntry()?.unitWhenGrouped != undefined)
+ return unit
+ return prev;
+ }, null);
+ unitWhenGrouped == member !== null ? member?.getDatabaseEntry()?.unitWhenGrouped : unitWhenGrouped;
+ }
+ if (unitWhenGrouped !== null)
+ return this.getDatabase()?.getByName(unitWhenGrouped);
+ else
+ return this.getDatabase()?.getByName(this.getName());
+ }
+
+ /* When we zoom past the grouping limit, grouping is enabled and the unit is a leader, we redraw the unit to apply any possible grouped marker */
+ checkRedraw(): boolean {
+ return (this.getIsLeader() && getApp().getMap().getVisibilityOptions()[HIDE_GROUP_MEMBERS] &&
+ (getApp().getMap().getZoom() >= GROUPING_ZOOM_TRANSITION && getApp().getMap().getPreviousZoom() < GROUPING_ZOOM_TRANSITION ||
+ getApp().getMap().getZoom() < GROUPING_ZOOM_TRANSITION && getApp().getMap().getPreviousZoom() >= GROUPING_ZOOM_TRANSITION))
+ }
}
export class NavyUnit extends Unit {