mirror of
https://github.com/Pax1601/DCSOlympus.git
synced 2025-10-29 16:56:34 +00:00
Compare commits
21 Commits
v0.4.10-al
...
v0.4.12-al
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
564a650403 | ||
|
|
0e403e8b74 | ||
|
|
840cdd9049 | ||
|
|
e5e7e9be14 | ||
|
|
e677968ba7 | ||
|
|
d24b955d52 | ||
|
|
48860ff514 | ||
|
|
0e78b7559b | ||
|
|
25edfc45e5 | ||
|
|
885825e5cc | ||
|
|
344413ae74 | ||
|
|
fa0643987b | ||
|
|
dcff462b32 | ||
|
|
fa04e5f8bb | ||
|
|
c8d5f9ce0e | ||
|
|
55642a89b1 | ||
|
|
f305aa3929 | ||
|
|
47ee88c339 | ||
|
|
022e041f68 | ||
|
|
0cc53890c1 | ||
|
|
e37f7a4977 |
49
README.md
49
README.md
@@ -19,6 +19,55 @@ The full feature list is simply too long to enumerate in a short summary but nee
|
||||
### Installing DCS Olympus
|
||||
A prebuilt installer will soon be released and available here
|
||||
|
||||
# Frequently Asked Questions
|
||||
### Can I join up and help out with the project? ###
|
||||
We are currently running towards first release in the very near future so we are not looking to add more people to the core team for the moment. However that does not mean we are not open to collaborations and help going forward, if you want to help for now we are committed to the free and open source model so feel free to check out the github, familiarize yourself with the project and maybe even start submitting pull requests for open issues.
|
||||
|
||||
Post-release we will be more interested in developing partnerships/collaborations with other teams/projects and potentially bringing in more team members, we will update this after release on how that will be managed!
|
||||
|
||||
### Can I be a beta/alpha-tester? ###
|
||||
With first public release planned for the very-near future we are fully committed to the final sprint, as such we will not be formally recruiting more people to test pre-release.
|
||||
|
||||
Post-release we will be eager to hear feedback of all forms and take in bug-reports, at this time after release we will begin considering bringing in more team members to test in development versions as we go.
|
||||
|
||||
### Do you have a roadmap? ###
|
||||
We do not have a roadmap no, we have a laundry list of things we are hoping to do.
|
||||
|
||||
These include but are not limited to:
|
||||
1) Enhancements to helicopter play
|
||||
2) More features around use of ground units
|
||||
3) More unique effects and behaviours
|
||||
4) ATC/AIC features
|
||||
5) Usability features like unit painters etc
|
||||
|
||||
However we cannot commit to specific features, feature release order, or timelines, please remember this isn't our job and we work on it in our free time because we love DCS
|
||||
|
||||
### Does Olympus support mods? ###
|
||||
Generally OIympus will not have any issues with other mods, however you may need to tell olympus about modded units in order to be able to dynamically spawn them etc
|
||||
|
||||
Keep in mind that any mods you do choose to spawn your players will need to have, some mod unit just appear as a su27 or leo2 etc. when a player is missing them, others can cause client crashes. So be smart about how you use them
|
||||
|
||||
### Is Olympus compatible with mission scripts? ###
|
||||
We have tried hard to keep Olympus from interfering with other scripts, we have tested with a variety of new and old mission scripts and generally expect it will not be an issue.
|
||||
|
||||
However we cannot foresee everything people come up with so we suggest testing with what you have in mind once olympus releases
|
||||
|
||||
### How does it work? ###
|
||||
The quick answer is magic.
|
||||
|
||||
The long answer is well all the code is there for you to read.
|
||||
|
||||
The middle answer is a bit like SRS does. Olympus consists of two parts.
|
||||
|
||||
(A) Olympus back end: A dll, run by DCS, that sends data out and gets commands in via a REST API;
|
||||
(B) Webserver exe: The one you start when starting the server via the desktop shortcut.
|
||||
|
||||
A and B never communicate when you connect the client you download the web page and some other minor stuff from B, and you get the DCS data from and send commands to A.
|
||||
|
||||
### How much does Olympus impact performance? ###
|
||||
Olympus by itself should not have a noticeable impact on server performance, however the ability for the user to spawn arbitrary units and command engagements means Olympus can be used in such a way that brings the game to it's knees.
|
||||
|
||||
Be cognizant of how you play, whether it's done through Olympus or the mission editor 500 MLRS units firing at once is not going to go over well with most servers
|
||||
|
||||
|
||||
|
||||
|
||||
24
client/@types/olympus/index.d.ts
vendored
24
client/@types/olympus/index.d.ts
vendored
@@ -128,7 +128,16 @@ declare module "constants/constants" {
|
||||
export const altitudeIncrements: {
|
||||
[key: string]: number;
|
||||
};
|
||||
export const minimapBoundaries: LatLng[][];
|
||||
export const minimapBoundaries: {
|
||||
Nevada: LatLng[];
|
||||
Syria: LatLng[];
|
||||
Caucasus: LatLng[];
|
||||
PersianGulf: LatLng[];
|
||||
MarianaIslands: LatLng[];
|
||||
Falklands: LatLng[];
|
||||
Normandy: LatLng[];
|
||||
SinaiMap: LatLng[];
|
||||
};
|
||||
export const mapBounds: {
|
||||
Syria: {
|
||||
bounds: LatLngBounds;
|
||||
@@ -2031,6 +2040,19 @@ declare module "unit/unitsmanager" {
|
||||
* @param category Either "Aircraft", "Helicopter", "GroundUnit", or "NavyUnit". Determines what class will be used to create the new unit accordingly.
|
||||
*/
|
||||
addUnit(ID: number, category: string): void;
|
||||
/** Sort units segregated groups based on controlling type and protection, if DCS-controlled
|
||||
*
|
||||
* @param units <Unit[]>
|
||||
* @returns Object
|
||||
*/
|
||||
segregateUnits(units: Unit[]): {
|
||||
[key: string]: [];
|
||||
};
|
||||
/**
|
||||
*
|
||||
* @param numOfProtectedUnits number
|
||||
*/
|
||||
showProtectedUnitsPopup(numOfProtectedUnits: number): void;
|
||||
/** Update the data of all the units. The data is directly decoded from the binary buffer received from the REST Server. This is necessary for performance and bandwidth reasons.
|
||||
*
|
||||
* @param buffer The arraybuffer, encoded according to the ICD defined in: TODO Add reference to ICD
|
||||
|
||||
@@ -112,5 +112,5 @@ function onListening() {
|
||||
debug('Listening on ' + bind);
|
||||
}
|
||||
|
||||
console.log("DCS Olympus server v0.4.9-alpha-rc1 started correctly!")
|
||||
console.log("DCS Olympus server v0.4.12-alpha-rc4 started correctly!")
|
||||
console.log("Waiting for connections...")
|
||||
|
||||
4
client/package-lock.json
generated
4
client/package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "DCSOlympus",
|
||||
"version": "v0.4.9-alpha-rc1",
|
||||
"version": "v0.4.12-alpha-rc4",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "DCSOlympus",
|
||||
"version": "v0.4.9-alpha-rc1",
|
||||
"version": "v0.4.12-alpha-rc4",
|
||||
"dependencies": {
|
||||
"@turf/turf": "^6.5.0",
|
||||
"body-parser": "^1.20.2",
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "DCSOlympus",
|
||||
"node-main": "./bin/www",
|
||||
"main": "http://localhost:3000",
|
||||
"version": "v0.4.9-alpha-rc1",
|
||||
"version": "v0.4.12-alpha-rc4",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "browserify .\\src\\index.ts --debug -o .\\public\\javascripts\\bundle.js -t [ babelify --global true --presets [ @babel/preset-env ] --extensions '.js'] -p [ tsify --noImplicitAny ] && copy.bat",
|
||||
|
||||
@@ -125,13 +125,6 @@ export class ControlTipsPlugin implements OlympusPlugin {
|
||||
"showIfHoveringOverAirbase": false,
|
||||
"showIfHoveringOverUnit": false
|
||||
},
|
||||
{
|
||||
"key": `Mouse2`,
|
||||
"action": `Quick options`,
|
||||
"showIfUnitSelected": false,
|
||||
"showIfHoveringOverAirbase": false,
|
||||
"showIfHoveringOverUnit": true
|
||||
},
|
||||
{
|
||||
"key": `Mouse2`,
|
||||
"action": `Airbase menu`,
|
||||
|
||||
@@ -107,147 +107,4 @@
|
||||
#coordinates-tool[data-location-system="MGRS"] [data-location-system="MGRS"],
|
||||
#coordinates-tool[data-location-system="UTM"] [data-location-system="UTM"] {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
#mouse-info-panel dl {
|
||||
margin-bottom: 4px;
|
||||
row-gap: 5px;
|
||||
}
|
||||
|
||||
#mouse-info-panel dt {
|
||||
height: fit-content;
|
||||
width: 30%;
|
||||
}
|
||||
|
||||
#mouse-info-panel dt::after, #coordinates-tool [data-label] {
|
||||
align-items: center;
|
||||
background-color: white;
|
||||
border-radius: var(--border-radius-sm);
|
||||
color: var(--background-steel);
|
||||
display: flex;
|
||||
font-size: 15.6px;
|
||||
font-weight: bolder;
|
||||
height: 16px;
|
||||
justify-content: center;
|
||||
line-height: 16px;
|
||||
padding: 4px;
|
||||
text-transform: uppercase;
|
||||
width: 16px;
|
||||
}
|
||||
|
||||
#coordinates-tool [data-label] {
|
||||
height:24px;
|
||||
width:24px;
|
||||
}
|
||||
|
||||
#mouse-info-panel #measuring-tool dt {
|
||||
height: 24px;
|
||||
width: 24px;
|
||||
background-color: var(--background-offwhite);
|
||||
border-radius: var(--border-radius-sm);
|
||||
}
|
||||
|
||||
#mouse-info-panel #measuring-tool svg {
|
||||
padding: 3px;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#mouse-info-panel #measuring-tool dt svg>* {
|
||||
fill: black;
|
||||
stroke: black;
|
||||
}
|
||||
|
||||
#mouse-info-panel [data-label]::after {
|
||||
content: attr(data-label);
|
||||
}
|
||||
|
||||
#mouse-info-panel dt[data-coalition="blue"]::after {
|
||||
background-color: var(--primary-blue);
|
||||
}
|
||||
|
||||
#mouse-info-panel dt[data-coalition="red"]::after {
|
||||
background-color: var(--primary-red);
|
||||
}
|
||||
|
||||
#mouse-info-panel [data-tooltip]:hover::before {
|
||||
background-color: var(--background-grey);
|
||||
border-radius: 5px;
|
||||
content: attr(data-tooltip);
|
||||
display: flex;
|
||||
flex-wrap: nowrap;
|
||||
padding: 5px;
|
||||
position: absolute;
|
||||
translate: calc(-100% - 15px) 0;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#coordinates-tool[data-location-system] [data-location-system] {
|
||||
display:none;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
#coordinates-tool[data-location-system="LatLng"] [data-location-system="LatLng"],
|
||||
#coordinates-tool[data-location-system="MGRS"] [data-location-system="MGRS"] {
|
||||
display:flex;
|
||||
}
|
||||
|
||||
#coordinates-tool > * > * {
|
||||
align-items: center;
|
||||
display:flex;
|
||||
flex-flow: row nowrap;
|
||||
}
|
||||
|
||||
#coordinates-tool > * > * > * {
|
||||
display:table-cell;
|
||||
width:fit-content;
|
||||
}
|
||||
|
||||
#coordinates-tool > * > * > :last-child {
|
||||
text-align: right;
|
||||
width:100%;
|
||||
}
|
||||
|
||||
.br-info::after {
|
||||
content: attr(data-bearing) '\00B0 / ' attr(data-distance) " " attr(data-distance-units);
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--background-offwhite);
|
||||
}
|
||||
|
||||
.br-info[data-coalition="blue"]::after {
|
||||
color: var(--primary-blue)
|
||||
}
|
||||
|
||||
.br-info[data-coalition="red"]::after {
|
||||
color: var(--primary-red)
|
||||
}
|
||||
|
||||
.br-info[data-message]::after {
|
||||
content: attr(data-message);
|
||||
}
|
||||
|
||||
.coordinates::after {
|
||||
content: attr(data-value);
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--background-offwhite);
|
||||
}
|
||||
|
||||
.elevation::after {
|
||||
content: attr(data-value);
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
color: var(--background-offwhite);
|
||||
} */
|
||||
}
|
||||
@@ -676,8 +676,8 @@ nav.ol-panel> :last-child {
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group button.off svg * {
|
||||
fill: white;
|
||||
stroke: white;
|
||||
fill: white !important; /* Higher price than the Soul Stone but inline styling is causing issues. */
|
||||
stroke: white !important; /* I'm sorry, daughter. */
|
||||
}
|
||||
|
||||
.ol-navbar-buttons-group button svg * {
|
||||
|
||||
@@ -67,70 +67,70 @@ export const minAltitudeValues: { [key: string]: number } = { Aircraft: 0, Helic
|
||||
export const maxAltitudeValues: { [key: string]: number } = { Aircraft: 50000, Helicopter: 10000 };
|
||||
export const altitudeIncrements: { [key: string]: number } = { Aircraft: 500, Helicopter: 100 };
|
||||
|
||||
export const minimapBoundaries = [
|
||||
[ // NTTR
|
||||
export const minimapBoundaries = {
|
||||
"Nevada": [ // NTTR
|
||||
new LatLng(39.7982463, -119.985425),
|
||||
new LatLng(34.4037128, -119.7806729),
|
||||
new LatLng(34.3483316, -112.4529351),
|
||||
new LatLng(39.7372411, -112.1130805),
|
||||
new LatLng(39.7982463, -119.985425)
|
||||
],
|
||||
[ // Syria
|
||||
"Syria": [ // Syria
|
||||
new LatLng(37.3630556, 29.2686111),
|
||||
new LatLng(31.8472222, 29.8975),
|
||||
new LatLng(32.1358333, 42.1502778),
|
||||
new LatLng(37.7177778, 42.3716667),
|
||||
new LatLng(37.3630556, 29.2686111)
|
||||
],
|
||||
[ // Caucasus
|
||||
"Caucasus": [ // Caucasus
|
||||
new LatLng(39.6170191, 27.634935),
|
||||
new LatLng(38.8735863, 47.1423108),
|
||||
new LatLng(47.3907982, 49.3101946),
|
||||
new LatLng(48.3955879, 26.7753625),
|
||||
new LatLng(39.6170191, 27.634935)
|
||||
],
|
||||
[ // Persian Gulf
|
||||
"PersianGulf": [ // Persian Gulf
|
||||
new LatLng(32.9355285, 46.5623682),
|
||||
new LatLng(21.729393, 47.572675),
|
||||
new LatLng(21.8501348, 63.9734737),
|
||||
new LatLng(33.131584, 64.7313594),
|
||||
new LatLng(32.9355285, 46.5623682)
|
||||
],
|
||||
[ // Marianas
|
||||
"MarianaIslands": [ // Marianas
|
||||
new LatLng(22.09, 135.0572222),
|
||||
new LatLng(10.5777778, 135.7477778),
|
||||
new LatLng(10.7725, 149.3918333),
|
||||
new LatLng(22.5127778, 149.5427778),
|
||||
new LatLng(22.09, 135.0572222)
|
||||
],
|
||||
[ // South Atlantic
|
||||
"Falklands": [ // South Atlantic
|
||||
new LatLng(-49.097217, -79.418267),
|
||||
new LatLng(-56.874517,-79.418267),
|
||||
new LatLng(-56.874517, -43.316433),
|
||||
new LatLng(-49.097217, -43.316433),
|
||||
new LatLng(-49.097217, -79.418267)
|
||||
],
|
||||
[ // Normandy
|
||||
"Normandy": [ // Normandy
|
||||
new LatLng(50.44, -3.29),
|
||||
new LatLng(48.12,-3.29),
|
||||
new LatLng(48.12, 3.70),
|
||||
new LatLng(50.44, 3.70),
|
||||
new LatLng(50.44, -3.29)
|
||||
],
|
||||
[ // Sinai
|
||||
"SinaiMap": [ // Sinai
|
||||
new LatLng(34.312222, 28.523333),
|
||||
new LatLng(25.946944, 28.523333),
|
||||
new LatLng(25.946944, 36.897778),
|
||||
new LatLng(34.312222, 36.897778),
|
||||
new LatLng(34.312222, 28.523333)
|
||||
]
|
||||
];
|
||||
};
|
||||
|
||||
export const mapBounds = {
|
||||
"Syria": { bounds: new LatLngBounds([31.8472222, 29.8975], [37.7177778, 42.3716667]), zoom: 5 },
|
||||
"MarianaIslands": { bounds: new LatLngBounds([10.5777778, 135.7477778], [22.5127778, 149.5427778]), zoom: 5 },
|
||||
"Nevada": { bounds: new LatLngBounds([34.4037128, -119.7806729], [39.7372411, -112.1130805]), zoom: 5 },
|
||||
"PersianGulf": { bounds: new LatLngBounds([21.729393, 47.572675], [33.131584, 64.7313594]), zoom: 5 },
|
||||
"PersianGulf": { bounds: new LatLngBounds([21.729393, 47.572675], [33.131584, 64.7313594]), zoom: 4 },
|
||||
"Caucasus": { bounds: new LatLngBounds([39.6170191, 27.634935], [47.3907982, 49.3101946]), zoom: 4 },
|
||||
"Falklands": { bounds: new LatLngBounds([-49.097217, -79.418267], [-56.874517, -43.316433]), zoom: 3 },
|
||||
"Normandy": { bounds: new LatLngBounds([50.44, -3.29], [48.12, 3.70]), zoom: 5 },
|
||||
|
||||
@@ -64,6 +64,7 @@ export class Map extends L.Map {
|
||||
#centerUnit: Unit | null = null;
|
||||
#miniMap: ClickableMiniMap | null = null;
|
||||
#miniMapLayerGroup: L.LayerGroup;
|
||||
#miniMapPolyline: L.Polyline;
|
||||
#temporaryMarkers: TemporaryUnitMarker[] = [];
|
||||
#selecting: boolean = false;
|
||||
#isZooming: boolean = false;
|
||||
@@ -123,8 +124,8 @@ export class Map extends L.Map {
|
||||
/* Minimap */
|
||||
var minimapLayer = new L.TileLayer(mapLayers[Object.keys(mapLayers)[0] as keyof typeof mapLayers].urlTemplate, { minZoom: 0, maxZoom: 13 });
|
||||
this.#miniMapLayerGroup = new L.LayerGroup([minimapLayer]);
|
||||
var miniMapPolyline = new L.Polyline(this.#getMinimapBoundaries(), { color: '#202831' });
|
||||
miniMapPolyline.addTo(this.#miniMapLayerGroup);
|
||||
this.#miniMapPolyline = new L.Polyline([], { color: '#202831' });
|
||||
this.#miniMapPolyline.addTo(this.#miniMapLayerGroup);
|
||||
|
||||
/* Scale */
|
||||
//@ts-ignore TODO more hacking because the module is provided as a pure javascript module only
|
||||
@@ -418,6 +419,9 @@ export class Map extends L.Map {
|
||||
if (this.#miniMap)
|
||||
this.setView(e.latlng);
|
||||
})
|
||||
|
||||
const boundaries = this.#getMinimapBoundaries();
|
||||
this.#miniMapPolyline.setLatLngs(boundaries[theatre as keyof typeof boundaries]);
|
||||
}
|
||||
|
||||
getMiniMapLayerGroup() {
|
||||
@@ -791,7 +795,7 @@ export class Map extends L.Map {
|
||||
|
||||
#showDestinationCursors() {
|
||||
const singleCursor = !this.#shiftKey;
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).length;
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true }).length;
|
||||
if (singleCursor) {
|
||||
this.#hideDestinationCursors();
|
||||
}
|
||||
@@ -817,7 +821,7 @@ export class Map extends L.Map {
|
||||
}
|
||||
|
||||
#updateDestinationCursors() {
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true }).length;
|
||||
const selectedUnitsCount = getApp().getUnitsManager().getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true }).length;
|
||||
if (selectedUnitsCount > 1) {
|
||||
const groupLatLng = this.#computeDestinationRotation && this.#destinationRotationCenter != null ? this.#destinationRotationCenter : this.getMouseCoordinates();
|
||||
if (this.#destinationPreviewCursors.length == 1)
|
||||
|
||||
@@ -29,7 +29,7 @@ import { UnitListPanel } from "./panels/unitlistpanel";
|
||||
import { ContextManager } from "./context/contextmanager";
|
||||
import { Context } from "./context/context";
|
||||
|
||||
var VERSION = "v0.4.9-alpha-rc1";
|
||||
var VERSION = "v0.4.12-alpha-rc4";
|
||||
var DEBUG = false;
|
||||
|
||||
export class OlympusApp {
|
||||
@@ -262,9 +262,7 @@ export class OlympusApp {
|
||||
const latestVersionSpan = document.getElementById("latest-version") as HTMLElement;
|
||||
if (latestVersionSpan) {
|
||||
latestVersionSpan.innerHTML = this.#latestVersion ?? "Unknown";
|
||||
if (this.#latestVersion !== VERSION) {
|
||||
latestVersionSpan.classList.add("new-version");
|
||||
}
|
||||
latestVersionSpan.classList.toggle("new-version", this.#latestVersion !== VERSION);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ export class UnitsManager {
|
||||
#slowDeleteDialog!: Dialog;
|
||||
#units: { [ID: number]: Unit };
|
||||
#groups: { [groupName: string]: Group } = {};
|
||||
#unitDataExport!:UnitDataFileExport;
|
||||
#unitDataImport!:UnitDataFileImport;
|
||||
#unitDataExport!: UnitDataFileExport;
|
||||
#unitDataImport!: UnitDataFileImport;
|
||||
|
||||
constructor() {
|
||||
this.#copiedUnits = [];
|
||||
@@ -100,6 +100,50 @@ export class UnitsManager {
|
||||
}
|
||||
}
|
||||
|
||||
/** Sort units segregated groups based on controlling type and protection, if DCS-controlled
|
||||
*
|
||||
* @param units <Unit[]>
|
||||
* @returns Object
|
||||
*/
|
||||
segregateUnits(units: Unit[]): { [key: string]: [] } {
|
||||
const data: any = {
|
||||
controllable: [],
|
||||
dcsProtected: [],
|
||||
dcsUnprotected: [],
|
||||
human: [],
|
||||
olympus: []
|
||||
};
|
||||
const map = getApp().getMap();
|
||||
|
||||
units.forEach(unit => {
|
||||
if (unit.getHuman())
|
||||
data.human.push(unit);
|
||||
else if (unit.isControlledByOlympus())
|
||||
data.olympus.push(unit);
|
||||
else if (map.getIsUnitProtected(unit))
|
||||
data.dcsProtected.push(unit);
|
||||
else
|
||||
data.dcsUnprotected.push(unit);
|
||||
});
|
||||
data.controllable = [].concat(data.dcsUnprotected, data.human, data.olympus);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param numOfProtectedUnits number
|
||||
*/
|
||||
showProtectedUnitsPopup(numOfProtectedUnits: number) {
|
||||
if (numOfProtectedUnits < 1)
|
||||
return;
|
||||
const messageText = (numOfProtectedUnits === 1) ? `Unit is protected` : `All selected units are protected`;
|
||||
(getApp().getPopupsManager().get("infoPopup") as Popup).setText(messageText);
|
||||
// Cheap way for now until we use more locks
|
||||
let lock = <HTMLElement>document.querySelector("#unit-visibility-control button.lock");
|
||||
lock.classList.add("prompt");
|
||||
setTimeout(() => lock.classList.remove("prompt"), 4000);
|
||||
}
|
||||
|
||||
/** Update the data of all the units. The data is directly decoded from the binary buffer received from the REST Server. This is necessary for performance and bandwidth reasons.
|
||||
*
|
||||
* @param buffer The arraybuffer, encoded according to the ICD defined in: TODO Add reference to ICD
|
||||
@@ -261,14 +305,8 @@ export class UnitsManager {
|
||||
}
|
||||
}
|
||||
if (options) {
|
||||
if (options.showProtectionReminder === true && numProtectedUnits > selectedUnits.length && selectedUnits.length === 0) {
|
||||
const messageText = (numProtectedUnits === 1) ? `Unit is protected` : `All selected units are protected`;
|
||||
(getApp().getPopupsManager().get("infoPopup") as Popup).setText(messageText);
|
||||
// Cheap way for now until we use more locks
|
||||
let lock = <HTMLElement>document.querySelector("#unit-visibility-control button.lock");
|
||||
lock.classList.add("prompt");
|
||||
setTimeout(() => lock.classList.remove("prompt"), 4000);
|
||||
}
|
||||
if (options.showProtectionReminder === true && numProtectedUnits > selectedUnits.length && selectedUnits.length === 0)
|
||||
this.showProtectedUnitsPopup(numProtectedUnits);
|
||||
|
||||
if (options.onlyOnePerGroup) {
|
||||
var temp: Unit[] = [];
|
||||
@@ -365,8 +403,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
/* Compute the destination for each unit. If mantainRelativePosition is true, compute the destination so to hold the relative positions */
|
||||
var unitDestinations: { [key: number]: LatLng } = {};
|
||||
@@ -399,8 +442,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: false });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
for (let idx in units) {
|
||||
const unit = units[idx];
|
||||
@@ -425,8 +473,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.landAt(latlng));
|
||||
|
||||
@@ -442,8 +495,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.changeSpeed(speedChange));
|
||||
}
|
||||
@@ -457,8 +515,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.changeAltitude(altitudeChange));
|
||||
}
|
||||
@@ -472,8 +535,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setSpeed(speed));
|
||||
this.#showActionMessage(units, `setting speed to ${msToKnots(speed)} kts`);
|
||||
@@ -488,8 +556,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setSpeedType(speedType));
|
||||
this.#showActionMessage(units, `setting speed type to ${speedType}`);
|
||||
@@ -504,8 +577,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setAltitude(altitude));
|
||||
this.#showActionMessage(units, `setting altitude to ${mToFt(altitude)} ft`);
|
||||
@@ -520,8 +598,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setAltitudeType(altitudeType));
|
||||
this.#showActionMessage(units, `setting altitude type to ${altitudeType}`);
|
||||
@@ -536,8 +619,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setROE(ROE));
|
||||
this.#showActionMessage(units, `ROE set to ${ROE}`);
|
||||
@@ -552,8 +640,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setReactionToThreat(reactionToThreat));
|
||||
this.#showActionMessage(units, `reaction to threat set to ${reactionToThreat}`);
|
||||
@@ -568,8 +661,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setEmissionsCountermeasures(emissionCountermeasure));
|
||||
this.#showActionMessage(units, `emissions & countermeasures set to ${emissionCountermeasure}`);
|
||||
@@ -584,8 +682,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setOnOff(onOff));
|
||||
this.#showActionMessage(units, `unit active set to ${onOff}`);
|
||||
@@ -600,8 +703,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setFollowRoads(followRoads));
|
||||
this.#showActionMessage(units, `follow roads set to ${followRoads}`);
|
||||
@@ -617,8 +725,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setOperateAs(operateAs));
|
||||
this.#showActionMessage(units, `operate as set to ${operateAs}`);
|
||||
@@ -633,8 +746,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.attackUnit(ID));
|
||||
this.#showActionMessage(units, `attacking unit ${this.getUnitByID(ID)?.getUnitName()}`);
|
||||
@@ -647,11 +765,14 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units.forEach((unit: Unit) => unit.refuel());
|
||||
this.#showActionMessage(units, `sent to nearest tanker`);
|
||||
segregatedUnits.controllable.forEach((unit: Unit) => unit.refuel());
|
||||
this.#showActionMessage(segregatedUnits.controllable, `sent to nearest tanker`);
|
||||
}
|
||||
|
||||
/** Instruct the selected units to follow another unit in a formation. Only works for aircrafts and helicopters.
|
||||
@@ -665,8 +786,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
if (offset == undefined) {
|
||||
/* Simple formations with fixed offsets */
|
||||
@@ -683,8 +809,7 @@ export class UnitsManager {
|
||||
var count = 1;
|
||||
var xr = 0; var yr = 1; var zr = -1;
|
||||
var layer = 1;
|
||||
for (let idx in units) {
|
||||
var unit = units[idx];
|
||||
units.forEach((unit: Unit) => {
|
||||
if (unit.ID !== ID) {
|
||||
if (offset != undefined)
|
||||
/* Offset is set, apply it */
|
||||
@@ -705,7 +830,7 @@ export class UnitsManager {
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
})
|
||||
this.#showActionMessage(units, `following unit ${this.getUnitByID(ID)?.getUnitName()}`);
|
||||
}
|
||||
|
||||
@@ -718,8 +843,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.bombPoint(latlng));
|
||||
this.#showActionMessage(units, `unit bombing point`);
|
||||
@@ -734,8 +864,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.carpetBomb(latlng));
|
||||
this.#showActionMessage(units, `unit carpet bombing point`);
|
||||
@@ -750,8 +885,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.fireAtArea(latlng));
|
||||
this.#showActionMessage(units, `unit firing at area`);
|
||||
@@ -766,8 +906,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
getGroundElevation(latlng, (response: string) => {
|
||||
var groundElevation: number | null = null;
|
||||
@@ -788,8 +933,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.scenicAAA());
|
||||
this.#showActionMessage(units, `unit set to perform scenic AAA`);
|
||||
@@ -802,8 +952,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.missOnPurpose());
|
||||
this.#showActionMessage(units, `unit set to perform miss-on-purpose AAA`);
|
||||
@@ -818,9 +973,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true, showProtectionReminder: true });
|
||||
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.landAtPoint(latlng));
|
||||
this.#showActionMessage(units, `unit landing at point`);
|
||||
@@ -835,8 +994,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setShotsScatter(shotsScatter));
|
||||
this.#showActionMessage(units, `shots scatter set to ${shotsScatter}`);
|
||||
@@ -851,8 +1015,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, onlyOnePerGroup: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
units.forEach((unit: Unit) => unit.setShotsIntensity(shotsIntensity));
|
||||
this.#showActionMessage(units, `shots intensity set to ${shotsIntensity}`);
|
||||
@@ -883,8 +1052,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: false, showProtectionReminder: true });
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
if (this.getUnitsCategories(units).length == 1) {
|
||||
var unitsData: { ID: number, location: LatLng }[] = [];
|
||||
@@ -929,8 +1103,13 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeProtected: true, showProtectionReminder: true }); /* Can be applied to humans too */
|
||||
|
||||
if (units.length === 0)
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return;
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
const selectionContainsAHuman = units.some((unit: Unit) => {
|
||||
return unit.getHuman() === true;
|
||||
@@ -968,6 +1147,14 @@ export class UnitsManager {
|
||||
if (units === null)
|
||||
units = this.getSelectedUnits({ excludeHumans: true, excludeProtected: true, onlyOnePerGroup: true });
|
||||
|
||||
const segregatedUnits = this.segregateUnits(units);
|
||||
if (segregatedUnits.controllable.length === 0) {
|
||||
this.showProtectedUnitsPopup(segregatedUnits.dcsProtected.length);
|
||||
return {};
|
||||
}
|
||||
|
||||
units = segregatedUnits.controllable;
|
||||
|
||||
if (units.length === 0)
|
||||
return {};
|
||||
|
||||
@@ -1005,7 +1192,7 @@ export class UnitsManager {
|
||||
*
|
||||
*/
|
||||
copy(units: Unit[] | null = null) {
|
||||
if ( !getApp().getContextManager().getCurrentContext().getAllowUnitCopying() )
|
||||
if (!getApp().getContextManager().getCurrentContext().getAllowUnitCopying())
|
||||
return;
|
||||
|
||||
if (units === null)
|
||||
@@ -1025,7 +1212,7 @@ export class UnitsManager {
|
||||
* @returns True if units were pasted successfully
|
||||
*/
|
||||
paste() {
|
||||
if ( !getApp().getContextManager().getCurrentContext().getAllowUnitPasting() )
|
||||
if (!getApp().getContextManager().getCurrentContext().getAllowUnitPasting())
|
||||
return;
|
||||
|
||||
let spawnPoints = 0;
|
||||
@@ -1127,7 +1314,7 @@ export class UnitsManager {
|
||||
if (Math.random() < IADSDensities[type]) {
|
||||
/* Get a random blueprint depending on the selected parameters and spawn the unit */
|
||||
const unitBlueprint = randomUnitBlueprint(groundUnitDatabase, { type: type, eras: activeEras, ranges: activeRanges });
|
||||
if (unitBlueprint)
|
||||
if (unitBlueprint)
|
||||
this.spawnUnits("GroundUnit", [{ unitType: unitBlueprint.name, location: latlng, liveryID: "" }], coalitionArea.getCoalition(), false, "", "");
|
||||
}
|
||||
}
|
||||
@@ -1152,7 +1339,7 @@ export class UnitsManager {
|
||||
if (Math.random() < IADSDensities[type]) {
|
||||
/* Get a random blueprint depending on the selected parameters and spawn the unit */
|
||||
const unitBlueprint = randomUnitBlueprint(groundUnitDatabase, { type: type, eras: activeEras, ranges: activeRanges });
|
||||
if (unitBlueprint)
|
||||
if (unitBlueprint)
|
||||
this.spawnUnits("GroundUnit", [{ unitType: unitBlueprint.name, location: latlng, liveryID: "" }], coalitionArea.getCoalition(), false, "", "");
|
||||
}
|
||||
}
|
||||
@@ -1169,7 +1356,7 @@ export class UnitsManager {
|
||||
this.#unitDataExport = new UnitDataFileExport("unit-export-dialog");
|
||||
this.#unitDataExport.showForm(Object.values(this.#units));
|
||||
}
|
||||
|
||||
|
||||
/** Import ground and navy units from file
|
||||
* TODO: extend to support aircraft and helicopters
|
||||
*/
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<div id="app-summary">
|
||||
<h2>DCS Olympus</h2>
|
||||
<h4>Dynamic Unit Command</h4>
|
||||
<div class="app-version">Version <span class="app-version-number">v0.4.9-alpha-rc1</span></div>
|
||||
<div class="app-version">Version <span class="app-version-number">v0.4.12-alpha-rc4</span></div>
|
||||
<div class="app-version">Latest version <span id="latest-version" class="app-version-number"></span></div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="ol-select-options">
|
||||
<div id="toolbar-summary">
|
||||
<h3>DCS Olympus</h3>
|
||||
<div class="accent-green app-version-number">version v0.4.9-alpha-rc1</div>
|
||||
<div class="accent-green app-version-number">version v0.4.12-alpha-rc4</div>
|
||||
</div>
|
||||
<div>
|
||||
<a href="https://discord.gg/wWXyVVBZT7" target="_blank">Discord</a>
|
||||
@@ -57,17 +57,17 @@
|
||||
<div id="coalition-visibility-control" class="ol-group ol-navbar-buttons-group">
|
||||
<div>
|
||||
<button id="coalition-visibility-control-blue" data-on-click="toggleCoalitionVisibility"
|
||||
data-on-click-params='{ "coalition": "blue" }'><img src="/resources/theme/images/buttons/visibility/shield.svg" class="fill-coalition" data-coalition="blue" inject-svg /></button>
|
||||
data-on-click-params='{ "coalition": "blue" }' title="Toggle Blue coalition visibility"><img src="/resources/theme/images/buttons/visibility/shield.svg" class="fill-coalition" data-coalition="blue" inject-svg /></button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button id="coalition-visibility-control-red" data-on-click="toggleCoalitionVisibility"
|
||||
data-on-click-params='{ "coalition": "red" }'><img src="/resources/theme/images/buttons/visibility/shield.svg" class="fill-coalition" data-coalition="red" inject-svg /></button>
|
||||
data-on-click-params='{ "coalition": "red" }' title="Toggle Red coalition visibility"><img src="/resources/theme/images/buttons/visibility/shield.svg" class="fill-coalition" data-coalition="red" inject-svg /></button>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<button id="coalition-visibility-control-neutral" data-on-click="toggleCoalitionVisibility"
|
||||
data-on-click-params='{ "coalition": "neutral" }'><img src="/resources/theme/images/buttons/visibility/shield.svg" class="fill-coalition" data-coalition="neutral" inject-svg /></button>
|
||||
data-on-click-params='{ "coalition": "neutral" }' title="Toggle Neutral coalition visibility"><img src="/resources/theme/images/buttons/visibility/shield.svg" class="fill-coalition" data-coalition="neutral" inject-svg /></button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
@@ -1,6 +1,6 @@
|
||||
#define nwjsFolder "..\..\nwjs\"
|
||||
#define nodejsFolder "..\..\node\"
|
||||
#define version "v0.4.9-alpha-rc1"
|
||||
#define version "v0.4.12-alpha-rc4"
|
||||
|
||||
[Setup]
|
||||
AppName=DCS Olympus
|
||||
@@ -51,36 +51,11 @@ Source: "..\scripts\python\configurator\dist\configurator.exe"; DestDir: "{app}\
|
||||
[Run]
|
||||
Filename: "{app}\Mods\Services\Olympus\configurator.exe"; Parameters: -a {code:GetAddress} -c {code:GetClientPort} -b {code:GetBackendPort} -p {code:GetPassword} -bp {code:GetBluePassword} -rp {code:GetRedPassword}; Check: CheckCallConfigurator
|
||||
|
||||
[Registry]
|
||||
Root: HKCU; Subkey: "Environment"; ValueType: string; ValueName: "DCSOLYMPUS_PATH"; ValueData: "{app}\Mods\Services\Olympus"; Flags: preservestringtype
|
||||
Root: HKCU; Subkey: "Environment"; ValueType: expandsz; ValueName: "Path"; ValueData: "{olddata};%DCSOLYMPUS_PATH%\bin"; Check: NeedsAddPath('%DCSOLYMPUS_PATH%\bin');
|
||||
|
||||
[Setup]
|
||||
; Tell Windows Explorer to reload the environment
|
||||
ChangesEnvironment=yes
|
||||
|
||||
[Icons]
|
||||
Name: "{userdesktop}\DCS Olympus Client"; Filename: "{app}\Mods\Services\Olympus\client\nw.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus.ico"; Check: CheckLocalInstall
|
||||
Name: "{userdesktop}\DCS Olympus Server"; Filename: "{app}\Mods\Services\Olympus\client\node.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_server.ico"; Parameters: ".\bin\www"; Check: CheckServerInstall
|
||||
Name: "{userdesktop}\DCS Olympus Configurator"; Filename: "{app}\Mods\Services\Olympus\configurator.exe"; Tasks: desktopicon; IconFilename: "{app}\Mods\Services\Olympus\img\olympus_configurator.ico"; Check: CheckServerInstall
|
||||
|
||||
[Code]
|
||||
function NeedsAddPath(Param: string): boolean;
|
||||
var
|
||||
OrigPath: string;
|
||||
begin
|
||||
if not RegQueryStringValue(HKCU,
|
||||
'Environment',
|
||||
'Path', OrigPath)
|
||||
then begin
|
||||
Result := True;
|
||||
exit;
|
||||
end;
|
||||
{ look for the path with leading and trailing semicolon }
|
||||
{ Pos() returns 0 if not found }
|
||||
Result := Pos(';' + Param + ';', ';' + OrigPath + ';') = 0;
|
||||
end;
|
||||
|
||||
[Code]
|
||||
var
|
||||
lblLocalInstall: TLabel;
|
||||
|
||||
@@ -15,7 +15,7 @@ declare_plugin(self_ID,
|
||||
shortName = "Olympus",
|
||||
fileMenuName = "Olympus",
|
||||
|
||||
version = "v0.4.9-alpha-rc1",
|
||||
version = "v0.4.12-alpha-rc4",
|
||||
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."),
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
local version = "v0.4.9-alpha-rc1"
|
||||
local version = "v0.4.12-alpha-rc4"
|
||||
|
||||
local debug = false -- True enables debug printing using DCS messages
|
||||
|
||||
-- .dll related variables
|
||||
Olympus.OlympusDLL = nil
|
||||
Olympus.DLLsloaded = false
|
||||
Olympus.OlympusModPath = os.getenv('DCSOLYMPUS_PATH')..'\\bin\\'
|
||||
|
||||
-- Logger reference
|
||||
Olympus.log = mist.Logger:new("Olympus", 'info')
|
||||
@@ -31,6 +30,10 @@ Olympus.weapons = {} -- Table holding references to all the currently existing
|
||||
Olympus.missionStartTime = DCS.getRealTime()
|
||||
Olympus.napalmCounter = 1
|
||||
Olympus.fireCounter = 1
|
||||
|
||||
-- Load the lua file system
|
||||
local lfs = require('lfs')
|
||||
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Olympus functions
|
||||
------------------------------------------------------------------------------------------------------
|
||||
@@ -49,7 +52,7 @@ end
|
||||
-- Loads the olympus .dll
|
||||
function Olympus.loadDLLs()
|
||||
-- Add the .dll paths
|
||||
package.cpath = package.cpath..';'..Olympus.OlympusModPath..'?.dll;'
|
||||
package.cpath = package.cpath..';'..Olympus.instancePath..'?.dll;'
|
||||
|
||||
local status
|
||||
status, Olympus.OlympusDLL = pcall(require, 'olympus')
|
||||
@@ -510,7 +513,7 @@ function Olympus.removeFire (smokeName)
|
||||
end
|
||||
|
||||
function Olympus.secondaries(vec3)
|
||||
Olympus.randomDebrie(vec3)
|
||||
Olympus.randomDebries(vec3)
|
||||
--trigger.action.explosion(vec3, 1)
|
||||
--for i = 1, 10 do
|
||||
-- timer.scheduleFunction(Olympus.randomDebries, vec3, timer.getTime() + math.random(0, 180))
|
||||
@@ -1361,6 +1364,9 @@ end
|
||||
------------------------------------------------------------------------------------------------------
|
||||
-- Olympus startup script
|
||||
------------------------------------------------------------------------------------------------------
|
||||
Olympus.instancePath = lfs.writedir().."Mods\\Services\\Olympus\\bin\\"
|
||||
Olympus.notify("Starting DCS Olympus backend session in "..Olympus.instancePath, 2)
|
||||
|
||||
local OlympusName = 'Olympus ' .. version .. ' C++ module';
|
||||
Olympus.DLLsloaded = Olympus.loadDLLs()
|
||||
if Olympus.DLLsloaded then
|
||||
@@ -1402,11 +1408,3 @@ Olympus.initializeUnits()
|
||||
|
||||
Olympus.notify("OlympusCommand script " .. version .. " loaded successfully", 2, true)
|
||||
|
||||
-- Load the current instance folder
|
||||
local lfs = require('lfs')
|
||||
|
||||
Olympus.instancePath = lfs.writedir().."Mods\\Services\\Olympus"
|
||||
|
||||
Olympus.notify("Starting DCS Olympus backend session in "..Olympus.instancePath, 2)
|
||||
Olympus.OlympusDLL.setInstancePath()
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
local version = 'v0.4.9-alpha-rc1'
|
||||
local version = 'v0.4.12-alpha-rc4'
|
||||
local lfs = require("lfs")
|
||||
|
||||
Olympus = {}
|
||||
Olympus.OlympusDLL = nil
|
||||
Olympus.cppRESTDLL = nil
|
||||
Olympus.DLLsloaded = false
|
||||
Olympus.OlympusModPath = os.getenv('DCSOLYMPUS_PATH')..'\\bin\\'
|
||||
Olympus.OlympusModPath = lfs.writedir().."Mods\\Services\\Olympus\\bin\\"
|
||||
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO,'Executing OlympusHook.lua')
|
||||
|
||||
@@ -15,7 +15,7 @@ function Olympus.loadDLLs()
|
||||
local status
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO, 'Loading olympus.dll from ['..Olympus.OlympusModPath..']')
|
||||
status, Olympus.OlympusDLL = pcall(require, 'olympus')
|
||||
if status then
|
||||
if status then
|
||||
log.write('Olympus.HOOKS.LUA', log.INFO, 'olympus.dll loaded successfully')
|
||||
return true
|
||||
else
|
||||
|
||||
@@ -113,7 +113,7 @@ class Move : public Command
|
||||
{
|
||||
public:
|
||||
Move(string groupName, Coords destination, double speed, string speedType, double altitude,
|
||||
string altitudeType, string taskOptions, string category, function<void(void)> callback = []() {}) :
|
||||
string altitudeType, string taskOptions, string category, bool onRoad, function<void(void)> callback = []() {}) :
|
||||
Command(callback),
|
||||
groupName(groupName),
|
||||
destination(destination),
|
||||
@@ -122,12 +122,13 @@ public:
|
||||
altitude(altitude),
|
||||
altitudeType(altitudeType),
|
||||
taskOptions(taskOptions),
|
||||
category(category)
|
||||
category(category),
|
||||
onRoad(onRoad)
|
||||
{
|
||||
priority = CommandPriority::MEDIUM;
|
||||
};
|
||||
virtual string getString();
|
||||
virtual unsigned int getLoad() { return 5; }
|
||||
virtual unsigned int getLoad() { return onRoad? 45: 5; }
|
||||
|
||||
private:
|
||||
const string groupName;
|
||||
@@ -138,6 +139,7 @@ private:
|
||||
const string altitudeType;
|
||||
const string taskOptions;
|
||||
const string category;
|
||||
const bool onRoad;
|
||||
};
|
||||
|
||||
/* Smoke command */
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
#include "unit.h"
|
||||
|
||||
#define GROUND_DEST_DIST_THR 100
|
||||
#define GROUND_DEST_DIST_THR 10
|
||||
|
||||
class GroundUnit : public Unit
|
||||
{
|
||||
|
||||
@@ -9,7 +9,6 @@ extern UnitsManager* unitsManager;
|
||||
/* Move command */
|
||||
string Move::getString()
|
||||
{
|
||||
|
||||
std::ostringstream commandSS;
|
||||
commandSS.precision(10);
|
||||
commandSS << "Olympus.move, "
|
||||
|
||||
@@ -52,8 +52,12 @@ extern "C" DllExport int coreDeinit(lua_State* L)
|
||||
}
|
||||
|
||||
/* Called when DCS simulation starts. All singletons are instantiated, and the custom Lua functions are registered in the Lua state. */
|
||||
extern "C" DllExport int coreInit(lua_State* L)
|
||||
extern "C" DllExport int coreInit(lua_State* L, const char* path)
|
||||
{
|
||||
instancePath = path;
|
||||
|
||||
log("Initializing core.dll with instance path " + instancePath);
|
||||
|
||||
sessionHash = random_string(16);
|
||||
unitsManager = new UnitsManager(L);
|
||||
weaponsManager = new WeaponsManager(L);
|
||||
@@ -70,20 +74,6 @@ extern "C" DllExport int coreInit(lua_State* L)
|
||||
return(0);
|
||||
}
|
||||
|
||||
extern "C" DllExport int coreInstancePath(lua_State * L)
|
||||
{
|
||||
/* Lock for thread safety */
|
||||
lock_guard<mutex> guard(mutexLock);
|
||||
|
||||
lua_getglobal(L, "Olympus");
|
||||
lua_getfield(L, -1, "instancePath");
|
||||
instancePath = lua_tostring(L, -1);
|
||||
|
||||
log("Setting instance path to " + instancePath);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
extern "C" DllExport int coreFrame(lua_State* L)
|
||||
{
|
||||
if (!initialized)
|
||||
|
||||
@@ -228,7 +228,7 @@ void GroundUnit::AIloop()
|
||||
Geodesic::WGS84().Inverse(getPosition().lat, getPosition().lng, scatteredTargetPosition.lat, scatteredTargetPosition.lng, distance, bearing1, bearing2);
|
||||
|
||||
/* Compute the scattered position applying a random scatter to the shot */
|
||||
double scatterDistance = distance * tan(10 /* degs */ * (ShotsScatter::LOW - shotsScatter) / 57.29577 + 2 /* degs */) * RANDOM_MINUS_ONE_TO_ONE;
|
||||
double scatterDistance = distance * tan(10 /* degs */ * (ShotsScatter::LOW - shotsScatter) / 57.29577 + 2 / 57.29577 /* degs */) * RANDOM_MINUS_ONE_TO_ONE;
|
||||
Geodesic::WGS84().Direct(scatteredTargetPosition.lat, scatteredTargetPosition.lng, bearing1 + 90, scatterDistance, scatteredTargetPosition.lat, scatteredTargetPosition.lng);
|
||||
|
||||
/* Recover the data from the database */
|
||||
|
||||
@@ -524,8 +524,8 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr) {
|
||||
unit->setState(State::BOMB_POINT);
|
||||
unit->setTargetPosition(loc);
|
||||
unit->setState(State::BOMB_POINT);
|
||||
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to bomb a point", true);
|
||||
}
|
||||
}
|
||||
@@ -539,8 +539,8 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr) {
|
||||
unit->setState(State::CARPET_BOMB);
|
||||
unit->setTargetPosition(loc);
|
||||
unit->setState(State::CARPET_BOMB);
|
||||
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to perform carpet bombing", true);
|
||||
}
|
||||
}
|
||||
@@ -555,8 +555,8 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr) {
|
||||
unit->setState(State::BOMB_BUILDING);
|
||||
unit->setTargetPosition(loc);
|
||||
unit->setState(State::BOMB_BUILDING);
|
||||
}
|
||||
}
|
||||
/************************/
|
||||
@@ -569,8 +569,8 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
|
||||
Coords loc; loc.lat = lat; loc.lng = lng;
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr) {
|
||||
unit->setState(State::FIRE_AT_AREA);
|
||||
unit->setTargetPosition(loc);
|
||||
unit->setState(State::FIRE_AT_AREA);
|
||||
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to fire at area", true);
|
||||
}
|
||||
}
|
||||
@@ -585,8 +585,8 @@ void Scheduler::handleRequest(string key, json::value value, string username, js
|
||||
Coords loc; loc.lat = lat; loc.lng = lng; loc.alt = alt;
|
||||
Unit* unit = unitsManager->getGroupLeader(ID);
|
||||
if (unit != nullptr) {
|
||||
unit->setState(State::SIMULATE_FIRE_FIGHT);
|
||||
unit->setTargetPosition(loc);
|
||||
unit->setState(State::SIMULATE_FIRE_FIGHT);
|
||||
log(username + " tasked unit " + unit->getUnitName() + "(" + unit->getName() + ") to simulate a fire fight", true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
extern string instancePath;
|
||||
|
||||
bool executeLuaScript(lua_State* L, string path)
|
||||
{
|
||||
replace(path.begin(), path.end(), '\\', '/');
|
||||
@@ -36,21 +38,8 @@ void registerLuaFunctions(lua_State* L)
|
||||
log("protectedCall registered successfully");
|
||||
}
|
||||
|
||||
char* buf = nullptr;
|
||||
size_t sz = 0;
|
||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
||||
{
|
||||
modLocation = buf;
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("DCSOLYMPUS_PATH environment variable is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
executeLuaScript(L, modLocation + "\\Scripts\\mist.lua");
|
||||
executeLuaScript(L, modLocation + "\\Scripts\\OlympusCommand.lua");
|
||||
executeLuaScript(L, modLocation + "\\Scripts\\unitPayloads.lua");
|
||||
executeLuaScript(L, modLocation + "\\Scripts\\templates.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\mist.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\OlympusCommand.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\unitPayloads.lua");
|
||||
executeLuaScript(L, instancePath + "..\\Scripts\\templates.lua");
|
||||
}
|
||||
|
||||
@@ -712,7 +712,7 @@ void Unit::goToDestination(string enrouteTask)
|
||||
{
|
||||
if (activeDestination != NULL)
|
||||
{
|
||||
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory(), [this]() { this->setHasTaskAssigned(true); }));
|
||||
Command* command = dynamic_cast<Command*>(new Move(groupName, activeDestination, getDesiredSpeed(), getDesiredSpeedType() ? "GS" : "CAS", getDesiredAltitude(), getDesiredAltitudeType() ? "AGL" : "ASL", enrouteTask, getCategory(), getFollowRoads(), [this]() { this->setHasTaskAssigned(true); }));
|
||||
scheduler->appendCommand(command);
|
||||
setHasTask(true);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ void DllExport stackUpdate(lua_State* L, int& stackDepth, int initialStack = 0);
|
||||
void DllExport stackPop(lua_State* L, int popDepth = 1);
|
||||
void DllExport stackClean(lua_State* L, int stackDepth);
|
||||
void DllExport luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys = false);
|
||||
void DllExport luaLogTableKeys(lua_State* L, int index);
|
||||
|
||||
#define STACK_UPDATE stackUpdate(L, stackDepth, initialStack);
|
||||
#define STACK_INIT int stackDepth = 0; int initialStack = 0; stackUpdate(L, initialStack);
|
||||
|
||||
@@ -18,6 +18,29 @@ void stackClean(lua_State* L, int stackDepth)
|
||||
lua_pop(L, stackDepth);
|
||||
}
|
||||
|
||||
|
||||
void luaLogTableKeys(lua_State* L, int index)
|
||||
{
|
||||
if (lua_istable(L, index))
|
||||
{
|
||||
STACK_INIT;
|
||||
|
||||
lua_pushvalue(L, index);
|
||||
lua_pushnil(L);
|
||||
while (lua_next(L, -2))
|
||||
{
|
||||
lua_pushvalue(L, -2);
|
||||
const char* key = lua_tostring(L, -1);
|
||||
log(key);
|
||||
lua_pop(L, 2);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
||||
STACK_CLEAN;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void luaTableToJSON(lua_State* L, int index, json::value& json, bool logKeys)
|
||||
{
|
||||
if (lua_istable(L, index))
|
||||
|
||||
BIN
src/olympus/olympus.aps
Normal file
BIN
src/olympus/olympus.aps
Normal file
Binary file not shown.
@@ -20,6 +20,9 @@
|
||||
<ProjectReference Include="..\logger\logger.vcxproj">
|
||||
<Project>{873ecabe-fcfe-4217-ac15-91959c3cf1c6}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\luatools\luatools.vcxproj">
|
||||
<Project>{de139ec1-4f88-47d5-be73-f41915fe14a3}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\utils\utils.vcxproj">
|
||||
<Project>{b85009ce-4a5c-4a5a-b85d-001b3a2651b2}</Project>
|
||||
</ProjectReference>
|
||||
@@ -112,6 +115,7 @@
|
||||
<EnableUAC>false</EnableUAC>
|
||||
<AdditionalDependencies>lua.lib</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>..\..\third-party\lua</AdditionalLibraryDirectories>
|
||||
<DelayLoadDLLs>dcstools.dll;logger.dll;utils.dll;%(DelayLoadDLLs)</DelayLoadDLLs>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
||||
@@ -5,40 +5,26 @@
|
||||
|
||||
/* Run-time linking to core dll allows for "hot swap". This is useful for development but could be removed when stable.*/
|
||||
HINSTANCE hGetProcIDDLL = NULL;
|
||||
typedef int(__stdcall* f_coreInit)(lua_State* L);
|
||||
typedef int(__stdcall* f_coreInit)(lua_State* L, const char* path);
|
||||
typedef int(__stdcall* f_coreDeinit)(lua_State* L);
|
||||
typedef int(__stdcall* f_coreFrame)(lua_State* L);
|
||||
typedef int(__stdcall* f_coreUnitsData)(lua_State* L);
|
||||
typedef int(__stdcall* f_coreWeaponsData)(lua_State* L);
|
||||
typedef int(__stdcall* f_coreMissionData)(lua_State* L);
|
||||
typedef int(__stdcall* f_coreInstancePath)(lua_State* L);
|
||||
f_coreInit coreInit = nullptr;
|
||||
f_coreDeinit coreDeinit = nullptr;
|
||||
f_coreFrame coreFrame = nullptr;
|
||||
f_coreUnitsData coreUnitsData = nullptr;
|
||||
f_coreWeaponsData coreWeaponsData = nullptr;
|
||||
f_coreMissionData coreMissionData = nullptr;
|
||||
f_coreInstancePath coreInstancePath = nullptr;
|
||||
|
||||
string modPath;
|
||||
|
||||
static int onSimulationStart(lua_State* L)
|
||||
{
|
||||
log("onSimulationStart callback called successfully");
|
||||
|
||||
string modLocation;
|
||||
string dllLocation;
|
||||
char* buf = nullptr;
|
||||
size_t sz = 0;
|
||||
if (_dupenv_s(&buf, &sz, "DCSOLYMPUS_PATH") == 0 && buf != nullptr)
|
||||
{
|
||||
modLocation = buf;
|
||||
free(buf);
|
||||
}
|
||||
else
|
||||
{
|
||||
log("DCSOLYMPUS_PATH environment variable is missing");
|
||||
goto error;
|
||||
}
|
||||
dllLocation = modLocation + "\\bin\\core.dll";
|
||||
string dllLocation = modPath + "\\core.dll";
|
||||
|
||||
log("Loading core.dll");
|
||||
hGetProcIDDLL = LoadLibrary(to_wstring(dllLocation).c_str());
|
||||
@@ -92,14 +78,7 @@ static int onSimulationStart(lua_State* L)
|
||||
goto error;
|
||||
}
|
||||
|
||||
coreInstancePath = (f_coreInstancePath)GetProcAddress(hGetProcIDDLL, "coreInstancePath");
|
||||
if (!coreInstancePath)
|
||||
{
|
||||
LogError(L, "Error getting coreInstancePath ProcAddress from DLL");
|
||||
goto error;
|
||||
}
|
||||
|
||||
coreInit(L);
|
||||
coreInit(L, modPath.c_str());
|
||||
|
||||
LogInfo(L, "Module loaded and started successfully.");
|
||||
|
||||
@@ -146,7 +125,6 @@ static int onSimulationStop(lua_State* L)
|
||||
coreUnitsData = nullptr;
|
||||
coreWeaponsData = nullptr;
|
||||
coreMissionData = nullptr;
|
||||
coreInstancePath = nullptr;
|
||||
}
|
||||
|
||||
hGetProcIDDLL = NULL;
|
||||
@@ -185,15 +163,6 @@ static int setMissionData(lua_State* L)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int setInstancePath(lua_State* L)
|
||||
{
|
||||
if (coreInstancePath)
|
||||
{
|
||||
coreInstancePath(L);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const luaL_Reg Map[] = {
|
||||
{"onSimulationStart", onSimulationStart},
|
||||
{"onSimulationFrame", onSimulationFrame},
|
||||
@@ -201,12 +170,39 @@ static const luaL_Reg Map[] = {
|
||||
{"setUnitsData", setUnitsData },
|
||||
{"setWeaponsData", setWeaponsData },
|
||||
{"setMissionData", setMissionData },
|
||||
{"setInstancePath", setInstancePath },
|
||||
{NULL, NULL}
|
||||
};
|
||||
|
||||
extern "C" DllExport int luaopen_olympus(lua_State * L)
|
||||
{
|
||||
lua_getglobal(L, "require");
|
||||
lua_pushstring(L, "lfs");
|
||||
lua_pcall(L, 1, 1, 0);
|
||||
lua_getfield(L, -1, "writedir");
|
||||
lua_pcall(L, 0, 1, 0);
|
||||
if (lua_isstring(L, -1)) {
|
||||
modPath = string(lua_tostring(L, -1)) + "Mods\\Services\\Olympus\\bin\\";
|
||||
SetDllDirectoryA(modPath.c_str());
|
||||
LogInfo(L, "Instance location retrieved successfully");
|
||||
}
|
||||
else {
|
||||
/* Log without using the helper dlls because we have not loaded them yet here */
|
||||
lua_getglobal(L, "log");
|
||||
lua_getfield(L, -1, "ERROR");
|
||||
int errorLevel = (int)lua_tointeger(L, -1);
|
||||
|
||||
lua_getglobal(L, "log");
|
||||
lua_getfield(L, -1, "write");
|
||||
lua_pushstring(L, "Olympus.dll");
|
||||
lua_pushnumber(L, errorLevel);
|
||||
lua_pushstring(L, "An error has occurred while trying to retrieve Olympus's instance location");
|
||||
lua_pcall(L, 3, 0, 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
LogInfo(L, "Loading .dlls from " + modPath);
|
||||
|
||||
luaL_register(L, "olympus", Map);
|
||||
return 1;
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#define VERSION "v0.4.9-alpha-rc1"
|
||||
#define VERSION "v0.4.12-alpha-rc4"
|
||||
#define LOG_NAME "Olympus_log.txt"
|
||||
#define REST_ADDRESS "http://localhost:30000"
|
||||
#define REST_URI "olympus"
|
||||
@@ -14,8 +14,8 @@
|
||||
|
||||
#define FRAMERATE_TIME_INTERVAL 0.05
|
||||
|
||||
#define OLYMPUS_JSON_PATH "\\olympus.json"
|
||||
#define AIRCRAFT_DATABASE_PATH "\\client\\public\\databases\\units\\aircraftdatabase.json"
|
||||
#define HELICOPTER_DATABASE_PATH "\\client\\public\\databases\\units\\helicopterdatabase.json"
|
||||
#define GROUNDUNIT_DATABASE_PATH "\\client\\public\\databases\\units\\groundunitdatabase.json"
|
||||
#define NAVYUNIT_DATABASE_PATH "\\client\\public\\databases\\units\\navyunitdatabase.json"
|
||||
#define OLYMPUS_JSON_PATH "..\\olympus.json"
|
||||
#define AIRCRAFT_DATABASE_PATH "..\\client\\public\\databases\\units\\aircraftdatabase.json"
|
||||
#define HELICOPTER_DATABASE_PATH "..\\client\\public\\databases\\units\\helicopterdatabase.json"
|
||||
#define GROUNDUNIT_DATABASE_PATH "..\\client\\public\\databases\\units\\groundunitdatabase.json"
|
||||
#define NAVYUNIT_DATABASE_PATH "..\\client\\public\\databases\\units\\navyunitdatabase.json"
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
{
|
||||
"version": "v0.4.9-alpha-rc1"
|
||||
"version": "v0.4.12-alpha-rc4"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user