diff --git a/client/app.js b/client/app.js index 228c1c07..de7446eb 100644 --- a/client/app.js +++ b/client/app.js @@ -2,6 +2,7 @@ var express = require('express'); var path = require('path'); var cookieParser = require('cookie-parser'); var logger = require('morgan'); +var fs = require('fs'); var indexRouter = require('./routes/index'); var uikitRouter = require('./routes/uikit'); @@ -21,12 +22,14 @@ app.use('/uikit', uikitRouter); app.set('view engine', 'ejs'); +let rawdata = fs.readFileSync('../olympus.json'); +let config = JSON.parse(rawdata); +app.get('/config', (req, res) => res.send(config)); + module.exports = app; const DemoDataGenerator = require('./demo.js'); - var demoDataGenerator = new DemoDataGenerator(10); - app.get('/demo/units', (req, res) => demoDataGenerator.units(req, res)); app.get('/demo/logs', (req, res) => demoDataGenerator.logs(req, res)); app.get('/demo/bullseyes', (req, res) => demoDataGenerator.bullseyes(req, res)); diff --git a/client/demo.js b/client/demo.js index 52d65a2c..4ea4ea1b 100644 --- a/client/demo.js +++ b/client/demo.js @@ -363,7 +363,7 @@ const DEMO_UNIT_DATA = { name: "CVN-75", unitName: "Olympus 1-9", groupName: "Group 1", - alive: false, + alive: true, category: "Aircraft", }, flightData: { @@ -406,7 +406,7 @@ const DEMO_UNIT_DATA = { name: "CVN-75", unitName: "Olympus 1-10", groupName: "Group 1", - alive: false, + alive: true, category: "Aircraft", }, flightData: { @@ -449,12 +449,12 @@ const DEMO_UNIT_DATA = { name: "CVN-75", unitName: "Olympus 1-11", groupName: "Group 1", - alive: false, + alive: true, category: "Missile", }, flightData: { latitude: 37.075, - longitude: -115.8, + longitude: -115.80, altitude: 2000, heading: 0.5, speed: 300 @@ -492,16 +492,102 @@ const DEMO_UNIT_DATA = { name: "CVN-75", unitName: "Olympus 1-12", groupName: "Group 1", - alive: false, + alive: true, category: "Missile", }, flightData: { latitude: 37.075, longitude: -115.75, altitude: 2000, + heading: 0.6, + speed: 300 + }, + missionData: { + fuel: 0.5, + flags: {human: false}, + ammo: [], + targets: [], + hasTask: true, + coalition: "red" + }, + formationData: { + formation: "Echelon", + isLeader: false, + isWingman: false, + leaderID: null, + wingmen: [], + wingmenIDs: [] + }, + taskData: { + currentTask: "Example task", + activePath: undefined, + targetSpeed: 400, + targetAltitude: 3000 + }, + optionsData: { + ROE: "None", + reactionToThreat: "None", + } + }, + ["13"]:{ + baseData: { + AI: true, + name: "CVN-75", + unitName: "Olympus 1-11", + groupName: "Group 1", + alive: true, + category: "Bomb", + }, + flightData: { + latitude: 37.05, + longitude: -115.8, + altitude: 2000, heading: 0.5, speed: 300 }, + missionData: { + fuel: 0.5, + flags: {human: false}, + ammo: [], + targets: [], + hasTask: true, + coalition: "blue" + }, + formationData: { + formation: "Echelon", + isLeader: false, + isWingman: false, + leaderID: null, + wingmen: [], + wingmenIDs: [] + }, + taskData: { + currentTask: "Example task", + activePath: undefined, + targetSpeed: 400, + targetAltitude: 3000 + }, + optionsData: { + ROE: "None", + reactionToThreat: "None", + } + }, + ["14"]:{ + baseData: { + AI: true, + name: "CVN-75", + unitName: "Olympus 1-12", + groupName: "Group 1", + alive: true, + category: "Bomb", + }, + flightData: { + latitude: 37.05, + longitude: -115.75, + altitude: 2000, + heading: 0.6, + speed: 300 + }, missionData: { fuel: 0.5, flags: {human: false}, diff --git a/client/package.json b/client/package.json index d4c79d6b..7f785313 100644 --- a/client/package.json +++ b/client/package.json @@ -2,7 +2,7 @@ "name": "DCSOlympus", "node-main": "./bin/www", "main": "http://localhost:3000", - "version": "0.1.0-alpha", + "version": "0.1.1-alpha", "private": true, "scripts": { "copy": "copy .\\node_modules\\leaflet\\dist\\leaflet.css .\\public\\stylesheets\\leaflet.css", diff --git a/client/public/javascripts/bundle.zip b/client/public/javascripts/bundle.zip new file mode 100644 index 00000000..cb88000c Binary files /dev/null and b/client/public/javascripts/bundle.zip differ diff --git a/client/public/stylesheets/contextmenus.css b/client/public/stylesheets/contextmenus.css index 475f7e9a..9ed665f4 100644 --- a/client/public/stylesheets/contextmenus.css +++ b/client/public/stylesheets/contextmenus.css @@ -88,7 +88,7 @@ } #ground-unit-spawn-button { - background-image: var( --spawn-ground-url ); + background-image: var( --spawn-groundunit-url ); background-size: 48px; } diff --git a/client/public/stylesheets/olympus.css b/client/public/stylesheets/olympus.css index e6c3ed83..013a8290 100644 --- a/client/public/stylesheets/olympus.css +++ b/client/public/stylesheets/olympus.css @@ -583,12 +583,12 @@ body[data-hide-aircraft] #unit-visibility-control-aircraft { background-image: var(--visibility-control-aircraft-hidden-url); } -#unit-visibility-control-ground { - background-image: var(--visibility-control-ground-visible-url); +#unit-visibility-control-groundunit { + background-image: var(--visibility-control-groundunit-visible-url); } -body[data-hide-ground] #unit-visibility-control-ground { - background-image: var(--visibility-control-ground-hidden-url); +body[data-hide-groundunit] #unit-visibility-control-groundunit { + background-image: var(--visibility-control-groundunit-hidden-url); } #unit-visibility-control-sam { @@ -607,12 +607,12 @@ body[data-hide-threat] #unit-visibility-control-threat { background-image: var(--visibility-control-threat-hidden-url); } -#unit-visibility-control-naval { - background-image: var(--visibility-control-naval-visible-url); +#unit-visibility-control-navyunit { + background-image: var(--visibility-control-navyunit-visible-url); } -body[data-hide-naval] #unit-visibility-control-naval { - background-image: var(--visibility-control-naval-hidden-url); +body[data-hide-navyunit] #unit-visibility-control-navyunit { + background-image: var(--visibility-control-navyunit-hidden-url); } @@ -666,101 +666,93 @@ body[data-hide-naval] #unit-visibility-control-naval { } #roe-buttons-container button::before, #reaction-to-threat-buttons-container button::before { + background-position:center; background-repeat: no-repeat; - background-size:16px 16px; content: ""; display:block; - height:16px; - width:16px; + height:24px; + width:24px; } -#roe-buttons-container button[title="Free"]::before { - background-image: url( "/themes/olympus/images/icons_roe_free_light.svg"); -} -#roe-buttons-container button[title="Designated free"]::before { +#roe-buttons-container button[title="Hold"]::before { background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg"); } -#roe-buttons-container button[title="Designated"]::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg"); +#roe-buttons-container button[title="Hold"].selected::before { + background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg"); } +/**/ + #roe-buttons-container button[title="Return"]::before { + background-image: url( "/themes/olympus/images/icons_roe_defend_light.svg"); +} + +#roe-buttons-container button[title="Return"].selected::before { + background-image: url( "/themes/olympus/images/icons_roe_defend_dark.svg"); +} + +/**/ + +#roe-buttons-container button[title="Designated"]::before { background-image: url( "/themes/olympus/images/icons_roe_target_light.svg"); } -#roe-buttons-container button[title="Hold"]::before { - background-image: url( "/themes/olympus/images/icons_actions_nothing_light.svg"); +#roe-buttons-container button[title="Designated"].selected::before { + background-image: url( "/themes/olympus/images/icons_roe_target_dark.svg"); +} + +/**/ + +#roe-buttons-container button[title="Free"]::before { + background-image: url( "/themes/olympus/images/icons_roe_free_light.svg"); } #roe-buttons-container button[title="Free"].selected::before { background-image: url( "/themes/olympus/images/icons_roe_free_dark.svg"); } -#roe-buttons-container button[title="Designated free"].selected::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg"); -} - -#roe-buttons-container button[title="Designated"].selected::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg"); -} - -#roe-buttons-container button[title="Return"].selected::before { - background-image: url( "/themes/olympus/images/icons_roe_target_dark.svg"); -} - -#roe-buttons-container button[title="Hold"].selected::before { - background-image: url( "/themes/olympus/images/icons_actions_nothing_dark.svg"); -} +/****************************************************************************************/ #reaction-to-threat-buttons-container button[title="None"]::before { - background-image: url( "/themes/olympus/images/icons_actions_nothing_light.svg"); + background-image: url( "/themes/olympus/images/icons_threat_nothing_light.svg"); } -#reaction-to-threat-buttons-container button[title="Passive"]::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg"); -} - -#reaction-to-threat-buttons-container button[title="Evade"]::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg"); -} - -#reaction-to-threat-buttons-container button[title="Escape"]::before { - background-image: url( "/themes/olympus/images/icons_threat_retreat_light.svg"); -} - -#reaction-to-threat-buttons-container button[title="Abort"]::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_light.svg"); -} -#reaction-to-threat-buttons-container button[title="None"]::before { - background-image: url( "/themes/olympus/images/icons_actions_nothing_light.svg"); -} - - #reaction-to-threat-buttons-container button[title="None"].selected::before { - background-image: url( "/themes/olympus/images/icons_actions_nothing_dark.svg"); + background-image: url( "/themes/olympus/images/icons_threat_nothing_dark.svg"); +} + + +/**/ + + +#reaction-to-threat-buttons-container button[title="Passive"]::before { + background-image: url( "/themes/olympus/images/icons_threat_cms_light.svg"); } #reaction-to-threat-buttons-container button[title="Passive"].selected::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg"); + background-image: url( "/themes/olympus/images/icons_threat_cms_dark.svg"); +} + + +/**/ + + +#reaction-to-threat-buttons-container button[title="Evade"]::before { + background-image: url( "/themes/olympus/images/icons_threat_defend_light.svg"); } #reaction-to-threat-buttons-container button[title="Evade"].selected::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg"); + background-image: url( "/themes/olympus/images/icons_threat_defend_dark.svg"); } -#reaction-to-threat-buttons-container button[title="Escape"].selected::before { - background-image: url( "/themes/olympus/images/icons_threat_retreat_dark.svg"); -} -#reaction-to-threat-buttons-container button[title="Abort"].selected::before { - background-image: url( "/themes/olympus/images/icons_roe_stop_dark.svg"); -} +/****************************************************************************************/ #splash-screen { diff --git a/client/public/stylesheets/unitcontrolpanel.css b/client/public/stylesheets/unitcontrolpanel.css index ddb5143d..346a7a91 100644 --- a/client/public/stylesheets/unitcontrolpanel.css +++ b/client/public/stylesheets/unitcontrolpanel.css @@ -13,7 +13,7 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { } #unit-control-panel #selected-units-container { - align-items: center; + align-items: left; border-radius: var( --border-radius-md ); display:flex; flex-direction: column; @@ -21,23 +21,66 @@ body.feature-forceShowUnitControlPanel #unit-control-panel { } #unit-control-panel #selected-units-container button { - font-size: 12px; + align-items: center; + border-radius: var( --border-radius-lg ); + display:flex; + font-size: 11px; + height:30px; padding:8px 0; position: relative; width:90%; } #unit-control-panel #selected-units-container button::before { - background-color: var( --accent-light-blue ); - border-radius: var( --border-radius-sm ); + background-color: var( --primary-grey ); + border-radius: var( --border-radius-md ); content: attr( data-short-label ); - padding:4px; - position: absolute; - translate:-40px -4px; + margin:0 5px; + padding:4px 6px; + white-space: nowrap; + width:fit-content; +} + + + +#unit-control-panel #selected-units-container button[data-coalition="blue"]::before { + background-color: var( --accent-light-blue ); +} + +#unit-control-panel #selected-units-container button[data-coalition="red"]::before { + background-color: var( --accent-light-red ); + color:var(--secondary-red-outline) } #unit-control-panel #selected-units-container button::after { + border-radius: var( --border-radius-sm ); content: attr( data-callsign ); + display: block; + overflow: hidden; + padding:4px; + padding-left:0; + text-align: left; + text-overflow: ellipsis; + white-space: nowrap; + width:fit-content; +} + + +#unit-control-panel #selected-units-container button:hover::after { + overflow: visible; + text-overflow:initial; +} + +#unit-control-panel #selected-units-container button:hover::after { + background-color: var( --background-grey ); +} + +#unit-control-panel #selected-units-container button[data-coalition="blue"]:hover::after { + background-color: var( --primary-blue ); +} + +#unit-control-panel #selected-units-container button[data-coalition="red"]:hover::after { + background-color: var( --primary-red ); } #unit-control-panel h4 { diff --git a/client/public/stylesheets/unitinfopanel.css b/client/public/stylesheets/unitinfopanel.css index 82a109d2..a4e7ae02 100644 --- a/client/public/stylesheets/unitinfopanel.css +++ b/client/public/stylesheets/unitinfopanel.css @@ -10,13 +10,14 @@ #unit-info-panel #unit-name { - line-height: 18px; - margin-bottom:10px; + padding:0px 0; + margin-bottom:4px; } #unit-info-panel #current-task { border-radius: var( --border-radius-lg ); - margin-top:15px; + margin-top:8px; + padding:6px 16px; } #unit-info-panel #current-task::after { @@ -25,36 +26,98 @@ } -#unit-info-panel #loadout-data { - max-width: 250px; +#loadout-container { + width:250px; } -#unit-info-panel #loadout-data .ol-data-grid { - margin: 6px 0; +#loadout { + display:flex; } -#unit-info-panel #loadout-data .ol-data-grid dt:first-child { - text-indent: 5px; +#loadout-silhouette { + align-items: center; + display:flex; + justify-content: center; + width:55%; } -#unit-info-panel #loadout-data .ol-data-grid dt:first-child::before { +#loadout-silhouette::before { + background-image: var( --loadout-background-image ); + background-repeat: no-repeat; + background-size:75px 75px; + content:""; + display:block; + filter: invert( 100% ); + height:75px; + translate:-10px 0; + width:75px; +} + +#loadout-items { + align-self: center; + display:flex; + flex-flow: column nowrap; + row-gap: 8px; + text-align: center; + width:45%; +} + + +#loadout-items > * { + align-items: center; + column-gap: 8px; + display:flex; + white-space: nowrap; +} + +#loadout-items > *::before { + align-items: center; + background-color: var( --secondary-light-grey ); + border-radius: 50%; + content: attr( data-qty ); + display:flex; + font-weight: var( --font-weight-bolder ); + justify-content: center; + height:20px; + width:20px; +} + +#loadout-items > *::after { + content: attr( data-item ); +} + + + +#fuel-percentage { + align-items: center; + display:flex; +} + +#fuel-percentage::before { content: url( /images/icons/fuel.svg ); display:inline-block; filter:invert(100%); height:16px; - text-indent:5px; - translate:-10px 5%; + margin-right:6px; width:16px; } -#unit-info-panel #loadout-fuel-level::after { - content: attr( data-fuel-level ) "%"; +#fuel-percentage::after { + content: attr( data-percentage ) "%"; } -#unit-info-panel #loadout-container .loadout-item { - background-color: black; + +#fuel-display { + background-color: var( --background-grey ); + border-radius: var( --border-radius-md ); + height:6px; + margin-top:4px; + overflow: hidden; + width:90%; +} + +#fuel-display #fuel-bar { + border-radius: var( --border-radius-md ); + height:100%; } -#unit-info-panel #loadout-container .loadout-item::before { - content: attr( data-loadout-qty )'\d7 ' attr( data-loadout-item ) ; -} \ No newline at end of file diff --git a/client/public/stylesheets/units.css b/client/public/stylesheets/units.css index f808da4c..6ec7a3cf 100644 --- a/client/public/stylesheets/units.css +++ b/client/public/stylesheets/units.css @@ -8,8 +8,8 @@ /* Air units' marker settings */ - --unit-air-label-x: calc( var( --unit-centre-x ) - ( var( --unit-air-width ) / 2 ) + ( var( --unit-stroke-width ) / 2 ) ); - --unit-air-label-y: calc( var( --unit-centre-y ) - ( var( --unit-air-height ) / 2 ) + ( var( --unit-stroke-width ) / 2 ) ); + --unit-aircraft-label-x: calc( var( --unit-centre-x ) - ( var( --unit-aircraft-width ) / 2 ) + ( var( --unit-stroke-width ) / 2 ) ); + --unit-aircraft-label-y: calc( var( --unit-centre-y ) - ( var( --unit-aircraft-height ) / 2 ) + ( var( --unit-stroke-width ) / 2 ) ); } @@ -21,18 +21,6 @@ position:relative; } -[data-hide-aircraft] #map-container [data-object|="unit-air"], -[data-hide-ground] #map-container [data-object|="unit-ground-mi"], -[data-hide-sam] #map-container [data-object|="unit-ground-sam"], -[data-hide-threat] #map-container .unit-threat, -[data-hide-naval] #map-container [data-object|="unit-naval"], -[data-hide-blue] #map-container [data-object|="unit"][data-coalition="blue"], -[data-hide-red] #map-container [data-object|="unit"][data-coalition="red"], -[data-hide-neutral] #map-container [data-object|="unit"][data-coalition="neutral"] { - display:none; -} - - [data-object|="unit"] .unit-selected-spotlight { background-color: var( --unit-spotlight-fill ); border-radius: 50%; @@ -50,9 +38,9 @@ justify-self: center; transform-origin: bottom; translate:0 -50%; - padding-bottom: calc( ( var( --unit-air-width ) / 2 ) + var( --unit-stroke-width ) ); + padding-bottom: calc( ( var( --unit-aircraft-width ) / 2 ) + var( --unit-stroke-width ) ); position:absolute; - width: var( --unit-air-vvi-width ); + width: var( --unit-aircraft-vvi-width ); z-index: 3; } @@ -82,9 +70,9 @@ [data-object|="unit"] .unit-marker-border { border-radius: var( --border-radius-sm ); display:none; - height: calc( var( --unit-air-height ) + ( var( --unit-label-border-width ) * 2 ) ); + height: calc( var( --unit-aircraft-height ) + ( var( --unit-label-border-width ) * 2 ) ); position:absolute; - width: calc( var( --unit-air-width ) + ( var( --unit-label-border-width ) * 2 ) ); + width: calc( var( --unit-aircraft-width ) + ( var( --unit-label-border-width ) * 2 ) ); z-index:2; } @@ -106,44 +94,44 @@ /* Air */ -[data-object|="unit-air"] .unit-marker { - background-image: var( --unit-air-marker-neutral-url ); - height: var( --unit-air-marker-height ); - width: var( --unit-air-marker-width ); +[data-object|="unit-aircraft"] .unit-marker { + background-image: var( --unit-aircraft-marker-neutral-url ); + height: var( --unit-aircraft-marker-height ); + width: var( --unit-aircraft-marker-width ); } -[data-object|="unit-air"]:hover .unit-marker { - background-image: var( --unit-air-marker-neutral-hover-url ); +[data-object|="unit-aircraft"]:hover .unit-marker { + background-image: var( --unit-aircraft-marker-neutral-hover-url ); } -[data-object|="unit-air"][data-is-selected] .unit-marker { - background-image: var( --unit-air-marker-neutral-selected-url ); +[data-object|="unit-aircraft"][data-is-selected] .unit-marker { + background-image: var( --unit-aircraft-marker-neutral-selected-url ); } -[data-object|="unit-air"][data-coalition="blue"] .unit-marker { - background-image: var( --unit-air-marker-blue-url ); +[data-object|="unit-aircraft"][data-coalition="blue"] .unit-marker { + background-image: var( --unit-aircraft-marker-blue-url ); } -[data-object|="unit-air"][data-coalition="blue"]:hover .unit-marker { - background-image: var( --unit-air-marker-blue-hover-url ); +[data-object|="unit-aircraft"][data-coalition="blue"]:hover .unit-marker { + background-image: var( --unit-aircraft-marker-blue-hover-url ); } -[data-object|="unit-air"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var( --unit-air-marker-blue-selected-url ); +[data-object|="unit-aircraft"][data-coalition="blue"][data-is-selected] .unit-marker { + background-image: var( --unit-aircraft-marker-blue-selected-url ); } -[data-object|="unit-air"][data-coalition="red"] .unit-marker { - background-image: var( --unit-air-marker-red-url ); +[data-object|="unit-aircraft"][data-coalition="red"] .unit-marker { + background-image: var( --unit-aircraft-marker-red-url ); } -[data-object|="unit-air"][data-coalition="red"]:hover .unit-marker { - background-image: var( --unit-air-marker-red-hover-url ); +[data-object|="unit-aircraft"][data-coalition="red"]:hover .unit-marker { + background-image: var( --unit-aircraft-marker-red-hover-url ); } -[data-object|="unit-air"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var( --unit-air-marker-red-selected-url ); +[data-object|="unit-aircraft"][data-coalition="red"][data-is-selected] .unit-marker { + background-image: var( --unit-aircraft-marker-red-selected-url ); } @@ -151,140 +139,140 @@ /* Ground vehicles (not SAMs) */ -[data-object|="unit-ground-mi"] .unit-marker { - background-image: var( --unit-ground-mi-marker-neutral-url ); - height: var( --unit-ground-mi-marker-height ); - width: var( --unit-ground-mi-marker-width ); +[data-object|="unit-groundunit"] .unit-marker { + background-image: var( --unit-groundunit-marker-neutral-url ); + height: var( --unit-groundunit-marker-height ); + width: var( --unit-groundunit-marker-width ); } -[data-object|="unit-ground-mi"]:hover .unit-marker { - background-image: var( --unit-ground-mi-marker-neutral-hover-url ); +[data-object|="unit-groundunit"]:hover .unit-marker { + background-image: var( --unit-groundunit-marker-neutral-hover-url ); } -[data-object|="unit-ground-mi"][data-is-selected] .unit-marker { - background-image: var( --unit-ground-mi-marker-neutral-selected-url ); +[data-object|="unit-groundunit"][data-is-selected] .unit-marker { + background-image: var( --unit-groundunit-marker-neutral-selected-url ); } -[data-object|="unit-ground-mi"][data-coalition="blue"] .unit-marker { - background-image: var( --unit-ground-mi-marker-blue-url ); +[data-object|="unit-groundunit"][data-coalition="blue"] .unit-marker { + background-image: var( --unit-groundunit-marker-blue-url ); } -[data-object|="unit-ground-mi"][data-coalition="blue"]:hover .unit-marker { - background-image: var( --unit-ground-mi-marker-blue-hover-url ); +[data-object|="unit-groundunit"][data-coalition="blue"]:hover .unit-marker { + background-image: var( --unit-groundunit-marker-blue-hover-url ); } -[data-object|="unit-ground-mi"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var( --unit-ground-mi-marker-blue-selected-url ); +[data-object|="unit-groundunit"][data-coalition="blue"][data-is-selected] .unit-marker { + background-image: var( --unit-groundunit-marker-blue-selected-url ); } -[data-object|="unit-ground-mi"][data-coalition="red"] .unit-marker { - background-image: var( --unit-ground-mi-marker-red-url ); +[data-object|="unit-groundunit"][data-coalition="red"] .unit-marker { + background-image: var( --unit-groundunit-marker-red-url ); } -[data-object|="unit-ground-mi"][data-coalition="red"]:hover .unit-marker { - background-image: var( --unit-ground-mi-marker-red-hover-url ); +[data-object|="unit-groundunit"][data-coalition="red"]:hover .unit-marker { + background-image: var( --unit-groundunit-marker-red-hover-url ); } -[data-object|="unit-ground-mi"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var( --unit-ground-mi-marker-red-selected-url ); +[data-object|="unit-groundunit"][data-coalition="red"][data-is-selected] .unit-marker { + background-image: var( --unit-groundunit-marker-red-selected-url ); } /* SAMs */ -[data-object|="unit-ground-sam"] .unit-selected-spotlight { +[data-object|="unit-sam"] .unit-selected-spotlight { translate:0 2px; } -[data-object|="unit-ground-sam"] .unit-marker { - background-image: var( --unit-ground-sam-marker-neutral-url ); +[data-object|="unit-sam"] .unit-marker { + background-image: var( --unit-sam-marker-neutral-url ); height: var( --unit-sam-marker-height ); width: var( --unit-sam-marker-width ); } -[data-object|="unit-ground-sam"]:hover .unit-marker { - background-image: var( --unit-ground-sam-marker-neutral-hover-url ); +[data-object|="unit-sam"]:hover .unit-marker { + background-image: var( --unit-sam-marker-neutral-hover-url ); } -[data-object|="unit-ground-sam"][data-is-selected] .unit-marker { - background-image: var( --unit-ground-sam-marker-neutral-selected-url ); +[data-object|="unit-sam"][data-is-selected] .unit-marker { + background-image: var( --unit-sam-marker-neutral-selected-url ); } -[data-object|="unit-ground-sam"][data-coalition="blue"] .unit-marker { - background-image: var( --unit-ground-sam-marker-blue-url ); +[data-object|="unit-sam"][data-coalition="blue"] .unit-marker { + background-image: var( --unit-sam-marker-blue-url ); } -[data-object|="unit-ground-sam"][data-coalition="blue"]:hover .unit-marker { - background-image: var( --unit-ground-sam-marker-blue-hover-url ); +[data-object|="unit-sam"][data-coalition="blue"]:hover .unit-marker { + background-image: var( --unit-sam-marker-blue-hover-url ); } -[data-object|="unit-ground-sam"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var( --unit-ground-sam-marker-blue-selected-url ); +[data-object|="unit-sam"][data-coalition="blue"][data-is-selected] .unit-marker { + background-image: var( --unit-sam-marker-blue-selected-url ); } -[data-object|="unit-ground-sam"][data-coalition="red"] .unit-marker { - background-image: var( --unit-ground-sam-marker-red-url ); +[data-object|="unit-sam"][data-coalition="red"] .unit-marker { + background-image: var( --unit-sam-marker-red-url ); } -[data-object|="unit-ground-sam"][data-coalition="red"]:hover .unit-marker { - background-image: var( --unit-ground-sam-marker-red-hover-url ); +[data-object|="unit-sam"][data-coalition="red"]:hover .unit-marker { + background-image: var( --unit-sam-marker-red-hover-url ); } -[data-object|="unit-ground-sam"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var( --unit-ground-sam-marker-red-selected-url ); +[data-object|="unit-sam"][data-coalition="red"][data-is-selected] .unit-marker { + background-image: var( --unit-sam-marker-red-selected-url ); } -/* Naval */ +/* navyunit */ -[data-object|="unit-naval"] .unit-selected-spotlight { +[data-object|="unit-navyunit"] .unit-selected-spotlight { translate:0 -2px; } -[data-object|="unit-naval"] .unit-marker { - background-image: var( --unit-naval-marker-neutral-url ); - height: var( --unit-naval-marker-height ); - width: var( --unit-naval-marker-width ); +[data-object|="unit-navyunit"] .unit-marker { + background-image: var( --unit-navyunit-marker-neutral-url ); + height: var( --unit-navyunit-marker-height ); + width: var( --unit-navyunit-marker-width ); } -[data-object|="unit-naval"]:hover .unit-marker { - background-image: var( --unit-naval-marker-neutral-hover-url ); +[data-object|="unit-navyunit"]:hover .unit-marker { + background-image: var( --unit-navyunit-marker-neutral-hover-url ); } -[data-object|="unit-naval"][data-is-selected] .unit-marker { - background-image: var( --unit-naval-marker-neutral-selected-url ); +[data-object|="unit-navyunit"][data-is-selected] .unit-marker { + background-image: var( --unit-navyunit-marker-neutral-selected-url ); } -[data-object|="unit-naval"][data-coalition="blue"] .unit-marker { - background-image: var( --unit-naval-marker-blue-url ); +[data-object|="unit-navyunit"][data-coalition="blue"] .unit-marker { + background-image: var( --unit-navyunit-marker-blue-url ); } -[data-object|="unit-naval"][data-coalition="blue"]:hover .unit-marker { - background-image: var( --unit-naval-marker-blue-hover-url ); +[data-object|="unit-navyunit"][data-coalition="blue"]:hover .unit-marker { + background-image: var( --unit-navyunit-marker-blue-hover-url ); } -[data-object|="unit-naval"][data-coalition="blue"][data-is-selected] .unit-marker { - background-image: var( --unit-naval-marker-blue-selected-url ); +[data-object|="unit-navyunit"][data-coalition="blue"][data-is-selected] .unit-marker { + background-image: var( --unit-navyunit-marker-blue-selected-url ); } -[data-object|="unit-naval"][data-coalition="red"] .unit-marker { - background-image: var( --unit-naval-marker-red-url ); +[data-object|="unit-navyunit"][data-coalition="red"] .unit-marker { + background-image: var( --unit-navyunit-marker-red-url ); } -[data-object|="unit-naval"][data-coalition="red"]:hover .unit-marker { - background-image: var( --unit-naval-marker-red-hover-url ); +[data-object|="unit-navyunit"][data-coalition="red"]:hover .unit-marker { + background-image: var( --unit-navyunit-marker-red-hover-url ); } -[data-object|="unit-naval"][data-coalition="red"][data-is-selected] .unit-marker { - background-image: var( --unit-naval-marker-red-selected-url ); +[data-object|="unit-navyunit"][data-coalition="red"][data-is-selected] .unit-marker { + background-image: var( --unit-navyunit-marker-red-selected-url ); } @@ -310,24 +298,36 @@ /* Weapons */ -[data-object|="unit-weapon"] { +[data-object|="unit-missile"], [data-object|="unit-bomb"] { cursor: default; } -[data-object|="unit-weapon-missile"] .unit-marker { - background-image: var( --unit-weapons-missile-marker-neutral-url ); - height: var( --unit-weapons-missile-marker-height ); - width: var( --unit-weapons-missile-marker-width ); +[data-object|="unit-missile"] .unit-marker { + background-image: var( --unit-missile-marker-neutral-url ); + height: var( --unit-missile-marker-height ); + width: var( --unit-missile-marker-width ); } - -[data-object|="unit-weapon-missile"][data-coalition="blue"] .unit-marker { - background-image: var( --unit-weapons-missile-marker-blue-url ); +[data-object|="unit-missile"][data-coalition="blue"] .unit-marker { + background-image: var( --unit-missile-marker-blue-url ); } +[data-object|="unit-missile"][data-coalition="red"] .unit-marker { + background-image: var( --unit-missile-marker-red-url ); +} -[data-object|="unit-weapon-missile"][data-coalition="red"] .unit-marker { - background-image: var( --unit-weapons-missile-marker-red-url ); +[data-object|="unit-bomb"] .unit-marker { + background-image: var( --unit-bomb-marker-neutral-url ); + height: var( --unit-bomb-marker-height ); + width: var( --unit-bomb-marker-width ); +} + +[data-object|="unit-bomb"][data-coalition="blue"] .unit-marker { + background-image: var( --unit-bomb-marker-blue-url ); +} + +[data-object|="unit-bomb"][data-coalition="red"] .unit-marker { + background-image: var( --unit-bomb-marker-red-url ); } @@ -344,28 +344,28 @@ z-index:10; } -[data-object|="unit-ground-mi"] .unit-short-label { +[data-object|="unit-groundunit"] .unit-short-label { translate: -1px 0; } -[data-object|="unit-ground-sam"] .unit-short-label { +[data-object|="unit-sam"] .unit-short-label { translate:0 50%; } -[data-object|="unit-naval"] .unit-short-label { +[data-object|="unit-navyunit"] .unit-short-label { translate:0 -50%; } [data-object|="unit"] .unit-fuel { background:white; - border: var( --unit-air-fuel-border-width ) solid var( --secondary-dark-steel ); + border: var( --unit-aircraft-fuel-border-width ) solid var( --secondary-dark-steel ); border-radius: var( --border-radius-sm ); display:none; - height: var( --unit-air-fuel-height ); + height: var( --unit-aircraft-fuel-height ); position: absolute; - translate:var( --unit-air-fuel-x ) var( --unit-air-fuel-y ); - width: var( --unit-air-fuel-width ); + translate:var( --unit-aircraft-fuel-x ) var( --unit-aircraft-fuel-y ); + width: var( --unit-aircraft-fuel-width ); z-index: 5; } @@ -377,19 +377,19 @@ [data-object|="unit"] .unit-ammo { - column-gap: var( --unit-air-ammo-spacing ); + column-gap: var( --unit-aircraft-ammo-spacing ); display:none; height:fit-content; position:absolute; - translate:var( --unit-air-ammo-x ) var( --unit-air-ammo-y ); + translate:var( --unit-aircraft-ammo-x ) var( --unit-aircraft-ammo-y ); width:fit-content; } [data-object|="unit"] .unit-ammo > * { background-color: white; - border: var( --unit-air-ammo-border-width ) solid var( --secondary-dark-steel ); + border: var( --unit-aircraft-ammo-border-width ) solid var( --secondary-dark-steel ); border-radius: 50%; - padding: var( --unit-air-ammo-radius ); + padding: var( --unit-aircraft-ammo-radius ); } @@ -509,82 +509,82 @@ [data-object|="unit"] .unit-status { background-repeat: no-repeat; position:absolute; - height:var( --unit-air-status-rtb-height ); - width:var( --unit-air-status-rtb-width ); + height:var( --unit-aircraft-status-rtb-height ); + width:var( --unit-aircraft-status-rtb-width ); z-index: 10; } [data-object|="unit"][data-status="rtb"] .unit-status { - background-image: var( --unit-air-status-rtb-neutral-url ); - height:var( --unit-air-status-rtb-height ); - width:var( --unit-air-status-rtb-width ); + background-image: var( --unit-aircraft-status-rtb-neutral-url ); + height:var( --unit-aircraft-status-rtb-height ); + width:var( --unit-aircraft-status-rtb-width ); } [data-object|="unit"][data-status="rtb"][data-coalition="blue"] .unit-status { - background-image: var( --unit-air-status-rtb-blue-url ); + background-image: var( --unit-aircraft-status-rtb-blue-url ); } [data-object|="unit"][data-status="rtb"][data-coalition="red"] .unit-status { - background-image: var( --unit-air-status-rtb-red-url ); + background-image: var( --unit-aircraft-status-rtb-red-url ); } [data-object|="unit"][data-status="hold"] .unit-status { - background-image: var( --unit-air-status-hold-neutral-url ); - height:var( --unit-air-status-hold-height ); - width:var( --unit-air-status-hold-width ); + background-image: var( --unit-aircraft-status-hold-neutral-url ); + height:var( --unit-aircraft-status-hold-height ); + width:var( --unit-aircraft-status-hold-width ); } [data-object|="unit"][data-status="hold"][data-coalition="blue"] .unit-status { - background-image: var( --unit-air-status-hold-blue-url ); + background-image: var( --unit-aircraft-status-hold-blue-url ); } [data-object|="unit"][data-status="hold"][data-coalition="red"] .unit-status { - background-image: var( --unit-air-status-hold-red-url ); + background-image: var( --unit-aircraft-status-hold-red-url ); } /*** DEAD ***/ -[data-object|="unit-air"][ data-is-dead ] { +[data-object|="unit-aircraft"][ data-is-dead ] { cursor: default; } -[data-object|="unit-air"][ data-is-dead ] .unit-marker { - background-image: var( --unit-air-marker-neutral-dead-url ); +[data-object|="unit-aircraft"][ data-is-dead ] .unit-marker { + background-image: var( --unit-aircraft-marker-neutral-dead-url ); background-position: 50% 50%; background-size: auto 32px; } -[data-object|="unit-air"][ data-is-dead ][data-coalition="blue"] .unit-marker { - background-image: var( --unit-air-marker-blue-dead-url ); +[data-object|="unit-aircraft"][ data-is-dead ][data-coalition="blue"] .unit-marker { + background-image: var( --unit-aircraft-marker-blue-dead-url ); } -[data-object|="unit-air"][ data-is-dead ][data-coalition="red"] .unit-marker { - background-image: var( --unit-air-marker-red-dead-url ); +[data-object|="unit-aircraft"][ data-is-dead ][data-coalition="red"] .unit-marker { + background-image: var( --unit-aircraft-marker-red-dead-url ); } -[data-object|="unit-air"][ data-is-dead ] .unit-selected-spotlight, -[data-object|="unit-air"][ data-is-dead ] .unit-short-label, -[data-object|="unit-air"][ data-is-dead ] .unit-vvi, -[data-object|="unit-air"][ data-is-dead ] .unit-hotgroup, -[data-object|="unit-air"][ data-is-dead ] .unit-hotgroup-id, -[data-object|="unit-air"][ data-is-dead ] .unit-status, -[data-object|="unit-air"][ data-is-dead ] .unit-fuel, -[data-object|="unit-air"][ data-is-dead ] .unit-ammo, -[data-object|="unit-air"][ data-is-dead ]:hover .unit-fuel, -[data-object|="unit-air"][ data-is-dead ]:hover .unit-ammo { +[data-object|="unit-aircraft"][ data-is-dead ] .unit-selected-spotlight, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-short-label, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-vvi, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-hotgroup, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-hotgroup-id, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-status, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-fuel, +[data-object|="unit-aircraft"][ data-is-dead ] .unit-ammo, +[data-object|="unit-aircraft"][ data-is-dead ]:hover .unit-fuel, +[data-object|="unit-aircraft"][ data-is-dead ]:hover .unit-ammo { display:none !important; } -[data-object|="unit-air"][ data-is-dead ] .unit-summary > * { +[data-object|="unit-aircraft"][ data-is-dead ] .unit-summary > * { display:none; } -[data-object|="unit-air"][ data-is-dead ] .unit-summary .unit-callsign { +[data-object|="unit-aircraft"][ data-is-dead ] .unit-summary .unit-callsign { display:block; } diff --git a/client/public/themes/olympus/images/icon_bomb_blue.svg b/client/public/themes/olympus/images/icon_bomb_blue.svg new file mode 100644 index 00000000..136deb4f --- /dev/null +++ b/client/public/themes/olympus/images/icon_bomb_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icon_bomb_neutral.svg b/client/public/themes/olympus/images/icon_bomb_neutral.svg new file mode 100644 index 00000000..e32f31b9 --- /dev/null +++ b/client/public/themes/olympus/images/icon_bomb_neutral.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icon_bomb_red.svg b/client/public/themes/olympus/images/icon_bomb_red.svg new file mode 100644 index 00000000..c86bf6f4 --- /dev/null +++ b/client/public/themes/olympus/images/icon_bomb_red.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icon_naval_blue.svg b/client/public/themes/olympus/images/icon_navyuni_blue.svg similarity index 100% rename from client/public/themes/olympus/images/icon_naval_blue.svg rename to client/public/themes/olympus/images/icon_navyuni_blue.svg diff --git a/client/public/themes/olympus/images/icon_naval_neutral.svg b/client/public/themes/olympus/images/icon_navyunit_neutral.svg similarity index 100% rename from client/public/themes/olympus/images/icon_naval_neutral.svg rename to client/public/themes/olympus/images/icon_navyunit_neutral.svg diff --git a/client/public/themes/olympus/images/icon_naval_red.svg b/client/public/themes/olympus/images/icon_navyunit_red.svg similarity index 100% rename from client/public/themes/olympus/images/icon_naval_red.svg rename to client/public/themes/olympus/images/icon_navyunit_red.svg diff --git a/client/public/themes/olympus/images/icons_actions_180_dark.svg b/client/public/themes/olympus/images/icons_actions_180_dark.svg new file mode 100644 index 00000000..79e0ade7 --- /dev/null +++ b/client/public/themes/olympus/images/icons_actions_180_dark.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/public/themes/olympus/images/icons_actions_180_light.svg b/client/public/themes/olympus/images/icons_actions_180_light.svg new file mode 100644 index 00000000..2db2cb63 --- /dev/null +++ b/client/public/themes/olympus/images/icons_actions_180_light.svg @@ -0,0 +1,4 @@ + + + + diff --git a/client/public/themes/olympus/images/icons_actions_cancel_dark.svg b/client/public/themes/olympus/images/icons_actions_cancel_dark.svg new file mode 100644 index 00000000..3582a48c --- /dev/null +++ b/client/public/themes/olympus/images/icons_actions_cancel_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_actions_cancel_light.svg b/client/public/themes/olympus/images/icons_actions_cancel_light.svg new file mode 100644 index 00000000..dc3335a8 --- /dev/null +++ b/client/public/themes/olympus/images/icons_actions_cancel_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_actions_gas_dark.svg b/client/public/themes/olympus/images/icons_actions_gas_dark.svg index feee9f86..4a5d7357 100644 --- a/client/public/themes/olympus/images/icons_actions_gas_dark.svg +++ b/client/public/themes/olympus/images/icons_actions_gas_dark.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_actions_gas_light.svg b/client/public/themes/olympus/images/icons_actions_gas_light.svg index f9c9ebd0..14bbef19 100644 --- a/client/public/themes/olympus/images/icons_actions_gas_light.svg +++ b/client/public/themes/olympus/images/icons_actions_gas_light.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_actions_rtb_dark.svg b/client/public/themes/olympus/images/icons_actions_rtb_dark.svg index c3682f22..081bff14 100644 --- a/client/public/themes/olympus/images/icons_actions_rtb_dark.svg +++ b/client/public/themes/olympus/images/icons_actions_rtb_dark.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_actions_rtb_light.svg b/client/public/themes/olympus/images/icons_actions_rtb_light.svg index 0c9231e3..9147bcc5 100644 --- a/client/public/themes/olympus/images/icons_actions_rtb_light.svg +++ b/client/public/themes/olympus/images/icons_actions_rtb_light.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_form_abreast_dark.svg b/client/public/themes/olympus/images/icons_form_abreast_dark.svg index c528c451..513d6b25 100644 --- a/client/public/themes/olympus/images/icons_form_abreast_dark.svg +++ b/client/public/themes/olympus/images/icons_form_abreast_dark.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/client/public/themes/olympus/images/icons_form_abreast_light.svg b/client/public/themes/olympus/images/icons_form_abreast_light.svg index 2408169f..0b302a04 100644 --- a/client/public/themes/olympus/images/icons_form_abreast_light.svg +++ b/client/public/themes/olympus/images/icons_form_abreast_light.svg @@ -1,5 +1,5 @@ - - - - + + + + diff --git a/client/public/themes/olympus/images/icons_form_admin_dark.svg b/client/public/themes/olympus/images/icons_form_admin_dark.svg index 49d375dd..44e42f62 100644 --- a/client/public/themes/olympus/images/icons_form_admin_dark.svg +++ b/client/public/themes/olympus/images/icons_form_admin_dark.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/client/public/themes/olympus/images/icons_form_admin_light.svg b/client/public/themes/olympus/images/icons_form_admin_light.svg index dbf4f074..532c523f 100644 --- a/client/public/themes/olympus/images/icons_form_admin_light.svg +++ b/client/public/themes/olympus/images/icons_form_admin_light.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/client/public/themes/olympus/images/icons_form_echelon_dark.svg b/client/public/themes/olympus/images/icons_form_echelon_dark.svg index 25144e4f..dc4b4b60 100644 --- a/client/public/themes/olympus/images/icons_form_echelon_dark.svg +++ b/client/public/themes/olympus/images/icons_form_echelon_dark.svg @@ -1,4 +1,5 @@ - - - + + + + diff --git a/client/public/themes/olympus/images/icons_form_echelon_light.svg b/client/public/themes/olympus/images/icons_form_echelon_light.svg index 42215873..a788953d 100644 --- a/client/public/themes/olympus/images/icons_form_echelon_light.svg +++ b/client/public/themes/olympus/images/icons_form_echelon_light.svg @@ -1,4 +1,5 @@ - - - + + + + diff --git a/client/public/themes/olympus/images/icons_form_trail_dark.svg b/client/public/themes/olympus/images/icons_form_trail_dark.svg index 0c9ff544..555ea0dd 100644 --- a/client/public/themes/olympus/images/icons_form_trail_dark.svg +++ b/client/public/themes/olympus/images/icons_form_trail_dark.svg @@ -1,4 +1,5 @@ - - - + + + + diff --git a/client/public/themes/olympus/images/icons_form_trail_light.svg b/client/public/themes/olympus/images/icons_form_trail_light.svg index bf9fcfd3..0ac432f7 100644 --- a/client/public/themes/olympus/images/icons_form_trail_light.svg +++ b/client/public/themes/olympus/images/icons_form_trail_light.svg @@ -1,4 +1,5 @@ - - - + + + + diff --git a/client/public/themes/olympus/images/icons_misc_brush_blue.svg b/client/public/themes/olympus/images/icons_misc_brush_blue.svg new file mode 100644 index 00000000..7ecf9816 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_brush_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_brush_dark.svg b/client/public/themes/olympus/images/icons_misc_brush_dark.svg new file mode 100644 index 00000000..ed925a5a --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_brush_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_brush_light.svg b/client/public/themes/olympus/images/icons_misc_brush_light.svg new file mode 100644 index 00000000..74d2a691 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_brush_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_gas_blue.svg b/client/public/themes/olympus/images/icons_misc_gas_blue.svg new file mode 100644 index 00000000..13afd5e5 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_gas_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_gas_dark.svg b/client/public/themes/olympus/images/icons_misc_gas_dark.svg new file mode 100644 index 00000000..53bb4a3f --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_gas_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_gas_light.svg b/client/public/themes/olympus/images/icons_misc_gas_light.svg new file mode 100644 index 00000000..8530905f --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_gas_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_map_blue.svg b/client/public/themes/olympus/images/icons_misc_map_blue.svg new file mode 100644 index 00000000..3e233196 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_map_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_map_dark.svg b/client/public/themes/olympus/images/icons_misc_map_dark.svg new file mode 100644 index 00000000..6b9a5219 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_map_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_map_light.svg b/client/public/themes/olympus/images/icons_misc_map_light.svg new file mode 100644 index 00000000..8bec4777 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_map_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_plane_blue.svg b/client/public/themes/olympus/images/icons_misc_plane_blue.svg new file mode 100644 index 00000000..7bf3bcd8 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_plane_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_plane_dark.svg b/client/public/themes/olympus/images/icons_misc_plane_dark.svg new file mode 100644 index 00000000..cec512c5 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_plane_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_plane_light.svg b/client/public/themes/olympus/images/icons_misc_plane_light.svg new file mode 100644 index 00000000..cf34b9c8 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_plane_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_settings_blue.svg b/client/public/themes/olympus/images/icons_misc_settings_blue.svg new file mode 100644 index 00000000..2d7004c6 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_settings_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_settings_dark.svg b/client/public/themes/olympus/images/icons_misc_settings_dark.svg new file mode 100644 index 00000000..04b375e4 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_settings_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_settings_light.svg b/client/public/themes/olympus/images/icons_misc_settings_light.svg new file mode 100644 index 00000000..19270b5c --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_settings_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_visible_blue.svg b/client/public/themes/olympus/images/icons_misc_visible_blue.svg new file mode 100644 index 00000000..66f1ae9a --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_visible_blue.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_visible_dark.svg b/client/public/themes/olympus/images/icons_misc_visible_dark.svg new file mode 100644 index 00000000..0023c2c1 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_visible_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_misc_visible_light.svg b/client/public/themes/olympus/images/icons_misc_visible_light.svg new file mode 100644 index 00000000..46f1b080 --- /dev/null +++ b/client/public/themes/olympus/images/icons_misc_visible_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_roe_attack_dark.svg b/client/public/themes/olympus/images/icons_roe_attack_dark.svg new file mode 100644 index 00000000..db976cbb --- /dev/null +++ b/client/public/themes/olympus/images/icons_roe_attack_dark.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/public/themes/olympus/images/icons_roe_attack_light.svg b/client/public/themes/olympus/images/icons_roe_attack_light.svg new file mode 100644 index 00000000..06ff8bb3 --- /dev/null +++ b/client/public/themes/olympus/images/icons_roe_attack_light.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/client/public/themes/olympus/images/icons_roe_defend_dark.svg b/client/public/themes/olympus/images/icons_roe_defend_dark.svg new file mode 100644 index 00000000..82c305aa --- /dev/null +++ b/client/public/themes/olympus/images/icons_roe_defend_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_roe_defend_light.svg b/client/public/themes/olympus/images/icons_roe_defend_light.svg new file mode 100644 index 00000000..1d956938 --- /dev/null +++ b/client/public/themes/olympus/images/icons_roe_defend_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_roe_stop_dark.svg b/client/public/themes/olympus/images/icons_roe_stop_dark.svg index fcc0c75f..3582a48c 100644 --- a/client/public/themes/olympus/images/icons_roe_stop_dark.svg +++ b/client/public/themes/olympus/images/icons_roe_stop_dark.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_roe_stop_light.svg b/client/public/themes/olympus/images/icons_roe_stop_light.svg index 98b50cb4..dc3335a8 100644 --- a/client/public/themes/olympus/images/icons_roe_stop_light.svg +++ b/client/public/themes/olympus/images/icons_roe_stop_light.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_roe_target_dark.svg b/client/public/themes/olympus/images/icons_roe_target_dark.svg index 3a2f17db..cb68d86b 100644 --- a/client/public/themes/olympus/images/icons_roe_target_dark.svg +++ b/client/public/themes/olympus/images/icons_roe_target_dark.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_roe_target_light.svg b/client/public/themes/olympus/images/icons_roe_target_light.svg index 9f8031ff..a9ec508c 100644 --- a/client/public/themes/olympus/images/icons_roe_target_light.svg +++ b/client/public/themes/olympus/images/icons_roe_target_light.svg @@ -1,3 +1,3 @@ - - + + diff --git a/client/public/themes/olympus/images/icons_threat_cms_dark.svg b/client/public/themes/olympus/images/icons_threat_cms_dark.svg new file mode 100644 index 00000000..f6f53fd5 --- /dev/null +++ b/client/public/themes/olympus/images/icons_threat_cms_dark.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/client/public/themes/olympus/images/icons_threat_cms_light.svg b/client/public/themes/olympus/images/icons_threat_cms_light.svg new file mode 100644 index 00000000..6032f934 --- /dev/null +++ b/client/public/themes/olympus/images/icons_threat_cms_light.svg @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/client/public/themes/olympus/images/icons_threat_defend_dark.svg b/client/public/themes/olympus/images/icons_threat_defend_dark.svg new file mode 100644 index 00000000..962971eb --- /dev/null +++ b/client/public/themes/olympus/images/icons_threat_defend_dark.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/client/public/themes/olympus/images/icons_threat_defend_light.svg b/client/public/themes/olympus/images/icons_threat_defend_light.svg new file mode 100644 index 00000000..0e598866 --- /dev/null +++ b/client/public/themes/olympus/images/icons_threat_defend_light.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/client/public/themes/olympus/images/icons_threat_nothing_dark.svg b/client/public/themes/olympus/images/icons_threat_nothing_dark.svg new file mode 100644 index 00000000..3582a48c --- /dev/null +++ b/client/public/themes/olympus/images/icons_threat_nothing_dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/icons_threat_nothing_light.svg b/client/public/themes/olympus/images/icons_threat_nothing_light.svg new file mode 100644 index 00000000..dc3335a8 --- /dev/null +++ b/client/public/themes/olympus/images/icons_threat_nothing_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/client/public/themes/olympus/images/visibility_naval_hidden.svg b/client/public/themes/olympus/images/visibility_navyunit_hidden.svg similarity index 100% rename from client/public/themes/olympus/images/visibility_naval_hidden.svg rename to client/public/themes/olympus/images/visibility_navyunit_hidden.svg diff --git a/client/public/themes/olympus/images/visibility_naval_visible.svg b/client/public/themes/olympus/images/visibility_navyunit_visible.svg similarity index 100% rename from client/public/themes/olympus/images/visibility_naval_visible.svg rename to client/public/themes/olympus/images/visibility_navyunit_visible.svg diff --git a/client/public/themes/olympus/olympus.css b/client/public/themes/olympus/olympus.css index 7e4986c3..3836ea74 100644 --- a/client/public/themes/olympus/olympus.css +++ b/client/public/themes/olympus/olympus.css @@ -19,6 +19,7 @@ --accent-green : #8bff63; --accent-light-blue : #5ca7ff; + --accent-light-red : #F5B6B6; --background-grey : #3d4651; --background-slate-blue : #363c43; @@ -54,14 +55,14 @@ --visibility-control-aircraft-visible-url: url( "/themes/olympus/images/visibility_aircraft_visible.svg" ); --visibility-control-aircraft-hidden-url: url( "/themes/olympus/images/visibility_aircraft_hidden.svg" ); - --visibility-control-ground-visible-url: url( "/themes/olympus/images/visibility_ground_visible.svg" ); - --visibility-control-ground-hidden-url: url( "/themes/olympus/images/visibility_ground_hidden.svg" ); + --visibility-control-groundunit-visible-url: url( "/themes/olympus/images/visibility_ground_visible.svg" ); + --visibility-control-groundunit-hidden-url: url( "/themes/olympus/images/visibility_ground_hidden.svg" ); --visibility-control-sam-visible-url: url( "/themes/olympus/images/visibility_sam_visible.svg" ); --visibility-control-sam-hidden-url: url( "/themes/olympus/images/visibility_sam_hidden.svg" ); - --visibility-control-naval-visible-url: url( "/themes/olympus/images/visibility_naval_visible.svg" ); - --visibility-control-naval-hidden-url: url( "/themes/olympus/images/visibility_naval_hidden.svg" ); + --visibility-control-navyunit-visible-url: url( "/themes/olympus/images/visibility_navyunit_visible.svg" ); + --visibility-control-navyunit-hidden-url: url( "/themes/olympus/images/visibility_navyunit_hidden.svg" ); --visibility-control-threat-visible-url: url( "/themes/olympus/images/visibility_threat_visible.svg" ); --visibility-control-threat-hidden-url: url( "/themes/olympus/images/visibility_threat_hidden.svg" ); @@ -84,108 +85,108 @@ /*** Air units ***/ - --unit-air-ammo-gap: calc( 2px + var( --unit-stroke-width ) ); - --unit-air-ammo-border-radius: 50%; - --unit-air-ammo-border-width: 2px; - --unit-air-ammo-radius: 2px; - --unit-air-ammo-spacing: 2px; - --unit-air-ammo-x:0px; - --unit-air-ammo-y:30px; - --unit-air-fuel-border-width: 2px; - --unit-air-fuel-height: 6px; - --unit-air-fuel-width: 36px; - --unit-air-fuel-x:0px; - --unit-air-fuel-y:22px; - --unit-air-height: 28px; - --unit-air-vvi-width: 4px; - --unit-air-width: var( --unit-air-height ); + --unit-aircraft-ammo-gap: calc( 2px + var( --unit-stroke-width ) ); + --unit-aircraft-ammo-border-radius: 50%; + --unit-aircraft-ammo-border-width: 2px; + --unit-aircraft-ammo-radius: 2px; + --unit-aircraft-ammo-spacing: 2px; + --unit-aircraft-ammo-x:0px; + --unit-aircraft-ammo-y:30px; + --unit-aircraft-fuel-border-width: 2px; + --unit-aircraft-fuel-height: 6px; + --unit-aircraft-fuel-width: 36px; + --unit-aircraft-fuel-x:0px; + --unit-aircraft-fuel-y:22px; + --unit-aircraft-height: 28px; + --unit-aircraft-vvi-width: 4px; + --unit-aircraft-width: var( --unit-aircraft-height ); - --unit-air-marker-height: 50px; - --unit-air-marker-width: 50px; + --unit-aircraft-marker-height: 50px; + --unit-aircraft-marker-width: 50px; - --unit-air-marker-blue-url: url( "/themes/olympus/images/icon_aircraft_blue.svg" ); - --unit-air-marker-blue-hover-url: url( "/themes/olympus/images/icon_aircraft_blue_hover.svg" ); - --unit-air-marker-blue-selected-url: url( "/themes/olympus/images/icon_aircraft_blue_selected.svg" ); - --unit-air-marker-blue-dead-url: url( "/themes/olympus/images/icon_death_blue.svg" ); + --unit-aircraft-marker-blue-url: url( "/themes/olympus/images/icon_aircraft_blue.svg" ); + --unit-aircraft-marker-blue-hover-url: url( "/themes/olympus/images/icon_aircraft_blue_hover.svg" ); + --unit-aircraft-marker-blue-selected-url: url( "/themes/olympus/images/icon_aircraft_blue_selected.svg" ); + --unit-aircraft-marker-blue-dead-url: url( "/themes/olympus/images/icon_death_blue.svg" ); - --unit-air-marker-neutral-url: url( "/themes/olympus/images/icon_aircraft_neutral.svg" ); - --unit-air-marker-neutral-hover-url: url( "/themes/olympus/images/icon_aircraft_neutral_hover.svg" ); - --unit-air-marker-neutral-selected-url: url( "/themes/olympus/images/icon_aircraft_neutral_selected.svg" ); - --unit-air-marker-neutral-dead-url: url( "/themes/olympus/images/icon_death_neutral.svg" ); + --unit-aircraft-marker-neutral-url: url( "/themes/olympus/images/icon_aircraft_neutral.svg" ); + --unit-aircraft-marker-neutral-hover-url: url( "/themes/olympus/images/icon_aircraft_neutral_hover.svg" ); + --unit-aircraft-marker-neutral-selected-url: url( "/themes/olympus/images/icon_aircraft_neutral_selected.svg" ); + --unit-aircraft-marker-neutral-dead-url: url( "/themes/olympus/images/icon_death_neutral.svg" ); - --unit-air-marker-red-url: url( "/themes/olympus/images/icon_aircraft_red.svg" ); - --unit-air-marker-red-hover-url: url( "/themes/olympus/images/icon_aircraft_red_hover.svg" ); - --unit-air-marker-red-selected-url: url( "/themes/olympus/images/icon_aircraft_red_selected.svg" ); - --unit-air-marker-red-dead-url: url( "/themes/olympus/images/icon_death_red.svg" ); + --unit-aircraft-marker-red-url: url( "/themes/olympus/images/icon_aircraft_red.svg" ); + --unit-aircraft-marker-red-hover-url: url( "/themes/olympus/images/icon_aircraft_red_hover.svg" ); + --unit-aircraft-marker-red-selected-url: url( "/themes/olympus/images/icon_aircraft_red_selected.svg" ); + --unit-aircraft-marker-red-dead-url: url( "/themes/olympus/images/icon_death_red.svg" ); /*** Air units' statuses ***/ - --unit-air-status-rtb-height: 50px; - --unit-air-status-rtb-width: 50px; + --unit-aircraft-status-rtb-height: 50px; + --unit-aircraft-status-rtb-width: 50px; - --unit-air-status-rtb-blue-url: url( "data:image/svg+xml,%3Csvg width='19' height='15' viewBox='0 0 19 15' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9.8125 4.99219L5.5 8.55469V12.375C5.5 12.5859 5.66406 12.75 5.875 12.75H8.5C8.6875 12.75 8.85156 12.5859 8.85156 12.375V10.125C8.85156 9.9375 9.03906 9.75 9.22656 9.75H10.7266C10.9375 9.75 11.1016 9.9375 11.1016 10.125V12.375C11.1016 12.5859 11.2891 12.75 11.4766 12.75H14.125C14.3125 12.75 14.5 12.5859 14.5 12.375V8.53125L10.1641 4.99219C10.1172 4.94531 10.0469 4.92188 10 4.92188C9.92969 4.92188 9.85938 4.94531 9.8125 4.99219ZM16.6328 7.40625L14.6875 5.78906V2.55469C14.6875 2.39062 14.5469 2.27344 14.4062 2.27344H13.0938C12.9297 2.27344 12.8125 2.39062 12.8125 2.55469V4.24219L10.7031 2.50781C10.5156 2.36719 10.2578 2.27344 10 2.27344C9.71875 2.27344 9.46094 2.36719 9.27344 2.50781L3.34375 7.40625C3.27344 7.45312 3.22656 7.54688 3.22656 7.61719C3.22656 7.6875 3.27344 7.75781 3.29688 7.80469L3.90625 8.53125C3.95312 8.60156 4.02344 8.625 4.11719 8.625C4.1875 8.625 4.25781 8.60156 4.30469 8.55469L9.8125 4.03125C9.85938 3.98438 9.92969 3.96094 10 3.96094C10.0469 3.96094 10.1172 3.98438 10.1641 4.03125L15.6719 8.55469C15.7188 8.60156 15.7891 8.625 15.8594 8.625C15.9531 8.625 16.0234 8.60156 16.0703 8.53125L16.6797 7.80469C16.7266 7.75781 16.75 7.6875 16.75 7.61719C16.75 7.54688 16.7031 7.45312 16.6328 7.40625Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M14.5 8.53125V12.375C14.5 12.5859 14.3125 12.75 14.125 12.75H11.4766C11.2891 12.75 11.1016 12.5859 11.1016 12.375V10.125C11.1016 9.9375 10.9375 9.75 10.7266 9.75H9.22656C9.03906 9.75 8.85156 9.9375 8.85156 10.125V12.375C8.85156 12.5859 8.6875 12.75 8.5 12.75H5.875C5.66406 12.75 5.5 12.5859 5.5 12.375V8.55469L9.8125 4.99219C9.85938 4.94531 9.92969 4.92188 10 4.92188C10.0469 4.92188 10.1172 4.94531 10.1641 4.99219L14.5 8.53125ZM15.6719 8.55469C15.673 8.55582 15.6741 8.55693 15.6753 8.55803C15.7136 8.5945 15.7664 8.61608 15.8218 8.62275C15.8342 8.62425 15.8468 8.625 15.8594 8.625C15.9531 8.625 16.0234 8.60156 16.0703 8.53125L16.6797 7.80469C16.7266 7.75781 16.75 7.6875 16.75 7.61719C16.75 7.58321 16.7391 7.54375 16.7198 7.50676C16.6992 7.46721 16.6691 7.43047 16.6328 7.40625L14.6875 5.78906V2.55469C14.6875 2.39062 14.5469 2.27344 14.4062 2.27344H13.0938C12.9297 2.27344 12.8125 2.39062 12.8125 2.55469V4.24219L10.7031 2.50781C10.6607 2.47601 10.6147 2.44661 10.5659 2.42014C10.399 2.32958 10.1995 2.27344 10 2.27344C9.71875 2.27344 9.46094 2.36719 9.27344 2.50781L3.34375 7.40625C3.31845 7.42312 3.29618 7.44605 3.27804 7.47178C3.27013 7.483 3.26301 7.49475 3.25676 7.50676C3.25438 7.51134 3.25212 7.51595 3.25 7.52059C3.23497 7.55343 3.22656 7.58741 3.22656 7.61719C3.22656 7.64997 3.23675 7.68274 3.25 7.71315C3.25988 7.73582 3.27147 7.75718 3.2818 7.77623C3.28734 7.78642 3.29251 7.79596 3.29688 7.80469L3.90625 8.53125C3.9119 8.53973 3.9179 8.54753 3.92423 8.55469C3.97043 8.60688 4.03475 8.625 4.11719 8.625C4.12975 8.625 4.14232 8.62425 4.15475 8.62275C4.20858 8.61627 4.2599 8.59576 4.29785 8.56121C4.30018 8.55909 4.30246 8.55692 4.30469 8.55469L9.8125 4.03125C9.85938 3.98438 9.92969 3.96094 10 3.96094C10.0469 3.96094 10.1172 3.98438 10.1641 4.03125L15.6719 8.55469ZM3.25 10.7274C2.87411 10.5959 2.46972 10.355 2.13819 9.92451L1.40281 9.04772L1.29673 8.83555C1.29616 8.83449 1.29556 8.83338 1.29494 8.83223C1.28063 8.80565 1.24385 8.73712 1.20461 8.65078C1.13819 8.50467 0.976562 8.12434 0.976562 7.61719C0.976562 7.12558 1.1254 6.71911 1.27773 6.4362C1.41591 6.17958 1.63146 5.88605 1.95204 5.63749L7.88118 0.739506L7.92344 0.707813C8.5004 0.275088 9.23192 0.0234375 10 0.0234375C10.6011 0.0234375 11.1776 0.186404 11.6675 0.458244C12.0727 0.183444 12.5631 0.0234375 13.0938 0.0234375H14.4062C15.6666 0.0234375 16.9375 1.02855 16.9375 2.55469V4.73359L18.0288 5.64079C18.347 5.88864 18.5613 6.18072 18.6988 6.4362C18.8512 6.71911 19 7.12558 19 7.61719C19 8.10158 18.8551 8.74439 18.3724 9.28773L17.8384 9.92451C17.5137 10.3461 17.1192 10.5858 16.75 10.719V12.375C16.75 13.9179 15.4639 15 14.125 15H11.4766C10.9469 15 10.4254 14.8306 9.98865 14.5304C9.57667 14.823 9.06944 15 8.5 15H5.875C4.42142 15 3.25 13.8286 3.25 12.375V10.7274Z' fill='%23082E44'/%3E%3C/svg%3E" ); - --unit-air-status-rtb-neutral-url: url( "data:image/svg+xml,%3Csvg width='19' height='15' viewBox='0 0 19 15' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.85938 4.99219L4.54688 8.55469V12.375C4.54688 12.5859 4.71094 12.75 4.92188 12.75H7.54688C7.73438 12.75 7.89844 12.5859 7.89844 12.375V10.125C7.89844 9.9375 8.08594 9.75 8.27344 9.75H9.77344C9.98438 9.75 10.1484 9.9375 10.1484 10.125V12.375C10.1484 12.5859 10.3359 12.75 10.5234 12.75H13.1719C13.3594 12.75 13.5469 12.5859 13.5469 12.375V8.53125L9.21094 4.99219C9.16406 4.94531 9.09375 4.92188 9.04688 4.92188C8.97656 4.92188 8.90625 4.94531 8.85938 4.99219ZM15.6797 7.40625L13.7344 5.78906V2.55469C13.7344 2.39062 13.5938 2.27344 13.4531 2.27344H12.1406C11.9766 2.27344 11.8594 2.39062 11.8594 2.55469V4.24219L9.75 2.50781C9.5625 2.36719 9.30469 2.27344 9.04688 2.27344C8.76562 2.27344 8.50781 2.36719 8.32031 2.50781L2.39062 7.40625C2.32031 7.45312 2.27344 7.54688 2.27344 7.61719C2.27344 7.6875 2.32031 7.75781 2.34375 7.80469L2.95312 8.53125C3 8.60156 3.07031 8.625 3.16406 8.625C3.23438 8.625 3.30469 8.60156 3.35156 8.55469L8.85938 4.03125C8.90625 3.98438 8.97656 3.96094 9.04688 3.96094C9.09375 3.96094 9.16406 3.98438 9.21094 4.03125L14.7188 8.55469C14.7656 8.60156 14.8359 8.625 14.9062 8.625C15 8.625 15.0703 8.60156 15.1172 8.53125L15.7266 7.80469C15.7734 7.75781 15.7969 7.6875 15.7969 7.61719C15.7969 7.54688 15.75 7.45312 15.6797 7.40625Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.5469 8.53125V12.375C13.5469 12.5859 13.3594 12.75 13.1719 12.75H10.5234C10.3359 12.75 10.1484 12.5859 10.1484 12.375V10.125C10.1484 9.9375 9.98438 9.75 9.77344 9.75H8.27344C8.08594 9.75 7.89844 9.9375 7.89844 10.125V12.375C7.89844 12.5859 7.73438 12.75 7.54688 12.75H4.92188C4.71094 12.75 4.54688 12.5859 4.54688 12.375V8.55469L8.85938 4.99219C8.90625 4.94531 8.97656 4.92188 9.04688 4.92188C9.09375 4.92188 9.16406 4.94531 9.21094 4.99219L13.5469 8.53125ZM14.7188 8.55469C14.7199 8.55582 14.721 8.55693 14.7222 8.55803C14.7604 8.5945 14.8132 8.61608 14.8687 8.62275C14.8811 8.62425 14.8937 8.625 14.9062 8.625C15 8.625 15.0703 8.60156 15.1172 8.53125L15.7266 7.80469C15.7734 7.75781 15.7969 7.6875 15.7969 7.61719C15.7969 7.58321 15.7859 7.54375 15.7667 7.50676C15.7461 7.46721 15.716 7.43047 15.6797 7.40625L13.7344 5.78906V2.55469C13.7344 2.39062 13.5938 2.27344 13.4531 2.27344H12.1406C11.9766 2.27344 11.8594 2.39062 11.8594 2.55469V4.24219L9.75 2.50781C9.7076 2.47601 9.6616 2.44661 9.61282 2.42014C9.4459 2.32958 9.24639 2.27344 9.04688 2.27344C8.76562 2.27344 8.50781 2.36719 8.32031 2.50781L2.39062 7.40625C2.36532 7.42312 2.34306 7.44605 2.32492 7.47178C2.31701 7.483 2.30989 7.49475 2.30364 7.50676C2.30125 7.51134 2.299 7.51595 2.29688 7.52059C2.28184 7.55343 2.27344 7.58741 2.27344 7.61719C2.27344 7.64997 2.28362 7.68274 2.29688 7.71315C2.30676 7.73582 2.31834 7.75718 2.32868 7.77623C2.33421 7.78642 2.33939 7.79596 2.34375 7.80469L2.95312 8.53125C2.95878 8.53973 2.96477 8.54753 2.97111 8.55469C3.0173 8.60688 3.08162 8.625 3.16406 8.625C3.17663 8.625 3.1892 8.62425 3.20163 8.62275C3.25545 8.61627 3.30677 8.59576 3.34472 8.56121C3.34705 8.55909 3.34933 8.55692 3.35156 8.55469L8.85938 4.03125C8.90625 3.98438 8.97656 3.96094 9.04688 3.96094C9.09375 3.96094 9.16406 3.98438 9.21094 4.03125L14.7188 8.55469ZM2.29688 10.7274C1.92098 10.5959 1.51659 10.355 1.18506 9.92451L0.449688 9.04772L0.343607 8.83555C0.343034 8.83449 0.342438 8.83338 0.341816 8.83223C0.327503 8.80565 0.290725 8.73712 0.25148 8.65078C0.185064 8.50467 0.0234375 8.12434 0.0234375 7.61719C0.0234375 7.12558 0.172273 6.71911 0.324604 6.4362C0.462785 6.17958 0.67834 5.88605 0.998912 5.63749L6.92805 0.739506L6.97031 0.707813C7.54728 0.275088 8.27879 0.0234375 9.04688 0.0234375C9.64799 0.0234375 10.2245 0.186404 10.7144 0.458244C11.1195 0.183444 11.61 0.0234375 12.1406 0.0234375H13.4531C14.7135 0.0234375 15.9844 1.02855 15.9844 2.55469V4.73359L17.0756 5.64079C17.3939 5.88864 17.6081 6.18072 17.7457 6.4362C17.898 6.71911 18.0469 7.12558 18.0469 7.61719C18.0469 8.10158 17.902 8.74439 17.4193 9.28773L16.8852 9.92451C16.5606 10.3461 16.1661 10.5858 15.7969 10.719V12.375C15.7969 13.9179 14.5108 15 13.1719 15H10.5234C9.99374 15 9.47232 14.8306 9.03552 14.5304C8.62355 14.823 8.11631 15 7.54688 15H4.92188C3.4683 15 2.29688 13.8286 2.29688 12.375V10.7274Z' fill='%232F2F2F'/%3E%3C/svg%3E" ); - --unit-air-status-rtb-red-url: url( "data:image/svg+xml,%3Csvg width='19' height='15' viewBox='0 0 19 15' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.83594 4.99219L4.52344 8.55469V12.375C4.52344 12.5859 4.6875 12.75 4.89844 12.75H7.52344C7.71094 12.75 7.875 12.5859 7.875 12.375V10.125C7.875 9.9375 8.0625 9.75 8.25 9.75H9.75C9.96094 9.75 10.125 9.9375 10.125 10.125V12.375C10.125 12.5859 10.3125 12.75 10.5 12.75H13.1484C13.3359 12.75 13.5234 12.5859 13.5234 12.375V8.53125L9.1875 4.99219C9.14062 4.94531 9.07031 4.92188 9.02344 4.92188C8.95312 4.92188 8.88281 4.94531 8.83594 4.99219ZM15.6562 7.40625L13.7109 5.78906V2.55469C13.7109 2.39062 13.5703 2.27344 13.4297 2.27344H12.1172C11.9531 2.27344 11.8359 2.39062 11.8359 2.55469V4.24219L9.72656 2.50781C9.53906 2.36719 9.28125 2.27344 9.02344 2.27344C8.74219 2.27344 8.48438 2.36719 8.29688 2.50781L2.36719 7.40625C2.29688 7.45312 2.25 7.54688 2.25 7.61719C2.25 7.6875 2.29688 7.75781 2.32031 7.80469L2.92969 8.53125C2.97656 8.60156 3.04688 8.625 3.14062 8.625C3.21094 8.625 3.28125 8.60156 3.32812 8.55469L8.83594 4.03125C8.88281 3.98438 8.95312 3.96094 9.02344 3.96094C9.07031 3.96094 9.14062 3.98438 9.1875 4.03125L14.6953 8.55469C14.7422 8.60156 14.8125 8.625 14.8828 8.625C14.9766 8.625 15.0469 8.60156 15.0938 8.53125L15.7031 7.80469C15.75 7.75781 15.7734 7.6875 15.7734 7.61719C15.7734 7.54688 15.7266 7.45312 15.6562 7.40625Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.5234 8.53125V12.375C13.5234 12.5859 13.3359 12.75 13.1484 12.75H10.5C10.3125 12.75 10.125 12.5859 10.125 12.375V10.125C10.125 9.9375 9.96094 9.75 9.75 9.75H8.25C8.0625 9.75 7.875 9.9375 7.875 10.125V12.375C7.875 12.5859 7.71094 12.75 7.52344 12.75H4.89844C4.6875 12.75 4.52344 12.5859 4.52344 12.375V8.55469L8.83594 4.99219C8.88281 4.94531 8.95312 4.92188 9.02344 4.92188C9.07031 4.92188 9.14062 4.94531 9.1875 4.99219L13.5234 8.53125ZM14.6953 8.55469C14.6964 8.55582 14.6976 8.55693 14.6987 8.55803C14.737 8.5945 14.7898 8.61608 14.8452 8.62275C14.8577 8.62425 14.8702 8.625 14.8828 8.625C14.9766 8.625 15.0469 8.60156 15.0938 8.53125L15.7031 7.80469C15.75 7.75781 15.7734 7.6875 15.7734 7.61719C15.7734 7.58321 15.7625 7.54375 15.7432 7.50676C15.7227 7.46721 15.6926 7.43047 15.6562 7.40625L13.7109 5.78906V2.55469C13.7109 2.39062 13.5703 2.27344 13.4297 2.27344H12.1172C11.9531 2.27344 11.8359 2.39062 11.8359 2.55469V4.24219L9.72656 2.50781C9.68416 2.47601 9.63816 2.44661 9.58938 2.42014C9.42246 2.32958 9.22295 2.27344 9.02344 2.27344C8.74219 2.27344 8.48438 2.36719 8.29688 2.50781L2.36719 7.40625C2.34189 7.42312 2.31962 7.44605 2.30148 7.47178C2.29357 7.483 2.28645 7.49475 2.2802 7.50676C2.27782 7.51134 2.27556 7.51595 2.27344 7.52059C2.25841 7.55343 2.25 7.58741 2.25 7.61719C2.25 7.64997 2.26019 7.68274 2.27344 7.71315C2.28332 7.73582 2.29491 7.75718 2.30524 7.77623C2.31078 7.78642 2.31595 7.79596 2.32031 7.80469L2.92969 8.53125C2.93534 8.53973 2.94134 8.54753 2.94767 8.55469C2.99386 8.60688 3.05818 8.625 3.14062 8.625C3.15319 8.625 3.16576 8.62425 3.17819 8.62275C3.23202 8.61627 3.28333 8.59576 3.32129 8.56121C3.32362 8.55909 3.3259 8.55692 3.32812 8.55469L8.83594 4.03125C8.88281 3.98438 8.95312 3.96094 9.02344 3.96094C9.07031 3.96094 9.14062 3.98438 9.1875 4.03125L14.6953 8.55469ZM2.27344 10.7274C1.89755 10.5959 1.49315 10.355 1.16162 9.92451L0.426251 9.04772L0.32017 8.83555C0.319597 8.83449 0.319 8.83338 0.318378 8.83223C0.304066 8.80565 0.267288 8.73712 0.228043 8.65078C0.161627 8.50467 0 8.12434 0 7.61719C0 7.12558 0.148836 6.71911 0.301167 6.4362C0.439348 6.17958 0.654902 5.88605 0.975475 5.63749L6.90462 0.739506L6.94688 0.707813C7.52384 0.275088 8.25535 0.0234375 9.02344 0.0234375C9.62455 0.0234375 10.201 0.186404 10.691 0.458244C11.0961 0.183444 11.5866 0.0234375 12.1172 0.0234375H13.4297C14.6901 0.0234375 15.9609 1.02855 15.9609 2.55469V4.73359L17.0522 5.64079C17.3704 5.88864 17.5847 6.18072 17.7223 6.4362C17.8746 6.71911 18.0234 7.12558 18.0234 7.61719C18.0234 8.10158 17.8785 8.74439 17.3959 9.28773L16.8618 9.92451C16.5372 10.3461 16.1426 10.5858 15.7734 10.719V12.375C15.7734 13.9179 14.4874 15 13.1484 15H10.5C9.9703 15 9.44888 14.8306 9.01208 14.5304C8.60011 14.823 8.09287 15 7.52344 15H4.89844C3.44486 15 2.27344 13.8286 2.27344 12.375V10.7274Z' fill='%23262222'/%3E%3C/svg%3E" ); + --unit-aircraft-status-rtb-blue-url: url( "data:image/svg+xml,%3Csvg width='19' height='15' viewBox='0 0 19 15' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M9.8125 4.99219L5.5 8.55469V12.375C5.5 12.5859 5.66406 12.75 5.875 12.75H8.5C8.6875 12.75 8.85156 12.5859 8.85156 12.375V10.125C8.85156 9.9375 9.03906 9.75 9.22656 9.75H10.7266C10.9375 9.75 11.1016 9.9375 11.1016 10.125V12.375C11.1016 12.5859 11.2891 12.75 11.4766 12.75H14.125C14.3125 12.75 14.5 12.5859 14.5 12.375V8.53125L10.1641 4.99219C10.1172 4.94531 10.0469 4.92188 10 4.92188C9.92969 4.92188 9.85938 4.94531 9.8125 4.99219ZM16.6328 7.40625L14.6875 5.78906V2.55469C14.6875 2.39062 14.5469 2.27344 14.4062 2.27344H13.0938C12.9297 2.27344 12.8125 2.39062 12.8125 2.55469V4.24219L10.7031 2.50781C10.5156 2.36719 10.2578 2.27344 10 2.27344C9.71875 2.27344 9.46094 2.36719 9.27344 2.50781L3.34375 7.40625C3.27344 7.45312 3.22656 7.54688 3.22656 7.61719C3.22656 7.6875 3.27344 7.75781 3.29688 7.80469L3.90625 8.53125C3.95312 8.60156 4.02344 8.625 4.11719 8.625C4.1875 8.625 4.25781 8.60156 4.30469 8.55469L9.8125 4.03125C9.85938 3.98438 9.92969 3.96094 10 3.96094C10.0469 3.96094 10.1172 3.98438 10.1641 4.03125L15.6719 8.55469C15.7188 8.60156 15.7891 8.625 15.8594 8.625C15.9531 8.625 16.0234 8.60156 16.0703 8.53125L16.6797 7.80469C16.7266 7.75781 16.75 7.6875 16.75 7.61719C16.75 7.54688 16.7031 7.45312 16.6328 7.40625Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M14.5 8.53125V12.375C14.5 12.5859 14.3125 12.75 14.125 12.75H11.4766C11.2891 12.75 11.1016 12.5859 11.1016 12.375V10.125C11.1016 9.9375 10.9375 9.75 10.7266 9.75H9.22656C9.03906 9.75 8.85156 9.9375 8.85156 10.125V12.375C8.85156 12.5859 8.6875 12.75 8.5 12.75H5.875C5.66406 12.75 5.5 12.5859 5.5 12.375V8.55469L9.8125 4.99219C9.85938 4.94531 9.92969 4.92188 10 4.92188C10.0469 4.92188 10.1172 4.94531 10.1641 4.99219L14.5 8.53125ZM15.6719 8.55469C15.673 8.55582 15.6741 8.55693 15.6753 8.55803C15.7136 8.5945 15.7664 8.61608 15.8218 8.62275C15.8342 8.62425 15.8468 8.625 15.8594 8.625C15.9531 8.625 16.0234 8.60156 16.0703 8.53125L16.6797 7.80469C16.7266 7.75781 16.75 7.6875 16.75 7.61719C16.75 7.58321 16.7391 7.54375 16.7198 7.50676C16.6992 7.46721 16.6691 7.43047 16.6328 7.40625L14.6875 5.78906V2.55469C14.6875 2.39062 14.5469 2.27344 14.4062 2.27344H13.0938C12.9297 2.27344 12.8125 2.39062 12.8125 2.55469V4.24219L10.7031 2.50781C10.6607 2.47601 10.6147 2.44661 10.5659 2.42014C10.399 2.32958 10.1995 2.27344 10 2.27344C9.71875 2.27344 9.46094 2.36719 9.27344 2.50781L3.34375 7.40625C3.31845 7.42312 3.29618 7.44605 3.27804 7.47178C3.27013 7.483 3.26301 7.49475 3.25676 7.50676C3.25438 7.51134 3.25212 7.51595 3.25 7.52059C3.23497 7.55343 3.22656 7.58741 3.22656 7.61719C3.22656 7.64997 3.23675 7.68274 3.25 7.71315C3.25988 7.73582 3.27147 7.75718 3.2818 7.77623C3.28734 7.78642 3.29251 7.79596 3.29688 7.80469L3.90625 8.53125C3.9119 8.53973 3.9179 8.54753 3.92423 8.55469C3.97043 8.60688 4.03475 8.625 4.11719 8.625C4.12975 8.625 4.14232 8.62425 4.15475 8.62275C4.20858 8.61627 4.2599 8.59576 4.29785 8.56121C4.30018 8.55909 4.30246 8.55692 4.30469 8.55469L9.8125 4.03125C9.85938 3.98438 9.92969 3.96094 10 3.96094C10.0469 3.96094 10.1172 3.98438 10.1641 4.03125L15.6719 8.55469ZM3.25 10.7274C2.87411 10.5959 2.46972 10.355 2.13819 9.92451L1.40281 9.04772L1.29673 8.83555C1.29616 8.83449 1.29556 8.83338 1.29494 8.83223C1.28063 8.80565 1.24385 8.73712 1.20461 8.65078C1.13819 8.50467 0.976562 8.12434 0.976562 7.61719C0.976562 7.12558 1.1254 6.71911 1.27773 6.4362C1.41591 6.17958 1.63146 5.88605 1.95204 5.63749L7.88118 0.739506L7.92344 0.707813C8.5004 0.275088 9.23192 0.0234375 10 0.0234375C10.6011 0.0234375 11.1776 0.186404 11.6675 0.458244C12.0727 0.183444 12.5631 0.0234375 13.0938 0.0234375H14.4062C15.6666 0.0234375 16.9375 1.02855 16.9375 2.55469V4.73359L18.0288 5.64079C18.347 5.88864 18.5613 6.18072 18.6988 6.4362C18.8512 6.71911 19 7.12558 19 7.61719C19 8.10158 18.8551 8.74439 18.3724 9.28773L17.8384 9.92451C17.5137 10.3461 17.1192 10.5858 16.75 10.719V12.375C16.75 13.9179 15.4639 15 14.125 15H11.4766C10.9469 15 10.4254 14.8306 9.98865 14.5304C9.57667 14.823 9.06944 15 8.5 15H5.875C4.42142 15 3.25 13.8286 3.25 12.375V10.7274Z' fill='%23082E44'/%3E%3C/svg%3E" ); + --unit-aircraft-status-rtb-neutral-url: url( "data:image/svg+xml,%3Csvg width='19' height='15' viewBox='0 0 19 15' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.85938 4.99219L4.54688 8.55469V12.375C4.54688 12.5859 4.71094 12.75 4.92188 12.75H7.54688C7.73438 12.75 7.89844 12.5859 7.89844 12.375V10.125C7.89844 9.9375 8.08594 9.75 8.27344 9.75H9.77344C9.98438 9.75 10.1484 9.9375 10.1484 10.125V12.375C10.1484 12.5859 10.3359 12.75 10.5234 12.75H13.1719C13.3594 12.75 13.5469 12.5859 13.5469 12.375V8.53125L9.21094 4.99219C9.16406 4.94531 9.09375 4.92188 9.04688 4.92188C8.97656 4.92188 8.90625 4.94531 8.85938 4.99219ZM15.6797 7.40625L13.7344 5.78906V2.55469C13.7344 2.39062 13.5938 2.27344 13.4531 2.27344H12.1406C11.9766 2.27344 11.8594 2.39062 11.8594 2.55469V4.24219L9.75 2.50781C9.5625 2.36719 9.30469 2.27344 9.04688 2.27344C8.76562 2.27344 8.50781 2.36719 8.32031 2.50781L2.39062 7.40625C2.32031 7.45312 2.27344 7.54688 2.27344 7.61719C2.27344 7.6875 2.32031 7.75781 2.34375 7.80469L2.95312 8.53125C3 8.60156 3.07031 8.625 3.16406 8.625C3.23438 8.625 3.30469 8.60156 3.35156 8.55469L8.85938 4.03125C8.90625 3.98438 8.97656 3.96094 9.04688 3.96094C9.09375 3.96094 9.16406 3.98438 9.21094 4.03125L14.7188 8.55469C14.7656 8.60156 14.8359 8.625 14.9062 8.625C15 8.625 15.0703 8.60156 15.1172 8.53125L15.7266 7.80469C15.7734 7.75781 15.7969 7.6875 15.7969 7.61719C15.7969 7.54688 15.75 7.45312 15.6797 7.40625Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.5469 8.53125V12.375C13.5469 12.5859 13.3594 12.75 13.1719 12.75H10.5234C10.3359 12.75 10.1484 12.5859 10.1484 12.375V10.125C10.1484 9.9375 9.98438 9.75 9.77344 9.75H8.27344C8.08594 9.75 7.89844 9.9375 7.89844 10.125V12.375C7.89844 12.5859 7.73438 12.75 7.54688 12.75H4.92188C4.71094 12.75 4.54688 12.5859 4.54688 12.375V8.55469L8.85938 4.99219C8.90625 4.94531 8.97656 4.92188 9.04688 4.92188C9.09375 4.92188 9.16406 4.94531 9.21094 4.99219L13.5469 8.53125ZM14.7188 8.55469C14.7199 8.55582 14.721 8.55693 14.7222 8.55803C14.7604 8.5945 14.8132 8.61608 14.8687 8.62275C14.8811 8.62425 14.8937 8.625 14.9062 8.625C15 8.625 15.0703 8.60156 15.1172 8.53125L15.7266 7.80469C15.7734 7.75781 15.7969 7.6875 15.7969 7.61719C15.7969 7.58321 15.7859 7.54375 15.7667 7.50676C15.7461 7.46721 15.716 7.43047 15.6797 7.40625L13.7344 5.78906V2.55469C13.7344 2.39062 13.5938 2.27344 13.4531 2.27344H12.1406C11.9766 2.27344 11.8594 2.39062 11.8594 2.55469V4.24219L9.75 2.50781C9.7076 2.47601 9.6616 2.44661 9.61282 2.42014C9.4459 2.32958 9.24639 2.27344 9.04688 2.27344C8.76562 2.27344 8.50781 2.36719 8.32031 2.50781L2.39062 7.40625C2.36532 7.42312 2.34306 7.44605 2.32492 7.47178C2.31701 7.483 2.30989 7.49475 2.30364 7.50676C2.30125 7.51134 2.299 7.51595 2.29688 7.52059C2.28184 7.55343 2.27344 7.58741 2.27344 7.61719C2.27344 7.64997 2.28362 7.68274 2.29688 7.71315C2.30676 7.73582 2.31834 7.75718 2.32868 7.77623C2.33421 7.78642 2.33939 7.79596 2.34375 7.80469L2.95312 8.53125C2.95878 8.53973 2.96477 8.54753 2.97111 8.55469C3.0173 8.60688 3.08162 8.625 3.16406 8.625C3.17663 8.625 3.1892 8.62425 3.20163 8.62275C3.25545 8.61627 3.30677 8.59576 3.34472 8.56121C3.34705 8.55909 3.34933 8.55692 3.35156 8.55469L8.85938 4.03125C8.90625 3.98438 8.97656 3.96094 9.04688 3.96094C9.09375 3.96094 9.16406 3.98438 9.21094 4.03125L14.7188 8.55469ZM2.29688 10.7274C1.92098 10.5959 1.51659 10.355 1.18506 9.92451L0.449688 9.04772L0.343607 8.83555C0.343034 8.83449 0.342438 8.83338 0.341816 8.83223C0.327503 8.80565 0.290725 8.73712 0.25148 8.65078C0.185064 8.50467 0.0234375 8.12434 0.0234375 7.61719C0.0234375 7.12558 0.172273 6.71911 0.324604 6.4362C0.462785 6.17958 0.67834 5.88605 0.998912 5.63749L6.92805 0.739506L6.97031 0.707813C7.54728 0.275088 8.27879 0.0234375 9.04688 0.0234375C9.64799 0.0234375 10.2245 0.186404 10.7144 0.458244C11.1195 0.183444 11.61 0.0234375 12.1406 0.0234375H13.4531C14.7135 0.0234375 15.9844 1.02855 15.9844 2.55469V4.73359L17.0756 5.64079C17.3939 5.88864 17.6081 6.18072 17.7457 6.4362C17.898 6.71911 18.0469 7.12558 18.0469 7.61719C18.0469 8.10158 17.902 8.74439 17.4193 9.28773L16.8852 9.92451C16.5606 10.3461 16.1661 10.5858 15.7969 10.719V12.375C15.7969 13.9179 14.5108 15 13.1719 15H10.5234C9.99374 15 9.47232 14.8306 9.03552 14.5304C8.62355 14.823 8.11631 15 7.54688 15H4.92188C3.4683 15 2.29688 13.8286 2.29688 12.375V10.7274Z' fill='%232F2F2F'/%3E%3C/svg%3E" ); + --unit-aircraft-status-rtb-red-url: url( "data:image/svg+xml,%3Csvg width='19' height='15' viewBox='0 0 19 15' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M8.83594 4.99219L4.52344 8.55469V12.375C4.52344 12.5859 4.6875 12.75 4.89844 12.75H7.52344C7.71094 12.75 7.875 12.5859 7.875 12.375V10.125C7.875 9.9375 8.0625 9.75 8.25 9.75H9.75C9.96094 9.75 10.125 9.9375 10.125 10.125V12.375C10.125 12.5859 10.3125 12.75 10.5 12.75H13.1484C13.3359 12.75 13.5234 12.5859 13.5234 12.375V8.53125L9.1875 4.99219C9.14062 4.94531 9.07031 4.92188 9.02344 4.92188C8.95312 4.92188 8.88281 4.94531 8.83594 4.99219ZM15.6562 7.40625L13.7109 5.78906V2.55469C13.7109 2.39062 13.5703 2.27344 13.4297 2.27344H12.1172C11.9531 2.27344 11.8359 2.39062 11.8359 2.55469V4.24219L9.72656 2.50781C9.53906 2.36719 9.28125 2.27344 9.02344 2.27344C8.74219 2.27344 8.48438 2.36719 8.29688 2.50781L2.36719 7.40625C2.29688 7.45312 2.25 7.54688 2.25 7.61719C2.25 7.6875 2.29688 7.75781 2.32031 7.80469L2.92969 8.53125C2.97656 8.60156 3.04688 8.625 3.14062 8.625C3.21094 8.625 3.28125 8.60156 3.32812 8.55469L8.83594 4.03125C8.88281 3.98438 8.95312 3.96094 9.02344 3.96094C9.07031 3.96094 9.14062 3.98438 9.1875 4.03125L14.6953 8.55469C14.7422 8.60156 14.8125 8.625 14.8828 8.625C14.9766 8.625 15.0469 8.60156 15.0938 8.53125L15.7031 7.80469C15.75 7.75781 15.7734 7.6875 15.7734 7.61719C15.7734 7.54688 15.7266 7.45312 15.6562 7.40625Z' fill='white'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M13.5234 8.53125V12.375C13.5234 12.5859 13.3359 12.75 13.1484 12.75H10.5C10.3125 12.75 10.125 12.5859 10.125 12.375V10.125C10.125 9.9375 9.96094 9.75 9.75 9.75H8.25C8.0625 9.75 7.875 9.9375 7.875 10.125V12.375C7.875 12.5859 7.71094 12.75 7.52344 12.75H4.89844C4.6875 12.75 4.52344 12.5859 4.52344 12.375V8.55469L8.83594 4.99219C8.88281 4.94531 8.95312 4.92188 9.02344 4.92188C9.07031 4.92188 9.14062 4.94531 9.1875 4.99219L13.5234 8.53125ZM14.6953 8.55469C14.6964 8.55582 14.6976 8.55693 14.6987 8.55803C14.737 8.5945 14.7898 8.61608 14.8452 8.62275C14.8577 8.62425 14.8702 8.625 14.8828 8.625C14.9766 8.625 15.0469 8.60156 15.0938 8.53125L15.7031 7.80469C15.75 7.75781 15.7734 7.6875 15.7734 7.61719C15.7734 7.58321 15.7625 7.54375 15.7432 7.50676C15.7227 7.46721 15.6926 7.43047 15.6562 7.40625L13.7109 5.78906V2.55469C13.7109 2.39062 13.5703 2.27344 13.4297 2.27344H12.1172C11.9531 2.27344 11.8359 2.39062 11.8359 2.55469V4.24219L9.72656 2.50781C9.68416 2.47601 9.63816 2.44661 9.58938 2.42014C9.42246 2.32958 9.22295 2.27344 9.02344 2.27344C8.74219 2.27344 8.48438 2.36719 8.29688 2.50781L2.36719 7.40625C2.34189 7.42312 2.31962 7.44605 2.30148 7.47178C2.29357 7.483 2.28645 7.49475 2.2802 7.50676C2.27782 7.51134 2.27556 7.51595 2.27344 7.52059C2.25841 7.55343 2.25 7.58741 2.25 7.61719C2.25 7.64997 2.26019 7.68274 2.27344 7.71315C2.28332 7.73582 2.29491 7.75718 2.30524 7.77623C2.31078 7.78642 2.31595 7.79596 2.32031 7.80469L2.92969 8.53125C2.93534 8.53973 2.94134 8.54753 2.94767 8.55469C2.99386 8.60688 3.05818 8.625 3.14062 8.625C3.15319 8.625 3.16576 8.62425 3.17819 8.62275C3.23202 8.61627 3.28333 8.59576 3.32129 8.56121C3.32362 8.55909 3.3259 8.55692 3.32812 8.55469L8.83594 4.03125C8.88281 3.98438 8.95312 3.96094 9.02344 3.96094C9.07031 3.96094 9.14062 3.98438 9.1875 4.03125L14.6953 8.55469ZM2.27344 10.7274C1.89755 10.5959 1.49315 10.355 1.16162 9.92451L0.426251 9.04772L0.32017 8.83555C0.319597 8.83449 0.319 8.83338 0.318378 8.83223C0.304066 8.80565 0.267288 8.73712 0.228043 8.65078C0.161627 8.50467 0 8.12434 0 7.61719C0 7.12558 0.148836 6.71911 0.301167 6.4362C0.439348 6.17958 0.654902 5.88605 0.975475 5.63749L6.90462 0.739506L6.94688 0.707813C7.52384 0.275088 8.25535 0.0234375 9.02344 0.0234375C9.62455 0.0234375 10.201 0.186404 10.691 0.458244C11.0961 0.183444 11.5866 0.0234375 12.1172 0.0234375H13.4297C14.6901 0.0234375 15.9609 1.02855 15.9609 2.55469V4.73359L17.0522 5.64079C17.3704 5.88864 17.5847 6.18072 17.7223 6.4362C17.8746 6.71911 18.0234 7.12558 18.0234 7.61719C18.0234 8.10158 17.8785 8.74439 17.3959 9.28773L16.8618 9.92451C16.5372 10.3461 16.1426 10.5858 15.7734 10.719V12.375C15.7734 13.9179 14.4874 15 13.1484 15H10.5C9.9703 15 9.44888 14.8306 9.01208 14.5304C8.60011 14.823 8.09287 15 7.52344 15H4.89844C3.44486 15 2.27344 13.8286 2.27344 12.375V10.7274Z' fill='%23262222'/%3E%3C/svg%3E" ); - --unit-air-status-hold-height: 50px; - --unit-air-status-hold-width: 50px; + --unit-aircraft-status-hold-height: 50px; + --unit-aircraft-status-hold-width: 50px; - --unit-air-status-hold-blue-url: url( "data:image/svg+xml,%3Csvg width='18' height='17' viewBox='0 0 18 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9.48873 0.900581C10.6482 -0.282964 12.5476 -0.302474 13.7311 0.857004L15.5175 2.607C16.0935 3.17128 16.4181 3.94367 16.4181 4.75C16.4181 4.98835 16.3897 5.22373 16.3349 5.45165C16.7777 5.85549 17.1041 6.39558 17.2419 7.02558L17.3634 7.58115L17.3634 7.58116C18.1864 11.3434 15.254 14.75 11.5216 14.75H9.59627C9.45579 15.0566 9.26081 15.3446 9.01119 15.5994C7.85171 16.783 5.95232 16.8025 4.76878 15.643L2.98245 13.893C2.40646 13.3287 2.08187 12.5563 2.08187 11.75C2.08187 11.5117 2.11023 11.2763 2.16507 11.0484C1.72225 10.6445 1.3958 10.1044 1.258 9.47436L1.13648 8.91882C1.13648 8.91881 1.13648 8.9188 1.13648 8.9188C0.313576 5.15664 3.24591 1.75 6.97832 1.75H8.90365C9.04413 1.44337 9.23911 1.15538 9.48873 0.900581ZM8.90365 7.75H8.85271C8.88343 7.77715 8.91372 7.80505 8.94357 7.83367C8.92981 7.80595 8.9165 7.77805 8.90365 7.75ZM9.55635 8.66633C9.57011 8.69406 9.58342 8.72195 9.59627 8.75H9.64721C9.61649 8.72285 9.5862 8.69496 9.55635 8.66633Z' fill='%23082E44'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11.0958 2.47515C11.3856 2.17926 11.8605 2.17438 12.1564 2.46425L13.9427 4.21425C14.0867 4.35532 14.1678 4.54842 14.1678 4.75C14.1678 4.95158 14.0867 5.14468 13.9427 5.28575L12.1564 7.03575C11.8605 7.32562 11.3856 7.32074 11.0958 7.02486C10.8059 6.72897 10.8108 6.25412 11.1067 5.96425L11.5805 5.5H6.9781C5.54192 5.5 4.50895 6.78851 4.79965 8.11751L4.79965 8.11751L4.92117 8.67308C5.00967 9.07772 4.75339 9.4775 4.34875 9.56601C3.9441 9.65452 3.54432 9.39824 3.45581 8.99359L3.33429 8.43803C3.33429 8.43803 3.33429 8.43803 3.33429 8.43802C2.83071 6.13576 4.62343 4 6.9781 4H11.5805L11.1067 3.53575C10.8108 3.24588 10.8059 2.77103 11.0958 2.47515ZM14.1507 6.93399C14.5554 6.84548 14.9552 7.10175 15.0437 7.5064L15.1652 8.06196L14.4609 8.21604L15.1652 8.06196C15.6688 10.3642 13.8761 12.5 11.5214 12.5H6.91894L7.39283 12.9643C7.68872 13.2541 7.69359 13.729 7.40372 14.0249C7.11385 14.3207 6.63901 14.3256 6.34312 14.0357L4.5568 12.2857C4.4128 12.1447 4.33165 11.9516 4.33165 11.75C4.33165 11.5484 4.4128 11.3553 4.5568 11.2143L6.34312 9.46425C6.63901 9.17438 7.11385 9.17926 7.40372 9.47515C7.69359 9.77103 7.68872 10.2459 7.39283 10.5357L6.91894 11H11.5214C12.9576 11 13.9906 9.71149 13.6998 8.38251L13.5783 7.82694C13.4898 7.42229 13.7461 7.02251 14.1507 6.93399Z' fill='white'/%3E%3C/svg%3E" ); - --unit-air-status-hold-neutral-url: url( "data:image/svg+xml,%3Csvg width='17' height='17' viewBox='0 0 17 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.5356 0.900581C9.69508 -0.282964 11.5945 -0.302474 12.778 0.857004L14.5643 2.607C15.1403 3.17128 15.4649 3.94367 15.4649 4.75C15.4649 4.98835 15.4366 5.22373 15.3817 5.45165C15.8245 5.85549 16.151 6.39558 16.2888 7.02558L16.4103 7.58115L16.4103 7.58116C17.2333 11.3434 14.3009 14.75 10.5685 14.75H8.64315C8.50267 15.0566 8.30769 15.3446 8.05807 15.5994C6.89859 16.783 4.99919 16.8025 3.81565 15.643L2.02933 13.893C1.45334 13.3287 1.12875 12.5563 1.12875 11.75C1.12875 11.5117 1.15711 11.2763 1.21194 11.0484C0.769126 10.6445 0.442675 10.1044 0.30487 9.47436L0.183357 8.91882C0.183355 8.91881 0.183354 8.9188 0.183352 8.9188C-0.639549 5.15664 2.29279 1.75 6.02519 1.75H7.95052C8.09101 1.44337 8.28598 1.15538 8.5356 0.900581ZM7.95052 7.75H7.89958C7.93031 7.77715 7.9606 7.80505 7.99045 7.83367C7.97668 7.80595 7.96338 7.77805 7.95052 7.75ZM8.60322 8.66633C8.61699 8.69406 8.6303 8.72195 8.64315 8.75H8.69409C8.66337 8.72285 8.63307 8.69496 8.60322 8.66633Z' fill='%232F2F2F'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.1426 2.47515C10.4325 2.17926 10.9074 2.17438 11.2032 2.46425L12.9896 4.21425C13.1336 4.35532 13.2147 4.54842 13.2147 4.75C13.2147 4.95158 13.1336 5.14468 12.9896 5.28575L11.2032 7.03575C10.9074 7.32562 10.4325 7.32074 10.1426 7.02486C9.85276 6.72897 9.85764 6.25412 10.1535 5.96425L10.6274 5.5H6.02497C4.5888 5.5 3.55582 6.78851 3.84652 8.11751L3.84652 8.11751L3.96804 8.67308C4.05655 9.07772 3.80027 9.4775 3.39562 9.56601C2.99097 9.65452 2.59119 9.39824 2.50268 8.99359L2.38117 8.43803C2.38117 8.43803 2.38117 8.43803 2.38117 8.43802C1.87759 6.13576 3.6703 4 6.02497 4H10.6274L10.1535 3.53575C9.85764 3.24588 9.85276 2.77103 10.1426 2.47515ZM13.1976 6.93399C13.6022 6.84548 14.002 7.10175 14.0905 7.5064L14.2121 8.06196L13.5077 8.21604L14.2121 8.06196C14.7157 10.3642 12.9229 12.5 10.5683 12.5H5.96582L6.4397 12.9643C6.73559 13.2541 6.74047 13.729 6.4506 14.0249C6.16073 14.3207 5.68588 14.3256 5.38999 14.0357L3.60367 12.2857C3.45967 12.1447 3.37853 11.9516 3.37853 11.75C3.37853 11.5484 3.45967 11.3553 3.60367 11.2143L5.38999 9.46425C5.68588 9.17438 6.16073 9.17926 6.4506 9.47515C6.74047 9.77103 6.73559 10.2459 6.4397 10.5357L5.96582 11H10.5683C12.0044 11 13.0374 9.71149 12.7467 8.38251L12.6252 7.82694C12.5367 7.42229 12.7929 7.02251 13.1976 6.93399Z' fill='white'/%3E%3C/svg%3E" ); - --unit-air-status-hold-red-url: url( "data:image/svg+xml,%3Csvg width='17' height='17' viewBox='0 0 17 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.51217 0.900581C9.67164 -0.282964 11.571 -0.302474 12.7546 0.857004L14.5409 2.607C15.1169 3.17128 15.4415 3.94367 15.4415 4.75C15.4415 4.98835 15.4131 5.22373 15.3583 5.45165C15.8011 5.85549 16.1275 6.39558 16.2654 7.02558L16.3869 7.58115L16.3869 7.58116C17.2098 11.3434 14.2774 14.75 10.5451 14.75H8.61971C8.47923 15.0566 8.28425 15.3446 8.03463 15.5994C6.87515 16.783 4.97576 16.8025 3.79221 15.643L2.00589 13.893C1.4299 13.3287 1.10531 12.5563 1.10531 11.75C1.10531 11.5117 1.13367 11.2763 1.1885 11.0484C0.745688 10.6445 0.419237 10.1044 0.281433 9.47436L0.159919 8.91882C0.159918 8.91881 0.159916 8.9188 0.159915 8.9188C-0.662986 5.15664 2.26935 1.75 6.00175 1.75H7.92709C8.06757 1.44337 8.26255 1.15538 8.51217 0.900581ZM7.92709 7.75H7.87615C7.90687 7.77715 7.93716 7.80505 7.96701 7.83367C7.95325 7.80595 7.93994 7.77805 7.92709 7.75ZM8.57979 8.66633C8.59355 8.69406 8.60686 8.72195 8.61971 8.75H8.67065C8.63993 8.72285 8.60963 8.69496 8.57979 8.66633Z' fill='%23262222'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.1192 2.47515C10.4091 2.17926 10.8839 2.17438 11.1798 2.46425L12.9661 4.21425C13.1101 4.35532 13.1913 4.54842 13.1913 4.75C13.1913 4.95158 13.1101 5.14468 12.9661 5.28575L11.1798 7.03575C10.8839 7.32562 10.4091 7.32074 10.1192 7.02486C9.82932 6.72897 9.8342 6.25412 10.1301 5.96425L10.604 5.5H6.00153C4.56536 5.5 3.53239 6.78851 3.82309 8.11751L3.82309 8.11751L3.9446 8.67308C4.03311 9.07772 3.77683 9.4775 3.37218 9.56601C2.96754 9.65452 2.56775 9.39824 2.47925 8.99359L2.35773 8.43803C2.35773 8.43803 2.35773 8.43803 2.35773 8.43802C1.85415 6.13576 3.64687 4 6.00153 4H10.604L10.1301 3.53575C9.8342 3.24588 9.82932 2.77103 10.1192 2.47515ZM13.1742 6.93399C13.5788 6.84548 13.9786 7.10175 14.0671 7.5064L14.1886 8.06196L13.4843 8.21604L14.1886 8.06196C14.6922 10.3642 12.8995 12.5 10.5448 12.5H5.94238L6.41627 12.9643C6.71215 13.2541 6.71703 13.729 6.42716 14.0249C6.13729 14.3207 5.66244 14.3256 5.36656 14.0357L3.58023 12.2857C3.43624 12.1447 3.35509 11.9516 3.35509 11.75C3.35509 11.5484 3.43624 11.3553 3.58023 11.2143L5.36656 9.46425C5.66244 9.17438 6.13729 9.17926 6.42716 9.47515C6.71703 9.77103 6.71215 10.2459 6.41627 10.5357L5.94238 11H10.5448C11.981 11 13.014 9.71149 12.7233 8.38251L12.6018 7.82694C12.5132 7.42229 12.7695 7.02251 13.1742 6.93399Z' fill='white'/%3E%3C/svg%3E" ); + --unit-aircraft-status-hold-blue-url: url( "data:image/svg+xml,%3Csvg width='18' height='17' viewBox='0 0 18 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M9.48873 0.900581C10.6482 -0.282964 12.5476 -0.302474 13.7311 0.857004L15.5175 2.607C16.0935 3.17128 16.4181 3.94367 16.4181 4.75C16.4181 4.98835 16.3897 5.22373 16.3349 5.45165C16.7777 5.85549 17.1041 6.39558 17.2419 7.02558L17.3634 7.58115L17.3634 7.58116C18.1864 11.3434 15.254 14.75 11.5216 14.75H9.59627C9.45579 15.0566 9.26081 15.3446 9.01119 15.5994C7.85171 16.783 5.95232 16.8025 4.76878 15.643L2.98245 13.893C2.40646 13.3287 2.08187 12.5563 2.08187 11.75C2.08187 11.5117 2.11023 11.2763 2.16507 11.0484C1.72225 10.6445 1.3958 10.1044 1.258 9.47436L1.13648 8.91882C1.13648 8.91881 1.13648 8.9188 1.13648 8.9188C0.313576 5.15664 3.24591 1.75 6.97832 1.75H8.90365C9.04413 1.44337 9.23911 1.15538 9.48873 0.900581ZM8.90365 7.75H8.85271C8.88343 7.77715 8.91372 7.80505 8.94357 7.83367C8.92981 7.80595 8.9165 7.77805 8.90365 7.75ZM9.55635 8.66633C9.57011 8.69406 9.58342 8.72195 9.59627 8.75H9.64721C9.61649 8.72285 9.5862 8.69496 9.55635 8.66633Z' fill='%23082E44'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M11.0958 2.47515C11.3856 2.17926 11.8605 2.17438 12.1564 2.46425L13.9427 4.21425C14.0867 4.35532 14.1678 4.54842 14.1678 4.75C14.1678 4.95158 14.0867 5.14468 13.9427 5.28575L12.1564 7.03575C11.8605 7.32562 11.3856 7.32074 11.0958 7.02486C10.8059 6.72897 10.8108 6.25412 11.1067 5.96425L11.5805 5.5H6.9781C5.54192 5.5 4.50895 6.78851 4.79965 8.11751L4.79965 8.11751L4.92117 8.67308C5.00967 9.07772 4.75339 9.4775 4.34875 9.56601C3.9441 9.65452 3.54432 9.39824 3.45581 8.99359L3.33429 8.43803C3.33429 8.43803 3.33429 8.43803 3.33429 8.43802C2.83071 6.13576 4.62343 4 6.9781 4H11.5805L11.1067 3.53575C10.8108 3.24588 10.8059 2.77103 11.0958 2.47515ZM14.1507 6.93399C14.5554 6.84548 14.9552 7.10175 15.0437 7.5064L15.1652 8.06196L14.4609 8.21604L15.1652 8.06196C15.6688 10.3642 13.8761 12.5 11.5214 12.5H6.91894L7.39283 12.9643C7.68872 13.2541 7.69359 13.729 7.40372 14.0249C7.11385 14.3207 6.63901 14.3256 6.34312 14.0357L4.5568 12.2857C4.4128 12.1447 4.33165 11.9516 4.33165 11.75C4.33165 11.5484 4.4128 11.3553 4.5568 11.2143L6.34312 9.46425C6.63901 9.17438 7.11385 9.17926 7.40372 9.47515C7.69359 9.77103 7.68872 10.2459 7.39283 10.5357L6.91894 11H11.5214C12.9576 11 13.9906 9.71149 13.6998 8.38251L13.5783 7.82694C13.4898 7.42229 13.7461 7.02251 14.1507 6.93399Z' fill='white'/%3E%3C/svg%3E" ); + --unit-aircraft-status-hold-neutral-url: url( "data:image/svg+xml,%3Csvg width='17' height='17' viewBox='0 0 17 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.5356 0.900581C9.69508 -0.282964 11.5945 -0.302474 12.778 0.857004L14.5643 2.607C15.1403 3.17128 15.4649 3.94367 15.4649 4.75C15.4649 4.98835 15.4366 5.22373 15.3817 5.45165C15.8245 5.85549 16.151 6.39558 16.2888 7.02558L16.4103 7.58115L16.4103 7.58116C17.2333 11.3434 14.3009 14.75 10.5685 14.75H8.64315C8.50267 15.0566 8.30769 15.3446 8.05807 15.5994C6.89859 16.783 4.99919 16.8025 3.81565 15.643L2.02933 13.893C1.45334 13.3287 1.12875 12.5563 1.12875 11.75C1.12875 11.5117 1.15711 11.2763 1.21194 11.0484C0.769126 10.6445 0.442675 10.1044 0.30487 9.47436L0.183357 8.91882C0.183355 8.91881 0.183354 8.9188 0.183352 8.9188C-0.639549 5.15664 2.29279 1.75 6.02519 1.75H7.95052C8.09101 1.44337 8.28598 1.15538 8.5356 0.900581ZM7.95052 7.75H7.89958C7.93031 7.77715 7.9606 7.80505 7.99045 7.83367C7.97668 7.80595 7.96338 7.77805 7.95052 7.75ZM8.60322 8.66633C8.61699 8.69406 8.6303 8.72195 8.64315 8.75H8.69409C8.66337 8.72285 8.63307 8.69496 8.60322 8.66633Z' fill='%232F2F2F'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.1426 2.47515C10.4325 2.17926 10.9074 2.17438 11.2032 2.46425L12.9896 4.21425C13.1336 4.35532 13.2147 4.54842 13.2147 4.75C13.2147 4.95158 13.1336 5.14468 12.9896 5.28575L11.2032 7.03575C10.9074 7.32562 10.4325 7.32074 10.1426 7.02486C9.85276 6.72897 9.85764 6.25412 10.1535 5.96425L10.6274 5.5H6.02497C4.5888 5.5 3.55582 6.78851 3.84652 8.11751L3.84652 8.11751L3.96804 8.67308C4.05655 9.07772 3.80027 9.4775 3.39562 9.56601C2.99097 9.65452 2.59119 9.39824 2.50268 8.99359L2.38117 8.43803C2.38117 8.43803 2.38117 8.43803 2.38117 8.43802C1.87759 6.13576 3.6703 4 6.02497 4H10.6274L10.1535 3.53575C9.85764 3.24588 9.85276 2.77103 10.1426 2.47515ZM13.1976 6.93399C13.6022 6.84548 14.002 7.10175 14.0905 7.5064L14.2121 8.06196L13.5077 8.21604L14.2121 8.06196C14.7157 10.3642 12.9229 12.5 10.5683 12.5H5.96582L6.4397 12.9643C6.73559 13.2541 6.74047 13.729 6.4506 14.0249C6.16073 14.3207 5.68588 14.3256 5.38999 14.0357L3.60367 12.2857C3.45967 12.1447 3.37853 11.9516 3.37853 11.75C3.37853 11.5484 3.45967 11.3553 3.60367 11.2143L5.38999 9.46425C5.68588 9.17438 6.16073 9.17926 6.4506 9.47515C6.74047 9.77103 6.73559 10.2459 6.4397 10.5357L5.96582 11H10.5683C12.0044 11 13.0374 9.71149 12.7467 8.38251L12.6252 7.82694C12.5367 7.42229 12.7929 7.02251 13.1976 6.93399Z' fill='white'/%3E%3C/svg%3E" ); + --unit-aircraft-status-hold-red-url: url( "data:image/svg+xml,%3Csvg width='17' height='17' viewBox='0 0 17 17' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M8.51217 0.900581C9.67164 -0.282964 11.571 -0.302474 12.7546 0.857004L14.5409 2.607C15.1169 3.17128 15.4415 3.94367 15.4415 4.75C15.4415 4.98835 15.4131 5.22373 15.3583 5.45165C15.8011 5.85549 16.1275 6.39558 16.2654 7.02558L16.3869 7.58115L16.3869 7.58116C17.2098 11.3434 14.2774 14.75 10.5451 14.75H8.61971C8.47923 15.0566 8.28425 15.3446 8.03463 15.5994C6.87515 16.783 4.97576 16.8025 3.79221 15.643L2.00589 13.893C1.4299 13.3287 1.10531 12.5563 1.10531 11.75C1.10531 11.5117 1.13367 11.2763 1.1885 11.0484C0.745688 10.6445 0.419237 10.1044 0.281433 9.47436L0.159919 8.91882C0.159918 8.91881 0.159916 8.9188 0.159915 8.9188C-0.662986 5.15664 2.26935 1.75 6.00175 1.75H7.92709C8.06757 1.44337 8.26255 1.15538 8.51217 0.900581ZM7.92709 7.75H7.87615C7.90687 7.77715 7.93716 7.80505 7.96701 7.83367C7.95325 7.80595 7.93994 7.77805 7.92709 7.75ZM8.57979 8.66633C8.59355 8.69406 8.60686 8.72195 8.61971 8.75H8.67065C8.63993 8.72285 8.60963 8.69496 8.57979 8.66633Z' fill='%23262222'/%3E%3Cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.1192 2.47515C10.4091 2.17926 10.8839 2.17438 11.1798 2.46425L12.9661 4.21425C13.1101 4.35532 13.1913 4.54842 13.1913 4.75C13.1913 4.95158 13.1101 5.14468 12.9661 5.28575L11.1798 7.03575C10.8839 7.32562 10.4091 7.32074 10.1192 7.02486C9.82932 6.72897 9.8342 6.25412 10.1301 5.96425L10.604 5.5H6.00153C4.56536 5.5 3.53239 6.78851 3.82309 8.11751L3.82309 8.11751L3.9446 8.67308C4.03311 9.07772 3.77683 9.4775 3.37218 9.56601C2.96754 9.65452 2.56775 9.39824 2.47925 8.99359L2.35773 8.43803C2.35773 8.43803 2.35773 8.43803 2.35773 8.43802C1.85415 6.13576 3.64687 4 6.00153 4H10.604L10.1301 3.53575C9.8342 3.24588 9.82932 2.77103 10.1192 2.47515ZM13.1742 6.93399C13.5788 6.84548 13.9786 7.10175 14.0671 7.5064L14.1886 8.06196L13.4843 8.21604L14.1886 8.06196C14.6922 10.3642 12.8995 12.5 10.5448 12.5H5.94238L6.41627 12.9643C6.71215 13.2541 6.71703 13.729 6.42716 14.0249C6.13729 14.3207 5.66244 14.3256 5.36656 14.0357L3.58023 12.2857C3.43624 12.1447 3.35509 11.9516 3.35509 11.75C3.35509 11.5484 3.43624 11.3553 3.58023 11.2143L5.36656 9.46425C5.66244 9.17438 6.13729 9.17926 6.42716 9.47515C6.71703 9.77103 6.71215 10.2459 6.41627 10.5357L5.94238 11H10.5448C11.981 11 13.014 9.71149 12.7233 8.38251L12.6018 7.82694C12.5132 7.42229 12.7695 7.02251 13.1742 6.93399Z' fill='white'/%3E%3C/svg%3E" ); /*** Ground ***/ - --unit-ground-mi-marker-height: 50px; - --unit-ground-mi-marker-width: 50px; + --unit-groundunit-marker-height: 50px; + --unit-groundunit-marker-width: 50px; - --unit-ground-mi-marker-blue-url: url( "/themes/olympus/images/icon_ground_blue.svg" ); - --unit-ground-mi-marker-blue-hover-url: url( "/themes/olympus/images/icon_ground_blue_hover.svg" ); - --unit-ground-mi-marker-blue-selected-url: url( "/themes/olympus/images/icon_ground_blue_selected.svg" ); + --unit-groundunit-marker-blue-url: url( "/themes/olympus/images/icon_ground_blue.svg" ); + --unit-groundunit-marker-blue-hover-url: url( "/themes/olympus/images/icon_ground_blue_hover.svg" ); + --unit-groundunit-marker-blue-selected-url: url( "/themes/olympus/images/icon_ground_blue_selected.svg" ); - --unit-ground-mi-marker-neutral-url: url( "/themes/olympus/images/icon_ground_neutral.svg" ); - --unit-ground-mi-marker-neutral-hover-url: url( "/themes/olympus/images/icon_ground_neutral_hover.svg" ); - --unit-ground-mi-marker-neutral-selected-url: url( "/themes/olympus/images/icon_ground_neutral_selected.svg" ); + --unit-groundunit-marker-neutral-url: url( "/themes/olympus/images/icon_ground_neutral.svg" ); + --unit-groundunit-marker-neutral-hover-url: url( "/themes/olympus/images/icon_ground_neutral_hover.svg" ); + --unit-groundunit-marker-neutral-selected-url: url( "/themes/olympus/images/icon_ground_neutral_selected.svg" ); - --unit-ground-mi-marker-red-url: url( "/themes/olympus/images/icon_ground_red.svg" ); - --unit-ground-mi-marker-red-hover-url: url( "/themes/olympus/images/icon_ground_red_hover.svg" ); - --unit-ground-mi-marker-red-selected-url: url( "/themes/olympus/images/icon_ground_red_selected.svg" ); + --unit-groundunit-marker-red-url: url( "/themes/olympus/images/icon_ground_red.svg" ); + --unit-groundunit-marker-red-hover-url: url( "/themes/olympus/images/icon_ground_red_hover.svg" ); + --unit-groundunit-marker-red-selected-url: url( "/themes/olympus/images/icon_ground_red_selected.svg" ); /*** SAMs ***/ --unit-sam-marker-height: 50px; --unit-sam-marker-width: 50px; - --unit-ground-sam-marker-blue-url: url( "/themes/olympus/images/icon_aa_blue.svg" ); - --unit-ground-sam-marker-blue-hover-url: url( "/themes/olympus/images/icon_aa_blue_hover.svg" ); - --unit-ground-sam-marker-blue-selected-url: url( "/themes/olympus/images/icon_aa_blue_selected.svg" ); + --unit-sam-marker-blue-url: url( "/themes/olympus/images/icon_aa_blue.svg" ); + --unit-sam-marker-blue-hover-url: url( "/themes/olympus/images/icon_aa_blue_hover.svg" ); + --unit-sam-marker-blue-selected-url: url( "/themes/olympus/images/icon_aa_blue_selected.svg" ); - --unit-ground-sam-marker-neutral-url: url( "/themes/olympus/images/icon_aa_neutral.svg" ); - --unit-ground-sam-marker-neutral-hover-url: url( "/themes/olympus/images/icon_aa_neutral_hover.svg" ); - --unit-ground-sam-marker-neutral-selected-url: url( "/themes/olympus/images/icon_aa_neutral_selected.svg" ); + --unit-sam-marker-neutral-url: url( "/themes/olympus/images/icon_aa_neutral.svg" ); + --unit-sam-marker-neutral-hover-url: url( "/themes/olympus/images/icon_aa_neutral_hover.svg" ); + --unit-sam-marker-neutral-selected-url: url( "/themes/olympus/images/icon_aa_neutral_selected.svg" ); - --unit-ground-sam-marker-red-url: url( "/themes/olympus/images/icon_aa_red.svg" ); - --unit-ground-sam-marker-red-hover-url: url( "/themes/olympus/images/icon_aa_red_hover.svg" ); - --unit-ground-sam-marker-red-selected-url: url( "/themes/olympus/images/icon_aa_red_selected.svg" ); + --unit-sam-marker-red-url: url( "/themes/olympus/images/icon_aa_red.svg" ); + --unit-sam-marker-red-hover-url: url( "/themes/olympus/images/icon_aa_red_hover.svg" ); + --unit-sam-marker-red-selected-url: url( "/themes/olympus/images/icon_aa_red_selected.svg" ); - /*** Naval ***/ - --unit-naval-marker-height: 50px; - --unit-naval-marker-width: 50px; + /*** navyunit ***/ + --unit-navyunit-marker-height: 50px; + --unit-navyunit-marker-width: 50px; - --unit-naval-marker-blue-url: url( "/themes/olympus/images/icon_ship_blue.svg" ); - --unit-naval-marker-blue-hover-url: url( "/themes/olympus/images/icon_ship_blue_hover.svg" ); - --unit-naval-marker-blue-selected-url: url( "/themes/olympus/images/icon_ship_blue_selected.svg" ); + --unit-navyunit-marker-blue-url: url( "/themes/olympus/images/icon_ship_blue.svg" ); + --unit-navyunit-marker-blue-hover-url: url( "/themes/olympus/images/icon_ship_blue_hover.svg" ); + --unit-navyunit-marker-blue-selected-url: url( "/themes/olympus/images/icon_ship_blue_selected.svg" ); - --unit-naval-marker-neutral-url: url( "/themes/olympus/images/icon_ship_neutral.svg" ); - --unit-naval-marker-neutral-hover-url: url( "/themes/olympus/images/icon_ship_neutral_hover.svg" ); - --unit-naval-marker-neutral-selected-url: url( "/themes/olympus/images/icon_ship_neutral_selected.svg" ); + --unit-navyunit-marker-neutral-url: url( "/themes/olympus/images/icon_ship_neutral.svg" ); + --unit-navyunit-marker-neutral-hover-url: url( "/themes/olympus/images/icon_ship_neutral_hover.svg" ); + --unit-navyunit-marker-neutral-selected-url: url( "/themes/olympus/images/icon_ship_neutral_selected.svg" ); - --unit-naval-marker-red-url: url( "/themes/olympus/images/icon_ship_red.svg" ); - --unit-naval-marker-red-hover-url: url( "/themes/olympus/images/icon_ship_red_hover.svg" ); - --unit-naval-marker-red-selected-url: url( "/themes/olympus/images/icon_ship_red_selected.svg" ); + --unit-navyunit-marker-red-url: url( "/themes/olympus/images/icon_ship_red.svg" ); + --unit-navyunit-marker-red-hover-url: url( "/themes/olympus/images/icon_ship_red_hover.svg" ); + --unit-navyunit-marker-red-selected-url: url( "/themes/olympus/images/icon_ship_red_selected.svg" ); /*** Building ***/ @@ -198,17 +199,24 @@ /*** Weapons ***/ - --unit-weapons-missile-marker-height: 50px; - --unit-weapons-missile-marker-width: 50px; + --unit-missile-marker-height: 50px; + --unit-missile-marker-width: 50px; - --unit-weapons-missile-marker-blue-url: url( "/themes/olympus/images/icon_missile_blue.svg" ); - --unit-weapons-missile-marker-neutral-url: url( "/themes/olympus/images/icon_missile_neutral.svg" ); - --unit-weapons-missile-marker-red-url: url( "/themes/olympus/images/icon_missile_red.svg" ); + --unit-missile-marker-blue-url: url( "/themes/olympus/images/icon_missile_blue.svg" ); + --unit-missile-marker-neutral-url: url( "/themes/olympus/images/icon_missile_neutral.svg" ); + --unit-missile-marker-red-url: url( "/themes/olympus/images/icon_missile_red.svg" ); + + --unit-bomb-marker-height: 50px; + --unit-bomb-marker-width: 50px; + + --unit-bomb-marker-blue-url: url( "/themes/olympus/images/icon_bomb_blue.svg" ); + --unit-bomb-marker-neutral-url: url( "/themes/olympus/images/icon_bomb_neutral.svg" ); + --unit-bomb-marker-red-url: url( "/themes/olympus/images/icon_bomb_red.svg" ); /*** Context menu ***/ --spawn-aircraft-url: url( "/themes/olympus/images/spawn_aircraft.svg" ); - --spawn-ground-url: url( "/themes/olympus/images/spawn_ground.svg" ); + --spawn-groundunit-url: url( "/themes/olympus/images/spawn_ground.svg" ); --spawn-smoke-url: url( "/themes/olympus/images/spawn_smoke.svg" ); /*** Airbase ***/ diff --git a/client/src/controls/mapcontextmenu.ts b/client/src/controls/mapcontextmenu.ts index fafc82ef..c96241b7 100644 --- a/client/src/controls/mapcontextmenu.ts +++ b/client/src/controls/mapcontextmenu.ts @@ -1,6 +1,6 @@ import { LatLng } from "leaflet"; import { getActiveCoalition, setActiveCoalition } from ".."; -import { spawnAircraft, spawnGroundUnit } from "../server/server"; +import { spawnAircraft, spawnGroundUnit, spawnSmoke } from "../server/server"; import { aircraftDatabase } from "../units/aircraftdatabase"; import { groundUnitsDatabase } from "../units/groundunitsdatabase"; import { ContextMenu } from "./contextmenu"; @@ -21,7 +21,7 @@ export class MapContextMenu extends ContextMenu { #aircraftLoadoutDropdown: Dropdown; #groundUnitRoleDropdown: Dropdown; #groundUnitTypeDropdown: Dropdown; - #spawnOptions: SpawnOptions = {role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null}; + #spawnOptions: SpawnOptions = { role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null }; constructor(id: string) { super(id); @@ -35,33 +35,38 @@ export class MapContextMenu extends ContextMenu { document.addEventListener("contextMenuShow", (e: any) => { this.showSubMenu(e.detail.type); - }) + }); document.addEventListener("contextMenuDeployAircraft", () => { this.hide(); this.#spawnOptions.coalition = getActiveCoalition(); if (this.#spawnOptions) spawnAircraft(this.#spawnOptions); - }) + }); document.addEventListener("contextMenuDeployGroundUnit", () => { this.hide(); this.#spawnOptions.coalition = getActiveCoalition(); if (this.#spawnOptions) spawnGroundUnit(this.#spawnOptions); - }) + }); + + document.addEventListener("contextMenuDeploySmoke", (e: any) => { + this.hide(); + spawnSmoke(e.detail.color, this.getLatLng()); + }); this.hide(); } show(x: number, y: number, latlng: LatLng) { - this.#spawnOptions = {role: "", type: "", latlng: new LatLng(0, 0), loadout: null, coalition: "blue", airbaseName: null}; + this.#spawnOptions.airbaseName = null; super.show(x, y, latlng); this.#spawnOptions.latlng = latlng; this.showUpperBar(); } - showSubMenu(type: string){ + showSubMenu(type: string) { this.getContainer()?.querySelector("#aircraft-spawn-menu")?.classList.toggle("hide", type !== "aircraft"); this.getContainer()?.querySelector("#aircraft-spawn-button")?.classList.toggle("is-open", type === "aircraft"); this.getContainer()?.querySelector("#ground-unit-spawn-menu")?.classList.toggle("hide", type !== "ground-unit"); @@ -84,31 +89,28 @@ export class MapContextMenu extends ContextMenu { this.getContainer()?.querySelector("#upper-bar")?.classList.toggle("hide", true); } - setAirbaseName(airbaseName: string) - { + setAirbaseName(airbaseName: string) { this.#spawnOptions.airbaseName = airbaseName; } - setLatLng(latlng: LatLng) - { + setLatLng(latlng: LatLng) { this.#spawnOptions.latlng = latlng; } #onSwitch(e: any) { if (this.getContainer() != null) { - if (e.srcElement.checked) + if (e.srcElement.checked) setActiveCoalition("red"); - else + else setActiveCoalition("blue"); } } /********* Aircraft spawn menu *********/ - #setAircraftRole(role: string) - { + #setAircraftRole(role: string) { this.#spawnOptions.role = role; - this.#resetAircraftRole(); - this.#aircraftTypeDropdown.setOptions(aircraftDatabase.getLabelsByRole(role)); + this.#resetAircraftType(); + this.#aircraftTypeDropdown.setOptions(aircraftDatabase.getByRole(role).map((blueprint) => { return blueprint.label })); this.#aircraftTypeDropdown.selectValue(0); this.clip(); } @@ -122,20 +124,18 @@ export class MapContextMenu extends ContextMenu { this.clip(); } - #setAircraftType(label: string) - { + #setAircraftType(label: string) { this.#resetAircraftType(); - var type = aircraftDatabase.getNameByLabel(label); - if (type != null) - { + var type = aircraftDatabase.getByLabel(label)?.name || null; + if (type != null) { this.#spawnOptions.type = type; this.#aircraftLoadoutDropdown.setOptions(aircraftDatabase.getLoadoutNamesByRole(type, this.#spawnOptions.role)); this.#aircraftLoadoutDropdown.selectValue(0); var image = (this.getContainer()?.querySelector("#unit-image")); image.src = `images/units/${aircraftDatabase.getByLabel(label)?.filename}`; - image.classList.toggle("hide", false); + image.classList.toggle("hide", false); } - + this.clip(); } @@ -147,15 +147,13 @@ export class MapContextMenu extends ContextMenu { this.clip(); } - #setAircraftLoadout(loadoutName: string) - { - var loadout = aircraftDatabase.getLoadoutsByName(this.#spawnOptions.type, loadoutName); - if (loadout) - { + #setAircraftLoadout(loadoutName: string) { + var loadout = aircraftDatabase.getLoadoutByName(this.#spawnOptions.type, loadoutName); + if (loadout) { this.#spawnOptions.loadout = loadout.code; (this.getContainer()?.querySelector("#aircraft-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = false; - var items = loadout.items.map((item: any) => {return `${item.quantity}x ${item.name}`;}); - items.length == 0? items.push("Empty loadout"): ""; + var items = loadout.items.map((item: any) => { return `${item.quantity}x ${item.name}`; }); + items.length == 0 ? items.push("Empty loadout") : ""; (this.getContainer()?.querySelector("#loadout-list")).replaceChildren( ...items.map((item: any) => { var div = document.createElement('div'); @@ -168,11 +166,10 @@ export class MapContextMenu extends ContextMenu { } /********* Ground unit spawn menu *********/ - #setGroundUnitRole(role: string) - { + #setGroundUnitRole(role: string) { this.#spawnOptions.role = role; - this.#resetGroundUnitRole(); - this.#groundUnitTypeDropdown.setOptions(groundUnitsDatabase.getLabelsByRole(role)); + this.#resetGroundUnitType(); + this.#groundUnitTypeDropdown.setOptions(groundUnitsDatabase.getByRole(role).map((blueprint) => { return blueprint.label })); this.#groundUnitTypeDropdown.selectValue(0); this.clip(); } @@ -186,12 +183,10 @@ export class MapContextMenu extends ContextMenu { this.clip(); } - #setGroundUnitType(label: string) - { + #setGroundUnitType(label: string) { this.#resetGroundUnitType(); - var type = groundUnitsDatabase.getNameByLabel(label); - if (type != null) - { + var type = groundUnitsDatabase.getByLabel(label)?.name || null; + if (type != null) { this.#spawnOptions.type = type; (this.getContainer()?.querySelector("#ground-unit-spawn-menu")?.querySelector(".deploy-unit-button")).disabled = false; } diff --git a/client/src/controls/slider.ts b/client/src/controls/slider.ts index 636c1f70..7cf185cc 100644 --- a/client/src/controls/slider.ts +++ b/client/src/controls/slider.ts @@ -75,7 +75,7 @@ export class Slider { { this.#value = newValue; if (this.#slider != null) - this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * 100); + this.#slider.value = String((newValue - this.#minValue) / (this.#maxValue - this.#minValue) * parseFloat(this.#slider.max)); this.#onValue() } } @@ -120,7 +120,7 @@ export class Slider { this.#dragged = false; if (this.#slider != null) { - this.#value = this.#minValue + parseFloat(this.#slider.value) / 100 * (this.#maxValue - this.#minValue); + this.#value = this.#minValue + parseFloat(this.#slider.value) / parseFloat(this.#slider.max) * (this.#maxValue - this.#minValue); this.#callback(this.getValue()); } } diff --git a/client/src/index.ts b/client/src/index.ts index c572af13..10a3b720 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -9,7 +9,7 @@ import { AIC } from "./aic/aic"; import { ATC } from "./atc/atc"; import { FeatureSwitches } from "./featureswitches"; import { LogPanel } from "./panels/logpanel"; -import { getAirbases, getBullseye as getBullseyes, getMission, getUnits, toggleDemoEnabled } from "./server/server"; +import { getAirbases, getBullseye as getBullseyes, getConfig, getMission, getUnits, setAddress, toggleDemoEnabled } from "./server/server"; import { UnitDataTable } from "./units/unitdatatable"; var map: Map; @@ -69,16 +69,33 @@ function setup() { /* Setup event handlers */ setupEvents(); - /* On the first connection, force request of full data */ - getAirbases((data: AirbasesData) => getMissionData()?.update(data)); - getBullseyes((data: BullseyesData) => getMissionData()?.update(data)); - getMission((data: any) => {getMissionData()?.update(data)}); - getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */); - - /* Start periodically requesting updates */ - startPeriodicUpdate(); + getConfig(readConfig) } +function readConfig(config: any) +{ + if (config && config["server"] != undefined && config["server"]["address"] != undefined && config["server"]["port"] != undefined) + { + const address = config["server"]["address"]; + const port = config["server"]["port"]; + if ((typeof address === 'string' || address instanceof String) && typeof port == 'number') + { + setAddress(window.location.hostname, port); + } + + /* On the first connection, force request of full data */ + getAirbases((data: AirbasesData) => getMissionData()?.update(data)); + getBullseyes((data: BullseyesData) => getMissionData()?.update(data)); + getMission((data: any) => {getMissionData()?.update(data)}); + getUnits((data: UnitsData) => getUnitsManager()?.update(data), true /* Does a full refresh */); + + /* Start periodically requesting updates */ + startPeriodicUpdate(); + } + else { + throw new Error('Could not read configuration file!'); + } +} function startPeriodicUpdate() { requestUpdate(); @@ -124,13 +141,16 @@ function checkSessionHash(newSessionHash: string) { function setupEvents() { /* Generic clicks */ document.addEventListener("click", (ev) => { - if (ev instanceof PointerEvent && ev.target instanceof HTMLElement) { + if (ev instanceof MouseEvent && ev.target instanceof HTMLElement) { + const target = ev.target; + if (target.classList.contains("olympus-dialog-close")) { target.closest("div.olympus-dialog")?.classList.add("hide"); } const triggerElement = target.closest("[data-on-click]"); + if (triggerElement instanceof HTMLElement) { const eventName: string = triggerElement.dataset.onClick || ""; let params = JSON.parse(triggerElement.dataset.onClickParams || "{}"); @@ -184,15 +204,6 @@ function setupEvents() { } //*/ - document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => { - ev.detail._element.classList.toggle("off"); - document.body.toggleAttribute("data-hide-" + ev.detail.coalition); - }); - - document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => { - document.body.toggleAttribute("data-hide-" + ev.detail.category); - }); - document.addEventListener( "closeDialog", (ev: CustomEventInit) => { ev.detail._element.closest( ".ol-dialog" ).classList.add( "hide" ); }); diff --git a/client/src/map/map.ts b/client/src/map/map.ts index 5fd71279..e76021ee 100644 --- a/client/src/map/map.ts +++ b/client/src/map/map.ts @@ -6,6 +6,7 @@ import { UnitContextMenu } from "../controls/unitcontextmenu"; import { AirbaseContextMenu } from "../controls/airbasecontextmenu"; import { Dropdown } from "../controls/dropdown"; import { Airbase } from "../missionhandler/airbase"; +import { Unit } from "../units/unit"; export const IDLE = "IDLE"; export const MOVE_UNIT = "MOVE_UNIT"; @@ -45,6 +46,17 @@ export class Map extends L.Map { this.on('mouseup', (e: any) => this.#onMouseUp(e)); this.on('mousemove', (e: any) => this.#onMouseMove(e)); + document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => { + ev.detail._element.classList.toggle("off"); + document.body.toggleAttribute("data-hide-" + ev.detail.coalition); + Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility()); + }); + + document.addEventListener("toggleUnitVisibility", (ev: CustomEventInit) => { + document.body.toggleAttribute("data-hide-" + ev.detail.category); + Object.values(getUnitsManager().getUnits()).forEach((unit: Unit) => unit.updateVisibility()); + }); + this.#mapSourceDropdown = new Dropdown("map-type", (layerName: string) => this.setLayer(layerName), this.getLayers()) } @@ -228,6 +240,7 @@ export class Map extends L.Map { #onMouseDown(e: any) { + this.hideAllContextMenus(); if ((e.originalEvent.which == 1) && (e.originalEvent.button == 0)) this.dragging.disable(); } diff --git a/client/src/other/utils.ts b/client/src/other/utils.ts index 7de8d03c..4cacf4a4 100644 --- a/client/src/other/utils.ts +++ b/client/src/other/utils.ts @@ -26,6 +26,27 @@ export function ConvertDDToDMS(D: number, lng: boolean) { } +export function dataPointMap( container:HTMLElement, data:any) { + + Object.keys( data ).forEach( ( key ) => { + + const val = "" + data[ key ]; // Ensure a string + + container.querySelectorAll( `[data-point="${key}"]`).forEach( el => { + + // We could probably have options here + if ( el instanceof HTMLInputElement ) { + el.value = val; + } else if ( el instanceof HTMLElement ) { + el.innerText = val; + } + }); + + }); + +} + + export function deg2rad(deg: number) { var pi = Math.PI; return deg * (pi / 180); diff --git a/client/src/panels/unitcontrolpanel.ts b/client/src/panels/unitcontrolpanel.ts index 856d43f5..6ed8e807 100644 --- a/client/src/panels/unitcontrolpanel.ts +++ b/client/src/panels/unitcontrolpanel.ts @@ -1,25 +1,30 @@ import { getUnitsManager } from ".."; import { Slider } from "../controls/slider"; +import { dataPointMap } from "../other/utils"; import { aircraftDatabase } from "../units/aircraftdatabase"; import { groundUnitsDatabase } from "../units/groundunitsdatabase"; import { Aircraft, GroundUnit, Unit } from "../units/unit"; -import { UnitsManager } from "../units/unitsmanager"; +import { UnitDatabase } from "../units/unitdatabase"; import { Panel } from "./panel"; -const ROEs: string[] = ["Free", "Designated free", "Designated", "Return", "Hold"]; -const reactionsToThreat: string[] = [ "None", "Passive", "Evade", "Escape", "Abort"]; -const minSpeedValues: {[key: string]: number} = {Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0}; -const maxSpeedValues: {[key: string]: number} = {Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60}; -const speedIncrements: {[key: string]: number} = {Aircraft: 25, Helicopter: 10, NavyUnit: 5, GroundUnit: 5}; -const minAltitudeValues: {[key: string]: number} = {Aircraft: 0, Helicopter: 0}; -const maxAltitudeValues: {[key: string]: number} = {Aircraft: 50000, Helicopter: 10000}; -const altitudeIncrements: {[key: string]: number} = {Aircraft: 2500, Helicopter: 1000}; +// const ROEs: string[] = ["Free", "Designated free", "Designated", "Return", "Hold"]; // Full list +// const reactionsToThreat: string[] = ["None", "Passive", "Evade", "Escape", "Abort"]; // Full list + +const ROEs: string[] = [ "Hold", "Return", "Designated", "Free" ]; +const reactionsToThreat: string[] = [ "None", "Passive", "Evade" ]; + +const minSpeedValues: { [key: string]: number } = { Aircraft: 100, Helicopter: 0, NavyUnit: 0, GroundUnit: 0 }; +const maxSpeedValues: { [key: string]: number } = { Aircraft: 800, Helicopter: 300, NavyUnit: 60, GroundUnit: 60 }; +const speedIncrements: { [key: string]: number } = { Aircraft: 25, Helicopter: 10, NavyUnit: 5, GroundUnit: 5 }; +const minAltitudeValues: { [key: string]: number } = { Aircraft: 0, Helicopter: 0 }; +const maxAltitudeValues: { [key: string]: number } = { Aircraft: 50000, Helicopter: 10000 }; +const altitudeIncrements: { [key: string]: number } = { Aircraft: 2500, Helicopter: 1000 }; export class UnitControlPanel extends Panel { #altitudeSlider: Slider; #airspeedSlider: Slider; - #optionButtons: {[key: string]: HTMLButtonElement[]} = {} - + #optionButtons: { [key: string]: HTMLButtonElement[] } = {} + constructor(ID: string) { super(ID); @@ -28,51 +33,68 @@ export class UnitControlPanel extends Panel { this.#airspeedSlider = new Slider("airspeed-slider", 0, 100, "kts", (value: number) => getUnitsManager().selectedUnitsSetSpeed(value / 1.94384)); /* Option buttons */ - this.#optionButtons["ROE"] = ROEs.map((option: string, index:number) => { + this.#optionButtons["ROE"] = ROEs.map((option: string, index: number) => { var button = document.createElement("button"); button.title = option; button.value = option; - button.addEventListener("click", () => {getUnitsManager().selectedUnitsSetROE(button.title);}); + button.addEventListener("click", () => { getUnitsManager().selectedUnitsSetROE(button.title); }); return button; }); - this.#optionButtons["reactionToThreat"] = reactionsToThreat.map((option: string, index:number) => { + this.#optionButtons["reactionToThreat"] = reactionsToThreat.map((option: string, index: number) => { var button = document.createElement("button"); button.title = option; button.value = option; - button.addEventListener("click", () => {getUnitsManager().selectedUnitsSetReactionToThreat(button.title);}); + button.addEventListener("click", () => { getUnitsManager().selectedUnitsSetReactionToThreat(button.title); }); return button; }); this.getElement().querySelector("#roe-buttons-container")?.append(...this.#optionButtons["ROE"]); this.getElement().querySelector("#reaction-to-threat-buttons-container")?.append(...this.#optionButtons["reactionToThreat"]); - document.addEventListener("unitUpdated", (e: CustomEvent) => {if (e.detail.getSelected()) this.update()}); - document.addEventListener("unitsSelection", (e: CustomEvent) => {this.show(); this.update()}); - document.addEventListener("clearSelection", () => {this.hide()}); + document.addEventListener("unitUpdated", (e: CustomEvent) => { if (e.detail.getSelected()) this.update() }); + document.addEventListener("unitsSelection", (e: CustomEvent) => { this.show(); this.update() }); + document.addEventListener("clearSelection", () => { this.hide() }); this.hide(); } update() { var units = getUnitsManager().getSelectedUnits(); - if (this.getElement() != null && units.length > 0) - { + if (this.getElement() != null && units.length > 0) { this.#showFlightControlSliders(units); - this.getElement().querySelector("#selected-units-container")?.replaceChildren(...units.map((unit: Unit) => - { - var button = document.createElement("button"); - button.innerText = unit.getBaseData().unitName; - - if (unit instanceof Aircraft) - button.setAttribute( "data-short-label", aircraftDatabase.getShortLabelByName(unit.getBaseData().name)); - else if (unit instanceof GroundUnit) - button.setAttribute( "data-short-label", groundUnitsDatabase.getShortLabelByName(unit.getBaseData().name)); - else - button.setAttribute( "data-short-label", ""); - button.setAttribute( "data-coalition", unit.getMissionData().coalition ); - button.classList.add( "pill", "highlight-coalition" ) + this.getElement().querySelector("#selected-units-container")?.replaceChildren(...units.map((unit: Unit, index: number) => { + let database: UnitDatabase | null; + if (unit instanceof Aircraft) + database = aircraftDatabase; + else if (unit instanceof GroundUnit) + database = groundUnitsDatabase; + else + database = null; // TODO add databases for other unit types + + if (index === 0) { + this.getElement().querySelectorAll(`[data-object|="unit"]`).forEach(marker => { + + marker.setAttribute("data-coalition", unit.getMissionData().coalition); + + dataPointMap( this.getElement(), { + "shortLabel" : database?.getByName(unit.getBaseData().name)?.shortLabel, + "unitName": unit.getBaseData().unitName + }); + + }); + } + + var button = document.createElement("button"); + var callsign = unit.getBaseData().unitName || ""; + + button.innerText = unit.getBaseData().unitName; + button.setAttribute("data-short-label", database?.getByName(unit.getBaseData().name)?.shortLabel || ""); + button.setAttribute("data-callsign", callsign); + + button.setAttribute("data-coalition", unit.getMissionData().coalition); + button.classList.add("pill", "highlight-coalition") button.addEventListener("click", () => getUnitsManager().selectUnit(unit.ID, true)); return (button); @@ -80,25 +102,33 @@ export class UnitControlPanel extends Panel { this.#optionButtons["ROE"].forEach((button: HTMLButtonElement) => { button.classList.toggle("selected", units.every((unit: Unit) => unit.getOptionsData().ROE === button.value)) - }); + }); this.#optionButtons["reactionToThreat"].forEach((button: HTMLButtonElement) => { button.classList.toggle("selected", units.every((unit: Unit) => unit.getOptionsData().reactionToThreat === button.value)) - }); + }); } } #showFlightControlSliders(units: Unit[]) { - this.#airspeedSlider.show(); - this.#altitudeSlider.show(); + if (getUnitsManager().getSelectedUnitsType() !== undefined) + this.#airspeedSlider.show() + else + this.#airspeedSlider.hide(); + + if (getUnitsManager().getSelectedUnitsType() === "Aircraft" || getUnitsManager().getSelectedUnitsType() === "Helicopter") + this.#altitudeSlider.show() + else + this.#altitudeSlider.hide(); + + this.getElement().querySelector(`#categories-tooltip`)?.classList.toggle("hide", getUnitsManager().getSelectedUnitsType() !== undefined); var unitsType = getUnitsManager().getSelectedUnitsType(); var targetAltitude = getUnitsManager().getSelectedUnitsTargetAltitude(); var targetSpeed = getUnitsManager().getSelectedUnitsTargetSpeed(); - if (unitsType != undefined) - { + if (unitsType != undefined) { if (["GroundUnit", "NavyUnit"].includes(unitsType)) this.#altitudeSlider.hide() diff --git a/client/src/panels/unitinfopanel.ts b/client/src/panels/unitinfopanel.ts index c46cd486..e2cfbbdb 100644 --- a/client/src/panels/unitinfopanel.ts +++ b/client/src/panels/unitinfopanel.ts @@ -1,34 +1,44 @@ +import { getUnitsManager } from ".."; import { ConvertDDToDMS, rad2deg } from "../other/utils"; +import { aircraftDatabase } from "../units/aircraftdatabase"; import { Unit } from "../units/unit"; import { Panel } from "./panel"; export class UnitInfoPanel extends Panel { - #unitName: HTMLElement; - #groupName: HTMLElement; - #name: HTMLElement; - #heading: HTMLElement; #altitude: HTMLElement; + #currentTask: HTMLElement; + #fuelBar: HTMLElement; + #fuelPercentage: HTMLElement; #groundSpeed: HTMLElement; - #fuel: HTMLElement; + #groupName: HTMLElement; + #heading: HTMLElement; + #name: HTMLElement; #latitude: HTMLElement; #longitude: HTMLElement; - #currentTask: HTMLElement; #loadoutContainer: HTMLElement; + #silhouette: HTMLElement; + #unitControl: HTMLElement; + #unitLabel: HTMLElement; + #unitName: HTMLElement; constructor(ID: string) { super(ID); - this.#unitName = (this.getElement().querySelector("#unit-name")); - this.#groupName= (this.getElement().querySelector("#group-name")); - this.#name = (this.getElement().querySelector("#name")); - this.#heading = (this.getElement().querySelector("#heading")); - this.#altitude = (this.getElement().querySelector("#altitude")); - this.#groundSpeed = (this.getElement().querySelector("#ground-speed")); - this.#fuel = (this.getElement().querySelector("#fuel")); - this.#latitude = (this.getElement().querySelector("#latitude")); - this.#longitude = (this.getElement().querySelector("#longitude")); - this.#currentTask = (this.getElement().querySelector("#current-task")); + this.#altitude = (this.getElement().querySelector("#altitude")); + this.#currentTask = (this.getElement().querySelector("#current-task")); + this.#groundSpeed = (this.getElement().querySelector("#ground-speed")); + this.#fuelBar = (this.getElement().querySelector("#fuel-bar")); + this.#fuelPercentage = (this.getElement().querySelector("#fuel-percentage")); + this.#groupName = (this.getElement().querySelector("#group-name")); + this.#heading = (this.getElement().querySelector("#heading")); + this.#name = (this.getElement().querySelector("#name")); + this.#latitude = (this.getElement().querySelector("#latitude")); this.#loadoutContainer = (this.getElement().querySelector("#loadout-container")); + this.#longitude = (this.getElement().querySelector("#longitude")); + this.#silhouette = (this.getElement().querySelector("#loadout-silhouette")); + this.#unitControl = (this.getElement().querySelector("#unit-control")); + this.#unitLabel = (this.getElement().querySelector("#unit-label")); + this.#unitName = (this.getElement().querySelector("#unit-name")); document.addEventListener("unitsSelection", (e: CustomEvent) => this.#onUnitsSelection(e.detail)); document.addEventListener("unitsDeselection", (e: CustomEvent) => this.#onUnitsDeselection(e.detail)); @@ -40,29 +50,53 @@ export class UnitInfoPanel extends Panel { #onUnitUpdate(unit: Unit) { if (this.getElement() != null && this.getVisible() && unit.getSelected()) { + + const baseData = unit.getBaseData(); + /* Set the unit info */ - this.#unitName.innerText = unit.getBaseData().unitName; - this.#groupName.innerText = unit.getBaseData().groupName; - this.#name.innerText = unit.getBaseData().name; + this.#unitLabel.innerText = aircraftDatabase.getByName(baseData.name)?.label || ""; + this.#unitName.innerText = baseData.unitName; + this.#unitControl.innerText = ( ( baseData.AI ) ? "AI" : "Human" ) + " controlled"; + // this.#groupName.innerText = baseData.groupName; + //this.#name.innerText = baseData.name; //this.#heading.innerText = String(Math.floor(rad2deg(unit.getFlightData().heading)) + " °"); //this.#altitude.innerText = String(Math.floor(unit.getFlightData().altitude / 0.3048) + " ft"); //this.#groundSpeed.innerText = String(Math.floor(unit.getFlightData().speed * 1.94384) + " kts"); - //this.#fuel.innerText = String(unit.getMissionData().fuel + "%"); + this.#fuelBar.style.width = String(unit.getMissionData().fuel + "%"); + this.#fuelPercentage.dataset.percentage = "" + unit.getMissionData().fuel; //this.#latitude.innerText = ConvertDDToDMS(unit.getFlightData().latitude, false); //this.#longitude.innerText = ConvertDDToDMS(unit.getFlightData().longitude, true); this.#currentTask.dataset.currentTask = unit.getTaskData().currentTask !== ""? unit.getTaskData().currentTask: "No task"; this.#currentTask.dataset.coalition = unit.getMissionData().coalition; + this.#silhouette.setAttribute( "style", `--loadout-background-image:url('/images/units/${aircraftDatabase.getByName( baseData.name )?.filename}');` );; + /* Add the loadout elements */ - this.#loadoutContainer.replaceChildren(...Object.values(unit.getMissionData().ammo).map( - (ammo: any) => { - var el = document.createElement("div"); - el.classList.add("pill", "loadout-item"); - el.dataset.loadoutQty = ammo.count; - el.dataset.loadoutItem = ammo.desc.displayName; - return el; + const items = this.#loadoutContainer.querySelector( "#loadout-items" ); + + + if ( items ) { + + const ammo = Object.values( unit.getMissionData().ammo ); + + if ( ammo.length > 0 ) { + + items.replaceChildren(...Object.values(unit.getMissionData().ammo).map( + (ammo: any) => { + var el = document.createElement("div"); + el.dataset.qty = ammo.count; + el.dataset.item = ammo.desc.displayName; + return el; + } + )); + + } else { + + items.innerText = "No loadout"; + } - )) + + } } } diff --git a/client/src/server/server.ts b/client/src/server/server.ts index 07e1f826..f45989fe 100644 --- a/client/src/server/server.ts +++ b/client/src/server/server.ts @@ -2,9 +2,8 @@ import * as L from 'leaflet' import { setConnected } from '..'; import { SpawnOptions } from '../controls/mapcontextmenu'; -/* Edit here to change server address */ -const REST_ADDRESS = "http://localhost:30000/olympus"; -const DEMO_ADDRESS = "http://localhost:3000/demo"; +var REST_ADDRESS = "http://localhost:30000/olympus"; +var DEMO_ADDRESS = window.location.href + "demo"; const UNITS_URI = "units"; const LOGS_URI = "logs"; const AIRBASES_URI = "airbases"; @@ -24,9 +23,14 @@ export function GET(callback: CallableFunction, uri: string){ xmlHttp.open("GET", `${demoEnabled? DEMO_ADDRESS: REST_ADDRESS}/${uri}`, true); xmlHttp.onload = function (e) { var data = JSON.parse(xmlHttp.responseText); - callback(data); - lastUpdateTime = parseInt(data.time); - setConnected(true); + if (parseInt(data.time) > lastUpdateTime) + { + callback(data); + lastUpdateTime = parseInt(data.time); + if (isNaN(lastUpdateTime)) + lastUpdateTime = 0; + setConnected(true); + } }; xmlHttp.onerror = function () { console.error("An error occurred during the XMLHttpRequest"); @@ -45,6 +49,24 @@ export function POST(request: object, callback: CallableFunction){ xhr.send(JSON.stringify(request)); } +export function getConfig(callback: CallableFunction) { + var xmlHttp = new XMLHttpRequest(); + xmlHttp.open("GET", window.location.href + "config", true); + xmlHttp.onload = function (e) { + var data = JSON.parse(xmlHttp.responseText); + callback(data); + }; + xmlHttp.onerror = function () { + console.error("An error occurred during the XMLHttpRequest, could not retrieve configuration file"); + }; + xmlHttp.send(null); +} + +export function setAddress(address: string, port: number) { + REST_ADDRESS = `http://${address}:${port}/olympus` + console.log(`Setting REST address to ${REST_ADDRESS}`) +} + export function getAirbases(callback: CallableFunction) { GET(callback, AIRBASES_URI); } diff --git a/client/src/units/aircraftdatabase.ts b/client/src/units/aircraftdatabase.ts index 1c88d193..477d1f48 100644 --- a/client/src/units/aircraftdatabase.ts +++ b/client/src/units/aircraftdatabase.ts @@ -3,7 +3,7 @@ import { UnitDatabase } from "./unitdatabase" export class AircraftDatabase extends UnitDatabase { constructor() { super(); - this.units = { + this.blueprints = { "A-10C": { "name": "A-10C", diff --git a/client/src/units/groundunitsdatabase.ts b/client/src/units/groundunitsdatabase.ts index 038e36e1..3fba1615 100644 --- a/client/src/units/groundunitsdatabase.ts +++ b/client/src/units/groundunitsdatabase.ts @@ -3,7 +3,7 @@ import { UnitDatabase } from "./unitdatabase" export class GroundUnitsDatabase extends UnitDatabase { constructor() { super(); - this.units = { + this.blueprints = { "2B11 mortar": { "name": "2B11 mortar", "label": "2B11 mortar", diff --git a/client/src/units/unit.ts b/client/src/units/unit.ts index 44edbd49..616d098c 100644 --- a/client/src/units/unit.ts +++ b/client/src/units/unit.ts @@ -1,7 +1,7 @@ import { Marker, LatLng, Polyline, Icon, DivIcon } from 'leaflet'; import { getMap, getUnitsManager } from '..'; import { rad2deg } from '../other/utils'; -import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, landAt, setAltitude, setReactionToThreat, setROE, setSpeed } from '../server/server'; +import { addDestination, attackUnit, changeAltitude, changeSpeed, createFormation as setLeader, deleteUnit, getUnits, landAt, setAltitude, setReactionToThreat, setROE, setSpeed } from '../server/server'; import { aircraftDatabase } from './aircraftdatabase'; import { groundUnitsDatabase } from './groundunitsdatabase'; @@ -79,7 +79,7 @@ export class Unit extends Marker { if (type === "NavyUnit") return NavyUnit; } - constructor(ID: number, data: UpdateData, html: string) { + constructor(ID: number, data: UpdateData) { super(new LatLng(0, 0), { riseOnHover: true }); this.ID = ID; @@ -89,19 +89,12 @@ export class Unit extends Marker { this.on('click', (e) => this.#onClick(e)); this.on('dblclick', (e) => this.#onDoubleClick(e)); this.on('contextmenu', (e) => this.#onContextMenu(e)); - - var icon = new DivIcon({ - html: html, - className: 'leaflet-unit-marker', - iconAnchor: [0, 0] - }); - this.setIcon(icon); - + this.#pathPolyline = new Polyline([], { color: '#2d3e50', weight: 3, opacity: 0.5, smoothFactor: 1 }); this.#pathPolyline.addTo(getMap()); this.#targetsPolylines = []; - // Deselect units if they are hidden + /* Deselect units if they are hidden */ document.addEventListener("toggleCoalitionVisibility", (ev: CustomEventInit) => { setTimeout(() => {this.setSelected(this.getSelected() && !this.getHidden())}, 300); }); @@ -110,7 +103,31 @@ export class Unit extends Marker { setTimeout(() => {this.setSelected(this.getSelected() && !this.getHidden())}, 300); }); + /* Set the unit data */ this.setData(data); + + /* Set the icon */ + var icon = new DivIcon({ + html: this.getMarkerHTML(), + className: 'leaflet-unit-marker', + iconAnchor: [0, 0] + }); + this.setIcon(icon); + + } + + getMarkerHTML() { + return `
+
+
+
+
` + } + + getMarkerCategory() + { + // Overloaded by child classes + return ""; } setData(data: UpdateData) { @@ -118,6 +135,7 @@ export class Unit extends Marker { var updateMarker = false; if ((data.flightData.latitude != undefined && data.flightData.longitude != undefined && (this.getFlightData().latitude != data.flightData.latitude || this.getFlightData().longitude != data.flightData.longitude)) + || (data.flightData.heading != undefined && this.getFlightData().heading != data.flightData.heading) || (data.baseData.alive != undefined && this.getBaseData().alive != data.baseData.alive) || this.#forceUpdate || !getMap().hasLayer(this)) updateMarker = true; @@ -253,13 +271,30 @@ export class Unit extends Marker { this.getTaskData().activePath = undefined; } + updateVisibility() + { + this.setHidden( document.body.getAttribute(`data-hide-${this.getMissionData().coalition}`) != null || + document.body.getAttribute(`data-hide-${this.getMarkerCategory()}`) != null || + !this.getBaseData().alive) + } + setHidden(hidden: boolean) { - this.#hidden = hidden; + this.#hidden = hidden; + + /* Add the marker if not present */ + if (!getMap().hasLayer(this) && !this.getHidden()) { + this.addTo(getMap()); + } + + /* Hide the marker if necessary*/ + if (getMap().hasLayer(this) && this.getHidden()) { + getMap().removeLayer(this); + } } getHidden() { - return (this.getElement()?.querySelector(`.unit`))?.offsetParent === null; + return this.#hidden; } getLeader() { @@ -282,10 +317,6 @@ export class Unit extends Marker { return wingmen; } - forceUpdate() { - this.#forceUpdate = true; - } - attackUnit(targetID: number) { /* Call DCS attackUnit function */ if (this.ID != targetID) { @@ -355,11 +386,14 @@ export class Unit extends Marker { var options = [ 'Attack' ] - getMap().showUnitContextMenu(e); - getMap().getUnitContextMenu().setOptions(options, (option: string) => { - getMap().hideUnitContextMenu(); - this.#executeAction(option); - }); + if (getUnitsManager().getSelectedUnits().length > 0 && !(getUnitsManager().getSelectedUnits().includes(this))) + { + getMap().showUnitContextMenu(e); + getMap().getUnitContextMenu().setOptions(options, (option: string) => { + getMap().hideUnitContextMenu(); + this.#executeAction(option); + }); + } } #executeAction(action: string) { @@ -368,21 +402,13 @@ export class Unit extends Marker { } #updateMarker() { - /* Add the marker if not present */ - if (!getMap().hasLayer(this) && !this.getHidden()) { - this.addTo(getMap()); - } + this.updateVisibility(); - /* Hide the marker if necessary*/ - if (getMap().hasLayer(this) && this.getHidden()) { - getMap().removeLayer(this); - } - else { + if (!this.getHidden()) { this.setLatLng(new LatLng(this.getFlightData().latitude, this.getFlightData().longitude)); var element = this.getElement(); if (element != null) { - element.querySelector(".unit-vvi")?.setAttribute("style", `height: ${15 + this.getFlightData().speed / 5}px;`); element.querySelector(".unit")?.setAttribute("data-pilot", this.getMissionData().flags.human? "human": "ai"); @@ -401,9 +427,8 @@ export class Unit extends Marker { } - const headingDeg = rad2deg( this.getFlightData().heading ); - element.querySelectorAll( "[data-rotate-to-heading]" ).forEach( el => { + const headingDeg = rad2deg( this.getFlightData().heading ); let currentStyle = el.getAttribute( "style" ) || ""; el.setAttribute( "style", currentStyle + `transform:rotate(${headingDeg}deg);` ); }); @@ -494,93 +519,120 @@ export class AirUnit extends Unit { export class Aircraft extends AirUnit { constructor(ID: number, data: UnitData) { - super(ID, data, - `
-
-
-
-
-
-
-
-
-
${aircraftDatabase.getShortLabelByName(data.baseData.name)}
-
-
-
-
-
-
-
-
-
-
-
${data.baseData.unitName}
-
-
-
-
`); + super(ID, data); + } + + getMarkerHTML() + { + return `
+
+
+
+
+
+
+
+
+
${aircraftDatabase.getByName(this.getBaseData().name)?.shortLabel || ""}
+
+
+
+
+
+
+
+
+
+
+
${this.getBaseData().unitName}
+
+
+
+
` + } + + getMarkerCategory() + { + return "aircraft"; } } export class Helicopter extends AirUnit { constructor(ID: number, data: UnitData) { - super(ID, data, - ``); + super(ID, data); + } + + getVisibilityCategory() + { + return "helicopter"; } } export class GroundUnit extends Unit { constructor(ID: number, data: UnitData) { - // TODO this is very messy - var role = groundUnitsDatabase.getByName(data.baseData.name)?.loadouts[0].roles[0]; - if (role == undefined) - role = "U"; - var roleType = (role === "SAM") ? "sam" : "mi"; + super(ID, data); + } - super(ID, data, ` -
-
-
-
${role?.substring(0, 1).toUpperCase()}
-
- `); + getMarkerHTML() { + var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0]; + return `
+
+
+
${role?.substring(0, 1)?.toUpperCase() || ""}
+
` + } + + getMarkerCategory() + { + // TODO this is very messy + var role = groundUnitsDatabase.getByName(this.getBaseData().name)?.loadouts[0].roles[0]; + var markerCategory = (role === "SAM") ? "sam" : "groundunit"; + return markerCategory; } } export class NavyUnit extends Unit { constructor(ID: number, data: UnitData) { - super(ID, data, ` -
-
-
-
N
-
- `); + super(ID, data); + } + + getMarkerCategory() { + return "navyunit"; } } export class Weapon extends Unit { - constructor(ID: number, data: UnitData, html: string) { - super(ID, data, html); + constructor(ID: number, data: UnitData) { + super(ID, data); this.setSelectable(false); } + + getMarkerHTML(): string { + return `
+
+
+
+
` + } + } export class Missile extends Weapon { constructor(ID: number, data: UnitData) { - super(ID, data, ` -
-
-
-
-
- `); + super(ID, data); + } + + getMarkerCategory() { + return "missile"; } } export class Bomb extends Weapon { constructor(ID: number, data: UnitData) { - super(ID, data, ""); + super(ID, data); + } + + getMarkerCategory() { + return "bomb"; } } diff --git a/client/src/units/unitdatabase.ts b/client/src/units/unitdatabase.ts index 564ab8f5..9bfd0095 100644 --- a/client/src/units/unitdatabase.ts +++ b/client/src/units/unitdatabase.ts @@ -1,34 +1,18 @@ export class UnitDatabase { - units: {[key: string]: UnitBlueprint} = {}; + blueprints: {[key: string]: UnitBlueprint} = {}; constructor() { } - getByName(name: string) - { - if (name in this.units) - return this.units[name]; - return null; - } - - getByLabel(label: string) - { - for (let unit in this.units) - { - if (this.units[unit].label === label) - return this.units[unit]; - } - return null; - } - + /* Returns a list of all possible roles in a database */ getRoles() { var roles: string[] = []; - for (let unit in this.units) + for (let unit in this.blueprints) { - for (let loadout of this.units[unit].loadouts) + for (let loadout of this.blueprints[unit].loadouts) { for (let role of loadout.roles) { @@ -40,16 +24,36 @@ export class UnitDatabase { return roles; } - getLabelsByRole(role: string) + /* Gets a specific blueprint by name */ + getByName(name: string) + { + if (name in this.blueprints) + return this.blueprints[name]; + return null; + } + + /* Gets a specific blueprint by label */ + getByLabel(label: string) + { + for (let unit in this.blueprints) + { + if (this.blueprints[unit].label === label) + return this.blueprints[unit]; + } + return null; + } + + /* Get all blueprints by role */ + getByRole(role: string) { var units = []; - for (let unit in this.units) + for (let unit in this.blueprints) { - for (let loadout of this.units[unit].loadouts) + for (let loadout of this.blueprints[unit].loadouts) { if (loadout.roles.includes(role) || loadout.roles.includes(role.toLowerCase())) { - units.push(this.units[unit].label) + units.push(this.blueprints[unit]) break; } } @@ -57,10 +61,11 @@ export class UnitDatabase { return units; } - getLoadoutNamesByRole(unit: string, role: string) + /* Get the names of all the loadouts for a specific unit and for a specific role */ + getLoadoutNamesByRole(name: string, role: string) { var loadouts = []; - for (let loadout of this.units[unit].loadouts) + for (let loadout of this.blueprints[name].loadouts) { if (loadout.roles.includes(role) || loadout.roles.includes("")) { @@ -70,37 +75,14 @@ export class UnitDatabase { return loadouts; } - getLoadoutsByName(unit: string, loadoutName: string) + /* Get the loadout content from the unit name and loadout name */ + getLoadoutByName(name: string, loadoutName: string) { - for (let loadout of this.units[unit].loadouts) + for (let loadout of this.blueprints[name].loadouts) { if (loadout.name === loadoutName) - { return loadout; - } } return null; } - - getNameByLabel(label: string) - { - for (let name in this.units) - { - if (this.units[name].label === label) - { - return name; - } - } - return null; - } - - getLabelByName(name: string) - { - return this.units[name] === undefined? name: this.units[name].label; - } - - getShortLabelByName(name: string) - { - return this.units[name] === undefined? "U": this.units[name].shortLabel; - } } \ No newline at end of file diff --git a/client/src/units/unitsmanager.ts b/client/src/units/unitsmanager.ts index e06dd39f..cfbee371 100644 --- a/client/src/units/unitsmanager.ts +++ b/client/src/units/unitsmanager.ts @@ -8,6 +8,7 @@ export class UnitsManager { #units: { [ID: number]: Unit }; #copiedUnits: Unit[]; #selectionEventDisabled: boolean = false; + #pasteDisabled: boolean = false; constructor() { this.#units = {}; @@ -330,10 +331,15 @@ export class UnitsManager { pasteUnits() { - for (let idx in this.#copiedUnits) + if (!this.#pasteDisabled) { - var unit = this.#copiedUnits[idx]; - cloneUnit(unit.ID, getMap().getMouseCoordinates()); + for (let idx in this.#copiedUnits) + { + var unit = this.#copiedUnits[idx]; + cloneUnit(unit.ID, getMap().getMouseCoordinates()); + } + this.#pasteDisabled = true; + setTimeout(() => this.#pasteDisabled = false, 250); } } diff --git a/client/views/contextmenus.ejs b/client/views/contextmenus.ejs index b9104ca0..b386ec9a 100644 --- a/client/views/contextmenus.ejs +++ b/client/views/contextmenus.ejs @@ -67,11 +67,11 @@
- - - - - + + + + +
diff --git a/client/views/index.ejs b/client/views/index.ejs index 2a0a91ff..79e15902 100644 --- a/client/views/index.ejs +++ b/client/views/index.ejs @@ -10,13 +10,13 @@ - - + + diff --git a/client/views/navbar.ejs b/client/views/navbar.ejs index 11b8e83c..9d5993c6 100644 --- a/client/views/navbar.ejs +++ b/client/views/navbar.ejs @@ -7,7 +7,7 @@

Olympus

-
v0.1.0
+
v0.1.1
Discord @@ -28,11 +28,11 @@
- - + + - +
diff --git a/client/views/uikit.ejs b/client/views/uikit.ejs index 8cea83f6..cccaa8be 100644 --- a/client/views/uikit.ejs +++ b/client/views/uikit.ejs @@ -170,7 +170,7 @@
Neutral
-
+
Z
@@ -182,7 +182,7 @@
Blue
-
+
Y
@@ -194,7 +194,7 @@
Red
-
+
X
@@ -216,7 +216,7 @@
Neutral
-
+
Z
@@ -228,7 +228,7 @@
Blue
-
+
Y
@@ -240,7 +240,7 @@
Red
-
+
X
@@ -254,14 +254,14 @@
-
Naval
+
navyunit
Neutral
-
+
Z
@@ -273,7 +273,7 @@
Blue
-
+
Y
@@ -285,7 +285,7 @@
Red
-
+
X
@@ -355,7 +355,7 @@
0% (empty)
-
+
4
@@ -379,7 +379,7 @@
10%
-
+
4
@@ -402,7 +402,7 @@
20%
-
+
4
@@ -425,7 +425,7 @@
50%
-
+
4
@@ -448,7 +448,7 @@
75%
-
+
4
@@ -471,7 +471,7 @@
100%
-
+
4
@@ -502,7 +502,7 @@
-
+
@@ -532,7 +532,7 @@
-
+
@@ -561,7 +561,7 @@
-
+
@@ -591,7 +591,7 @@
-
+
@@ -621,7 +621,7 @@
-
+
@@ -650,7 +650,7 @@
-
+
@@ -688,7 +688,7 @@
-
+
@@ -718,7 +718,7 @@
-
+
@@ -747,7 +747,7 @@
-
+
@@ -790,7 +790,7 @@
-
+
@@ -799,7 +799,7 @@
-
+
@@ -807,7 +807,7 @@
-
+
@@ -1019,6 +1019,50 @@
+ +
+
Airfield menu
+
+
+ +
+ +
+ +
+

Olympus 1-1

+
+
Name
+
AI Controlled
+
+
+
+ +
+ +
+
+
+ Empty loadout +
+
+ + +
+
+
+
+ +
+ +
+ +
+ +
+
+
+
diff --git a/client/views/unitcontrolpanel.ejs b/client/views/unitcontrolpanel.ejs index 50e6db2c..a95ef177 100644 --- a/client/views/unitcontrolpanel.ejs +++ b/client/views/unitcontrolpanel.ejs @@ -3,12 +3,12 @@
-
+
-
18
+
- +
@@ -36,6 +36,7 @@
+
Multiple categories selected
diff --git a/client/views/unitinfopanel.ejs b/client/views/unitinfopanel.ejs index 72276a47..83787d3b 100644 --- a/client/views/unitinfopanel.ejs +++ b/client/views/unitinfopanel.ejs @@ -3,25 +3,25 @@
-

Olympus 1-1

+

-
Name
-
Group
+
+
-
+
+ +
+
+
+
+
-

Loadout

- -
-
Fuel
-
-
- -
- +
+
+
diff --git a/img/olympus.ico b/img/olympus.ico new file mode 100644 index 00000000..d3567a53 Binary files /dev/null and b/img/olympus.ico differ diff --git a/installer/olympus.iss b/installer/olympus.iss index 25d344e2..5aa5bc1a 100644 --- a/installer/olympus.iss +++ b/installer/olympus.iss @@ -1,23 +1,25 @@ #define nwjsFolder "C:\Users\dpass\Documents\nwjs\" +#define version "v0.1.1-alpha" [Setup] AppName=DCS Olympus -AppVerName=DCS Olympus Alpha v0.1.0 +AppVerName={#version} DefaultDirName={usersavedgames}\DCS.openbeta DefaultGroupName=DCSOlympus -OutputBaseFilename=DCSOlympus +OutputBaseFilename=DCSOlympus_{#version} UninstallFilesDir={app}\Mods\Services\Olympus +;SetupIconFile="..\img\olympus.ico" [Tasks] ; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required. Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked - [Files] ; NOTE: Don't use "Flags: ignoreversion" on any shared system files ;Source: "..\scripts\OlympusExport.lua"; DestDir: "{app}\Scripts"; Flags: ignoreversion ;Source: "..\scripts\OlympusPatcher.exe"; DestDir: "{app}\Scripts"; Flags: ignoreversion Source: "..\scripts\OlympusHook.lua"; DestDir: "{app}\Scripts\Hooks"; Flags: ignoreversion +Source: "..\olympus.json"; DestDir: "{app}\Mods\Services\Olympus"; Flags: onlyifdoesntexist Source: "..\scripts\OlympusCommand.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion Source: "..\scripts\unitPayloads.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion ;Source: "..\scripts\OlympusMission.lua"; DestDir: "{app}\Mods\Services\Olympus\Scripts"; Flags: ignoreversion @@ -30,6 +32,7 @@ Source: "..\client\public\*"; DestDir: "{app}\Mods\Services\Olympus\client\publi Source: "..\client\routes\*"; DestDir: "{app}\Mods\Services\Olympus\client\routes"; Flags: ignoreversion recursesubdirs; Source: "..\client\views\*"; DestDir: "{app}\Mods\Services\Olympus\client\views"; Flags: ignoreversion recursesubdirs; Source: "..\client\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion; +Source: "..\img\olympus.ico"; DestDir: "{app}\Mods\Services\Olympus\img"; Flags: ignoreversion; Source: "{#nwjsFolder}\*.*"; DestDir: "{app}\Mods\Services\Olympus\client"; Flags: ignoreversion recursesubdirs; [Code] @@ -58,7 +61,7 @@ Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; Value ChangesEnvironment=yes [Icons] -Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon +Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico" ;[Run] ;Filename: "{app}\Scripts\OlympusPatcher.exe"; Parameters: "-i" diff --git a/mod/entry.lua b/mod/entry.lua index 319e5f60..b2a04abe 100644 --- a/mod/entry.lua +++ b/mod/entry.lua @@ -15,7 +15,7 @@ declare_plugin(self_ID, shortName = "Olympus", fileMenuName = "Olympus", - version = "0.1.0-alpha", + version = "0.1.1-alpha", state = "installed", developerName= "DCS Refugees 767 squadron", info = _("DCS Olympus is a mod for DCS World. It allows users to spawn, control, task, group, and remove units from a DCS World server using a real-time map interface, similarly to Real Time Strategy games. The user interface also provides useful informations units, like loadouts, fuel, tasking, and so on. In the future, more features for DCS World GCI and JTAC will be available."), diff --git a/olympus.json b/olympus.json new file mode 100644 index 00000000..7b1b026b --- /dev/null +++ b/olympus.json @@ -0,0 +1,6 @@ +{ + "server": { + "address": "localhost", + "port": 30000 + } +} diff --git a/scripts/OlympusCommand.lua b/scripts/OlympusCommand.lua index a174955d..deebce65 100644 --- a/scripts/OlympusCommand.lua +++ b/scripts/OlympusCommand.lua @@ -1,4 +1,4 @@ -local version = "v0.1.0-alpha" +local version = "v0.1.1-alpha" local debug = false @@ -341,8 +341,13 @@ function Olympus.delete(ID, lat, lng) Olympus.debug("Olympus.delete " .. ID, 2) local unit = Olympus.getUnitByID(ID) if unit then - unit:destroy(); - Olympus.debug("Olympus.delete completed successfully", 2) + if unit:getPlayerName() then + trigger.action.explosion(unit:getPoint() , 250 ) --consider replacing with forcibly deslotting the player, however this will work for now + Olympus.debug("Olympus.delete completed successfully", 2) + else + unit:destroy(); --works for AI units not players + Olympus.debug("Olympus.delete completed successfully", 2) + end end end diff --git a/scripts/OlympusExport.lua b/scripts/OlympusExport.lua deleted file mode 100644 index fbc8f3f8..00000000 --- a/scripts/OlympusExport.lua +++ /dev/null @@ -1,40 +0,0 @@ -local version = 'v0.1.0-alpha' - -Olympus = {} -Olympus.OlympusDLL = nil -Olympus.cppRESTDLL = nil -Olympus.DLLsloaded = false -Olympus.OlympusModPath = os.getenv('DCSOLYMPUS_PATH')..'\\bin\\' - -log.write('Olympus.EXPORT.LUA', log.INFO, 'Executing OlympusExport.lua') - -function Olympus.loadDLLs() - -- Add the .dll paths - package.cpath = package.cpath..';'..Olympus.OlympusModPath..'?.dll;' - - local status - log.write('Olympus.HOOKS.LUA', log.INFO, 'Loading olympus.dll from ['..Olympus.OlympusModPath..']') - status, Olympus.OlympusDLL = pcall(require, 'olympus') - if status then - log.write('Olympus.HOOKS.LUA', log.INFO, 'olympus.dll loaded successfully') - return true - else - log.write('Olympus.HOOKS.LUA', log.ERROR, 'Error loading olympus.dll: '..Olympus.OlympusDLL) - return false - end -end - -do - if isOlympusModuleInitialized~=true then - local OlympusName = 'Olympus ' .. version .. ' C++ module'; - isOlympusModuleInitialized=true; - Olympus.DLLsloaded = Olympus.loadDLLs() - if Olympus.DLLsloaded then - log.write('Olympus.EXPORT.LUA', log.INFO, OlympusName..' successfully loaded.') - else - log.write('Olympus.EXPORT.LUA', log.ERROR, 'Failed to load '..OlympusName) - end - else - log.write('Olympus.EXPORT.LUA', log.INFO, 'olympus.dll already initialized') - end -end \ No newline at end of file diff --git a/scripts/OlympusHook.lua b/scripts/OlympusHook.lua index fbae7406..3948f693 100644 --- a/scripts/OlympusHook.lua +++ b/scripts/OlympusHook.lua @@ -1,4 +1,4 @@ -local version = 'v0.1.0-alpha' +local version = 'v0.1.1-alpha' Olympus = {} Olympus.OlympusDLL = nil diff --git a/scripts/OlympusMission.lua b/scripts/OlympusMission.lua deleted file mode 100644 index a0690e32..00000000 --- a/scripts/OlympusMission.lua +++ /dev/null @@ -1,135 +0,0 @@ -local version = 'v0.1.0-alpha' - -Olympus = {} -Olympus.groupIndex = 0 -Olympus.groupStep = 40 - -function Olympus.notify(message, displayFor) - trigger.action.outText(message, displayFor) -end - -function Olympus.setMissionData(arg, time) - local missionData = {} - - -- Bullseye data - local bullseyes = {} - for i = 0, 2 do - local bullseyeVec3 = coalition.getMainRefPoint(i) - local bullseyeLatitude, bullseyeLongitude, bullseyeAltitude = coord.LOtoLL(bullseyeVec3) - bullseyes[i] = {} - bullseyes[i]["latitude"] = bullseyeLatitude - bullseyes[i]["longitude"] = bullseyeLongitude - end - - -- Units tactical data - local unitsData = {} - - local startIndex = Olympus.groupIndex - local endIndex = startIndex + Olympus.groupStep - local index = 0 - for groupName, gp in pairs(mist.DBs.groupsByName) do - index = index + 1 - if index > startIndex then - if groupName ~= nil then - local group = Group.getByName(groupName) - if group ~= nil then - local controller = group:getController() - for index, unit in pairs(group:getUnits()) do - local table = {} - table["targets"] = {} - table["targets"]["visual"] = controller:getDetectedTargets(1) - table["targets"]["radar"] = controller:getDetectedTargets(4) - table["targets"]["rwr"] = controller:getDetectedTargets(16) - table["targets"]["other"] = controller:getDetectedTargets(2, 8, 32) - - table["hasTask"] = controller:hasTask() - - table["ammo"] = unit:getAmmo() - table["fuel"] = unit:getFuel() - table["life"] = unit:getLife() / unit:getLife0() - unitsData[unit:getObjectID()] = table - end - end - end - end - if index >= endIndex then - break - end - end - if index ~= endIndex then - Olympus.groupIndex = 0 - else - Olympus.groupIndex = endIndex - end - - -- Airbases data - local base = world.getAirbases() - local airbases = {} - for i = 1, #base do - local info = {} - local latitude, longitude, altitude = coord.LOtoLL(Airbase.getPoint(base[i])) - info["callsign"] = Airbase.getCallsign(base[i]) - local coalitionID = Airbase.getCoalition(base[i]) - if coalitionID == 0 then - info["coalition"] = "neutral" - elseif coalitionID == 1 then - info["coalition"] = "red" - else - info["coalition"] = "blue" - end - info["latitude"] = latitude - info["longitude"] = longitude - if Airbase.getUnit(base[i]) then - info["unitId"] = Airbase.getUnit(base[i]):getID() - end - airbases[i] = info - end - - local mission = {} - mission.theatre = env.mission.theatre - - -- Assemble missionData table - missionData["bullseyes"] = bullseyes - missionData["unitsData"] = unitsData - missionData["airbases"] = airbases - missionData["mission"] = mission - - local command = "Olympus.missionData = " .. Olympus.serializeTable(missionData) .. "\n" .. "Olympus.OlympusDLL.setMissionData()" - net.dostring_in("export", command) - return time + 1 -end - -function Olympus.serializeTable(val, name, skipnewlines, depth) - skipnewlines = skipnewlines or false - depth = depth or 0 - - local tmp = string.rep(" ", depth) - if name then - if type(name) == "number" then - tmp = tmp .. "[" .. name .. "]" .. " = " - else - tmp = tmp .. name .. " = " - end - end - - if type(val) == "table" then - tmp = tmp .. "{" .. (not skipnewlines and "\n" or "") - for k, v in pairs(val) do - tmp = tmp .. Olympus.serializeTable(v, k, skipnewlines, depth + 1) .. "," .. (not skipnewlines and "\n" or "") - end - tmp = tmp .. string.rep(" ", depth) .. "}" - elseif type(val) == "number" then - tmp = tmp .. tostring(val) - elseif type(val) == "string" then - tmp = tmp .. string.format("%q", val) - elseif type(val) == "boolean" then - tmp = tmp .. (val and "true" or "false") - else - tmp = tmp .. "\"[inserializeable datatype:" .. type(val) .. "]\"" - end - - return tmp -end - -timer.scheduleFunction(Olympus.setMissionData, {}, timer.getTime() + 1) -Olympus.notify("OlympusMission " .. version .. " script loaded correctly", 10) diff --git a/scripts/OlympusPatcher.exe b/scripts/OlympusPatcher.exe deleted file mode 100644 index 2c93d37e..00000000 Binary files a/scripts/OlympusPatcher.exe and /dev/null differ diff --git a/scripts/OlympusPatcher.py b/scripts/OlympusPatcher.py deleted file mode 100644 index 1fb13784..00000000 --- a/scripts/OlympusPatcher.py +++ /dev/null @@ -1,42 +0,0 @@ -import shutil -import sys - -START_STRING = "-- Olympus START\n" -END_STRING = "-- Olympus END\n" -EXPORT_STRING = "local Olympuslfs=require('lfs');dofile(Olympuslfs.writedir()..'Scripts/OlympusExport.lua')\n" - -def main(flag): - if flag == "-i": - try: - with open("Export.lua", "r") as f: - shutil.copyfile("Export.lua", "Export.lua.bak") - lines = f.readlines() - if START_STRING in lines: - return - except FileNotFoundError: - print('File does not exist') - - with open("Export.lua", "a") as f: - f.writelines(["\n", START_STRING, EXPORT_STRING, END_STRING, "\n"]) - elif flag == "-u": - try: - with open("Export.lua", "r") as f: - shutil.copyfile("Export.lua", "Export.lua.bak") - lines = f.readlines() - except FileNotFoundError: - print('File does not exist') - - with open("Export.lua", "w") as f: - block = False - for line in lines: - if line == START_STRING: - block = True - - if not block: - f.write(line) - - if line == END_STRING: - block = False - -if __name__ == "__main__": - main(sys.argv[1]) diff --git a/scripts/OlympusPatcher.spec b/scripts/OlympusPatcher.spec deleted file mode 100644 index 59ead9c4..00000000 --- a/scripts/OlympusPatcher.spec +++ /dev/null @@ -1,44 +0,0 @@ -# -*- mode: python ; coding: utf-8 -*- - - -block_cipher = None - - -a = Analysis( - ['OlympusPatcher.py'], - pathex=[], - binaries=[], - datas=[], - hiddenimports=[], - hookspath=[], - hooksconfig={}, - runtime_hooks=[], - excludes=[], - win_no_prefer_redirects=False, - win_private_assemblies=False, - cipher=block_cipher, - noarchive=False, -) -pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) - -exe = EXE( - pyz, - a.scripts, - a.binaries, - a.zipfiles, - a.datas, - [], - name='OlympusPatcher', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - upx_exclude=[], - runtime_tmpdir=None, - console=True, - disable_windowed_traceback=False, - argv_emulation=False, - target_arch=None, - codesign_identity=None, - entitlements_file=None, -) diff --git a/scripts/coolEffects.lua b/scripts/coolEffects.lua new file mode 100644 index 00000000..52efb537 --- /dev/null +++ b/scripts/coolEffects.lua @@ -0,0 +1,305 @@ +effects = {} +effects.shooterName = "TestInfantry" +effects.napalmCounter = 1 + +effects.fireCounter = 1 + +function effects.notify(message, displayFor) + trigger.action.outText(message, displayFor, false) +end + +-------------------------------------------- +-------------------------------------------- +-------------------------------------------- +----NAPALM + + +function effects.napalmSingle () + unit = Unit.getByName(effects.shooterName) + local unitPos = unit:getPosition().p + vec3 = mist.utils.makeVec3GL(unitPos) + effects.spawnNapalm (vec3) +end + + +function effects.spawnNapalm (vec3) + + napeName = "napalmStrike" .. effects.napalmCounter + effects.napalmCounter = effects.napalmCounter + 1 + mist.dynAddStatic( + { + country = 20, + category = 'Fortifications', + hidden = true, + name = napeName, + type ="Fuel tank", + x = vec3.x, + y = vec3.z, + heading = 0, + } -- end of function + ) + timer.scheduleFunction(effects.explode,vec3, timer.getTime() + 0.1) + timer.scheduleFunction(effects.napalam_death,napeName, timer.getTime() + 0.12) +end + +function effects.explode(vec3) + trigger.action.explosion(vec3, 10) +end + +function effects.napalam_death(staticName) --yes i know bad pun, removes the fuel tank after a set time + StaticObject.getByName(staticName):destroy() +end + +-------------------------------------------- +-------------------------------------------- +-------------------------------------------- +----Basic smoke or fire that despawns +function effects.smokeFire () + unit = Unit.getByName(effects.shooterName) + local unitPos = unit:getPosition().p + vec3 = mist.utils.makeVec3GL(unitPos) + effects.createFire (vec3, 2) + -- 1 = small smoke and fire + -- 2 = medium smoke and fire + -- 3 = large smoke and fire + -- 4 = huge smoke and fire + -- 5 = small smoke + -- 6 = medium smoke + -- 7 = large smoke + -- 8 = huge smoke +end + +function effects.createFire (vec3, size) + smokeName = "smokeName" .. effects.fireCounter + effects.fireCounter = effects.fireCounter + 1 + trigger.action.effectSmokeBig(vec3 , size , 1, smokeName) + trigger.action.explosion(vec3, 1) -- looks wierd to spawn in on flat land without this + timer.scheduleFunction(effects.removeFire,smokeName, timer.getTime() + 20) --you could set a timer, or if selected give option to despawn later +end + +function effects.removeFire (smokeName) + trigger.action.effectSmokeStop(smokeName) +end + +-------------------------------------------- +-------------------------------------------- +-------------------------------------------- +----White phosporus secondaries extra effect, like round cooking off +--if you up the number going pop to somewhere in the 200-400 region with a white phosporus impact it would look mental cool +function effects.secondaries () + unit = Unit.getByName(effects.shooterName) + local unitPos = unit:getPosition().p + vec3 = mist.utils.makeVec3GL(unitPos) + --trigger.action.smoke(vec3 , 2 ) + for i = 1,math.random(3,10) do + angle = mist.utils.toRadian((math.random(1,360))) + local randVec = mist.utils.makeVec3GL((mist.getRandPointInCircle(vec3 ,5 , 1 ,0 ,360))) + trigger.action.signalFlare(randVec , 2 , angle ) + end + +end + +-------------------------------------------- +-------------------------------------------- +-------------------------------------------- +----Depth Charges +-- these also make, on land, good dust clouds for a bomb hit in a sandy area? +-- local surface = land.getSurfaceType(mist.utils.makeVec2(unitPos)) -- optional check for water, value 3 or 2 + +function effects.depthCharge () + local unit = Unit.getByName(effects.shooterName) + local unitPos = unit:getPosition().p + + vec3 = mist.utils.makeVec3GL(unitPos) + vec3.y = vec3.y - 1000 + bang = vec3 + distance = 20 + explosionSize = 2 + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + trigger.action.explosion(vec3,explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + trigger.action.explosion(vec3,explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + bang = mist.getRandPointInCircle(vec3 , distance ,1,359,0) + trigger.action.explosion(mist.utils.makeVec3GL(bang),explosionSize) + timer.scheduleFunction(effects.depthChargeMain,vec3, timer.getTime() + 5) +end + + + +function effects.depthChargeMain (vec3) + explosionSize = 250 + trigger.action.explosion(vec3,explosionSize) + trigger.action.explosion(vec3,explosionSize) + vec3.x = vec3.x + trigger.action.explosion(vec3,explosionSize) + vec3.x = vec3.x - 10 + trigger.action.explosion(vec3,explosionSize) + vec3.z = vec3.z + trigger.action.explosion(vec3,explosionSize) + vec3.z = vec3.z - 10 +end + +-------------------------------------------- +-------------------------------------------- +-------------------------------------------- +----Normal small explosion + +function effects.normalSmallExplosion (vec3) + unit = Unit.getByName(effects.shooterName) + local unitPos = unit:getPosition().p + vec3 = mist.utils.makeVec3GL(unitPos) + trigger.action.explosion(vec3,10) +end + + + +do + longRangeShots = missionCommands.addSubMenu("Effects") + missionCommands.addCommand ("Napalm", longRangeShots, effects.napalmSingle) + missionCommands.addCommand ("Fire or smoke", longRangeShots, effects.smokeFire) + missionCommands.addCommand ("Secondary explosions", longRangeShots, effects.secondaries) + missionCommands.addCommand ("Depth Charge", longRangeShots, effects.depthCharge) + missionCommands.addCommand ("A regular explosion", longRangeShots, effects.normalSmallExplosion) +end + +effects.notify("effects.lua ran", 2) \ No newline at end of file diff --git a/scripts/dynamicTanking.lua b/scripts/dynamicTanking.lua new file mode 100644 index 00000000..daa5761d --- /dev/null +++ b/scripts/dynamicTanking.lua @@ -0,0 +1,681 @@ +tankers = {} +tankers.tankerName = "TankerClone" + +function tankers.notify(message, displayFor) + trigger.action.outText(message, displayFor, false) +end + + +function tankers.setFrequency(freq) + + unit = Unit.getByName(tankers.tankerName) + local controller = unit:getController() + + freq = freq or 260 --in MHz, 260 channel 19 is our default tanker thing in refs + + SetFrequency = { + id = 'SetFrequency', + params = { + frequency = freq*1000000 , --in Hz + modulation = 0, --AM 0 or FM 1 + } + } + + controller:setCommand(SetFrequency) +end + +function tankers.changeCallsign() + ---https://wiki.hoggitworld.com/view/DCS_command_setCallsign + unit = Unit.getByName(tankers.tankerName) + local controller = unit:getController() + + SetCallsign = { + id = 'SetCallsign', + params = { + callname = 3, --1 texaco, --2 arco -- 3 shell + number = 1, --1 through 9 valid for tankers only ever 1? + } + } + + controller:setCommand(SetCallsign) +end + +--remember to only pick valid tacan channel ranges + + +-- https://wiki.radioreference.com/index.php/Instrument_Landing_System_(ILS)_Frequencies -- what freqs go with which tacans +-- you want the reply channels on the tankers so the fighter tunes the one you want + +function tankers.setTacan(channel, xRay) + + defaultTac = 40 + defaultXray = true + channel = channel or defaultTac -- the channel you want to tell the fighters to enter in, if not provided defaults + xRay = xRay or defaultXray -- X or Y are only options so true or false + + unit = Unit.getByName(tankers.tankerName) + local controller = unit:getController() + + --tacan maths is easy + --for X ray reply it is, channel + 961, Yankee reply is channel + 1087 + + if xRay == true then + --to not break everyone elses datalink / tacan 37 and above (X) + if channel > 36 then + freq = channel + 961 + ActivateBeacon = { + id = 'ActivateBeacon', + params = { + type = 4, + system = 3, + name = "TKR", + callsign = "ABC", --what shows as a listed word / plays as morese code, 3 max no spaces + frequency = freq*1000000, + } + } + controller:setCommand(ActivateBeacon) + end + + elseif xRay == false then + --to not break everyone elses datalink / tacan 30 - 46 (Y) but I don't think the "above" is correct + if channel > 29 then + freq = channel + 1087 + ActivateBeacon = { + id = 'ActivateBeacon', + params = { + type = 4, + system = 3, + name = "TKR", + callsign = "ABC", --what shows as a listed word / plays as morese code, 3 max no spaces + frequency = freq*1000000, + } + } + controller:setCommand(ActivateBeacon) + end + end +end + +function tankers.dryPlugTanking () -- for whatever reason this ends up being no fuel transfer? + --tankers.setFrequency(260) + --tankers.setTacan(41, true) + --tankers.changeCallsign() + + unit = Unit.getByName(tankers.tankerName) + cvn = Unit.getByName("CVN") + local cvnPos = cvn:getPosition().p + local tnkrPos = unit:getPosition().p + local speed = 250 + local controller = unit:getController() + + --if you want to try making a tanker do something else + --https://www.digitalcombatsimulator.com/en/support/faq/1267/#3307682 maybe? stop conditions etc + --personally i think delete the thing if it doesn't work + --there is a recovery tanker option, but for me it makes planes stall and hit the floor and we can fake it with this already + + -- this might all seem very over the top compared to the docs, but if you don't do it the tanker instantly RTBs, though you can tank on final which is hillarious + + task1 = { + ["number"] = 1, + ["auto"] = false, + ["id"] = "ControlledTask", + ["enabled"] = true, + ["params"] = + { + ["task"] = + { + ["id"] = "Tanker", + ["params"] = + { + }, -- end of ["params"] + }, -- end of ["task"] + ["stopCondition"] = + { + ["duration"] = 600, + ["userFlag"] = "1", + }, -- end of ["stopCondition"] + }, -- end of ["params"] + } + + task2 = { + ["number"] = 2, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "ActivateBeacon", + ["params"] = + { + ["type"] = 4, + ["AA"] = false, + ["callsign"] = "TKR", + ["modeChannel"] = "Y", + ["channel"] = 71, + ["system"] = 5, + ["unitId"] = 188, + ["bearing"] = true, + ["frequency"] = 1032000000, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + } + task3 = + { + ["number"] = 3, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "SetFrequency", + ["params"] = + { + ["power"] = 10, + ["modulation"] = 0, + ["frequency"] = 305000000, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + } + + task4 = + { + ["number"] = 4, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "SetInvisible", + ["params"] = + { + ["value"] = true, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + } + + point1 = { + ['speed_locked'] = false, + ['type'] = 'Turning Point', + ['action'] = 'Turning Point', + ['alt_type'] = 'BARO', + ['y'] = cvnPos.z, + ['x'] = cvnPos.x, + ['speed'] = 128.611, + ['task'] = { + ['id'] = 'ComboTask', + ['params'] = { + ['tasks'] = { + [1] = task1, --tanker first + [2] = task2, --whatever second + [3] = task3, + [4] = task4, + } + } + }, + ['alt'] = tnkrPos.y + } + point2 = { + ['speed_locked'] = true, + ['type'] = 'Turning Point', + ['action'] = 'Turning Point', + ['alt_type'] = 'BARO', + ['y'] = 30553, + ['x'] = 35881, + ['speed'] = 128.611, + ['task'] = { + ['id'] = 'ComboTask', + ['params'] = { + ['tasks'] = { + } + } + }, + ['alt'] = 2133.6 + } + + missionTask = + { + ['id'] = 'Mission', + ['params'] = { + ['route'] = { + ['points'] = { + [1] = point1, + --[2] = point2, + } + }, + ['airborne'] = true + } + } + controller:pushTask(missionTask) +end + +function tankers.followInFront () + unit = Unit.getByName(tankers.tankerName) + local controller = unit:getController() + + FollowAheadOfGroup = { + ["enabled"] = true, + ["auto"] = false, + ["id"] = "Follow", + ["number"] = 1, + ["params"] = + { + ["lastWptIndexFlagChangedManually"] = false, + ["groupId"] = 74, + ["lastWptIndex"] = 2, + ["lastWptIndexFlag"] = false, + ["pos"] = + { + ["y"] = 152.4, --mins for KC 135 to accidentally stern rejoin and overfly + ["x"] = 1000.8, + ["z"] = 39.9288, + }, -- end of ["pos"] + }, -- end of ["params"] + } + + controller:pushTask(FollowAheadOfGroup) +end + +function tankers.followInFrontClose () + unit = Unit.getByName(tankers.tankerName) + local controller = unit:getController() + + FollowAheadOfGroup = { + ["enabled"] = true, + ["auto"] = false, + ["id"] = "Follow", + ["number"] = 1, + ["params"] = + { + ["lastWptIndexFlagChangedManually"] = false, + ["groupId"] = 74, + ["lastWptIndex"] = 2, + ["lastWptIndexFlag"] = false, + ["pos"] = + { + ["y"] = 25, --mins for KC 135 to accidentally stern rejoin and overfly + ["x"] = 150, + ["z"] = 41.45, + }, -- end of ["pos"] + }, -- end of ["params"] + } + + controller:pushTask(FollowAheadOfGroup) +end + +function tankers.cloneTanker() + +local groupName = 'TankerClone' -- Name of the group in the ME + +group = mist.getGroupData(groupName) +group.route = { points = mist.getGroupRoute(groupName, true) } +group.groupName = "Tanker1" +group.groupId = nil +group.units[1].unitId = nil +group.units[1].unitName = newName +group.country = country +group.category = 'AIRPLANE' + +mist.dynAdd(group) + +end + +function tankers.newTanker() + +local groupName = 'TankerClone' -- Name of the group in the ME +local cloneGroupPos = Unit.getByName(groupName):getPosition().p +cvn = Unit.getByName("CVN") +local cvnPos = cvn:getPosition().p + + +group = mist.getGroupData(groupName) +group.route = { + ["points"] = + { + [1] = + { + ["alt"] = 2133.6, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["speed"] = 179.86111111111, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["number"] = 1, + ["auto"] = false, + ["id"] = "ControlledTask", + ["enabled"] = true, + ["params"] = + { + ["task"] = + { + ["id"] = "Tanker", + ["params"] = + { + }, -- end of ["params"] + }, -- end of ["task"] + ["stopCondition"] = + { + ["duration"] = 900, + }, -- end of ["stopCondition"] + }, -- end of ["params"] + }, -- end of [1] + [2] = + { + ["number"] = 2, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "ActivateBeacon", + ["params"] = + { + ["type"] = 4, + ["AA"] = false, + ["callsign"] = "TKR", + ["modeChannel"] = "Y", + ["channel"] = 71, + ["system"] = 5, + ["unitId"] = 188, + ["bearing"] = true, + ["frequency"] = 1032000000, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + }, -- end of [2] + [3] = + { + ["number"] = 3, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "SetFrequency", + ["params"] = + { + ["power"] = 10, + ["modulation"] = 0, + ["frequency"] = 260000000, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + }, -- end of [3] + [4] = + { + ["number"] = 4, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "SetInvisible", + ["params"] = + { + ["value"] = true, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + }, -- end of [4] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 96.50677034026, + ["ETA_locked"] = false, + ["y"] = cvnPos.z, + ["x"] = cvnPos.x, + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + } + +--group.units[1].type = "S-3B Tanker" +group.groupName = "Tanker1" +group.groupId = nil +group.units[1].unitId = nil +group.units[1].unitName = newName +group.country = country +group.category = 'AIRPLANE' +group.units[1].x = cloneGroupPos.x +group.units[1].y = cloneGroupPos.z +group.units[1].z = cloneGroupPos.y +group.units[1].speed = 999999 + + +Group.destroy(Group.getByName(groupName)) +mist.dynAdd(group) +--timer.scheduleFunction(mist.dynAdd,group, timer.getTime() + 0.00000000001) + +end + + +function tankers.startEnrouteTankingTest (vec3) -- this is the one that works well, clone an existing tanker that is currently mission editor tanking + + --tankers.setFrequency(260) + --tankers.setTacan(41, true) + --tankers.changeCallsign() + route = mist.getGroupRoute(tankers.tankerName, true) + unit = Unit.getByName(tankers.tankerName) + cvn = Unit.getByName("CVN") + + local cvnPos = cvn:getPosition().p + + local vec3 = vec3 or cvnPos + route[1].x = unit:getPosition().p.x + route[1].y = unit:getPosition().p.z + route[2].x = vec3.x + route[2].y = vec3.z + route[2].z = vec3.y + 100 + + mist.goRoute(tankers.tankerName , route ) +end + +function tankers.hyperSpace (vec3) -- this is the one that works well, clone an existing tanker that is currently mission editor tanking +local groupName = 'TankerClone' -- Name of the group in the ME +local cloneGroupPos = Unit.getByName(groupName):getPosition().p +cvn = Unit.getByName("CVN") +local cvnPos = cvn:getPosition().p + + +group = mist.getGroupData(groupName) +group.route = { + ["points"] = + { + [1] = + { + ["alt"] = 2133.6, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["speed"] = 179.86111111111, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["number"] = 1, + ["auto"] = false, + ["id"] = "ControlledTask", + ["enabled"] = true, + ["params"] = + { + ["task"] = + { + ["id"] = "Tanker", + ["params"] = + { + }, -- end of ["params"] + }, -- end of ["task"] + ["stopCondition"] = + { + ["duration"] = 900, + }, -- end of ["stopCondition"] + }, -- end of ["params"] + }, -- end of [1] + [2] = + { + ["number"] = 2, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "ActivateBeacon", + ["params"] = + { + ["type"] = 4, + ["AA"] = false, + ["callsign"] = "TKR", + ["modeChannel"] = "Y", + ["channel"] = 71, + ["system"] = 5, + ["unitId"] = 188, + ["bearing"] = true, + ["frequency"] = 1032000000, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + }, -- end of [2] + [3] = + { + ["number"] = 3, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "SetFrequency", + ["params"] = + { + ["power"] = 10, + ["modulation"] = 0, + ["frequency"] = 260000000, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + }, -- end of [3] + [4] = + { + ["number"] = 4, + ["auto"] = false, + ["id"] = "WrappedAction", + ["enabled"] = true, + ["params"] = + { + ["action"] = + { + ["id"] = "SetInvisible", + ["params"] = + { + ["value"] = true, + }, -- end of ["params"] + }, -- end of ["action"] + }, -- end of ["params"] + }, -- end of [4] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 96.50677034026, + ["ETA_locked"] = false, + ["y"] = cvnPos.z, + ["x"] = cvnPos.x, + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + } + +--group.units[1].type = "S-3B Tanker" +group.groupName = "Tanker1" +group.groupId = nil +group.units[1].unitId = nil +group.units[1].unitName = newName +group.country = country +group.category = 'AIRPLANE' +group.units[1].x = cvnPos.x-100 +group.units[1].y = cvnPos.z +group.units[1].z = cloneGroupPos.y +group.units[1].heading = 0.000000000001 +group.units[1].speed = 300 + +--Group.destroy(Group.getByName(groupName)) +mist.dynAdd(group) +group.groupName = "Tanker2" +group.units[1].x = cvnPos.x+100 +group.units[1].heading = 3.1415926537 +group.units[1].y = cvnPos.z +mist.dynAdd(group) + +end + + +handler = {} + +local function protectedCall(...) + local status, retval = pcall(...) + if not status then + + end +end + +function tankers.eventHandler (event) + if (26 == event.id) then --this is when someone types into a mark + local vec3 = mist.utils.makeVec3GL(event.pos) + tankers.startEnrouteTankingTest (vec3) + end +end + +function handler:onEvent(event) + protectedCall(tankers.eventHandler, event) +end + +do + --world.addEventHandler(handler) + world.addEventHandler(handler) +end + +do + longRangeShots = missionCommands.addSubMenu("Dynamic Tanking") + missionCommands.addCommand ("Hyperspace entry", longRangeShots, tankers.hyperSpace) + missionCommands.addCommand ("Start tanking", longRangeShots, tankers.startEnrouteTankingTest) + missionCommands.addCommand ("Frequency change approved", longRangeShots, tankers.setFrequency) + missionCommands.addCommand ("Callsign change approved", longRangeShots, tankers.changeCallsign) + missionCommands.addCommand ("Tacan change approved", longRangeShots, tankers.setTacan) + missionCommands.addCommand ("Start a new tanker", longRangeShots, tankers.newTanker) + missionCommands.addCommand ("Rejoin on a unit", longRangeShots, tankers.followInFront) + missionCommands.addCommand ("Rejoin close", longRangeShots, tankers.followInFrontClose) + + +end + +tankers.notify("tankers.lua loaded",2) \ No newline at end of file diff --git a/scripts/forceBubble.lua b/scripts/forceBubble.lua new file mode 100644 index 00000000..803e887b --- /dev/null +++ b/scripts/forceBubble.lua @@ -0,0 +1,112 @@ +--Spawn a SAM integrated with IADS +--Spawn a normal SAM +--SAM bubble shields + +forceBub = {} +forceBub.handler = {} +forceBub.missileList = {} +forceBub.missilesActive = 0 +forceBub.shieldOn = false + +function forceBub.notify(message, displayFor) + trigger.action.outText(message, displayFor, true) +end + +function forceBub.setShield() + forceBub.notify("Shield on", 2) +end + +function forceBub.stopShield() + forceBub.shieldOn = false +end + + + +local function protectedCall(...) + local status, retval = pcall(...) + if not status then + --rf.notify("Caught error " .. retval,2) + end +end + +function forceBub.handler:onEvent(event) + protectedCall(forceBub.eventHandler, event) +end + +function forceBub.checkMissiles () + local currentTime = timer.getTime() + if forceBub.missilesActive > 0 then + for index, data in pairs(forceBub.missileList) do + output = mist.utils.tableShow(forceBub.missileList[index]) + if forceBub.missileList[index].exists == true then + if Object.isExist(forceBub.missileList[index].weapon) == true then + forceBub.missileList[index].pos = forceBub.missileList[index].weapon:getPosition() + + + local missilePosition = forceBub.missileList[index].pos.p + + unit = Unit.getByName("Test") + local unitPosition = unit:getPosition().p + + local distance = mist.utils.get3DDist(unitPosition , missilePosition ) + forceBub.notify(distance,1) + + if forceBub.shieldOn == true and distance < 100 then --this distance is the sweet spot any less and you probably take damage and die, less than 75 death + + trigger.action.explosion(missilePosition , 1) --just blows up the missile + + end + + + else + forceBub.missileList[index] = nil + forceBub.missilesActive = forceBub.missilesActive - 1 + end + else + end + + end + end + timer.scheduleFunction(forceBub.checkMisProtectCall,{},currentTime + 0.01) +end + + + +function forceBub.eventHandler (event) + --forceBub.notify(mist.utils.tableShow(event),10) + if (event.id == 1) then + --check if weapon is a missile + --rf.notify("Missile fired id " .. event.weapon.id_ ,2) + forceBub.notify(mist.utils.tableShow(Weapon.getDesc(event.weapon)),10) + if Weapon.getDesc(event.weapon).missileCategory == 2 then + local newMis = {} + newMis.id = event.weapon.id_ + newMis.pos = event.weapon:getPosition() + newMis.weapon = event.weapon + newMis.exists = Object.isExist(newMis.weapon) + forceBub.missileList[event.weapon.id_] = newMis + forceBub.missilesActive = forceBub.missilesActive + 1 + end + end +end + +function forceBub.checkMisProtectCall() + protectedCall(forceBub.checkMissiles,{}) +end + +function forceBub.setShield() + forceBub.shieldOn = true +end + +do + forceField = missionCommands.addSubMenu("Force Field") + missionCommands.addCommand ("Forcefield on", forceField, forceBub.setShield) + missionCommands.addCommand ("Stop Field", forceField, forceBub.stopShield) +end + +do + world.addEventHandler(forceBub.handler) +end + +protectedCall(forceBub.checkMissiles,{}) +forceBub.notify("forceBubble.lua loaded", 2) \ No newline at end of file diff --git a/scripts/poleGen.lua b/scripts/poleGen.lua new file mode 100644 index 00000000..16b9e336 --- /dev/null +++ b/scripts/poleGen.lua @@ -0,0 +1,628 @@ +--max range, altitude and it fails? +--shoot right up +--fix sa10 and sa 11 + +--different static layouts on a carrier depending on what is going on +--guns on a static ship at sea? + + +pg = {} +handler = {} +pg.name = "Sam" +pg.cloneName = "Clone" +pg.fakeTargetName = "Player" +pg.samCounter = 1 +pg.droneAlt = 20000 +pg.delay = 40 +pg.missileSpeed = 565 +pg.samLoc = {} +pg.samLoc.x = 1 +pg.samLoc.y = 1 +pg.samLoc.z = 1 +pg.missilesActive = 0 +pg.droneName = nil +pg.droneSpeed = 300 +pg.hidden = false +pg.samDB = {[1] = {["missileDelay"] = 40, ["missileSpeed"] = 770}, + [2] = {["missileDelay"] = 40, ["missileSpeed"] = 770}, + [3] = {["missileDelay"] = 120, ["missileSpeed"] = 550}, + [4] = {["missileDelay"] = 40, ["missileSpeed"] = 770}, + [5] = {["missileDelay"] = 65, ["missileSpeed"] = 770}, + [6] = {["missileDelay"] = 60, ["missileSpeed"] = 500}, + [7] = {["missileDelay"] = 40, ["missileSpeed"] = 770}, + [8] = {["missileDelay"] = 40, ["missileSpeed"] = 770}, + [9] = {["missileDelay"] = 40, ["missileSpeed"] = 770}, + [10] = {["missileDelay"] = 60, ["missileSpeed"] = 1400}, + } + +function pg.notify(message, displayFor) + trigger.action.outText(message, displayFor, false) +end + + +function pg.fakeSam(vec3) + + playerTarget = Unit.getByName(pg.fakeTargetName) + pointFakeTarget = playerTarget:getPosition().p + vec3 = vec3 or pg.samLoc + + vecSub = mist.vec.sub(pointFakeTarget , vec3) + planeHeading = mist.utils.getDir(vecSub) + missileType = 2 + pg.spawnDrone (vec3,planeHeading,playerTarget,missileType) + + --pg.notify("FakeSam Ran", 10) + + targetID = Group.getByName("TargetDrone" .. pg.samCounter):getUnit(1):getID() + samGroup = Group.getByName("poleGenerator" .. pg.samCounter) + vars = {[1] = targetID, [2] = samGroup} + timer.scheduleFunction(pg.attack ,vars, timer.getTime() + 1) + pg.samCounter = pg.samCounter + 1 + +end + + +function pg.spawnSamSA2 (vec3,heading) + --where + --name + group = {} + group.groupName = "poleGenerator" .. pg.samCounter + group.units = { + [1] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["hidden"] = pg.hidden, + ["type"] = "S_75M_Volhov", + --["unitId"] = 35, + ["y"] = vec3.z-40, + ["x"] = vec3.x-40, + --["name"] = "Ground-1-2", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [1] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "SNR_75V", + --["unitId"] = 34, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + } + group.hidden = pg.hidden + group.category = "VEHICLE" + group.country = 54 + mist.dynAdd(group) + --heading +end + +function pg.spawnSamSA3 (vec3,heading) + --where + --name + group = {} + group.groupName = "poleGenerator" .. pg.samCounter + group.units = { + [1] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["hidden"] = pg.hidden, + ["type"] = "snr s-125 tr", + --["unitId"] = 35, + ["y"] = vec3.z-40, + ["x"] = vec3.x-40, + --["name"] = "Ground-1-2", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [1] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "5p73 s-125 ln", + --["unitId"] = 34, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + } + group.hidden = pg.hidden + group.category = "VEHICLE" + group.country = 54 + mist.dynAdd(group) + --heading +end + +function pg.spawnSamSA5 (vec3,heading) + --where + --name + group = {} + group.groupName = "poleGenerator" .. pg.samCounter + group.units = { + [1] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["hidden"] = pg.hidden, + ["type"] = "RPC_5N62V", + --["unitId"] = 35, + ["y"] = vec3.z-40, + ["x"] = vec3.x-40, + --["name"] = "Ground-1-2", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [1] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "RLS_19J6", + --["unitId"] = 34, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + [3] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "S-200_Launcher", + --["unitId"] = 34, + ["y"] = vec3.z-80, + ["x"] = vec3.x-80, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [3] + } + group.hidden = pg.hidden + group.category = "VEHICLE" + group.country = 54 + mist.dynAdd(group) + --heading +end + +function pg.spawnSamSA6 (vec3,heading) + --where + --name + group = {} + group.groupName = "poleGenerator" .. pg.samCounter + group.units = { + [1] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["hidden"] = pg.hidden, + ["type"] = "Kub 1S91 str", + --["unitId"] = 35, + ["y"] = vec3.z-40, + ["x"] = vec3.x-40, + --["name"] = "Ground-1-2", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [1] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "Kub 2P25 ln", + --["unitId"] = 34, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + } + group.hidden = pg.hidden + group.category = "VEHICLE" + group.country = 54 + mist.dynAdd(group) + --heading +end + +function pg.spawnSamSA10 (vec3,heading) + --where + --name + group = {} + group.groupName = "poleGenerator" .. pg.samCounter + group.units = { + [1] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["hidden"] = pg.hidden, + ["type"] = "S-300PS 40B6M tr", + --["unitId"] = 35, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-2", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [1] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "S-300PS 64H6E sr", + --["unitId"] = 34, + ["y"] = vec3.z-10, + ["x"] = vec3.x-10, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + [3] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "S-300PS 54K6 cp", + --["unitId"] = 34, + ["y"] = vec3.z-20, + ["x"] = vec3.x-20, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [3] + [4] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "S-300PS 5P85C ln", + --["unitId"] = 34, + ["y"] = vec3.z-40, + ["x"] = vec3.x-40, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [4] + } + group.hidden = pg.hidden + group.category = "VEHICLE" + group.country = 54 + mist.dynAdd(group) + --heading +end + +function pg.spawnSamSA11 (vec3,heading) + --where + --name + group = {} + group.groupName = "poleGenerator" .. pg.samCounter + group.units = { + [1] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["hidden"] = pg.hidden, + ["type"] = "SA-11 Buk SR 9S18M1", + --["unitId"] = 35, + ["y"] = vec3.z-40, + ["x"] = vec3.x-40, + --["name"] = "Ground-1-2", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [1] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "SA-11 Buk CC 9S470M1", + --["unitId"] = 34, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + [2] = + { + ["skill"] = "High", + ["coldAtStart"] = false, + ["type"] = "SA-11 Buk LN 9A310M1", + --["unitId"] = 34, + ["y"] = vec3.z, + ["x"] = vec3.x, + --["name"] = "Ground-1-1", + ["heading"] = heading+math.pi, + ["playerCanDrive"] = false, + }, -- end of [2] + } + group.hidden = pg.hidden + group.category = "VEHICLE" + group.country = 54 + mist.dynAdd(group) + --heading +end + + + +function pg.spawnDrone(vec3,planeHeading,playerTarget,missileType) + -- where is the plane going to be in x seconds + playerTargetPos = playerTarget:getPosition().p + futurePlayerTargetPos = playerTargetPos + playerMotionVec = Object.getVelocity(playerTarget) + + --work out what type of SAM we are shooting to work out the delay, missile speed etc + + if missileType == 2 then + pg.delay = pg.samDB[2].missileDelay + pg.missileSpeed = pg.samDB[2].missileSpeed + elseif missileType == 3 then + pg.delay = pg.samDB[3].missileDelay + pg.missileSpeed = pg.samDB[3].missileSpeed + elseif missileType == 5 then + pg.delay = pg.samDB[5].missileDelay + pg.missileSpeed = pg.samDB[5].missileSpeed + elseif missileType == 6 then + pg.delay = pg.samDB[6].missileDelay + pg.missileSpeed = pg.samDB[5].missileSpeed + elseif missileType == 10 then + pg.delay = pg.samDB[10].missileDelay + pg.missileSpeed = pg.samDB[10].missileSpeed + elseif missileType == 11 then + pg.delay = pg.samDB[11].missileDelay + pg.missileSpeed = pg.samDB[11].missileSpeed + else --assume SA2 + pg.delay = pg.samDB[2].missileDelay + pg.missileSpeed = pg.samDB[2].missileSpeed + end + + futurePlayerTargetPos.x = playerTargetPos.x + playerMotionVec.x*pg.delay + futurePlayerTargetPos.y = playerTargetPos.y + playerMotionVec.y*pg.delay + futurePlayerTargetPos.z = playerTargetPos.z + playerMotionVec.z*pg.delay + droneTurnPoint = mist.projectPoint(futurePlayerTargetPos, 10000 ,planeHeading+math.pi) + --this is where the plane will be when the missile is launched + + + + --pythago to get hyp + --x^2 + y^x = hyp^2 + x = mist.utils.get2DDist(futurePlayerTargetPos,vec3) + + y = playerTargetPos.y + --pg.notify(y,5) + hyp = math.sqrt(x^2 + y^2) + roughFlightTime = hyp /pg.missileSpeed-- distance / speed + + futurePlayerTargetPos.x = futurePlayerTargetPos.x + playerMotionVec.x*roughFlightTime + futurePlayerTargetPos.y = futurePlayerTargetPos.y + playerMotionVec.y*roughFlightTime + futurePlayerTargetPos.z = futurePlayerTargetPos.z + playerMotionVec.z*roughFlightTime + --this is where the plane will be when the missile arrives at its altitude + + --now we need to work out where the drone is going to go + vecSub = mist.vec.sub(vec3,futurePlayerTargetPos) + heading = mist.utils.getDir(vecSub) --heading between picked location and future pos + extendDistance = x + 10000 + + alt = (((futurePlayerTargetPos.y) * extendDistance)/x) + + droneAtTimePos = mist.projectPoint(vec3, extendDistance ,heading +math.pi) + + extendDistance = extendDistance + pg.droneSpeed*roughFlightTime + droneAtStartPos = mist.projectPoint(vec3, extendDistance ,heading +math.pi) + --we want to curve the missile in the players direction + --planeHeading + + pg.makeDrone(droneAtStartPos,heading, droneAtTimePos, futurePlayerTargetPos,alt,droneTurnPoint) + if missileType == 2 then + pg.spawnSamSA2 (vec3,heading) + elseif missileType == 3 then + pg.spawnSamSA3 (vec3,heading) + elseif missileType == 5 then + pg.spawnSamSA5 (vec3,heading) + elseif missileType == 6 then + pg.spawnSamSA6 (vec3,heading) + elseif missileType == 10 then + pg.spawnSamSA10 (vec3,heading) + else --assume SA2 + pg.spawnSamSA2 (vec3,heading) + end + + +end + +function pg.makeDrone(spawnVec,heading, routeVec, nextRouteVec,alt,droneTurnPoint) + --this spawns in the drone + group = DroneClone + group.groupName = "TargetDrone" .. pg.samCounter + group.groupId = nil + group.units[1].unitId = nil + group.units[1].unitName = nil + group.units[1].y = spawnVec.z + group.units[1].x = spawnVec.x + group.units[1].heading = heading + group.units[1].alt = alt + group.route["points"][2] = group.route["points"][1] + group.route["points"][3] = group.route["points"][1] + group.route["points"][1]["y"] = routeVec.z + group.route["points"][1]["x"] = routeVec.x + group.route["points"][1]["alt"] = alt + group.route["points"][2]["y"] = nextRouteVec.z + group.route["points"][2]["x"] = nextRouteVec.x + group.route["points"][2]["alt"] = alt + group.route["points"][3]["y"] = droneTurnPoint.z + group.route["points"][3]["x"] = droneTurnPoint.x + group.route["points"][3]["alt"] = alt + group.countryId = 56 + group.category = 'AIRPLANE' + mist.dynAdd(group) +end + + +function pg.attack (vars) + targetID = vars[1] + samGroup = vars[2] + AttackUnit = { + id = 'AttackUnit', + params = { + unitId = targetID, + attackQtyLimit = true, + attackQty = 1, + } + } + + local controller = samGroup:getController() + controller:pushTask(AttackUnit) +end + + + +function pg.radarOff () + group = Group.getByName(pg.name) + local controller = group:getController() + controller:setOption(9,1) +end + +function pg.radarOn () + group = Group.getByName(pg.name) + local controller = group:getController() + controller:setOption(9,0) +end + + DroneClone= + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["task"] = "Reconnaissance", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 2000, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["speed"] = 82.222222222222, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + {}, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 0, + ["x"] = 0, + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [1] + [2] = + { + ["alt"] = 2000, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["speed"] = 82.222222222222, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 157.20107538291, + ["ETA_locked"] = false, + ["y"] = 0, + ["x"] = 0, + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [2] + }, -- end of ["points"] + }, -- end of ["route"] + --["groupId"] = 1, + ["hidden"] = pg.hidden, + ["units"] = + { + [1] = + { + ["alt"] = 2000, + ["alt_type"] = "BARO", + ["livery_id"] = "'camo' scheme", + ["skill"] = "High", + ["speed"] = 82.222222222222, + ["type"] = "MQ-9 Reaper", + --["unitId"] = 1, + --["psi"] = -3.129323330636, + ["y"] = 0, + ["x"] = 0, + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 1300, + ["flare"] = 0, + ["chaff"] = 0, + ["gun"] = 100, + }, -- end of ["payload"] + ["heading"] = 0.5, + ["callsign"] = + { + [1] = 1, + [2] = 1, + [3] = 1, + ["name"] = "Enfield11", + }, -- end of ["callsign"] + ["onboard_num"] = "010", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 0, + ["x"] = 0, + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 124, + } + + +local function protectedCall(...) + local status, retval = pcall(...) + if not status then + + end +end + +function handler:onEvent(event) + protectedCall(pg.eventHandler, event) +end + +function pg.eventHandler (event) + if (26 == event.id) then --this is when someone types into a mark + local vec3 = mist.utils.makeVec3GL(event.pos) + pg.fakeSam (vec3) + end +end + +function handler:onEvent(event) + protectedCall(pg.eventHandler, event) +end + + +do + longRangeShots = missionCommands.addSubMenu("SAM") + missionCommands.addCommand ("Generate pole", longRangeShots, pg.fakeSam) + world.addEventHandler(handler) +end + +pg.notify("poleGen.lua",10) + diff --git a/scripts/raisedShots.lua b/scripts/raisedShots.lua new file mode 100644 index 00000000..95fdc8f8 --- /dev/null +++ b/scripts/raisedShots.lua @@ -0,0 +1,319 @@ +shots = {} --https://www.youtube.com/watch?v=XNtTEibFvlQ mandatory terrible listening +shots.shooterName = "TestInfantry" +shots.targetName = "TestTarget1" + +function shots.notify(message, displayFor) + trigger.action.outText(message, displayFor, false) +end + + + +--infantry + +function shots.set556 () --red + roundVelocity = 910 + unitBarrelHeight = 1 + shotsToFire = 5 + shotDelay = 4.5 + shots.notify("5.56 M4 Georgia", 2) + shots.fire() +end + +function shots.set556SAW () --red + roundVelocity = 915 + unitBarrelHeight = 0.4 + shotsToFire = 5 + shotDelay = 4.5 + shots.notify("5.56 M249 SAW", 2) + shots.fire() + +end + +function shots.setAk74() --red + roundVelocity = 900 + unitBarrelHeight = 0.9 + shotsToFire = 5 + shotDelay = 4.5 + shots.notify("Ak74", 2) + shots.fire() +end + +--technicals + +function shots.hmmwv() --red + roundVelocity = 928 + unitBarrelHeight = 2.6 + shotsToFire = 5 + shotDelay = 2.5 + shots.notify("Humm drumm Vee", 2) + shots.fire() + shots.notify(unitBarrelHeight,2) + +end + +function shots.technicalDHSKA() --green + roundVelocity = 928 + unitBarrelHeight = 2.2 + shotsToFire = 5 + shotDelay = 2.5 + shots.notify("technicalDHSKA", 2) + shots.fire() + shots.notify(unitBarrelHeight,2) + +end + +function shots.cobra() --green + roundVelocity = 928 + unitBarrelHeight = 2.85 + shotsToFire = 5 + shotDelay = 2.6 + shots.notify("Cobra", 2) + shots.fire() + shots.notify(unitBarrelHeight,2) + +end +--IFVs + +function shots.setWarrior() --white + roundVelocity = 1070 + unitBarrelHeight = 2.28 + shotsToFire = 3 + shotDelay = 6.3 + shots.fire() +end + +function shots.setBMP2() --red + roundVelocity = 970 + unitBarrelHeight = 1.95 + shotsToFire = 3 + shotDelay = 6 + shots.fire() +end + +--Tanks + +function shots.m1a1() --red + roundVelocity = 928 + unitBarrelHeight = 2.15 + shotsToFire = 5 + shotDelay = 3 + shots.notify("Abrams 50 cal", 2) + shots.fire() + shots.notify(unitBarrelHeight,2) + +end + +function shots.t55() --red and green + roundVelocity = 928 + unitBarrelHeight = 1.75 + shotsToFire = 5 + shotDelay = 2.6 + shots.notify("T-72B", 2) + shots.fire() + shots.notify(unitBarrelHeight,2) +end + +---aaaaaaaaaaaaaaaa + +function shots.ZSU57() --red + roundVelocity = 1070 + shotsToFire = 2 + shotDelay = 10.5 + shots.notify("ZSU57", 2) + unitMaxRange = 6000 + shots.fireAAA() +end + +function shots.ZSU23() --red + roundVelocity = 1050 + shotsToFire = 2 + shotDelay = 12 + shots.notify("ZSU23", 2) + unitMaxRange = 2000 + shots.fireAAA() +end + +function shots.vulcan() --red + roundVelocity = 1030 + shotsToFire = 5 + shotDelay = 5 + shots.notify("Vulcan M163", 2) + unitMaxRange = 1500 + shots.fireAAA() +end + +function shots.flak18() --red and green + roundVelocity = 870 + shotsToFire = 1 + shotDelay = 10.5 + shots.notify("Flak 18", 2) + unitMaxRange = 4000 + shots.fireAAA() +end + + + + +-- This one is really obvious, however I set towards the end of this file the "parameters" of the shots. +function shots.fire() + unit = Unit.getByName(shots.shooterName) + target = Unit.getByName(shots.targetName) + local targetMotionVec = Object.getVelocity(target) --if you don't want to do this i.e. shoot a point send a nil or a vec3 of 0's + --local targetMotionVec = nil + local targetPos = target:getPosition().p + shots.calculateAngle(roundVelocity, unit, targetPos, unitBarrelHeight, shotsToFire,shotDelay, targetMotionVec) +end + +--main bit that does the maths for simulating a "roughly level" fire fight, not to be used when aiming AAA at aircraft +function shots.calculateAngle(v, unit, targetPos, unitBarrelHeight, shotsToFire,shotDelay, targetMotionVector) + --v muzzle velocity + --unit is unit object you want shooting + --targetPos is a position on the ground, doesn't have to be a targets actual location + --unitBarrelHeigh is the height the gun is at when it fires + --shotsToFire is how many rounds to shoot, 5 is a nice number except for large calibre slow guns + --shotDelay how long it on average takes to aim from scratch at something and shoot, mostly used in aiming lead + --targetMotionVector a vec3 of the targets motion if nil just shoots at a spot + + g = 9.81 -- gravity, change if on the moon veltro you comment reading prick + + local unitPos = unit:getPosition().p + local x = mist.utils.get2DDist(unitPos,targetPos) -- horizontal range + local x3d = mist.utils.get3DDist(unitPos,targetPos) -- slant range + + y = targetPos.y - unitPos.y + y = y - unitBarrelHeight + + --works out some stuff for trig later, like x,y and hypoteneueussueee + + if targetMotionVector == nil then + --no moving? nothing to ammend + else --work out where target will be when the bullet arrives + shotDelay = shotDelay + x3d/v --time taken to aim and time for bullet to fly to spot + newPosition = mist.utils.tableShow(targetMotionVector) + targetPos.x = targetPos.x + targetMotionVector.x*shotDelay + targetPos.y = targetPos.y + targetMotionVector.y*shotDelay + targetPos.z = targetPos.z + targetMotionVector.z*shotDelay + end + + x = x - 10 --we actually are aiming 10m in front always so need to remove this + + local inner = v^4 - g * (g * x^2 + 2 * y * v^2) -- this is the inner bit of the quadratic equation for ease of code + + if inner < 0 then + -- No solution exists for these parameters, too far away do nothing we can't hit it, saves us crashing if sqrt of negative + else + local angle2 = math.atan((v^2 - math.sqrt(inner)) / (g * x)) -- do the whole quadratic equation + -- we didn't need to do the +- sqrt b^2..... bits as we care about the flat path not the one shot miles up falling down + + local aimUp = 10 * math.tan(angle2)*math.cos(angle2) -- we have to tell dcs to "aim up" at a point 10m ahead of it, this is distance * tan(angle) , so where the fuck has the cos come from? That is because aim correction for shooting up and down is basically modfied by cos(angle) so lazy correction and dcs can't shoot vertically up + local xPosDifference = (targetPos.x - unitPos.x) + local zPosDifference = (targetPos.z - unitPos.z) + local hyp = math.sqrt((xPosDifference*xPosDifference) + (zPosDifference*zPosDifference)) + xPosDifference = (xPosDifference /hyp) * 10 + zPosDifference = (zPosDifference / hyp) * 10 + + unitPos.x = unitPos.x + xPosDifference + unitPos.z = unitPos.z + zPosDifference + + --that was all basic trig maths + + local controller = unit:getController() + FireAtPoint = { + id = 'FireAtPoint', + params = { + point = {x = unitPos.x, y = unitPos.z}, + radius = 0.0001, + expendQty = shotsToFire, + expendQtyEnabled = true, + altitude = unitPos.y+unitBarrelHeight +aimUp, --this is a realtive to sea level shot, so we can shoot down + alt_type = 0, --0 = sea level, 1 = ground level + } + } + controller:pushTask(FireAtPoint) --FIREEEEEE + end +end + + +function shots.fireAAA() + unit = Unit.getByName(shots.shooterName) + target = Unit.getByName(shots.targetName) + targetMotionVec = Object.getVelocity(target) --if you don't want to do this i.e. shoot a point send a nil or a vec3 of 0's + --local targetMotionVec = nil + targetPos = target:getPosition().p + shots.aaa(roundVelocity, unit, unitMaxRange, targetPos, shotsToFire,shotDelay, targetMotionVec) +end + +--aaa fires almost straight up, no line of sight fakery needed or working out lobbing bullets onto random points +--if in range just needs to be told to shoot where the target will be in a few seconds +--if out of range, we just need to extrapolate back and fire inside max range and randomise the up and down, then let it miss + +function shots.aaa(v, unit, unitMaxRange, targetPos, shotsToFire,shotDelay, targetMotionVector) + local unitPos = unit:getPosition().p + local x = mist.utils.get2DDist(unitPos,targetPos) -- horizontal range + local x3d = mist.utils.get3DDist(unitPos,targetPos) -- slant range + + if x3d > unitMaxRange then + if targetMotionVector == nil then + --no moving? nothing to ammend + else --work out where target will be when the bullet arrives + shotDelay = shotDelay + x3d/(v/2) --time taken to aim and time for bullet to fly to spot long range roughly 50% slowdown + newPosition = mist.utils.tableShow(targetMotionVector) + targetPos.x = targetPos.x + targetMotionVector.x*shotDelay + targetPos.y = targetPos.y + targetMotionVector.y*shotDelay + targetPos.z = targetPos.z + targetMotionVector.z*shotDelay + end + + difference = mist.vec.sub(targetPos,unitPos) + unitVec = mist.vec.getUnitVec(difference) + extendPath = mist.vec.scalar_mult(unitVec ,unitMaxRange) + targetPos = mist.vec.add(extendPath,unitPos) + + + local controller = unit:getController() + FireAtPoint = { + id = 'FireAtPoint', + params = { + point = {x = targetPos.x, y = targetPos.z}, + radius = 0.0001, + expendQty = shotsToFire, + expendQtyEnabled = true, + altitude = targetPos.y+math.random(1,500), --this is a realtive to sea level shot, so we can shoot down + alt_type = 0, --0 = sea level, 1 = ground level + } + } + controller:pushTask(FireAtPoint) --FIREEEEEE + else + if targetMotionVector == nil then + --no moving? nothing to ammend + else --work out where target will be when the bullet arrives + shotDelay = shotDelay + x3d/v --time taken to aim and time for bullet to fly to spot + newPosition = mist.utils.tableShow(targetMotionVector) + targetPos.x = targetPos.x + targetMotionVector.x*shotDelay + targetPos.y = targetPos.y + targetMotionVector.y*shotDelay + targetPos.z = targetPos.z + targetMotionVector.z*shotDelay + end + + local controller = unit:getController() + FireAtPoint = { + id = 'FireAtPoint', + params = { + point = {x = targetPos.x, y = targetPos.z}, + radius = 0.0001, + expendQty = shotsToFire, + expendQtyEnabled = true, + altitude = targetPos.y, --this is a realtive to sea level shot, so we can shoot down + alt_type = 0, --0 = sea level, 1 = ground level + } + } + controller:pushTask(FireAtPoint) --FIREEEEEE + end +end + + +do + longRangeShots = missionCommands.addSubMenu("Firefight") + missionCommands.addCommand ("Fire", longRangeShots, shots.vulcan) + +end + +shots.notify("raisedShots.lua ran", 2) \ No newline at end of file diff --git a/scripts/samSimulator.lua b/scripts/samSimulator.lua new file mode 100644 index 00000000..bc17b69a --- /dev/null +++ b/scripts/samSimulator.lua @@ -0,0 +1,540 @@ +--Spawn a SAM integrated with IADS +--Spawn a normal SAM +--SAM bubble shields + +samSim = {} +samSim.samSuffix = 1 + +do -- needs to go early on + redIADS = SkynetIADS:create('Red') + redIADS:setUpdateInterval(5) + redIADS:activate() + --redIADS:addRadioMenu() +end + +function samSim.genSAten() --gens an SA 10 as you can imagine, + unit = Unit.getByName("Test") + local pointVec3Gl = unit:getPosition().p -- this is just to find where my aircraft is and whack an SA10 below it, lazy not relevant + local isHiddenCheck = math.random(100) + if isHiddenCheck > 10 then + isHidden = false + else + isHidden = true -- fairly obvious hides from F10 and F7 view + end + mist.dynAdd( + { + country = 'USSR', + category = 'vehicle', + name = "SAM " .. samSim.samSuffix, + groupName = "SAM " .. samSim.samSuffix, + groupId = 10000+samSim.samSuffix, + hidden = isHidden, + units = + { [1] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 40B6MD sr", --search radar needs to be first always for avoiding a skynet bug + ["y"] = pointVec3Gl.z + 50, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [1] + [2] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 40B6M tr", + ["y"] = pointVec3Gl.z, + ["x"] = pointVec3Gl.x, + ["heading"] = 4.7123889803847, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [2] + + [3] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 54K6 cp", + ["y"] = pointVec3Gl.z + 100, + ["x"] = pointVec3Gl.x, + ["heading"] = 3.1415926535898, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [3] + [4] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 64H6E sr", + ["y"] = pointVec3Gl.z - 50, + ["x"] = pointVec3Gl.x, + ["heading"] = 3.1415926535898, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [4] + [5] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 5P85C ln", + ["y"] = pointVec3Gl.z +200 , + ["x"] = pointVec3Gl.x, + ["heading"] = 3.1415926535898, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [5] + [6] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 5P85C ln", + ["y"] = pointVec3Gl.z -200, + ["x"] = pointVec3Gl.x, + ["heading"] = 3.3161255787892, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [6] + [7] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S-300PS 5P85C ln", + ["y"] = pointVec3Gl.z , + ["x"] = pointVec3Gl.x + 200, + ["heading"] = 2.9670597283904, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [7] + [8] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Excellent", + ["type"] = "S-300PS 5P85C ln", + ["y"] = pointVec3Gl.z, + ["x"] = pointVec3Gl.x -200, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [8] + [9] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "generator_5i57", + ["y"] = pointVec3Gl.z +200, + ["x"] = pointVec3Gl.x + 200, + ["heading"] = 6.1086523819802, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [9] + [10] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "ATZ-5", + ["y"] = pointVec3Gl.z -200, + ["x"] = pointVec3Gl.x -200, + ["heading"] = 0.17453292519943, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [10] + [11] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "ATZ-5", + ["y"] = pointVec3Gl.z +550, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [11] + [12] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "GAZ-66", + ["y"] = pointVec3Gl.z +580, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [12] + [13] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "ATZ-60_Maz", + ["y"] = pointVec3Gl.z +600, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [13] + [14] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "KAMAZ Truck", + ["y"] = pointVec3Gl.z +500, + ["x"] = pointVec3Gl.x + 20, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [14] + }, -- end of units + } -- end of function + ) + redIADS:addSAMSite("SAM " .. samSim.samSuffix) --skynet bit + local detectChance = math.random(50,90) + local goLiveRange = math.random(50,90) + local harmStop = math.random(2) + if harmStop == 1 then + harmStopping = true + else + harmStopping = false + end + redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setHARMDetectionChance(detectChance) -- doesn't bloody work no idea, don't care want to reinvent this myself + redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setGoLiveRangeInPercent(goLiveRange) -- doesn't bloody work no idea, don't care want to reinvent this myself + redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setCanEngageHARM(harmStopping) -- doesn't bloody work no idea, don't care want to reinvent this myself + + samSim.samSuffix = samSim.samSuffix + 1 +end + +function samSim.genSAtwo() + unit = Unit.getByName("Test") + local pointVec3Gl = unit:getPosition().p -- this is just to find where my aircraft is and whack an SA10 below it, lazy not relevant + + local isHiddenCheck = math.random(100) + if isHiddenCheck > 50 then + isHidden = false + else + isHidden = true + end + + mist.dynAdd( + { + country = 'USSR', + category = 'vehicle', + name = "SAM " .. samSim.samSuffix, + groupName = "SAM " .. samSim.samSuffix, + groupId = 10000+samSim.samSuffix, + hidden = isHidden, + units = + { + [1] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "SNR_75V", + ["y"] = pointVec3Gl.z, + ["x"] = pointVec3Gl.x, + ["heading"] = 4.7123889803847, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [1] + [2] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S_75M_Volhov", + ["y"] = pointVec3Gl.z + 50, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [2] + [3] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S_75M_Volhov", + ["y"] = pointVec3Gl.z + 100, + ["x"] = pointVec3Gl.x, + ["heading"] = 3.1415926535898, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [3] + [4] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S_75M_Volhov", + ["y"] = pointVec3Gl.z - 50, + ["x"] = pointVec3Gl.x, + ["heading"] = 3.1415926535898, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [4] + [5] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S_75M_Volhov", + ["y"] = pointVec3Gl.z +200 , + ["x"] = pointVec3Gl.x, + ["heading"] = 3.1415926535898, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [5] + [6] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "S_75M_Volhov", + ["y"] = pointVec3Gl.z -200, + ["x"] = pointVec3Gl.x, + ["heading"] = 3.3161255787892, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [6] + [7] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "SKP-11", + ["y"] = pointVec3Gl.z , + ["x"] = pointVec3Gl.x + 200, + ["heading"] = 2.9670597283904, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [7] + [8] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Excellent", + ["type"] = "SKP-11", + ["y"] = pointVec3Gl.z, + ["x"] = pointVec3Gl.x -200, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [8] + [9] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "p-19 s-125 sr", + ["y"] = pointVec3Gl.z +200, + ["x"] = pointVec3Gl.x + 200, + ["heading"] = 6.1086523819802, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [9] + [10] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "Ural-4320 APA-5D", + ["y"] = pointVec3Gl.z -200, + ["x"] = pointVec3Gl.x -200, + ["heading"] = 0.17453292519943, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [10] + [11] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "ATMZ-5", + ["y"] = pointVec3Gl.z +550, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [11] + [12] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "Ural-4320T", + ["y"] = pointVec3Gl.z +580, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [12] + [13] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "Ural-4320T", + ["y"] = pointVec3Gl.z +600, + ["x"] = pointVec3Gl.x, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [13] + [14] = + { + ["transportable"] = + { + ["randomTransportable"] = false, + }, -- end of ["transportable"] + ["skill"] = "Random", + ["type"] = "ATMZ-5", + ["y"] = pointVec3Gl.z +500, + ["x"] = pointVec3Gl.x + 20, + ["heading"] = 0, + ["playerCanDrive"] = true, + livery_id = "desert", + }, -- end of [14] + }, -- end of units + } -- end of function + ) + redIADS:addSAMSite("SAM " .. samSim.samSuffix) + local detectChance = math.random(75,100) + local goLiveRange = math.random(50,90) + redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setHARMDetectionChance(detectChance) + redIADS:getSAMSiteByGroupName("SAM " .. samSim.samSuffix):setGoLiveRangeInPercent(goLiveRange) + + samSim.samSuffix = samSim.samSuffix + 1 +end + +function samSim.genCMD() + unit = Unit.getByName("Test") + local pointVec3Gl = unit:getPosition().p + mist.dynAddStatic( + { + country = 'USSR', + category = 'Fortifications', + name = "CMD " .. samSim.samSuffix, + type = ".Command Center", + x = pointVec3Gl.x, + y = pointVec3Gl.z, + heading = math.pi*3/2, + } -- end of function + ) + nameToAdd = "CMD ".. samSim.samSuffix --.. " " .. "unit1" + local commandCenter = StaticObject.getByName(nameToAdd) + redIADS:addCommandCenter(commandCenter) + redIADS = SkynetIADS:create(nameToAdd) + redIADS:activate() + samSim.samSuffix = samSim.samSuffix + 1 +end + +function samSim.genEWR() + unit = Unit.getByName("Test") + local pointVec3Gl = unit:getPosition().p + mist.dynAdd( + { + country = 'USSR', + category = 'vehicle', + groupName = "EW " .. samSim.samSuffix, + name = "EW " .. samSim.samSuffix, + groupId = 20000+samSim.samSuffix, + units = + { + [1] = + { + ["skill"] = "Random", + ["type"] = "55G6 EWR", + ["y"] = pointVec3Gl.z, + ["x"] = pointVec3Gl.x, + livery_id = "", + ["heading"] = 0, + ["playerCanDrive"] = true, + }, + }, -- end of units + } -- end of function + ) + nameToAdd = "EW ".. samSim.samSuffix .. " " .. "unit1" -- oddly this is the unit name not the group, if you don't use this naming convention change it + redIADS:addEarlyWarningRadar(nameToAdd) + --redIADS:addEarlyWarningRadarsByPrefix("EW") + samSim.samSuffix = samSim.samSuffix + 1 +end + + + + +do + samSims = missionCommands.addSubMenu("Sam stuff") + missionCommands.addCommand ("Spawn SA 10", samSims, samSim.genSAten) + missionCommands.addCommand ("Spawn EWR", samSims, samSim.genEWR) + missionCommands.addCommand ("Spawn SA 2", samSims, samSim.genSAtwo) + missionCommands.addCommand ("Spawn Command Centre and activate", samSims, samSim.genCMD) +end \ No newline at end of file diff --git a/src/core/src/aircraft.cpp b/src/core/src/aircraft.cpp index 8b90ee4d..79f2694d 100644 --- a/src/core/src/aircraft.cpp +++ b/src/core/src/aircraft.cpp @@ -63,11 +63,13 @@ void Aircraft::changeAltitude(wstring change) void Aircraft::setTargetSpeed(double newTargetSpeed) { targetSpeed = newTargetSpeed; addMeasure(L"targetSpeed", json::value(targetSpeed)); - goToDestination(); + if (activeDestination != NULL) + goToDestination(); } void Aircraft::setTargetAltitude(double newTargetAltitude) { targetAltitude = newTargetAltitude; addMeasure(L"targetAltitude", json::value(targetAltitude)); - goToDestination(); + if (activeDestination != NULL) + goToDestination(); } \ No newline at end of file diff --git a/src/core/src/airunit.cpp b/src/core/src/airunit.cpp index b3c455be..08922240 100644 --- a/src/core/src/airunit.cpp +++ b/src/core/src/airunit.cpp @@ -149,7 +149,7 @@ bool AirUnit::updateActivePath(bool looping) /* Push the next destination in the queue to the front */ if (looping) pushActivePathBack(activePath.front()); - activePath.pop_front(); + popActivePathFront(); log(unitName + L" active path front popped"); return true; } diff --git a/src/core/src/server.cpp b/src/core/src/server.cpp index 3286cbaa..192a0440 100644 --- a/src/core/src/server.cpp +++ b/src/core/src/server.cpp @@ -179,7 +179,35 @@ void Server::handle_put(http_request request) void Server::task() { - http_listener listener(wstring(REST_ADDRESS) + L"/" + wstring(REST_URI)); + wstring address = wstring(REST_ADDRESS); + wstring modLocation; + char* buf = nullptr; + size_t sz = 0; + if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr) + { + std::ifstream ifstream(string(buf) + "\\olympus.json"); + std::stringstream ss; + ss << ifstream.rdbuf(); + std::error_code errorCode; + json::value config = json::value::parse(to_wstring(ss.str()), errorCode); + if (config.is_object() && config.has_object_field(L"server") && + config[L"server"].has_string_field(L"address") && config[L"server"].has_number_field(L"port")) + { + address = L"http://" + config[L"server"][L"address"].as_string() + L":" + to_wstring(config[L"server"][L"port"].as_number().to_int32()); + log(L"Starting server on " + address); + } + else + { + log(L"Error reading configuration file. Starting server on " + address); + } + free(buf); + } + else + { + log(L"DCSOLYMPUS_PATH environment variable is missing, starting server on " + address); + } + + http_listener listener(address + L"/" + wstring(REST_URI)); std::function handle_options = std::bind(&Server::handle_options, this, std::placeholders::_1); std::function handle_get = std::bind(&Server::handle_get, this, std::placeholders::_1); diff --git a/src/core/src/unit.cpp b/src/core/src/unit.cpp index 0f5fcdfd..5c14c6bd 100644 --- a/src/core/src/unit.cpp +++ b/src/core/src/unit.cpp @@ -201,7 +201,6 @@ void Unit::popActivePathFront() setActivePath(path); } - void Unit::setCoalitionID(int newCoalitionID) { if (newCoalitionID == 0) diff --git a/src/shared/include/defines.h b/src/shared/include/defines.h index 6a75f828..bb868841 100644 --- a/src/shared/include/defines.h +++ b/src/shared/include/defines.h @@ -1,12 +1,10 @@ #pragma once -#define VERSION "v0.0.1" +#define VERSION "v0.1.1" #define LOG_NAME "Olympus_log.txt" #define REST_ADDRESS L"http://localhost:30000" #define REST_URI L"olympus" #define UNITS_URI L"units" -#define UPDATE_URI L"update" -#define REFRESH_URI L"refresh" #define LOGS_URI L"logs" #define AIRBASES_URI L"airbases" #define BULLSEYE_URI L"bullseyes"