From 53911cf314c4a412f87b168dd16d55e5428ee4ee Mon Sep 17 00:00:00 2001 From: dpassoni Date: Thu, 16 Mar 2023 15:34:35 +0100 Subject: [PATCH 01/30] Renamed files --- client/src/aic/AICFormation.ts | 6 +- client/src/aic/AICFormation/Azimuth.ts | 10 +- client/src/aic/AICFormation/Range.ts | 10 +- client/src/aic/AICFormation/Single.ts | 4 +- client/src/aic/AICFormationDescriptor.ts | 12 +- .../Distance.ts | 2 +- .../Distance/Range.ts | 2 +- .../src/aic/AICFormationDescriptorPhrase.ts | 6 +- .../src/aic/AICFormationDescriptorSection.ts | 6 +- .../Formation.ts | 10 +- .../NumGroups.ts | 10 +- .../aic/AICFormationDescriptorSection/Unit.ts | 10 +- .../aic/AICFormationDescriptorSection/Who.ts | 10 +- client/src/aic/aic.ts | 10 +- client/src/aic/aicformation.ts | 54 +++ client/src/aic/aicformation/azimuth.ts | 38 +++ client/src/aic/aicformation/range.ts | 38 +++ client/src/aic/aicformation/single.ts | 24 ++ client/src/aic/aicformationdescriptor.ts | 55 +++ .../aic/aicformationdescriptorcomponent.ts | 18 + .../distance.ts | 9 + .../distance/range.ts | 9 + .../src/aic/aicformationdescriptorphrase.ts | 40 +++ .../src/aic/aicformationdescriptorsection.ts | 40 +++ .../formation.ts | 39 +++ .../numgroups.ts | 35 ++ .../aic/aicformationdescriptorsection/unit.ts | 83 +++++ .../aic/aicformationdescriptorsection/who.ts | 35 ++ client/src/atc/ATC.ts | 4 +- client/src/atc/ATCMockAPI/Flights.ts | 2 +- client/src/atc/FlightList.ts | 2 +- client/src/atc/atc.ts | 87 +++++ client/src/atc/atcmockapi.ts | 7 + client/src/atc/atcmockapi/flights.ts | 40 +++ client/src/atc/flightlist.ts | 18 + client/src/featureswitches.ts | 161 +++++++++ client/src/index.ts | 4 +- client/src/toggleablefeature.ts | 35 ++ installer/{DCSOlympus.iss => olympus.iss} | 0 missions/olympus.miz | Bin 0 -> 7456 bytes src/core/include/commands.h | 275 +++++++++++++++ src/core/include/scheduler.h | 20 ++ src/core/include/unit.h | 184 ++++++++++ src/core/src/commands.cpp | 135 ++++++++ src/core/src/scheduler.cpp | 263 ++++++++++++++ src/core/src/unit.cpp | 322 ++++++++++++++++++ src/olympus.sln | 42 +++ src/olympus/olympus.filters | 29 ++ src/olympus/olympus.vcxproj | 120 +++++++ src/olympus/olympus.vcxproj.filters | 16 + src/olympus/src/olympus.cpp | 152 +++++++++ 51 files changed, 2483 insertions(+), 60 deletions(-) create mode 100644 client/src/aic/aicformation.ts create mode 100644 client/src/aic/aicformation/azimuth.ts create mode 100644 client/src/aic/aicformation/range.ts create mode 100644 client/src/aic/aicformation/single.ts create mode 100644 client/src/aic/aicformationdescriptor.ts create mode 100644 client/src/aic/aicformationdescriptorcomponent.ts create mode 100644 client/src/aic/aicformationdescriptorcomponent/distance.ts create mode 100644 client/src/aic/aicformationdescriptorcomponent/distance/range.ts create mode 100644 client/src/aic/aicformationdescriptorphrase.ts create mode 100644 client/src/aic/aicformationdescriptorsection.ts create mode 100644 client/src/aic/aicformationdescriptorsection/formation.ts create mode 100644 client/src/aic/aicformationdescriptorsection/numgroups.ts create mode 100644 client/src/aic/aicformationdescriptorsection/unit.ts create mode 100644 client/src/aic/aicformationdescriptorsection/who.ts create mode 100644 client/src/atc/atc.ts create mode 100644 client/src/atc/atcmockapi.ts create mode 100644 client/src/atc/atcmockapi/flights.ts create mode 100644 client/src/atc/flightlist.ts create mode 100644 client/src/featureswitches.ts create mode 100644 client/src/toggleablefeature.ts rename installer/{DCSOlympus.iss => olympus.iss} (100%) create mode 100644 missions/olympus.miz create mode 100644 src/core/include/commands.h create mode 100644 src/core/include/scheduler.h create mode 100644 src/core/include/unit.h create mode 100644 src/core/src/commands.cpp create mode 100644 src/core/src/scheduler.cpp create mode 100644 src/core/src/unit.cpp create mode 100644 src/olympus.sln create mode 100644 src/olympus/olympus.filters create mode 100644 src/olympus/olympus.vcxproj create mode 100644 src/olympus/olympus.vcxproj.filters create mode 100644 src/olympus/src/olympus.cpp diff --git a/client/src/aic/AICFormation.ts b/client/src/aic/AICFormation.ts index e13d1acc..588f4326 100644 --- a/client/src/aic/AICFormation.ts +++ b/client/src/aic/AICFormation.ts @@ -1,6 +1,6 @@ -import { AICFormationContextDataInterface, AICFormationDescriptor } from "./AICFormationDescriptor"; -import { AICFormationDescriptorPhrase } from "./AICFormationDescriptorPhrase"; -import { AICFormationDescriptorSection } from "./AICFormationDescriptorSection"; +import { AICFormationContextDataInterface, AICFormationDescriptor } from "./aicformationdescriptor"; +import { AICFormationDescriptorPhrase } from "./aicformationdescriptorphrase"; +import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; export interface AICFormationInterface { "icon" : string, diff --git a/client/src/aic/AICFormation/Azimuth.ts b/client/src/aic/AICFormation/Azimuth.ts index 65a9a003..7db676ae 100644 --- a/client/src/aic/AICFormation/Azimuth.ts +++ b/client/src/aic/AICFormation/Azimuth.ts @@ -1,8 +1,8 @@ -import { AICFormation, AICFormationInterface } from "../AICFormation"; -import { AICFormationContextDataInterface } from "../AICFormationDescriptor"; -import { AICFormationDescriptorSection } from "../AICFormationDescriptorSection"; -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; -import { AICFormationDescriptorPhrase } from "../AICFormationDescriptorPhrase"; +import { AICFormation, AICFormationInterface } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; export class AICFormation_Azimuth extends AICFormation implements AICFormationInterface { diff --git a/client/src/aic/AICFormation/Range.ts b/client/src/aic/AICFormation/Range.ts index 32e48557..08c00cd5 100644 --- a/client/src/aic/AICFormation/Range.ts +++ b/client/src/aic/AICFormation/Range.ts @@ -1,8 +1,8 @@ -import { AICFormation, AICFormationInterface } from "../AICFormation"; -import { AICFormationContextDataInterface } from "../AICFormationDescriptor"; -import { AICFormationDescriptorSection } from "../AICFormationDescriptorSection"; -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; -import { AICFormationDescriptorPhrase } from "../AICFormationDescriptorPhrase"; +import { AICFormation, AICFormationInterface } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; export class AICFormation_Range extends AICFormation implements AICFormationInterface { diff --git a/client/src/aic/AICFormation/Single.ts b/client/src/aic/AICFormation/Single.ts index dd9a8ae4..09830c40 100644 --- a/client/src/aic/AICFormation/Single.ts +++ b/client/src/aic/AICFormation/Single.ts @@ -1,5 +1,5 @@ -import { AICFormation, AICFormationInterface } from "../AICFormation"; -import { AICFormationContextDataInterface, AICFormationDescriptor } from "../AICFormationDescriptor"; +import { AICFormation, AICFormationInterface } from "../aicformation"; +import { AICFormationContextDataInterface, AICFormationDescriptor } from "../aicformationdescriptor"; export class AICFormation_Single extends AICFormation implements AICFormationInterface { diff --git a/client/src/aic/AICFormationDescriptor.ts b/client/src/aic/AICFormationDescriptor.ts index 8bc43c54..c7a5a563 100644 --- a/client/src/aic/AICFormationDescriptor.ts +++ b/client/src/aic/AICFormationDescriptor.ts @@ -1,9 +1,9 @@ -import { AICFormation } from "./AICFormation"; -import { AICFormationDescriptorSection } from "./AICFormationDescriptorSection"; -import { AICFormationDescriptorSection_Formation } from "./AICFormationDescriptorSection/Formation"; -import { AICFormationDescriptorSection_Unit } from "./AICFormationDescriptorSection/Unit"; -import { AICFormationDescriptorSection_NumGroups } from "./AICFormationDescriptorSection/NumGroups"; -import { AICFormationDescriptorSection_Who } from "./AICFormationDescriptorSection/Who"; +import { AICFormation } from "./aicformation"; +import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; +import { AICFormationDescriptorSection_Formation } from "./aicformationdescriptorsection/formation"; +import { AICFormationDescriptorSection_Unit } from "./aicformationdescriptorsection/unit"; +import { AICFormationDescriptorSection_NumGroups } from "./aicformationdescriptorsection/numgroups"; +import { AICFormationDescriptorSection_Who } from "./aicformationdescriptorsection/who"; export interface AICFormationContextDataInterface { diff --git a/client/src/aic/AICFormationDescriptorComponent/Distance.ts b/client/src/aic/AICFormationDescriptorComponent/Distance.ts index fe942ac6..2a3766f3 100644 --- a/client/src/aic/AICFormationDescriptorComponent/Distance.ts +++ b/client/src/aic/AICFormationDescriptorComponent/Distance.ts @@ -1,4 +1,4 @@ -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; export abstract class AICFormactionDescriptorComponent_Distance extends AICFormationDescriptorComponent { diff --git a/client/src/aic/AICFormationDescriptorComponent/Distance/Range.ts b/client/src/aic/AICFormationDescriptorComponent/Distance/Range.ts index 88a23446..ab8a58d3 100644 --- a/client/src/aic/AICFormationDescriptorComponent/Distance/Range.ts +++ b/client/src/aic/AICFormationDescriptorComponent/Distance/Range.ts @@ -1,4 +1,4 @@ -import { AICFormactionDescriptorComponent_Distance } from "../Distance"; +import { AICFormactionDescriptorComponent_Distance } from "../distance"; export class AICFormationDescriptorComponent_Distance_Range extends AICFormactionDescriptorComponent_Distance { diff --git a/client/src/aic/AICFormationDescriptorPhrase.ts b/client/src/aic/AICFormationDescriptorPhrase.ts index 8ac473ac..b2a519a0 100644 --- a/client/src/aic/AICFormationDescriptorPhrase.ts +++ b/client/src/aic/AICFormationDescriptorPhrase.ts @@ -1,6 +1,6 @@ -import { AICFormation } from "./AICFormation"; -import { AICFormationContextDataInterface } from "./AICFormationDescriptor"; -import { AICFormationDescriptorComponent } from "./AICFormationDescriptorComponent"; +import { AICFormation } from "./aicformation"; +import { AICFormationContextDataInterface } from "./aicformationdescriptor"; +import { AICFormationDescriptorComponent } from "./aicformationdescriptorcomponent"; export interface AICFormationDescriptorPhraseInterface { "generate" : CallableFunction, diff --git a/client/src/aic/AICFormationDescriptorSection.ts b/client/src/aic/AICFormationDescriptorSection.ts index ede57edd..bcd2f3c3 100644 --- a/client/src/aic/AICFormationDescriptorSection.ts +++ b/client/src/aic/AICFormationDescriptorSection.ts @@ -1,6 +1,6 @@ -import { AICFormation } from "./AICFormation"; -import { AICFormationContextDataInterface } from "./AICFormationDescriptor"; -import { AICFormationDescriptorPhrase } from "./AICFormationDescriptorPhrase"; +import { AICFormation } from "./aicformation"; +import { AICFormationContextDataInterface } from "./aicformationdescriptor"; +import { AICFormationDescriptorPhrase } from "./aicformationdescriptorphrase"; export interface AICFormationDescriptorSectionInterface { "generate" : CallableFunction, diff --git a/client/src/aic/AICFormationDescriptorSection/Formation.ts b/client/src/aic/AICFormationDescriptorSection/Formation.ts index 9b742151..c77cb4be 100644 --- a/client/src/aic/AICFormationDescriptorSection/Formation.ts +++ b/client/src/aic/AICFormationDescriptorSection/Formation.ts @@ -1,8 +1,8 @@ -import { AICFormation } from "../AICFormation"; -import { AICFormationContextDataInterface } from "../AICFormationDescriptor"; -import { AICFormationDescriptorSection } from "../AICFormationDescriptorSection"; -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; -import { AICFormationDescriptorPhrase } from "../AICFormationDescriptorPhrase"; +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; export class AICFormationDescriptorSection_Formation extends AICFormationDescriptorSection { diff --git a/client/src/aic/AICFormationDescriptorSection/NumGroups.ts b/client/src/aic/AICFormationDescriptorSection/NumGroups.ts index 2714b8f6..81b92a86 100644 --- a/client/src/aic/AICFormationDescriptorSection/NumGroups.ts +++ b/client/src/aic/AICFormationDescriptorSection/NumGroups.ts @@ -1,8 +1,8 @@ -import { AICFormation } from "../AICFormation"; -import { AICFormationContextDataInterface } from "../AICFormationDescriptor"; -import { AICFormationDescriptorSection } from "../AICFormationDescriptorSection"; -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; -import { AICFormationDescriptorPhrase } from "../AICFormationDescriptorPhrase"; +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; export class AICFormationDescriptorSection_NumGroups extends AICFormationDescriptorSection { diff --git a/client/src/aic/AICFormationDescriptorSection/Unit.ts b/client/src/aic/AICFormationDescriptorSection/Unit.ts index 70743ee9..749fe625 100644 --- a/client/src/aic/AICFormationDescriptorSection/Unit.ts +++ b/client/src/aic/AICFormationDescriptorSection/Unit.ts @@ -1,8 +1,8 @@ -import { AICFormation } from "../AICFormation"; -import { AICFormationContextDataInterface } from "../AICFormationDescriptor"; -import { AICFormationDescriptorSection } from "../AICFormationDescriptorSection"; -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; -import { AICFormationDescriptorPhrase } from "../AICFormationDescriptorPhrase"; +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; interface addUnitInformationInterface { omitTrack?: boolean diff --git a/client/src/aic/AICFormationDescriptorSection/Who.ts b/client/src/aic/AICFormationDescriptorSection/Who.ts index 5856c871..244b0558 100644 --- a/client/src/aic/AICFormationDescriptorSection/Who.ts +++ b/client/src/aic/AICFormationDescriptorSection/Who.ts @@ -1,8 +1,8 @@ -import { AICFormation } from "../AICFormation"; -import { AICFormationContextDataInterface } from "../AICFormationDescriptor"; -import { AICFormationDescriptorSection } from "../AICFormationDescriptorSection"; -import { AICFormationDescriptorComponent } from "../AICFormationDescriptorComponent"; -import { AICFormationDescriptorPhrase } from "../AICFormationDescriptorPhrase"; +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; export class AICFormationDescriptorSection_Who extends AICFormationDescriptorSection { diff --git a/client/src/aic/aic.ts b/client/src/aic/aic.ts index a28aaa9d..770fd695 100644 --- a/client/src/aic/aic.ts +++ b/client/src/aic/aic.ts @@ -1,8 +1,8 @@ -import { ToggleableFeature } from "../ToggleableFeature"; -import { AICFormation_Azimuth } from "./AICFormation/Azimuth"; -import { AICFormation_Range } from "./AICFormation/Range"; -import { AICFormation_Single } from "./AICFormation/Single"; -import { AICFormationDescriptorSection } from "./AICFormationDescriptorSection"; +import { ToggleableFeature } from "../toggleablefeature"; +import { AICFormation_Azimuth } from "./aicformation/azimuth"; +import { AICFormation_Range } from "./aicformation/range"; +import { AICFormation_Single } from "./aicformation/single"; +import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; export class AIC extends ToggleableFeature { diff --git a/client/src/aic/aicformation.ts b/client/src/aic/aicformation.ts new file mode 100644 index 00000000..588f4326 --- /dev/null +++ b/client/src/aic/aicformation.ts @@ -0,0 +1,54 @@ +import { AICFormationContextDataInterface, AICFormationDescriptor } from "./aicformationdescriptor"; +import { AICFormationDescriptorPhrase } from "./aicformationdescriptorphrase"; +import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; + +export interface AICFormationInterface { + "icon" : string, + "label" : string, + "name" : string, + "numGroups" : number, + "summary" : string, + "unitBreakdown" : string[] +} + + + +export abstract class AICFormation { + + "icon" = ""; + "label" = ""; + "name" = ""; + "numGroups" = 1; + "summary" = ""; + "unitBreakdown":string[] = [] + + + constructor() { + + this.unitBreakdown = []; + } + + + addToDescriptorPhrase( section: AICFormationDescriptorSection, phrase: AICFormationDescriptorPhrase, contextData: AICFormationContextDataInterface ) { + return phrase; + } + + + getDescriptor( contextData: AICFormationContextDataInterface ) { + + return new AICFormationDescriptor().generate( this, contextData ); + + } + + + hasUnitBreakdown() { + return this.unitBreakdown.length > 0; + } + + + showFormationNameInDescriptor() { + return true; + } + + +} \ No newline at end of file diff --git a/client/src/aic/aicformation/azimuth.ts b/client/src/aic/aicformation/azimuth.ts new file mode 100644 index 00000000..7db676ae --- /dev/null +++ b/client/src/aic/aicformation/azimuth.ts @@ -0,0 +1,38 @@ +import { AICFormation, AICFormationInterface } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; + +export class AICFormation_Azimuth extends AICFormation implements AICFormationInterface { + + "icon" = "azimuth.png"; + "label" = "Azimuth"; + "name" = "azimuth"; + "numGroups" = 2; + "summary" = "Two contacts, side-by-side in a line perpedicular to the perspective."; + "unitBreakdown" = [ " group", " group" ]; + + constructor() { + + super(); + + } + + addToDescriptorPhrase( section: AICFormationDescriptorSection, phrase: AICFormationDescriptorPhrase, contextData: AICFormationContextDataInterface ) { + + switch ( section.name ) { + + case "formation": + + phrase.addComponent( new AICFormationDescriptorComponent( "" ) ); + phrase.addComponent( new AICFormationDescriptorComponent( "track " ) ); + + } + + return phrase; + + + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformation/range.ts b/client/src/aic/aicformation/range.ts new file mode 100644 index 00000000..08c00cd5 --- /dev/null +++ b/client/src/aic/aicformation/range.ts @@ -0,0 +1,38 @@ +import { AICFormation, AICFormationInterface } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; + +export class AICFormation_Range extends AICFormation implements AICFormationInterface { + + "icon" = "range.png"; + "label" = "Range"; + "name" = "range"; + "numGroups" = 2; + "summary" = "Two contacts, one behind the other"; + "unitBreakdown" = [ "Lead group", "Trail group" ]; + + constructor() { + + super(); + + } + + addToDescriptorPhrase( section: AICFormationDescriptorSection, phrase: AICFormationDescriptorPhrase, contextData: AICFormationContextDataInterface ) { + + switch ( section.name ) { + + case "formation": + + phrase.addComponent( new AICFormationDescriptorComponent( "" ) ); + phrase.addComponent( new AICFormationDescriptorComponent( "track " ) ); + + + } + + return phrase; + + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformation/single.ts b/client/src/aic/aicformation/single.ts new file mode 100644 index 00000000..09830c40 --- /dev/null +++ b/client/src/aic/aicformation/single.ts @@ -0,0 +1,24 @@ +import { AICFormation, AICFormationInterface } from "../aicformation"; +import { AICFormationContextDataInterface, AICFormationDescriptor } from "../aicformationdescriptor"; + +export class AICFormation_Single extends AICFormation implements AICFormationInterface { + + "icon" = "single.png"; + "label" = "Single"; + "name" = "single"; + "numGroups" = 1; + "summary" = "One contact on its own"; + "unitBreakdown" = []; + + constructor() { + + super(); + + } + + + showFormationNameInDescriptor() { + return false; + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptor.ts b/client/src/aic/aicformationdescriptor.ts new file mode 100644 index 00000000..c7a5a563 --- /dev/null +++ b/client/src/aic/aicformationdescriptor.ts @@ -0,0 +1,55 @@ +import { AICFormation } from "./aicformation"; +import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; +import { AICFormationDescriptorSection_Formation } from "./aicformationdescriptorsection/formation"; +import { AICFormationDescriptorSection_Unit } from "./aicformationdescriptorsection/unit"; +import { AICFormationDescriptorSection_NumGroups } from "./aicformationdescriptorsection/numgroups"; +import { AICFormationDescriptorSection_Who } from "./aicformationdescriptorsection/who"; + + +export interface AICFormationContextDataInterface { + "aicCallsign" : string, + "bullseyeName" : string, + "control" : "broadcast" | "tactical", + "numGroups" : number +} + + +export class AICFormationDescriptor { + + #sections:AICFormationDescriptorSection[] = [ + new AICFormationDescriptorSection_Who(), + new AICFormationDescriptorSection_NumGroups(), + new AICFormationDescriptorSection_Formation(), + new AICFormationDescriptorSection_Unit() + ] + + constructor() { + } + + + addSection( section:AICFormationDescriptorSection ) { + this.#sections.push( section ); + } + + + getSections() { + return this.#sections; + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + let output:object[] = []; + + for ( const section of this.#sections ) { + output.push( + section.generate( formation, contextData ) + ); + } + + return output; + + } + + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorcomponent.ts b/client/src/aic/aicformationdescriptorcomponent.ts new file mode 100644 index 00000000..da194576 --- /dev/null +++ b/client/src/aic/aicformationdescriptorcomponent.ts @@ -0,0 +1,18 @@ +interface ComponentInterface { + "label" : string; + "value" : string; +} + +export class AICFormationDescriptorComponent implements ComponentInterface { + + label = "(not set)"; + value = "(not set)"; + + constructor( value:any, label?:string ) { + + this.label = label || "(not set)"; + this.value = value; + + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorcomponent/distance.ts b/client/src/aic/aicformationdescriptorcomponent/distance.ts new file mode 100644 index 00000000..2a3766f3 --- /dev/null +++ b/client/src/aic/aicformationdescriptorcomponent/distance.ts @@ -0,0 +1,9 @@ +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; + +export abstract class AICFormactionDescriptorComponent_Distance extends AICFormationDescriptorComponent { + + constructor( value:string, label?:string ) { + super( value, label ); + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorcomponent/distance/range.ts b/client/src/aic/aicformationdescriptorcomponent/distance/range.ts new file mode 100644 index 00000000..ab8a58d3 --- /dev/null +++ b/client/src/aic/aicformationdescriptorcomponent/distance/range.ts @@ -0,0 +1,9 @@ +import { AICFormactionDescriptorComponent_Distance } from "../distance"; + +export class AICFormationDescriptorComponent_Distance_Range extends AICFormactionDescriptorComponent_Distance { + + constructor( value:string, label?:string ) { + super( value, label ); + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorphrase.ts b/client/src/aic/aicformationdescriptorphrase.ts new file mode 100644 index 00000000..b2a519a0 --- /dev/null +++ b/client/src/aic/aicformationdescriptorphrase.ts @@ -0,0 +1,40 @@ +import { AICFormation } from "./aicformation"; +import { AICFormationContextDataInterface } from "./aicformationdescriptor"; +import { AICFormationDescriptorComponent } from "./aicformationdescriptorcomponent"; + +export interface AICFormationDescriptorPhraseInterface { + "generate" : CallableFunction, + "label" : string, + "name" : string +} + +export class AICFormationDescriptorPhrase { + + #components : AICFormationDescriptorComponent[] = []; + label = ""; + name = ""; + + constructor() { + } + + + addComponent( component:AICFormationDescriptorComponent ) { + this.#components.push( component ); + return this; + } + + + + getComponents() { + return this.#components; + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + return this; + + } + + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorsection.ts b/client/src/aic/aicformationdescriptorsection.ts new file mode 100644 index 00000000..bcd2f3c3 --- /dev/null +++ b/client/src/aic/aicformationdescriptorsection.ts @@ -0,0 +1,40 @@ +import { AICFormation } from "./aicformation"; +import { AICFormationContextDataInterface } from "./aicformationdescriptor"; +import { AICFormationDescriptorPhrase } from "./aicformationdescriptorphrase"; + +export interface AICFormationDescriptorSectionInterface { + "generate" : CallableFunction, + "label" : string, + "name" : string, + "omitSection" : boolean +} + +export abstract class AICFormationDescriptorSection { + + #phrases : AICFormationDescriptorPhrase[] = []; + label = ""; + name = ""; + omitSection = false; + + constructor() { + } + + + addPhrase( phrase:AICFormationDescriptorPhrase ) { + this.#phrases.push( phrase ); + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + return this; + + } + + + getPhrases() { + return this.#phrases; + } + + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorsection/formation.ts b/client/src/aic/aicformationdescriptorsection/formation.ts new file mode 100644 index 00000000..c77cb4be --- /dev/null +++ b/client/src/aic/aicformationdescriptorsection/formation.ts @@ -0,0 +1,39 @@ +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; + +export class AICFormationDescriptorSection_Formation extends AICFormationDescriptorSection { + + label = "Formation"; + name = "formation"; + + constructor() { + + super(); + + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + if ( !formation.showFormationNameInDescriptor() ) { + this.omitSection = true; + return this; + } + + let phrase = new AICFormationDescriptorPhrase(); + + phrase.addComponent( new AICFormationDescriptorComponent( formation.label, "Formation" ) ); + + phrase = formation.addToDescriptorPhrase( this, phrase, contextData ); + + this.addPhrase( phrase ); + + + return this; + + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorsection/numgroups.ts b/client/src/aic/aicformationdescriptorsection/numgroups.ts new file mode 100644 index 00000000..81b92a86 --- /dev/null +++ b/client/src/aic/aicformationdescriptorsection/numgroups.ts @@ -0,0 +1,35 @@ +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; + +export class AICFormationDescriptorSection_NumGroups extends AICFormationDescriptorSection { + + label = "Groups"; + name = "numgroups"; + + constructor() { + + super(); + + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + let value = "Single group"; + + if ( contextData.numGroups > 1 ) { + value = contextData.numGroups + " groups"; + } + + let phrase = new AICFormationDescriptorPhrase(); + phrase.addComponent( new AICFormationDescriptorComponent( value, "Number of groups" ) ); + this.addPhrase( phrase ); + + return this; + + } + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorsection/unit.ts b/client/src/aic/aicformationdescriptorsection/unit.ts new file mode 100644 index 00000000..749fe625 --- /dev/null +++ b/client/src/aic/aicformationdescriptorsection/unit.ts @@ -0,0 +1,83 @@ +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; + +interface addUnitInformationInterface { + omitTrack?: boolean +} + +export class AICFormationDescriptorSection_Unit extends AICFormationDescriptorSection { + + label = "Unit"; + name = "unit"; + + constructor() { + + super(); + + } + + + addUnitInformation( formation:AICFormation, contextData: AICFormationContextDataInterface, phrase: AICFormationDescriptorPhrase, options?:addUnitInformationInterface ) { + + options = options || {}; + + const originPoint = ( contextData.control === "broadcast" ) ? contextData.bullseyeName : "BRAA"; + + phrase.addComponent( new AICFormationDescriptorComponent( originPoint, "Bearing origin point" ) ); + phrase.addComponent( new AICFormationDescriptorComponent( "", "Bearing" ) ); + phrase.addComponent( new AICFormationDescriptorComponent( "", "Range" ) ); + phrase.addComponent( new AICFormationDescriptorComponent( "", "Altitude" ) ); + + if ( contextData.control === "broadcast" ) { + if ( !options.hasOwnProperty( "omitTrack" ) || options.omitTrack !== true ) { + phrase.addComponent( new AICFormationDescriptorComponent( "track ", "Tracking" ) ); + } + } else { + phrase.addComponent( new AICFormationDescriptorComponent( "[hot|flanking [left|right]|beam |cold]", "Azimuth" ) ); + } + + return phrase; + + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + if ( formation.hasUnitBreakdown() ) { + + for ( const [ i, unitRef ] of formation.unitBreakdown.entries() ) { + + let phrase = new AICFormationDescriptorPhrase(); + + phrase.addComponent( new AICFormationDescriptorComponent( unitRef, "Unit reference" ) ); + + if ( i === 0 ) { + this.addUnitInformation( formation, contextData, phrase, { "omitTrack": true } ); + } else { + phrase.addComponent( new AICFormationDescriptorComponent( "" ) ); + } + + phrase.addComponent( new AICFormationDescriptorComponent( "hostile" ) ); + + this.addPhrase( phrase ); + + + } + + } else { + + this.addPhrase( + this.addUnitInformation( formation, contextData, new AICFormationDescriptorPhrase() ) + ); + + } + + return this; + + } + + +} \ No newline at end of file diff --git a/client/src/aic/aicformationdescriptorsection/who.ts b/client/src/aic/aicformationdescriptorsection/who.ts new file mode 100644 index 00000000..244b0558 --- /dev/null +++ b/client/src/aic/aicformationdescriptorsection/who.ts @@ -0,0 +1,35 @@ +import { AICFormation } from "../aicformation"; +import { AICFormationContextDataInterface } from "../aicformationdescriptor"; +import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; +import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; +import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; + +export class AICFormationDescriptorSection_Who extends AICFormationDescriptorSection { + + label = "Who"; + name = "who"; + + constructor() { + + super(); + + } + + + generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { + + let phrase = new AICFormationDescriptorPhrase(); + + if ( contextData.control === "tactical" ) { + phrase.addComponent( new AICFormationDescriptorComponent( "", "Their callsign" ) ); + } + + phrase.addComponent( new AICFormationDescriptorComponent( contextData.aicCallsign, "Your callsign" ) ); + + this.addPhrase( phrase ); + + return this; + + } + +} \ No newline at end of file diff --git a/client/src/atc/ATC.ts b/client/src/atc/ATC.ts index c409b02e..14710071 100644 --- a/client/src/atc/ATC.ts +++ b/client/src/atc/ATC.ts @@ -1,6 +1,6 @@ -import { ToggleableFeature } from "../ToggleableFeature"; +import { ToggleableFeature } from "../toggleablefeature"; import Sortable from 'sortablejs'; -import { ATCFLightList } from "./FlightList"; +import { ATCFLightList } from "./flightlist"; export class ATC extends ToggleableFeature { diff --git a/client/src/atc/ATCMockAPI/Flights.ts b/client/src/atc/ATCMockAPI/Flights.ts index b710b016..6d6b6435 100644 --- a/client/src/atc/ATCMockAPI/Flights.ts +++ b/client/src/atc/ATCMockAPI/Flights.ts @@ -1,4 +1,4 @@ -import { ATCMockAPI } from "../ATCMockAPI"; +import { ATCMockAPI } from "../atcmockapi"; export class ATCMockAPI_Flights extends ATCMockAPI { diff --git a/client/src/atc/FlightList.ts b/client/src/atc/FlightList.ts index a24a55e2..36185eef 100644 --- a/client/src/atc/FlightList.ts +++ b/client/src/atc/FlightList.ts @@ -1,4 +1,4 @@ -import { ATCMockAPI_Flights } from "./ATCMockAPI/Flights"; +import { ATCMockAPI_Flights } from "./atcmockapi/flights"; export class ATCFLightList { diff --git a/client/src/atc/atc.ts b/client/src/atc/atc.ts new file mode 100644 index 00000000..14710071 --- /dev/null +++ b/client/src/atc/atc.ts @@ -0,0 +1,87 @@ +import { ToggleableFeature } from "../toggleablefeature"; +import Sortable from 'sortablejs'; +import { ATCFLightList } from "./flightlist"; + +export class ATC extends ToggleableFeature { + + constructor() { + + super( true ); + + //this.#generateFlightList(); + + let $list = document.getElementById( "atc-strip-board-arrivals" ); + + if ( $list instanceof HTMLElement ) { + Sortable.create( $list, { + "handle": ".handle" + }); + } + + } + + + #generateFlightList() { + + const flightList = new ATCFLightList(); + const flights:any = flightList.getFlights( true ); + + const $tbody = document.getElementById( "atc-flight-list-table-body" ); + + if ( $tbody instanceof HTMLElement ) { + + if ( flights.length > 0 ) { + + let flight:any = {}; + + let $button, i; + + for ( [ i, flight ] of flights.entries() ) { + + const $row = document.createElement( "tr" ); + $row.dataset.status = flight.status + + let $td = document.createElement( "td" ); + $td.innerText = flight.name; + $row.appendChild( $td ); + + $td = document.createElement( "td" ); + $td.innerText = flight.takeOffTime; + $row.appendChild( $td ); + + $td = document.createElement( "td" ); + $td.innerText = "00:0" + ( 5 + i ); + $row.appendChild( $td ); + + $td = document.createElement( "td" ); + $td.innerText = flight.status; + $row.appendChild( $td ); + + + $td = document.createElement( "td" ); + $button = document.createElement( "button" ); + $button.innerText = "..."; + + $td.appendChild( $button ); + + $row.appendChild( $td ); + + + $tbody.appendChild( $row ); + + } + + } + + } + + } + + + protected onStatusUpdate(): void { + + document.body.classList.toggle( "atc-enabled", this.getStatus() ); + + } + +} \ No newline at end of file diff --git a/client/src/atc/atcmockapi.ts b/client/src/atc/atcmockapi.ts new file mode 100644 index 00000000..9720e2d0 --- /dev/null +++ b/client/src/atc/atcmockapi.ts @@ -0,0 +1,7 @@ +export abstract class ATCMockAPI { + + constructor() {} + + generateMockData() {} + +} \ No newline at end of file diff --git a/client/src/atc/atcmockapi/flights.ts b/client/src/atc/atcmockapi/flights.ts new file mode 100644 index 00000000..6d6b6435 --- /dev/null +++ b/client/src/atc/atcmockapi/flights.ts @@ -0,0 +1,40 @@ +import { ATCMockAPI } from "../atcmockapi"; + +export class ATCMockAPI_Flights extends ATCMockAPI { + + + generateMockData() { + + let data = []; + const statuses = [ "unknown", "checkedIn", "readyToTaxi" ] + + for ( const [ i, flightName ] of [ "Shark", "Whale", "Dolphin" ].entries() ) { + + data.push({ + "name": flightName, + "status": statuses[ i ], + "takeOffTime": "18:0" + i + }); + + } + + localStorage.setItem( "flightList", JSON.stringify( data ) ); + + } + + + get( generateMockDataIfEmpty?:boolean ) : object { + + generateMockDataIfEmpty = generateMockDataIfEmpty || false; + + let data = localStorage.getItem( "flightList" ) || "[]"; + + if ( data === "[]" && generateMockDataIfEmpty ) { + this.generateMockData(); + } + + return JSON.parse( data ); + + } + +} \ No newline at end of file diff --git a/client/src/atc/flightlist.ts b/client/src/atc/flightlist.ts new file mode 100644 index 00000000..36185eef --- /dev/null +++ b/client/src/atc/flightlist.ts @@ -0,0 +1,18 @@ +import { ATCMockAPI_Flights } from "./atcmockapi/flights"; + +export class ATCFLightList { + + + constructor() { + + + + } + + + getFlights( generateMockDataIfEmpty?:boolean ) { + let api = new ATCMockAPI_Flights(); + return api.get( generateMockDataIfEmpty ); + } + +} \ No newline at end of file diff --git a/client/src/featureswitches.ts b/client/src/featureswitches.ts new file mode 100644 index 00000000..ed52d8eb --- /dev/null +++ b/client/src/featureswitches.ts @@ -0,0 +1,161 @@ +export interface FeatureSwitchInterface { + "defaultEnabled": boolean, // default on/off state (if allowed by masterSwitch) + "label": string, + "masterSwitch": boolean, // on/off regardless of user preference + "name": string, + "onEnabled"?: CallableFunction, + "options"?: object, + "removeArtifactsIfDisabled"?: boolean +} + + +class FeatureSwitch { + + // From config param + defaultEnabled; + label; + masterSwitch; + name; + onEnabled; + removeArtifactsIfDisabled = true; + + // Self-set + userPreference; + + + constructor( config:FeatureSwitchInterface ) { + + this.defaultEnabled = config.defaultEnabled; + this.label = config.label; + this.masterSwitch = config.masterSwitch; + this.name = config.name; + this.onEnabled = config.onEnabled; + + this.userPreference = this.getUserPreference(); + + } + + + getUserPreference() { + + let preferences = JSON.parse( localStorage.getItem( "featureSwitches" ) || "{}" ); + + return ( preferences.hasOwnProperty( this.name ) ) ? preferences[ this.name ] : this.defaultEnabled; + + } + + + isEnabled() { + + if ( !this.masterSwitch ) { + return false; + } + + return this.userPreference; + } + +} + +export class FeatureSwitches { + + #featureSwitches:FeatureSwitch[] = [ + + new FeatureSwitch({ + "defaultEnabled": false, + "label": "AIC", + "masterSwitch": true, + "name": "aic" + }), + + new FeatureSwitch({ + "defaultEnabled": false, + "label": "AI Formations", + "masterSwitch": true, + "name": "ai-formations", + "removeArtifactsIfDisabled": false + }), + + new FeatureSwitch({ + "defaultEnabled": false, + "label": "ATC", + "masterSwitch": true, + "name": "atc" + }), + + new FeatureSwitch({ + "defaultEnabled": false, + "label": "Force show unit control panel", + "masterSwitch": true, + "name": "forceShowUnitControlPanel" + }), + + new FeatureSwitch({ + "defaultEnabled": false, + "label": "Show splash screen", + "masterSwitch": true, + "name": "splashScreen" + }) + + ]; + + + constructor() { + + this.#testSwitches(); + + this.savePreferences(); + + } + + + getSwitch( switchName:string ) { + + return this.#featureSwitches.find( featureSwitch => featureSwitch.name === switchName ); + + } + + + #testSwitches() { + + for ( const featureSwitch of this.#featureSwitches ) { + + if ( featureSwitch.isEnabled() ) { + + if ( typeof featureSwitch.onEnabled === "function" ) { + featureSwitch.onEnabled(); + } + + } else { + + document.querySelectorAll( "[data-feature-switch='" + featureSwitch.name + "']" ).forEach( el => { + + if ( featureSwitch.removeArtifactsIfDisabled === false ) { + el.remove(); + } else { + el.classList.add( "hide" ); + } + + }); + + } + + document.body.classList.toggle( "feature-" + featureSwitch.name, featureSwitch.isEnabled() ); + + } + + } + + + savePreferences() { + + let preferences:any = {}; + + for ( const featureSwitch of this.#featureSwitches ) { + preferences[ featureSwitch.name ] = featureSwitch.isEnabled(); + } + + localStorage.setItem( "featureSwitches", JSON.stringify( preferences ) ); + + } + +} \ No newline at end of file diff --git a/client/src/index.ts b/client/src/index.ts index f74f7476..130c3717 100644 --- a/client/src/index.ts +++ b/client/src/index.ts @@ -6,8 +6,8 @@ import { MissionHandler } from "./missionhandler/missionhandler"; import { UnitControlPanel } from "./panels/unitcontrolpanel"; import { MouseInfoPanel } from "./panels/mouseinfopanel"; import { AIC } from "./aic/aic"; -import { ATC } from "./atc/ATC"; -import { FeatureSwitches } from "./FeatureSwitches"; +import { ATC } from "./atc/atc"; +import { FeatureSwitches } from "./featureswitches"; import { LogPanel } from "./panels/logpanel"; import { getAirbases, getBulllseye as getBulllseyes, getMission, getUnits, toggleDemoEnabled } from "./server/server"; diff --git a/client/src/toggleablefeature.ts b/client/src/toggleablefeature.ts new file mode 100644 index 00000000..5873fb6e --- /dev/null +++ b/client/src/toggleablefeature.ts @@ -0,0 +1,35 @@ +export abstract class ToggleableFeature { + + #status:boolean = false; + + + constructor( defaultStatus:boolean ) { + + this.#status = defaultStatus; + + this.onStatusUpdate(); + + } + + + getStatus() : boolean { + return this.#status; + } + + + protected onStatusUpdate() {} + + + toggleStatus( force?:boolean ) : void { + + if ( force ) { + this.#status = force; + } else { + this.#status = !this.#status; + } + + this.onStatusUpdate(); + + } + +} \ No newline at end of file diff --git a/installer/DCSOlympus.iss b/installer/olympus.iss similarity index 100% rename from installer/DCSOlympus.iss rename to installer/olympus.iss diff --git a/missions/olympus.miz b/missions/olympus.miz new file mode 100644 index 0000000000000000000000000000000000000000..eaf4b79701d7d4ba9f6f67616061cee63c5ced49 GIT binary patch literal 7456 zcmZ`;1yCH_vR+(+ySuvvOK{g+++70%XK}Xx!96&^J-7u(kSy+j;0}vx&`0ijb^mu$ zb*HM&be-w%tFE4zI^Q|1t^@~<2Y>}20{{Rjz>}}U^CTt!U|0eGAic~u+PS&eIXfL0 zIl2|S#(By$S>J##Xw{=d-z+U+#+&eTtK{Sy{p{-c$r`ipx&Seh@V#{>=zdj=sxBOh zNS=YzFSoM&6E?6iPrGt<+5Ys$xj)21|83J)_ot?bJhdE~r}}zPHWf#!X;=U0>w zAKypza2OnULfi@1y@n6SL3%{N3Yg#30(f6>`oMyzOmHyo1_)Z<8m{I%LQ2cTj+MEC z7#GiuouNTuwH=0wX;NIN$3Y^aMmA;$@-zYMCe57R5rq;8?M4o;OkO2ZCw6?zP zx&72}Ti?`2(26Sw4U?3HK5gkYjr|vz5xT@v2ri)9d)8`vioJ~Nue|T_JTZx#XfEtF zC^Rs8Drq|DcWd*loQIDq%TEn>i~<6`i3Bf@rUg3xbi!KdFd1QV$bFYaZ~n_tHZvto zIm8h6UT%-7O|r~7;#sJ$Kl}}Jd`H{HeFA~w%)TcBQFyG2Y*0YA?TJK8;L5Z^ps{y> z5F&(SLlpeu!mrKaVxGa^oEr#XZM54&;q^0=+wcXcCNcANer-uZQHF&1#HS~^2a#{~ z3S5=k%OBE#4aWsm`UeC)2}$whqA#(}#qy(eDCaPuY(D$Rp(NATzBTB+GX1Gt$DV5z zyg^R8&M|}f#tS2fjyu_zgh`h^?KdkWoBVmalOUKW3;!GabIyJvO915~ z`P3xbjp=RuioD(dK_Qn3QhcDeDGJ_PeLbj#?&Db)iMi4Cz)oX5*K3}^vnX@VYnM|S z1eyEf2_9KMFyl{p!#OC*u60>_j|}Eg1)WkpoF)}&Og>9G^T38JsXXkKhlXd%F&kRzF>GG3*+)rRnRKq5EF7n4LL}*k4 zrPGdC<*IpRE2NWAG%HD(6*Y?pJW5aixkEuG1~3Go%jk9nQQ5Tb0aK&cqTJIWeT>$& zasd8zepn{!+YeYF==;dD?5~I<@b;zb1Lmxf}HFM3YkQeG&F-tnAA<}V%X~W zWK#9AXg;v11mh@yEQ3o}Pz|&+6U$lEEe>MPGuvrSm5nqsKi4F922bF_aHYy1DqCSw z8R#u6(pnJ^E>R?JL8iB(7aVrmu!{Baqt&O(eIr_PeO;ypc$6NarAy<-ri zuE@tI83rs|N7mJ{TYT|`ZMkF>c$wCkM)>5I==Ce%V|n_$!hi+yz$o>YFJ;o57yB#b zVZh>2JZ?pj&L|D*EZP*Hb&>hur%arp5k8B!l5~l04w=EBH}s<|VK?+D27TI*PT!Z3 zj1`$-nXTe!-u3PCC)c5jWA&yn@>;UsjHHkq0lrdgW#+$t4ihT7d%H2zudILxdAUb$W%uS=0bJ7rlaMat9QbD_y! zoetbBG2-tni75uNG%^6xBKsQ{fJuvxkZKy#GdJ>`f}V$xTJWa^=Nwy zt!r8YRo5JqqG2tC>qQ2r_59dJVox<;|l@U@D_x7?6QIR|0Mjm#J6TTf%dw^dcFJ@YeeyulqehMCx;Ht}xF zo_?ySxoGSzrrl{d=5dgpk(@;az`O(O_~g$nD)?K!afAn0lzS@$mb~M)MVpVMB;Kdb zwk?$QwN)N()$m07%Mwa<7cq1F2Bl7@;$fQe*Jm$K3H>kD1P~`$}6P9yE(QlR0Ot7`BRGZ#29~(@pz%>Zg*MbTd?&ZtXX9gP$wT@NX%CwMKEdt8z{W zCV~68+#jng_^rU}LbuV4)w^{;96~w(P9(MJ{honpH~hyE2k`pijSPL#lMQ5mzwj5* z;aU0OLOSJeaVA-F@J!`5@iN!#*{s(9PC@?1hZ1zb&I4foy9aN5+Zw6dEhwxTmw9@7CzXdzhyWNrB<&=xmMqpZDwL0 zshf~=g7mNF&u{wX`<6Uu^`lgg8_uBf7=sw#xWX3k;Tx!j%yRK^>HyjbdhiQ;LOc?}Dwxh^~|(Kll@-0gj3(&i@6`YUf!sZm{sqU1IX z6i%NM z>@taaCE0M74c}4!{o|}&Nja}aic9&=!)|2t%AAkmwHuqO7Dp?pIQ)k<6&y0v=j%S< zsTDt@77}ID)pb#{@a-k#iYlL12RFi8!T0To>J2rnN$c@LzjA-Dm_T!Ley~6~TuK{$ zfa*uf7j}Hrd|8^!roc#6sWGscO}GdPg+mTk5EcaE1Nq6yr9yX>N>RPLA&Nt2v1(_1i;Jh|~C73cY>rtWX;@YKHYx^qok zg}vuQJZ)4DG*)~CO>ZV8EM!qkdpzwq&oGl?_+5PMkmvcnAJg9tJ6gS~drDW1H}Lt^ zH$2ulvz2t7x{TYkn|rQ~oZ`F0j5^Y|*_>UDd~W*%JJf1#YY26%@3J{tRnk3I!4k)5 zd2Bixb88=oeX3T=%)F~FyJ+}1RztKp6_;SXRNpS8$98mn+2vaT8!u;P|H@sLBNv*} zxsGZiAH`$wRE~R~2;k6LMehke+3msu$*^{++<_qXkJiHVFN@(tGCLInb%sv`o2Mmb zQcV~do(?uXk5sj1Gpf6X0>{Sfp#ebJdpDBuyeawTSj012k}67=b;TNnvwq57kU8cP zIg>J!O||fqaLTjM`#yYb>{JP{qn7^rSDottAa5D$31$OuPwG_6j`L`aNi!I;BRO-) z+;4tf=@GExw+Tk(7gpWWr7I7WQjIqINy@pqu;sHHphoE_CrHT%_ZYyFq1xZ$?ri-% zTv$yFylUo2xiG1Ip1Id~ImhVK)L^cH_)`w)4a5)-3J}@9?ntila2Lr?xg6fR>sLOB zw;3L?HhU8r@zCAAe(1oO@piwt4Lu7XW#?1SEIBQVvgJ|w@`f7H=KivDUP0i2V5nLD zWh;7a=dwsgwuduGr=!KwaGt;dhp3L+z;U@5Nw#@sYCFgq|G#E*8mMiMMX-E!JZ~Gfgn9J@N9VQEM@yYJ?`A$n3ez zgPjNp!*)Y$jP}|n`t>4REIX%n!a;PaTftlh{_ot`de?f~ixfNBSPzA5KPI*>BnRvpbPBQT{UswG5(QAr3 znK8Ij`;V8ub&p>)n7ZCrdo6B>5xbf|nfTP5FEolbAac`o`rgF#Bl7G57f<%%Li>&A zkzHLO#(`vlBR0bgc{akI8;`3de}9Juz?}9EMzmWn4}h%u+$q=x{d8=T<~ck^X1VB5 zsv6A9-RUUwQshm|(-8PB2N=GK!a&n8rTo1sX-#b0=eI7pkdgNDWrc!vWTV)g&|HZH zy}FJ^_ui@~nc#mN5_v5bcikqJGEQ#qb|dd;b#q!{X+p=xJ#PqKJXL;oXzSwAIa|IL8-=FXJqt7yNk``^XD|UQeW$I_dDK@OOGkx5~5jFtAF4WQM+-(~3Cp;XC z+j}wla~7Tj#;-q5gkl;Ul^8Lm``q- zm+mJ_cPSe4PL2g8QA}xuYTFzrBpHJ2w{him`jYd{J?(EtGa`EMnj#Y#D&jhb8lpc? zA51=}v~0}^&Sz(T=-|I9+z{MZb6?%^zq-@`3X?`=yg_7B@&n<; z+9}^iakO_+Kv}5GQyF!O`7?NRK-$(ReFP(;@R?4$@CUwdyjHa~z<=f`Bxg`V`;s5? zixK^ur=!_>pp~1mhpUAZM1>7mk$sGlT~Sr*Uzt{DP0VV^k1A;lsey)M)t;x4J$v#Haao&rkwRE8h6 z&v%ap_f6(>l=!pX@5H&U7$y|xEY2M?Ac-=U3T&e;vKkcZ`qkF#J5BqJj$ph1Crw!uR(Hi6fv99#zSNHlplsb8R}_a=yUgWZhi*|ztF9Wr+5;{)(!XiPdGBlFF!w?dC)t#)S>x9~Ul=?5+{=u;2H`UHd2% z*gldc_Q%D1aM>HDxUix8chvZUP|(|d5kx+baRo}F0br;A@Ii*2l+CT;dw~(+SjezK z_)&u5XnfR?RLJnbIjG+{un-opsIlNf#8nYC{G(vwqF#a|s7hhaRHcKprC)-m5wAydE+|t$c z*;G`DmKsox#_T;Q5|z4Vu~|C$v%Rz&nM=C553^b(%QAW-4B>Acm-dGPRaN(IY8#XK z5oZONPNA!p4^Yw?HQY7B#*)|fGg$b_j6*`mDcU;jvl6343<|DXXIasjH5PZJub4m@ zBvxmj5ASQJz=2ucZ~OCczHZ|8H(e)LZ@T0#e|t@Rh6ise%Uwl%=GK}DEKv^X_5Sf? zx@qp5cx1m357H>WO^2eSL6pP{H&ES|Wrt|!)vDUNP$*2&LV1|u&PklkU_9i$87P>T zV*!M*e8BUeO)^yI4M^Gm648Uj;}NLsl%DnC69`(KFY!=bm)|+1IBQ!TkQTc+r@)Ey4qA@INa)O=fIZ- ze#Pftw8J)<35{?N9xfyU>xQ04^dMvjdP@hi;VtjfY|P%@8b0ak_%JLuZii~haeb}K z{h`CM?^}d@3^(;yNl}62k$1LAbpIYp2C#u4V?~x5oVn#m$SAdWT~hYC#cB_-Y?#1A z%w!iYRq{AEqv~Ro?owe&jy#RJH<-SUW*eBxjBgz_+{fc&&R|}*G(@J}KsmH8Tc8Ir z8j$Oq=)mI=mxOy=Kw}SMFXh+WP84&jQ`taEH^wvbF;mo-MSB2vDlXNq1|*0?FD%iD z9;Cj0WAMqp?ZMAqezzZg2|*T@RtdpsEJ-|1FMm$+=~B!kzD(mg_2LY-I%-Z~0fXu) zE}lw$Y=>T2G;YKka^*Ps7fxK3{NoeExbKF{4x=|^|GV=lHc?B2dsxkK{0q=o$ zcG_{G-vQJ%m_+rpJUF<0Uq$_b$tU+!UX7mp!JN~>{0EB1t^0(h%viViEEA4<3+;Ta zFk^+XHR5@khXvurQf0+-u(PetrEODoSXoyM_CptREMMsOZs2V1a44Jg2E|pd-yka& z7RBw{`)S*rWL5N;Ho#{w*?qXV*rdiONUF~ap?2I&O=|)74Z;4hb%K9({r#05P{5ZV z#hyRgTjbt-Z(wOYGE{KI31=*+qJ-|mPa+xe1@k=j4j;q=l`D^SYLmV)l_>G*Jy=XC zvCDJILOS?84@ooiE`_Q{MEBj+yILlf8e|1&r9eN^bGD#(%zV_;wyV-XO7tmgoyr0h zD8KG*%fGrd6ze$vD=xVl{r-OSPq1)Mqf#1Qoo@!;3 zCFXBS44~3NkXTAnQF9NH@xwG8WuR5J!TIEkJpGdaNpI+;31*=H1$)Md_07`3<#X^} zf;^@6Gf@cAI`L&_Q^e8t^~c{=-afi^6YZZe2a6{2R8^e(KK!yry7;)P67U>r)6wqcA`~Qv zFX(>QOn=J*XzD+lC#bzRyUIgO%C#NO2&X$V>MXkabq|B|IV^W;wXtgDTlM>KXQ~av zxo29lnW#lc8*$~KFTvMH=KYab+4L%2zD_ztMR#Pa?V(%F>~xX&9Raz9h1jNYU?E|e zgLqe_a$XD~IE5$bLqB*(O^RM{__`-y^ z*zRS>421ruYW+~ii+yJpV;NSM{8cnlwLBb1Bu>ahY`_Qco3DK#1F^>(nqpXik0{gVoDqQD>e#bD4LPPD~lf0WBtPF~yBKnC!WZ z%8$D{W+9EW){>9DbX?`H zcQ;$@nub^3*a(wNqw?OcCm_5Daew-Bf$U0{jH?_!Rg`x0RN|}{s#SB f+kZg5r2nq8x)Q>l+P}O2M1c8ARmxr-0RaC4++od` literal 0 HcmV?d00001 diff --git a/src/core/include/commands.h b/src/core/include/commands.h new file mode 100644 index 00000000..c8ffbb21 --- /dev/null +++ b/src/core/include/commands.h @@ -0,0 +1,275 @@ +#pragma once +#include "framework.h" +#include "luatools.h" +#include "utils.h" + +namespace CommandPriority { + enum CommandPriorities { LOW, MEDIUM, HIGH }; +}; + +namespace CommandType { + enum CommandTypes { NO_TYPE, MOVE, SMOKE, SPAWN_AIR, SPAWN_GROUND, CLONE, FOLLOW, RESET_TASK, SET_OPTION, SET_COMMAND, SET_TASK }; +}; + +namespace SetCommandType { + enum SetCommandTypes { + ROE = 0, + REACTION_ON_THREAT = 1, + RADAR_USING = 3, + FLARE_USING = 4, + FORMATION = 5, + RTB_ON_BINGO = 6, + SILENCE = 7, + RTB_ON_OUT_OF_AMMO = 10, + ECM_USING = 13, + PROHIBIT_AA = 14, + PROHIBIT_JETT = 15, + PROHIBIT_AB = 16, + PROHIBIT_AG = 17, + MISSILE_ATTACK = 18, + PROHIBIT_WP_PASS_REPORT = 19, + OPTION_RADIO_USAGE_CONTACT = 21, + OPTION_RADIO_USAGE_ENGAGE = 22, + OPTION_RADIO_USAGE_KILL = 23, + JETT_TANKS_IF_EMPTY = 25, + FORCED_ATTACK = 26 + }; +} + +namespace ROE { + enum ROEs { + WEAPON_FREE = 0, + OPEN_FIRE_WEAPON_FREE = 1, + OPEN_FIRE = 2, + RETURN_FIRE = 3, + WEAPON_HOLD = 4, + }; +} + +namespace ReactionToThreat { + enum ReactionToThreats { + NO_REACTION = 0, + PASSIVE_DEFENCE = 1, + EVADE_FIRE = 2, + BYPASS_AND_ESCAPE = 3, + ALLOW_ABORT_MISSION = 4 + }; +} + +/* Base command class */ +class Command +{ +public: + int getPriority() { return priority; } + int getType() { return type; } + virtual wstring getString(lua_State* L) = 0; + virtual int getLoad() = 0; + +protected: + int priority = CommandPriority::LOW; + int type = CommandType::NO_TYPE; +}; + +/* Simple low priority move command (from user click) */ +class Move : public Command +{ +public: + Move(int ID, Coords destination, double speed, double altitude, wstring unitCategory, wstring taskOptions): + ID(ID), + destination(destination), + speed(speed), + altitude(altitude), + unitCategory(unitCategory), + taskOptions(taskOptions) + { + priority = CommandPriority::HIGH; + type = CommandType::MOVE; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 5; } + +private: + const int ID; + const Coords destination; + const wstring unitCategory; + const double speed; + const double altitude; + const wstring taskOptions; +}; + +/* Smoke command */ +class Smoke : public Command +{ +public: + Smoke(wstring color, Coords location) : + color(color), + location(location) + { + priority = CommandPriority::LOW; + type = CommandType::SMOKE; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 5; } + +private: + const wstring color; + const Coords location; +}; + +/* Spawn ground unit command */ +class SpawnGroundUnit : public Command +{ +public: + SpawnGroundUnit(wstring coalition, wstring unitType, Coords location) : + coalition(coalition), + unitType(unitType), + location(location) + { + priority = CommandPriority::LOW; + type = CommandType::SPAWN_GROUND; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 100; } + +private: + const wstring coalition; + const wstring unitType; + const Coords location; +}; + +/* Spawn air unit command */ +class SpawnAircraft : public Command +{ +public: + SpawnAircraft(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName) : + coalition(coalition), + unitType(unitType), + location(location), + payloadName(payloadName), + airbaseName(airbaseName) + { + priority = CommandPriority::LOW; + type = CommandType::SPAWN_AIR; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 100; } + +private: + const wstring coalition; + const wstring unitType; + const Coords location; + const wstring payloadName; + const wstring airbaseName; +}; + +/* Clone unit command */ +class Clone : public Command +{ +public: + Clone(int ID, Coords location) : + ID(ID), + location(location) + { + priority = CommandPriority::LOW; + type = CommandType::CLONE; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 100; } + +private: + const int ID; + const Coords location; +}; + +/* Delete unit command */ +class Delete : public Command +{ +public: + Delete(int ID) : + ID(ID) + { + priority = CommandPriority::HIGH; + type = CommandType::CLONE; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 20; } + +private: + const int ID; +}; + +/* Follow command */ +class SetTask : public Command +{ +public: + SetTask(int ID, wstring task) : + ID(ID), + task(task) + { + priority = CommandPriority::MEDIUM; + type = CommandType::FOLLOW; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 10; } + +private: + const int ID; + const wstring task; +}; + +/* Reset task command */ +class ResetTask : public Command +{ +public: + ResetTask(int ID) : + ID(ID) + { + priority = CommandPriority::HIGH; + type = CommandType::RESET_TASK; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 10; } + +private: + const int ID; +}; + +/* Set command */ +class SetCommand : public Command +{ +public: + SetCommand(int ID, wstring command) : + ID(ID), + command(command) + { + priority = CommandPriority::HIGH; + type = CommandType::RESET_TASK; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 10; } + +private: + const int ID; + const wstring command; +}; + +/* Set option command */ +class SetOption : public Command +{ +public: + SetOption(int ID, int optionID, int optionValue) : + ID(ID), + optionID(optionID), + optionValue(optionValue) + { + priority = CommandPriority::HIGH; + type = CommandType::RESET_TASK; + }; + virtual wstring getString(lua_State* L); + virtual int getLoad() { return 10; } + +private: + const int ID; + const int optionID; + const int optionValue; +}; \ No newline at end of file diff --git a/src/core/include/scheduler.h b/src/core/include/scheduler.h new file mode 100644 index 00000000..d5ebfcf6 --- /dev/null +++ b/src/core/include/scheduler.h @@ -0,0 +1,20 @@ +#pragma once +#include "framework.h" +#include "luatools.h" +#include "commands.h" + +class Scheduler +{ +public: + Scheduler(lua_State* L); + ~Scheduler(); + + void appendCommand(Command* command); + void execute(lua_State* L); + void handleRequest(wstring key, json::value value); + +private: + list commands; + int load; +}; + diff --git a/src/core/include/unit.h b/src/core/include/unit.h new file mode 100644 index 00000000..b94f7b1a --- /dev/null +++ b/src/core/include/unit.h @@ -0,0 +1,184 @@ +#pragma once +#include "framework.h" +#include "utils.h" +#include "dcstools.h" +#include "luatools.h" +#include "measure.h" + +namespace State +{ + enum States + { + IDLE, + REACH_DESTINATION, + ATTACK, + WINGMAN, + FOLLOW, + LAND, + REFUEL, + AWACS, + EWR, + TANKER, + RUN_AWAY + }; +}; + +class Unit +{ +public: + Unit(json::value json, int ID); + ~Unit(); + + /********** Public methods **********/ + int getID() { return ID; } + void updateExportData(json::value json); + void updateMissionData(json::value json); + json::value getData(long long time); + + /********** Base data **********/ + void setAI(bool newAI) { AI = newAI; addMeasure(L"AI", json::value(newAI)); } + void setName(wstring newName) { name = newName; addMeasure(L"name", json::value(newName));} + void setUnitName(wstring newUnitName) { unitName = newUnitName; addMeasure(L"unitName", json::value(newUnitName));} + void setGroupName(wstring newGroupName) { groupName = newGroupName; addMeasure(L"groupName", json::value(newGroupName));} + void setAlive(bool newAlive) { alive = newAlive; addMeasure(L"alive", json::value(newAlive));} + void setType(json::value newType) { type = newType; addMeasure(L"type", newType);} + void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));} + bool getAI() { return AI; } + wstring getName() { return name; } + wstring getUnitName() { return unitName; } + wstring getGroupName() { return groupName; } + bool getAlive() { return alive; } + json::value getType() { return type; } + int getCountry() { return country; } + + /********** Flight data **********/ + void setLatitude(double newLatitude) {latitude = newLatitude; addMeasure(L"latitude", json::value(newLatitude));} + void setLongitude(double newLongitude) {longitude = newLongitude; addMeasure(L"longitude", json::value(newLongitude));} + void setAltitude(double newAltitude) {altitude = newAltitude; addMeasure(L"altitude", json::value(newAltitude));} + void setHeading(double newHeading) {heading = newHeading; addMeasure(L"heading", json::value(newHeading));} + void setSpeed(double newSpeed) {speed = newSpeed; addMeasure(L"speed", json::value(newSpeed));} + double getLatitude() { return latitude; } + double getLongitude() { return longitude; } + double getAltitude() { return altitude; } + double getHeading() { return heading; } + double getSpeed() { return speed; } + + /********** Mission data **********/ + void setFuel(double newFuel) { fuel = newFuel; addMeasure(L"fuel", json::value(newFuel));} + void setAmmo(json::value newAmmo) { ammo = newAmmo; addMeasure(L"ammo", json::value(newAmmo));} + void setTargets(json::value newTargets) {targets = newTargets; addMeasure(L"targets", json::value(newTargets));} + void setHasTask(bool newHasTask) { hasTask = newHasTask; addMeasure(L"hasTask", json::value(newHasTask));} + void setCoalitionID(int newCoalitionID); + void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));} + double getFuel() { return fuel; } + json::value getAmmo() { return ammo; } + json::value getTargets() { return targets; } + bool getHasTask() { return hasTask; } + wstring getCoalition() { return coalition; } + int getCoalitionID(); + json::value getFlags() { return flags; } + + /********** Formation data **********/ + void setIsLeader(bool newIsLeader); + void setIsWingman(bool newIsWingman); + void setLeader(Unit* newLeader); + void setWingmen(vector newWingmen); + void setFormation(wstring newFormation) { formation = newFormation; addMeasure(L"formation", json::value(formation));} + void setFormationOffset(Offset formationOffset); + bool getIsLeader() { return isLeader; } + bool getIsWingman() { return isWingman; } + Unit* getLeader() { return leader; } + vector getWingmen() { return wingmen; } + wstring getFormation() { return formation; } + Offset getFormationoffset() { return formationOffset; } + + /********** Task data **********/ + void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask;addMeasure(L"currentTask", json::value(newCurrentTask)); } + virtual void setTargetSpeed(double newTargetSpeed) { targetSpeed = newTargetSpeed; addMeasure(L"targetSpeed", json::value(newTargetSpeed));} + virtual void setTargetAltitude(double newTargetAltitude) { targetAltitude = newTargetAltitude; addMeasure(L"targetAltitude", json::value(newTargetAltitude));} //TODO fix, double definition + void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix + void setActivePath(list newActivePath); + void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));} + wstring getCurrentTask() { return currentTask; } + virtual double getTargetSpeed() { return targetSpeed; }; + virtual double getTargetAltitude() { return targetAltitude; }; + Coords getActiveDestination() { return activeDestination; } + list getActivePath() { return activePath; } + int getTargetID() { return targetID; } + + /********** Options data **********/ + void setROE(wstring newROE); + void setReactionToThreat(wstring newReactionToThreat); + wstring getROE() { return ROE; } + wstring getReactionToThreat() {return reactionToThreat;} + + /********** Control functions **********/ + void landAt(Coords loc); + virtual void changeSpeed(wstring change){}; + virtual void changeAltitude(wstring change){}; + void resetActiveDestination(); + virtual void setState(int newState) { state = newState; }; + void resetTask(); + +protected: + int ID; + + map measures; + + /********** Base data **********/ + bool AI = false; + wstring name = L"undefined"; + wstring unitName = L"undefined"; + wstring groupName = L"undefined"; + bool alive = true; + json::value type = json::value::null(); + int country = NULL; + + /********** Flight data **********/ + double latitude = NULL; + double longitude = NULL; + double altitude = NULL; + double speed = NULL; + double heading = NULL; + + /********** Mission data **********/ + double fuel = 0; + json::value ammo = json::value::null(); + json::value targets = json::value::null(); + bool hasTask = false; + wstring coalition = L""; + json::value flags = json::value::null(); + + /********** Formation data **********/ + bool isLeader = false; + bool isWingman = false; + wstring formation = L""; + Unit *leader = nullptr; + vector wingmen; + Offset formationOffset = Offset(NULL); + + /********** Task data **********/ + wstring currentTask = L""; + double targetSpeed = 0; + double targetAltitude = 0; + list activePath; + Coords activeDestination = Coords(0); + int targetID = NULL; + + /********** Options data **********/ + wstring ROE = L""; + wstring reactionToThreat = L""; + + /********** State machine **********/ + int state = State::IDLE; + + /********** Other **********/ + Coords oldPosition = Coords(0); // Used to approximate speed + + /********** Functions **********/ + virtual wstring getCategory() { return L"No category"; }; + wstring getTargetName(); + bool isTargetAlive(); + virtual void AIloop() = 0; + void addMeasure(wstring key, json::value value); +}; diff --git a/src/core/src/commands.cpp b/src/core/src/commands.cpp new file mode 100644 index 00000000..ef5a7535 --- /dev/null +++ b/src/core/src/commands.cpp @@ -0,0 +1,135 @@ +#include "commands.h" +#include "logger.h" +#include "dcstools.h" + +/* Move command */ +wstring Move::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.move, " + << ID << ", " + << destination.lat << ", " + << destination.lng << ", " + << altitude << ", " + << speed << ", " + << "\"" << unitCategory << "\"" << ", " + << taskOptions; + return commandSS.str(); +} + +/* Smoke command */ +wstring Smoke::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.smoke, " + << "\"" << color << "\"" << ", " + << location.lat << ", " + << location.lng; + return commandSS.str(); +} + +/* Spawn ground command */ +wstring SpawnGroundUnit::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.spawnGroundUnit, " + << "\"" << coalition << "\"" << ", " + << "\"" << unitType << "\"" << ", " + << location.lat << ", " + << location.lng; + return commandSS.str(); +} + +/* Spawn air command */ +wstring SpawnAircraft::getString(lua_State* L) +{ + std::wostringstream optionsSS; + optionsSS.precision(10); + optionsSS << "{" + << "payloadName = \"" << payloadName << "\", " + << "airbaseName = \"" << airbaseName << "\"," + << "}"; + + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.spawnAircraft, " + << "\"" << coalition << "\"" << ", " + << "\"" << unitType << "\"" << ", " + << location.lat << ", " + << location.lng << "," + << optionsSS.str(); + return commandSS.str(); +} + +/* Clone unit command */ +wstring Clone::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.clone, " + << ID << ", " + << location.lat << ", " + << location.lng; + return commandSS.str(); +} + +/* Delete unit command */ +wstring Delete::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.delete, " + << ID; + return commandSS.str(); +} + +/* Set task command */ +wstring SetTask::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.setTask, " + << ID << "," + << task; + + return commandSS.str(); +} + +/* Reset task command */ +wstring ResetTask::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.resetTask, " + << ID; + + return commandSS.str(); +} + +/* Set command command */ +wstring SetCommand::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.setCommand, " + << ID << "," + << command; + + return commandSS.str(); +} + +/* Set option command */ +wstring SetOption::getString(lua_State* L) +{ + std::wostringstream commandSS; + commandSS.precision(10); + commandSS << "Olympus.setOption, " + << ID << "," + << optionID << "," + << optionValue; + + return commandSS.str(); +} \ No newline at end of file diff --git a/src/core/src/scheduler.cpp b/src/core/src/scheduler.cpp new file mode 100644 index 00000000..8e80f9bf --- /dev/null +++ b/src/core/src/scheduler.cpp @@ -0,0 +1,263 @@ +#include "scheduler.h" +#include "logger.h" +#include "dcstools.h" +#include "unitsManager.h" +#include "utils.h" +#include "unit.h" + +extern UnitsManager* unitsManager; + +Scheduler::Scheduler(lua_State* L): + load(0) +{ + LogInfo(L, "Scheduler constructor called successfully"); +} + +Scheduler::~Scheduler() +{ + +} + +void Scheduler::appendCommand(Command* command) +{ + commands.push_back(command); +} + +void Scheduler::execute(lua_State* L) +{ + /* Decrease the active computation load. New commands can be sent only if the load has reached 0. + This is needed to avoid server lag. */ + if (load > 0) { + load--; + return; + } + + int priority = CommandPriority::HIGH; + while (priority >= CommandPriority::LOW) + { + for (auto command : commands) + { + if (command->getPriority() == priority) + { + wstring commandString = L"Olympus.protectedCall(" + command->getString(L) + L")"; + if (dostring_in(L, "server", to_string(commandString))) + log(L"Error executing command " + commandString); + load = command->getLoad(); + commands.remove(command); + return; + } + } + priority--; + } +} + +void Scheduler::handleRequest(wstring key, json::value value) +{ + Command* command = nullptr; + + log(L"Received request with ID: " + key); + if (key.compare(L"setPath") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + { + wstring unitName = unit->getUnitName(); + json::value path = value[L"path"]; + list newPath; + for (int i = 1; i <= path.as_object().size(); i++) + { + wstring WP = to_wstring(i); + double lat = path[WP][L"lat"].as_double(); + double lng = path[WP][L"lng"].as_double(); + log(unitName + L" set path destination " + WP + L" (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + Coords dest; dest.lat = lat; dest.lng = lng; + newPath.push_back(dest); + } + + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + { + unit->setActivePath(newPath); + unit->setState(State::REACH_DESTINATION); + log(unitName + L" new path set successfully"); + } + else + log(unitName + L" not found, request will be discarded"); + } + } + else if (key.compare(L"smoke") == 0) + { + wstring color = value[L"color"].as_string(); + double lat = value[L"location"][L"lat"].as_double(); + double lng = value[L"location"][L"lng"].as_double(); + log(L"Adding " + color + L" smoke at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + Coords loc; loc.lat = lat; loc.lng = lng; + command = dynamic_cast(new Smoke(color, loc)); + } + else if (key.compare(L"spawnGround") == 0) + { + wstring coalition = value[L"coalition"].as_string(); + wstring type = value[L"type"].as_string(); + double lat = value[L"location"][L"lat"].as_double(); + double lng = value[L"location"][L"lng"].as_double(); + log(L"Spawning " + coalition + L" ground unit of type " + type + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); + Coords loc; loc.lat = lat; loc.lng = lng; + command = dynamic_cast(new SpawnGroundUnit(coalition, type, loc)); + } + else if (key.compare(L"spawnAir") == 0) + { + wstring coalition = value[L"coalition"].as_string(); + wstring type = value[L"type"].as_string(); + double lat = value[L"location"][L"lat"].as_double(); + double lng = value[L"location"][L"lng"].as_double(); + Coords loc; loc.lat = lat; loc.lng = lng; + wstring payloadName = value[L"payloadName"].as_string(); + wstring airbaseName = value[L"airbaseName"].as_string(); + log(L"Spawning " + coalition + L" air unit of type " + type + L" with payload " + payloadName + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L" " + airbaseName + L")"); + command = dynamic_cast(new SpawnAircraft(coalition, type, loc, payloadName, airbaseName)); + } + else if (key.compare(L"attackUnit") == 0) + { + int ID = value[L"ID"].as_integer(); + int targetID = value[L"targetID"].as_integer(); + + Unit* unit = unitsManager->getUnit(ID); + Unit* target = unitsManager->getUnit(targetID); + + wstring unitName; + wstring targetName; + + if (unit != nullptr) + unitName = unit->getUnitName(); + else + return; + + if (target != nullptr) + targetName = target->getUnitName(); + else + return; + + log(L"Unit " + unitName + L" attacking unit " + targetName); + unit->setTargetID(targetID); + unit->setState(State::ATTACK); + } + else if (key.compare(L"stopAttack") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + unit->setState(State::REACH_DESTINATION); + else + return; + } + else if (key.compare(L"changeSpeed") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + unit->changeSpeed(value[L"change"].as_string()); + } + else if (key.compare(L"changeAltitude") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + unit->changeAltitude(value[L"change"].as_string()); + } + else if (key.compare(L"setSpeed") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + unit->setTargetSpeed(value[L"speed"].as_double()); + } + else if (key.compare(L"setAltitude") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + if (unit != nullptr) + unit->setTargetAltitude(value[L"altitude"].as_double()); + } + else if (key.compare(L"cloneUnit") == 0) + { + int ID = value[L"ID"].as_integer(); + double lat = value[L"location"][L"lat"].as_double(); + double lng = value[L"location"][L"lng"].as_double(); + Coords loc; loc.lat = lat; loc.lng = lng; + command = dynamic_cast(new Clone(ID, loc)); + log(L"Cloning unit " + to_wstring(ID)); + } + else if (key.compare(L"setLeader") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + bool isLeader = value[L"isLeader"].as_bool(); + if (isLeader) + { + json::value wingmenIDs = value[L"wingmenIDs"]; + vector wingmen; + if (unit != nullptr) + { + for (auto itr = wingmenIDs.as_array().begin(); itr != wingmenIDs.as_array().end(); itr++) + { + Unit* wingman = unitsManager->getUnit(itr->as_integer()); + if (wingman != nullptr) + wingmen.push_back(wingman); + } + unit->setFormation(L"Line abreast"); + unit->setIsLeader(true); + unit->setWingmen(wingmen); + log(L"Setting " + unit->getName() + L" as formation leader"); + } + } + else { + unit->setIsLeader(false); + } + } + else if (key.compare(L"setFormation") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + wstring formation = value[L"formation"].as_string(); + unit->setFormation(formation); + } + else if (key.compare(L"setROE") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + wstring ROE = value[L"ROE"].as_string(); + unit->setROE(ROE); + } + else if (key.compare(L"setReactionToThreat") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + wstring reactionToThreat = value[L"reactionToThreat"].as_string(); + unit->setReactionToThreat(reactionToThreat); + } + else if (key.compare(L"landAt") == 0) + { + int ID = value[L"ID"].as_integer(); + Unit* unit = unitsManager->getUnit(ID); + double lat = value[L"location"][L"lat"].as_double(); + double lng = value[L"location"][L"lng"].as_double(); + Coords loc; loc.lat = lat; loc.lng = lng; + unit->landAt(loc); + } + else if (key.compare(L"deleteUnit") == 0) + { + int ID = value[L"ID"].as_integer(); + unitsManager->deleteUnit(ID); + } + else + { + log(L"Unknown command: " + key); + } + + if (command != nullptr) + { + appendCommand(command); + } +} + diff --git a/src/core/src/unit.cpp b/src/core/src/unit.cpp new file mode 100644 index 00000000..09bb63bd --- /dev/null +++ b/src/core/src/unit.cpp @@ -0,0 +1,322 @@ +#include "unit.h" +#include "utils.h" +#include "logger.h" +#include "commands.h" +#include "scheduler.h" +#include "defines.h" +#include "unitsManager.h" + +#include +using namespace std::chrono; + +#include +using namespace GeographicLib; + +extern Scheduler* scheduler; +extern UnitsManager* unitsManager; + +Unit::Unit(json::value json, int ID) : + ID(ID) +{ + log("Creating unit with ID: " + to_string(ID)); +} + +Unit::~Unit() +{ + +} + +void Unit::addMeasure(wstring key, json::value value) +{ + milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); + if (measures.find(key) == measures.end()) + measures[key] = new Measure(value, ms.count()); + else + { + if (measures[key]->getValue() != value) + { + measures[key]->setValue(value); + measures[key]->setTime(ms.count()); + } + } +} + +void Unit::updateExportData(json::value json) +{ + /* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */ + if (oldPosition != NULL) + { + double dist = 0; + Geodesic::WGS84().Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist); + setSpeed(getSpeed() * 0.95 + (dist / UPDATE_TIME_INTERVAL) * 0.05); + } + oldPosition = Coords(latitude, longitude, altitude); + + if (json.has_string_field(L"Name")) + setName(json[L"Name"].as_string()); + if (json.has_string_field(L"UnitName")) + setUnitName(json[L"UnitName"].as_string()); + if (json.has_string_field(L"GroupName")) + setGroupName(json[L"GroupName"].as_string()); + if (json.has_object_field(L"Type")) + setType(json[L"Type"]); + if (json.has_number_field(L"Country")) + setCountry(json[L"Country"].as_number().to_int32()); + if (json.has_number_field(L"CoalitionID")) + setCoalitionID(json[L"CoalitionID"].as_number().to_int32()); + if (json.has_object_field(L"LatLongAlt")) + { + setLatitude(json[L"LatLongAlt"][L"Lat"].as_number().to_double()); + setLongitude(json[L"LatLongAlt"][L"Long"].as_number().to_double()); + setAltitude(json[L"LatLongAlt"][L"Alt"].as_number().to_double()); + } + if (json.has_number_field(L"Heading")) + setHeading(json[L"Heading"].as_number().to_double()); + if (json.has_object_field(L"Flags")) + setFlags(json[L"Flags"]); + + /* All units which contain the name "Olympus" are automatically under AI control */ + /* TODO: I don't really like using this method */ + setAI(getUnitName().find(L"Olympus") != wstring::npos); + + /* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */ + if (getAI() && getAlive() && getFlags()[L"Human"].as_bool() == false) + AIloop(); +} + +void Unit::updateMissionData(json::value json) +{ + if (json.has_number_field(L"fuel")) + setFuel(int(json[L"fuel"].as_number().to_double() * 100)); + if (json.has_object_field(L"ammo")) + setAmmo(json[L"ammo"]); + if (json.has_object_field(L"targets")) + setTargets(json[L"targets"]); + if (json.has_boolean_field(L"hasTask")) + setHasTask(json[L"hasTask"].as_bool()); +} + +json::value Unit::getData(long long time) +{ + auto json = json::value::object(); + + /********** Base data **********/ + json[L"baseData"] = json::value::object(); + for (auto key : { L"AI", L"name", L"unitName", L"groupName", L"alive", L"category"}) + { + if (measures.find(key) != measures.end() && measures[key]->getTime() > time) + json[L"baseData"][key] = measures[key]->getValue(); + } + + /********** Flight data **********/ + json[L"flightData"] = json::value::object(); + for (auto key : { L"latitude", L"longitude", L"altitude", L"speed", L"heading"}) + { + if (measures.find(key) != measures.end() && measures[key]->getTime() > time) + json[L"flightData"][key] = measures[key]->getValue(); + } + + /********** Mission data **********/ + json[L"missionData"] = json::value::object(); + for (auto key : { L"fuel", L"ammo", L"targets", L"hasTask", L"coalition", L"flags"}) + { + if (measures.find(key) != measures.end() && measures[key]->getTime() > time) + json[L"missionData"][key] = measures[key]->getValue(); + } + + /********** Formation data **********/ + json[L"formationData"] = json::value::object(); + for (auto key : { L"isLeader", L"isWingman", L"formation", L"wingmenIDs", L"leaderID" }) + { + if (measures.find(key) != measures.end() && measures[key]->getTime() > time) + json[L"missionData"][key] = measures[key]->getValue(); + } + + /********** Task data **********/ + json[L"taskData"] = json::value::object(); + for (auto key : { L"currentTask", L"targetSpeed", L"targetAltitude", L"activePath" }) + { + if (measures.find(key) != measures.end() && measures[key]->getTime() > time) + json[L"taskData"][key] = measures[key]->getValue(); + } + + /********** Options data **********/ + json[L"optionsData"] = json::value::object(); + for (auto key : { L"ROE", L"reactionToThreat" }) + { + if (measures.find(key) != measures.end() && measures[key]->getTime() > time) + json[L"optionsData"][key] = measures[key]->getValue(); + } + + return json; +} + +void Unit::setActivePath(list newPath) +{ + if (state != State::WINGMAN && state != State::FOLLOW) + { + activePath = newPath; + resetActiveDestination(); + } + + auto path = json::value::object(); + if (activePath.size() > 0) { + int count = 1; + for (auto& destination : activePath) + { + auto json = json::value::object(); + json[L"lat"] = destination.lat; + json[L"lng"] = destination.lng; + json[L"alt"] = destination.alt; + path[to_wstring(count++)] = json; + } + } + addMeasure(L"activePath", path); +} + +void Unit::setCoalitionID(int newCoalitionID) +{ + if (newCoalitionID == 0) + coalition = L"neutral"; + else if (newCoalitionID == 1) + coalition = L"red"; + else + coalition = L"blue"; + addMeasure(L"coalition", json::value(coalition)); +} + +int Unit::getCoalitionID() +{ + if (coalition == L"neutral") + return 0; + else if (coalition == L"red") + return 1; + else + return 2; +} + +void Unit::setLeader(Unit* newLeader) +{ + leader = newLeader; + if (leader != nullptr) + addMeasure(L"leaderID", json::value(leader->getID())); +} + +void Unit::setWingmen(vector newWingmen) { + wingmen = newWingmen; + auto wingmenIDs = json::value::object(); + int i = 0; + for (auto itr = wingmen.begin(); itr != wingmen.end(); itr++) + wingmenIDs[i++] = (*itr)->getID(); + addMeasure(L"wingmen", wingmenIDs); +} + +wstring Unit::getTargetName() +{ + if (isTargetAlive()) + { + Unit* target = unitsManager->getUnit(targetID); + if (target != nullptr) + return target->getUnitName(); + } + return L""; +} + +bool Unit::isTargetAlive() +{ + if (targetID == NULL) + return false; + + Unit* target = unitsManager->getUnit(targetID); + if (target != nullptr) + return target->alive; + else + return false; +} + +void Unit::resetActiveDestination() +{ + activeDestination = Coords(NULL); +} + +void Unit::resetTask() +{ + Command* command = dynamic_cast(new ResetTask(ID)); + scheduler->appendCommand(command); +} + +void Unit::setIsLeader(bool newIsLeader) { + isLeader = newIsLeader; + if (!isLeader) { + for (auto wingman : wingmen) + { + wingman->setFormation(L""); + wingman->setIsWingman(false); + wingman->setLeader(nullptr); + } + } + addMeasure(L"isLeader", json::value(newIsLeader)); +} + +void Unit::setIsWingman(bool newIsWingman) +{ + isWingman = newIsWingman; + if (isWingman) + setState(State::WINGMAN); + else + setState(State::IDLE); + + addMeasure(L"isWingman", json::value(isWingman)); +} + +void Unit::setFormationOffset(Offset newFormationOffset) +{ + formationOffset = newFormationOffset; + resetTask(); +} + +void Unit::setROE(wstring newROE) { + ROE = newROE; + int ROEEnum; + if (newROE.compare(L"Free") == 0) + ROEEnum = ROE::WEAPON_FREE; + else if (newROE.compare(L"Designated free") == 0) + ROEEnum = ROE::OPEN_FIRE_WEAPON_FREE; + else if (newROE.compare(L"Designated") == 0) + ROEEnum = ROE::OPEN_FIRE; + else if (newROE.compare(L"Return") == 0) + ROEEnum = ROE::RETURN_FIRE; + else if (newROE.compare(L"Hold") == 0) + ROEEnum = ROE::WEAPON_HOLD; + else + return; + Command* command = dynamic_cast(new SetOption(ID, SetCommandType::ROE, ROEEnum)); + scheduler->appendCommand(command); + addMeasure(L"ROE", json::value(newROE)); +} + +void Unit::setReactionToThreat(wstring newReactionToThreat) { + reactionToThreat = newReactionToThreat; + int reactionToThreatEnum; + if (newReactionToThreat.compare(L"None") == 0) + reactionToThreatEnum = ReactionToThreat::NO_REACTION; + else if (newReactionToThreat.compare(L"Passive") == 0) + reactionToThreatEnum = ReactionToThreat::PASSIVE_DEFENCE; + else if (newReactionToThreat.compare(L"Evade") == 0) + reactionToThreatEnum = ReactionToThreat::EVADE_FIRE; + else if (newReactionToThreat.compare(L"Escape") == 0) + reactionToThreatEnum = ReactionToThreat::BYPASS_AND_ESCAPE; + else if (newReactionToThreat.compare(L"Abort") == 0) + reactionToThreatEnum = ReactionToThreat::ALLOW_ABORT_MISSION; + else + return; + Command* command = dynamic_cast(new SetOption(ID, SetCommandType::REACTION_ON_THREAT, reactionToThreatEnum)); + scheduler->appendCommand(command); + addMeasure(L"reactionToThreat", json::value(newReactionToThreat)); +} + +void Unit::landAt(Coords loc) { + activePath.clear(); + activePath.push_back(loc); + setState(State::LAND); +} \ No newline at end of file diff --git a/src/olympus.sln b/src/olympus.sln new file mode 100644 index 00000000..bbebd79f --- /dev/null +++ b/src/olympus.sln @@ -0,0 +1,42 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 17 +VisualStudioVersion = 17.3.32929.385 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "core", "core\core.vcxproj", "{8A48D855-0E01-42BA-BD8C-07B0877C68DF}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "logger", "logger\logger.vcxproj", "{873ECABE-FCFE-4217-AC15-91959C3CF1C6}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dcstools", "dcstools\dcstools.vcxproj", "{2B255368-39A0-431A-A6DE-CC739AC70DC1}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "luatools", "luatools\luatools.vcxproj", "{DE139EC1-4F88-47D5-BE73-F41915FE14A3}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "utils", "utils\utils.vcxproj", "{B85009CE-4A5C-4A5A-B85D-001B3A2651B2}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "olympus", "olympus\olympus.vcxproj", "{5F3FC91E-1FBC-4223-8011-9708DE913474}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Release|x64 = Release|x64 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Release|x64.ActiveCfg = Release|x64 + {8A48D855-0E01-42BA-BD8C-07B0877C68DF}.Release|x64.Build.0 = Release|x64 + {873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Release|x64.ActiveCfg = Release|x64 + {873ECABE-FCFE-4217-AC15-91959C3CF1C6}.Release|x64.Build.0 = Release|x64 + {2B255368-39A0-431A-A6DE-CC739AC70DC1}.Release|x64.ActiveCfg = Release|x64 + {2B255368-39A0-431A-A6DE-CC739AC70DC1}.Release|x64.Build.0 = Release|x64 + {DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Release|x64.ActiveCfg = Release|x64 + {DE139EC1-4F88-47D5-BE73-F41915FE14A3}.Release|x64.Build.0 = Release|x64 + {B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Release|x64.ActiveCfg = Release|x64 + {B85009CE-4A5C-4A5A-B85D-001B3A2651B2}.Release|x64.Build.0 = Release|x64 + {5F3FC91E-1FBC-4223-8011-9708DE913474}.Release|x64.ActiveCfg = Release|x64 + {5F3FC91E-1FBC-4223-8011-9708DE913474}.Release|x64.Build.0 = Release|x64 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {FAB9F592-7511-4EB9-B365-078842ED9BDD} + EndGlobalSection +EndGlobal diff --git a/src/olympus/olympus.filters b/src/olympus/olympus.filters new file mode 100644 index 00000000..2bcbeefa --- /dev/null +++ b/src/olympus/olympus.filters @@ -0,0 +1,29 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + + + inc + + + inc + + + + + src + + + src + + + \ No newline at end of file diff --git a/src/olympus/olympus.vcxproj b/src/olympus/olympus.vcxproj new file mode 100644 index 00000000..50e68d5c --- /dev/null +++ b/src/olympus/olympus.vcxproj @@ -0,0 +1,120 @@ + + + + + Debug + x64 + + + Release + x64 + + + + + + + + {2b255368-39a0-431a-a6de-cc739ac70dc1} + + + {873ecabe-fcfe-4217-ac15-91959c3cf1c6} + + + {b85009ce-4a5c-4a5a-b85d-001b3a2651b2} + + + + 16.0 + Win32Proj + {5f3fc91e-1fbc-4223-8011-9708de913474} + Olympus + 10.0 + olympus + + + + DynamicLibrary + true + v143 + Unicode + + + DynamicLibrary + false + v143 + true + Unicode + + + + + + + + + + + + + + + false + .\..\..\bin\$(Platform)\$(Configuration)\ + + + false + .\..\..\bin\ + + + true + + + + Level3 + true + _CRT_SECURE_NO_WARNINGS; _DEBUG;OLYMPUS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + pch.h + include; ..\..\third-party\lua\include; ..\utils\include; ..\shared\include + stdcpp17 + AssemblyCode + + + Windows + true + false + lua.lib + ..\..\third-party\lua + + + + + Level3 + true + true + true + _CRT_SECURE_NO_WARNINGS; NDEBUG;OLYMPUS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) + true + NotUsing + + + include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include + stdcpp20 + NoListing + + + Windows + true + true + true + false + lua.lib + ..\..\third-party\lua + + + + + + \ No newline at end of file diff --git a/src/olympus/olympus.vcxproj.filters b/src/olympus/olympus.vcxproj.filters new file mode 100644 index 00000000..fa32be80 --- /dev/null +++ b/src/olympus/olympus.vcxproj.filters @@ -0,0 +1,16 @@ + + + + + {c021f649-26ec-4040-abd4-13132def4a81} + + + {2809fbbc-77d2-465e-afef-230525a60c66} + + + + + Source Files + + + \ No newline at end of file diff --git a/src/olympus/src/olympus.cpp b/src/olympus/src/olympus.cpp new file mode 100644 index 00000000..67189855 --- /dev/null +++ b/src/olympus/src/olympus.cpp @@ -0,0 +1,152 @@ +#include "framework.h" +#include "dcstools.h" +#include "logger.h" +#include "utils.h" + +/* 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_coreDeinit)(lua_State* L); +typedef int(__stdcall* f_coreFrame)(lua_State* L); +typedef int(__stdcall* f_coreMissionData)(lua_State* L); +f_coreInit coreInit = nullptr; +f_coreDeinit coreDeinit = nullptr; +f_coreFrame coreFrame = nullptr; +f_coreMissionData coreMissionData = nullptr; + +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"; + + log("Loading core.dll"); + hGetProcIDDLL = LoadLibrary(to_wstring(dllLocation).c_str()); + + if (!hGetProcIDDLL) { + LogError(L, "Error loading core DLL"); + goto error; + } + + log("Core DLL loaded successfully"); + + coreInit = (f_coreInit)GetProcAddress(hGetProcIDDLL, "coreInit"); + if (!coreInit) + { + LogError(L, "Error getting coreInit ProcAddress from DLL"); + goto error; + } + + coreDeinit = (f_coreDeinit)GetProcAddress(hGetProcIDDLL, "coreDeinit"); + if (!coreInit) + { + LogError(L, "Error getting coreDeinit ProcAddress from DLL"); + goto error; + } + + coreFrame = (f_coreFrame)GetProcAddress(hGetProcIDDLL, "coreFrame"); + if (!coreFrame) + { + LogError(L, "Error getting coreFrame ProcAddress from DLL"); + goto error; + } + + coreMissionData = (f_coreFrame)GetProcAddress(hGetProcIDDLL, "coreMissionData"); + if (!coreFrame) + { + LogError(L, "Error getting coreMissionData ProcAddress from DLL"); + goto error; + } + + coreInit(L); + + LogInfo(L, "Module loaded and started successfully."); + + return 0; + +error: + LogError(L, "Error while loading module, see Olympus.log in temporary folder for additional details."); + return 0; +} + +static int onSimulationFrame(lua_State* L) +{ + if (coreFrame) + { + coreFrame(L); + } + return 0; +} + +static int onSimulationStop(lua_State* L) +{ + log("onSimulationStop callback called successfully"); + if (hGetProcIDDLL) + { + log("Trying to unload core DLL"); + if (coreDeinit) + { + coreDeinit(L); + } + + if (FreeLibrary(hGetProcIDDLL)) + { + log("Core DLL unloaded successfully"); + } + else + { + LogError(L, "Error unloading DLL"); + goto error; + } + + coreInit = nullptr; + coreDeinit = nullptr; + coreFrame = nullptr; + coreMissionData = nullptr; + } + + hGetProcIDDLL = NULL; + + return 0; + +error: + LogError(L, "Error while unloading module, see Olympus.log in temporary folder for additional details."); + return 0; +} + +static int setMissionData(lua_State* L) +{ + if (coreMissionData) + { + coreMissionData(L); + } + return 0; +} + +static const luaL_Reg Map[] = { + {"onSimulationStart", onSimulationStart}, + {"onSimulationFrame", onSimulationFrame}, + {"onSimulationStop", onSimulationStop}, + {"setMissionData", setMissionData }, + {NULL, NULL} +}; + +extern "C" DllExport int luaopen_olympus(lua_State * L) +{ + luaL_register(L, "olympus", Map); + return 1; +} \ No newline at end of file From e668c5f9cf8ea236eb2eb1522c0e8afa9245bb73 Mon Sep 17 00:00:00 2001 From: dpassoni Date: Thu, 16 Mar 2023 15:53:53 +0100 Subject: [PATCH 02/30] Renamed folders --- client/src/aic/{AICFormation => aicformation}/Azimuth.ts | 0 client/src/aic/{AICFormation => aicformation}/Range.ts | 0 client/src/aic/{AICFormation => aicformation}/Single.ts | 0 .../Distance.ts | 0 .../Distance/Range.ts | 0 .../Formation.ts | 0 .../NumGroups.ts | 0 .../Unit.ts | 0 .../Who.ts | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename client/src/aic/{AICFormation => aicformation}/Azimuth.ts (100%) rename client/src/aic/{AICFormation => aicformation}/Range.ts (100%) rename client/src/aic/{AICFormation => aicformation}/Single.ts (100%) rename client/src/aic/{AICFormationDescriptorComponent => aicformationdescriptorcomponent}/Distance.ts (100%) rename client/src/aic/{AICFormationDescriptorComponent => aicformationdescriptorcomponent}/Distance/Range.ts (100%) rename client/src/aic/{AICFormationDescriptorSection => aicformationdescriptorsection}/Formation.ts (100%) rename client/src/aic/{AICFormationDescriptorSection => aicformationdescriptorsection}/NumGroups.ts (100%) rename client/src/aic/{AICFormationDescriptorSection => aicformationdescriptorsection}/Unit.ts (100%) rename client/src/aic/{AICFormationDescriptorSection => aicformationdescriptorsection}/Who.ts (100%) diff --git a/client/src/aic/AICFormation/Azimuth.ts b/client/src/aic/aicformation/Azimuth.ts similarity index 100% rename from client/src/aic/AICFormation/Azimuth.ts rename to client/src/aic/aicformation/Azimuth.ts diff --git a/client/src/aic/AICFormation/Range.ts b/client/src/aic/aicformation/Range.ts similarity index 100% rename from client/src/aic/AICFormation/Range.ts rename to client/src/aic/aicformation/Range.ts diff --git a/client/src/aic/AICFormation/Single.ts b/client/src/aic/aicformation/Single.ts similarity index 100% rename from client/src/aic/AICFormation/Single.ts rename to client/src/aic/aicformation/Single.ts diff --git a/client/src/aic/AICFormationDescriptorComponent/Distance.ts b/client/src/aic/aicformationdescriptorcomponent/Distance.ts similarity index 100% rename from client/src/aic/AICFormationDescriptorComponent/Distance.ts rename to client/src/aic/aicformationdescriptorcomponent/Distance.ts diff --git a/client/src/aic/AICFormationDescriptorComponent/Distance/Range.ts b/client/src/aic/aicformationdescriptorcomponent/Distance/Range.ts similarity index 100% rename from client/src/aic/AICFormationDescriptorComponent/Distance/Range.ts rename to client/src/aic/aicformationdescriptorcomponent/Distance/Range.ts diff --git a/client/src/aic/AICFormationDescriptorSection/Formation.ts b/client/src/aic/aicformationdescriptorsection/Formation.ts similarity index 100% rename from client/src/aic/AICFormationDescriptorSection/Formation.ts rename to client/src/aic/aicformationdescriptorsection/Formation.ts diff --git a/client/src/aic/AICFormationDescriptorSection/NumGroups.ts b/client/src/aic/aicformationdescriptorsection/NumGroups.ts similarity index 100% rename from client/src/aic/AICFormationDescriptorSection/NumGroups.ts rename to client/src/aic/aicformationdescriptorsection/NumGroups.ts diff --git a/client/src/aic/AICFormationDescriptorSection/Unit.ts b/client/src/aic/aicformationdescriptorsection/Unit.ts similarity index 100% rename from client/src/aic/AICFormationDescriptorSection/Unit.ts rename to client/src/aic/aicformationdescriptorsection/Unit.ts diff --git a/client/src/aic/AICFormationDescriptorSection/Who.ts b/client/src/aic/aicformationdescriptorsection/Who.ts similarity index 100% rename from client/src/aic/AICFormationDescriptorSection/Who.ts rename to client/src/aic/aicformationdescriptorsection/Who.ts From 9517946691cb4139f10163e30265df652d6fb233 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:55:32 +0100 Subject: [PATCH 03/30] Delete Azimuth.ts --- client/src/aic/aicformation/Azimuth.ts | 38 -------------------------- 1 file changed, 38 deletions(-) delete mode 100644 client/src/aic/aicformation/Azimuth.ts diff --git a/client/src/aic/aicformation/Azimuth.ts b/client/src/aic/aicformation/Azimuth.ts deleted file mode 100644 index 7db676ae..00000000 --- a/client/src/aic/aicformation/Azimuth.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { AICFormation, AICFormationInterface } from "../aicformation"; -import { AICFormationContextDataInterface } from "../aicformationdescriptor"; -import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; -import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; - -export class AICFormation_Azimuth extends AICFormation implements AICFormationInterface { - - "icon" = "azimuth.png"; - "label" = "Azimuth"; - "name" = "azimuth"; - "numGroups" = 2; - "summary" = "Two contacts, side-by-side in a line perpedicular to the perspective."; - "unitBreakdown" = [ " group", " group" ]; - - constructor() { - - super(); - - } - - addToDescriptorPhrase( section: AICFormationDescriptorSection, phrase: AICFormationDescriptorPhrase, contextData: AICFormationContextDataInterface ) { - - switch ( section.name ) { - - case "formation": - - phrase.addComponent( new AICFormationDescriptorComponent( "" ) ); - phrase.addComponent( new AICFormationDescriptorComponent( "track " ) ); - - } - - return phrase; - - - } - -} \ No newline at end of file From 769e5772fbf6df3680eaf3ad55bd35b93276356d Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:55:40 +0100 Subject: [PATCH 04/30] Delete Range.ts --- client/src/aic/aicformation/Range.ts | 38 ---------------------------- 1 file changed, 38 deletions(-) delete mode 100644 client/src/aic/aicformation/Range.ts diff --git a/client/src/aic/aicformation/Range.ts b/client/src/aic/aicformation/Range.ts deleted file mode 100644 index 08c00cd5..00000000 --- a/client/src/aic/aicformation/Range.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { AICFormation, AICFormationInterface } from "../aicformation"; -import { AICFormationContextDataInterface } from "../aicformationdescriptor"; -import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; -import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; - -export class AICFormation_Range extends AICFormation implements AICFormationInterface { - - "icon" = "range.png"; - "label" = "Range"; - "name" = "range"; - "numGroups" = 2; - "summary" = "Two contacts, one behind the other"; - "unitBreakdown" = [ "Lead group", "Trail group" ]; - - constructor() { - - super(); - - } - - addToDescriptorPhrase( section: AICFormationDescriptorSection, phrase: AICFormationDescriptorPhrase, contextData: AICFormationContextDataInterface ) { - - switch ( section.name ) { - - case "formation": - - phrase.addComponent( new AICFormationDescriptorComponent( "" ) ); - phrase.addComponent( new AICFormationDescriptorComponent( "track " ) ); - - - } - - return phrase; - - } - -} \ No newline at end of file From aea9840d0d7bc7ad0ee865ea94e16f117db65dc6 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:55:45 +0100 Subject: [PATCH 05/30] Delete Single.ts --- client/src/aic/aicformation/Single.ts | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 client/src/aic/aicformation/Single.ts diff --git a/client/src/aic/aicformation/Single.ts b/client/src/aic/aicformation/Single.ts deleted file mode 100644 index 09830c40..00000000 --- a/client/src/aic/aicformation/Single.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { AICFormation, AICFormationInterface } from "../aicformation"; -import { AICFormationContextDataInterface, AICFormationDescriptor } from "../aicformationdescriptor"; - -export class AICFormation_Single extends AICFormation implements AICFormationInterface { - - "icon" = "single.png"; - "label" = "Single"; - "name" = "single"; - "numGroups" = 1; - "summary" = "One contact on its own"; - "unitBreakdown" = []; - - constructor() { - - super(); - - } - - - showFormationNameInDescriptor() { - return false; - } - -} \ No newline at end of file From 851899e6a692cc9bda6957ec0d20e95bb8be27d1 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:06 +0100 Subject: [PATCH 06/30] Delete Range.ts --- .../aicformationdescriptorcomponent/Distance/Range.ts | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 client/src/aic/aicformationdescriptorcomponent/Distance/Range.ts diff --git a/client/src/aic/aicformationdescriptorcomponent/Distance/Range.ts b/client/src/aic/aicformationdescriptorcomponent/Distance/Range.ts deleted file mode 100644 index ab8a58d3..00000000 --- a/client/src/aic/aicformationdescriptorcomponent/Distance/Range.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { AICFormactionDescriptorComponent_Distance } from "../distance"; - -export class AICFormationDescriptorComponent_Distance_Range extends AICFormactionDescriptorComponent_Distance { - - constructor( value:string, label?:string ) { - super( value, label ); - } - -} \ No newline at end of file From 5f431fa52b6f51624654db87d4f778b3198fe80b Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:13 +0100 Subject: [PATCH 07/30] Delete Distance.ts --- .../src/aic/aicformationdescriptorcomponent/Distance.ts | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 client/src/aic/aicformationdescriptorcomponent/Distance.ts diff --git a/client/src/aic/aicformationdescriptorcomponent/Distance.ts b/client/src/aic/aicformationdescriptorcomponent/Distance.ts deleted file mode 100644 index 2a3766f3..00000000 --- a/client/src/aic/aicformationdescriptorcomponent/Distance.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; - -export abstract class AICFormactionDescriptorComponent_Distance extends AICFormationDescriptorComponent { - - constructor( value:string, label?:string ) { - super( value, label ); - } - -} \ No newline at end of file From 24470dc80ecfd4b1218cf734cd7060aaaf8576b3 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:27 +0100 Subject: [PATCH 08/30] Delete Formation.ts --- .../Formation.ts | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 client/src/aic/aicformationdescriptorsection/Formation.ts diff --git a/client/src/aic/aicformationdescriptorsection/Formation.ts b/client/src/aic/aicformationdescriptorsection/Formation.ts deleted file mode 100644 index c77cb4be..00000000 --- a/client/src/aic/aicformationdescriptorsection/Formation.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { AICFormation } from "../aicformation"; -import { AICFormationContextDataInterface } from "../aicformationdescriptor"; -import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; -import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; - -export class AICFormationDescriptorSection_Formation extends AICFormationDescriptorSection { - - label = "Formation"; - name = "formation"; - - constructor() { - - super(); - - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - if ( !formation.showFormationNameInDescriptor() ) { - this.omitSection = true; - return this; - } - - let phrase = new AICFormationDescriptorPhrase(); - - phrase.addComponent( new AICFormationDescriptorComponent( formation.label, "Formation" ) ); - - phrase = formation.addToDescriptorPhrase( this, phrase, contextData ); - - this.addPhrase( phrase ); - - - return this; - - } - -} \ No newline at end of file From fc2bc36d6b3cc5a2b4e3d491c9bc66d1e65aeade Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:30 +0100 Subject: [PATCH 09/30] Delete NumGroups.ts --- .../NumGroups.ts | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 client/src/aic/aicformationdescriptorsection/NumGroups.ts diff --git a/client/src/aic/aicformationdescriptorsection/NumGroups.ts b/client/src/aic/aicformationdescriptorsection/NumGroups.ts deleted file mode 100644 index 81b92a86..00000000 --- a/client/src/aic/aicformationdescriptorsection/NumGroups.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { AICFormation } from "../aicformation"; -import { AICFormationContextDataInterface } from "../aicformationdescriptor"; -import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; -import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; - -export class AICFormationDescriptorSection_NumGroups extends AICFormationDescriptorSection { - - label = "Groups"; - name = "numgroups"; - - constructor() { - - super(); - - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - let value = "Single group"; - - if ( contextData.numGroups > 1 ) { - value = contextData.numGroups + " groups"; - } - - let phrase = new AICFormationDescriptorPhrase(); - phrase.addComponent( new AICFormationDescriptorComponent( value, "Number of groups" ) ); - this.addPhrase( phrase ); - - return this; - - } - -} \ No newline at end of file From f484f96c89f3d99b53e538fe2785752edba5013c Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:33 +0100 Subject: [PATCH 10/30] Delete Unit.ts --- .../aic/aicformationdescriptorsection/Unit.ts | 83 ------------------- 1 file changed, 83 deletions(-) delete mode 100644 client/src/aic/aicformationdescriptorsection/Unit.ts diff --git a/client/src/aic/aicformationdescriptorsection/Unit.ts b/client/src/aic/aicformationdescriptorsection/Unit.ts deleted file mode 100644 index 749fe625..00000000 --- a/client/src/aic/aicformationdescriptorsection/Unit.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { AICFormation } from "../aicformation"; -import { AICFormationContextDataInterface } from "../aicformationdescriptor"; -import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; -import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; - -interface addUnitInformationInterface { - omitTrack?: boolean -} - -export class AICFormationDescriptorSection_Unit extends AICFormationDescriptorSection { - - label = "Unit"; - name = "unit"; - - constructor() { - - super(); - - } - - - addUnitInformation( formation:AICFormation, contextData: AICFormationContextDataInterface, phrase: AICFormationDescriptorPhrase, options?:addUnitInformationInterface ) { - - options = options || {}; - - const originPoint = ( contextData.control === "broadcast" ) ? contextData.bullseyeName : "BRAA"; - - phrase.addComponent( new AICFormationDescriptorComponent( originPoint, "Bearing origin point" ) ); - phrase.addComponent( new AICFormationDescriptorComponent( "", "Bearing" ) ); - phrase.addComponent( new AICFormationDescriptorComponent( "", "Range" ) ); - phrase.addComponent( new AICFormationDescriptorComponent( "", "Altitude" ) ); - - if ( contextData.control === "broadcast" ) { - if ( !options.hasOwnProperty( "omitTrack" ) || options.omitTrack !== true ) { - phrase.addComponent( new AICFormationDescriptorComponent( "track ", "Tracking" ) ); - } - } else { - phrase.addComponent( new AICFormationDescriptorComponent( "[hot|flanking [left|right]|beam |cold]", "Azimuth" ) ); - } - - return phrase; - - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - if ( formation.hasUnitBreakdown() ) { - - for ( const [ i, unitRef ] of formation.unitBreakdown.entries() ) { - - let phrase = new AICFormationDescriptorPhrase(); - - phrase.addComponent( new AICFormationDescriptorComponent( unitRef, "Unit reference" ) ); - - if ( i === 0 ) { - this.addUnitInformation( formation, contextData, phrase, { "omitTrack": true } ); - } else { - phrase.addComponent( new AICFormationDescriptorComponent( "" ) ); - } - - phrase.addComponent( new AICFormationDescriptorComponent( "hostile" ) ); - - this.addPhrase( phrase ); - - - } - - } else { - - this.addPhrase( - this.addUnitInformation( formation, contextData, new AICFormationDescriptorPhrase() ) - ); - - } - - return this; - - } - - -} \ No newline at end of file From 1e2c194d013cdd172f3ad6830ba082e5bb9d420f Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:36 +0100 Subject: [PATCH 11/30] Delete Who.ts --- .../aic/aicformationdescriptorsection/Who.ts | 35 ------------------- 1 file changed, 35 deletions(-) delete mode 100644 client/src/aic/aicformationdescriptorsection/Who.ts diff --git a/client/src/aic/aicformationdescriptorsection/Who.ts b/client/src/aic/aicformationdescriptorsection/Who.ts deleted file mode 100644 index 244b0558..00000000 --- a/client/src/aic/aicformationdescriptorsection/Who.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { AICFormation } from "../aicformation"; -import { AICFormationContextDataInterface } from "../aicformationdescriptor"; -import { AICFormationDescriptorSection } from "../aicformationdescriptorsection"; -import { AICFormationDescriptorComponent } from "../aicformationdescriptorcomponent"; -import { AICFormationDescriptorPhrase } from "../aicformationdescriptorphrase"; - -export class AICFormationDescriptorSection_Who extends AICFormationDescriptorSection { - - label = "Who"; - name = "who"; - - constructor() { - - super(); - - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - let phrase = new AICFormationDescriptorPhrase(); - - if ( contextData.control === "tactical" ) { - phrase.addComponent( new AICFormationDescriptorComponent( "", "Their callsign" ) ); - } - - phrase.addComponent( new AICFormationDescriptorComponent( contextData.aicCallsign, "Your callsign" ) ); - - this.addPhrase( phrase ); - - return this; - - } - -} \ No newline at end of file From d3ad071d84f7ee2ed223152b7745a21e4fb4d5d6 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:53 +0100 Subject: [PATCH 12/30] Delete AICFormation.ts --- client/src/aic/AICFormation.ts | 54 ---------------------------------- 1 file changed, 54 deletions(-) delete mode 100644 client/src/aic/AICFormation.ts diff --git a/client/src/aic/AICFormation.ts b/client/src/aic/AICFormation.ts deleted file mode 100644 index 588f4326..00000000 --- a/client/src/aic/AICFormation.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { AICFormationContextDataInterface, AICFormationDescriptor } from "./aicformationdescriptor"; -import { AICFormationDescriptorPhrase } from "./aicformationdescriptorphrase"; -import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; - -export interface AICFormationInterface { - "icon" : string, - "label" : string, - "name" : string, - "numGroups" : number, - "summary" : string, - "unitBreakdown" : string[] -} - - - -export abstract class AICFormation { - - "icon" = ""; - "label" = ""; - "name" = ""; - "numGroups" = 1; - "summary" = ""; - "unitBreakdown":string[] = [] - - - constructor() { - - this.unitBreakdown = []; - } - - - addToDescriptorPhrase( section: AICFormationDescriptorSection, phrase: AICFormationDescriptorPhrase, contextData: AICFormationContextDataInterface ) { - return phrase; - } - - - getDescriptor( contextData: AICFormationContextDataInterface ) { - - return new AICFormationDescriptor().generate( this, contextData ); - - } - - - hasUnitBreakdown() { - return this.unitBreakdown.length > 0; - } - - - showFormationNameInDescriptor() { - return true; - } - - -} \ No newline at end of file From b4c0331f47b9e42c574a7eb3bf91abb96c6bc859 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:56 +0100 Subject: [PATCH 13/30] Delete AICFormationDescriptor.ts --- client/src/aic/AICFormationDescriptor.ts | 55 ------------------------ 1 file changed, 55 deletions(-) delete mode 100644 client/src/aic/AICFormationDescriptor.ts diff --git a/client/src/aic/AICFormationDescriptor.ts b/client/src/aic/AICFormationDescriptor.ts deleted file mode 100644 index c7a5a563..00000000 --- a/client/src/aic/AICFormationDescriptor.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { AICFormation } from "./aicformation"; -import { AICFormationDescriptorSection } from "./aicformationdescriptorsection"; -import { AICFormationDescriptorSection_Formation } from "./aicformationdescriptorsection/formation"; -import { AICFormationDescriptorSection_Unit } from "./aicformationdescriptorsection/unit"; -import { AICFormationDescriptorSection_NumGroups } from "./aicformationdescriptorsection/numgroups"; -import { AICFormationDescriptorSection_Who } from "./aicformationdescriptorsection/who"; - - -export interface AICFormationContextDataInterface { - "aicCallsign" : string, - "bullseyeName" : string, - "control" : "broadcast" | "tactical", - "numGroups" : number -} - - -export class AICFormationDescriptor { - - #sections:AICFormationDescriptorSection[] = [ - new AICFormationDescriptorSection_Who(), - new AICFormationDescriptorSection_NumGroups(), - new AICFormationDescriptorSection_Formation(), - new AICFormationDescriptorSection_Unit() - ] - - constructor() { - } - - - addSection( section:AICFormationDescriptorSection ) { - this.#sections.push( section ); - } - - - getSections() { - return this.#sections; - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - let output:object[] = []; - - for ( const section of this.#sections ) { - output.push( - section.generate( formation, contextData ) - ); - } - - return output; - - } - - -} \ No newline at end of file From 8f859692dceac1e00fe568ab19ed439a47762f51 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:56:59 +0100 Subject: [PATCH 14/30] Delete AICFormationDescriptorComponent.ts --- .../src/aic/AICFormationDescriptorComponent.ts | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 client/src/aic/AICFormationDescriptorComponent.ts diff --git a/client/src/aic/AICFormationDescriptorComponent.ts b/client/src/aic/AICFormationDescriptorComponent.ts deleted file mode 100644 index da194576..00000000 --- a/client/src/aic/AICFormationDescriptorComponent.ts +++ /dev/null @@ -1,18 +0,0 @@ -interface ComponentInterface { - "label" : string; - "value" : string; -} - -export class AICFormationDescriptorComponent implements ComponentInterface { - - label = "(not set)"; - value = "(not set)"; - - constructor( value:any, label?:string ) { - - this.label = label || "(not set)"; - this.value = value; - - } - -} \ No newline at end of file From 319815dff207b916669f214e3ae5ed3d408e17bd Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:57:03 +0100 Subject: [PATCH 15/30] Delete AICFormationDescriptorPhrase.ts --- .../src/aic/AICFormationDescriptorPhrase.ts | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 client/src/aic/AICFormationDescriptorPhrase.ts diff --git a/client/src/aic/AICFormationDescriptorPhrase.ts b/client/src/aic/AICFormationDescriptorPhrase.ts deleted file mode 100644 index b2a519a0..00000000 --- a/client/src/aic/AICFormationDescriptorPhrase.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AICFormation } from "./aicformation"; -import { AICFormationContextDataInterface } from "./aicformationdescriptor"; -import { AICFormationDescriptorComponent } from "./aicformationdescriptorcomponent"; - -export interface AICFormationDescriptorPhraseInterface { - "generate" : CallableFunction, - "label" : string, - "name" : string -} - -export class AICFormationDescriptorPhrase { - - #components : AICFormationDescriptorComponent[] = []; - label = ""; - name = ""; - - constructor() { - } - - - addComponent( component:AICFormationDescriptorComponent ) { - this.#components.push( component ); - return this; - } - - - - getComponents() { - return this.#components; - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - return this; - - } - - -} \ No newline at end of file From d9389d29abedd3a2aeae147c231da09800b11fe9 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:57:06 +0100 Subject: [PATCH 16/30] Delete AICFormationDescriptorSection.ts --- .../src/aic/AICFormationDescriptorSection.ts | 40 ------------------- 1 file changed, 40 deletions(-) delete mode 100644 client/src/aic/AICFormationDescriptorSection.ts diff --git a/client/src/aic/AICFormationDescriptorSection.ts b/client/src/aic/AICFormationDescriptorSection.ts deleted file mode 100644 index bcd2f3c3..00000000 --- a/client/src/aic/AICFormationDescriptorSection.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { AICFormation } from "./aicformation"; -import { AICFormationContextDataInterface } from "./aicformationdescriptor"; -import { AICFormationDescriptorPhrase } from "./aicformationdescriptorphrase"; - -export interface AICFormationDescriptorSectionInterface { - "generate" : CallableFunction, - "label" : string, - "name" : string, - "omitSection" : boolean -} - -export abstract class AICFormationDescriptorSection { - - #phrases : AICFormationDescriptorPhrase[] = []; - label = ""; - name = ""; - omitSection = false; - - constructor() { - } - - - addPhrase( phrase:AICFormationDescriptorPhrase ) { - this.#phrases.push( phrase ); - } - - - generate( formation:AICFormation, contextData: AICFormationContextDataInterface ) { - - return this; - - } - - - getPhrases() { - return this.#phrases; - } - - -} \ No newline at end of file From b247240b3565e924013e80efe845cfd1aa84ffa1 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:57:52 +0100 Subject: [PATCH 17/30] Delete FeatureSwitches.ts --- client/src/FeatureSwitches.ts | 161 ---------------------------------- 1 file changed, 161 deletions(-) delete mode 100644 client/src/FeatureSwitches.ts diff --git a/client/src/FeatureSwitches.ts b/client/src/FeatureSwitches.ts deleted file mode 100644 index ed52d8eb..00000000 --- a/client/src/FeatureSwitches.ts +++ /dev/null @@ -1,161 +0,0 @@ -export interface FeatureSwitchInterface { - "defaultEnabled": boolean, // default on/off state (if allowed by masterSwitch) - "label": string, - "masterSwitch": boolean, // on/off regardless of user preference - "name": string, - "onEnabled"?: CallableFunction, - "options"?: object, - "removeArtifactsIfDisabled"?: boolean -} - - -class FeatureSwitch { - - // From config param - defaultEnabled; - label; - masterSwitch; - name; - onEnabled; - removeArtifactsIfDisabled = true; - - // Self-set - userPreference; - - - constructor( config:FeatureSwitchInterface ) { - - this.defaultEnabled = config.defaultEnabled; - this.label = config.label; - this.masterSwitch = config.masterSwitch; - this.name = config.name; - this.onEnabled = config.onEnabled; - - this.userPreference = this.getUserPreference(); - - } - - - getUserPreference() { - - let preferences = JSON.parse( localStorage.getItem( "featureSwitches" ) || "{}" ); - - return ( preferences.hasOwnProperty( this.name ) ) ? preferences[ this.name ] : this.defaultEnabled; - - } - - - isEnabled() { - - if ( !this.masterSwitch ) { - return false; - } - - return this.userPreference; - } - -} - -export class FeatureSwitches { - - #featureSwitches:FeatureSwitch[] = [ - - new FeatureSwitch({ - "defaultEnabled": false, - "label": "AIC", - "masterSwitch": true, - "name": "aic" - }), - - new FeatureSwitch({ - "defaultEnabled": false, - "label": "AI Formations", - "masterSwitch": true, - "name": "ai-formations", - "removeArtifactsIfDisabled": false - }), - - new FeatureSwitch({ - "defaultEnabled": false, - "label": "ATC", - "masterSwitch": true, - "name": "atc" - }), - - new FeatureSwitch({ - "defaultEnabled": false, - "label": "Force show unit control panel", - "masterSwitch": true, - "name": "forceShowUnitControlPanel" - }), - - new FeatureSwitch({ - "defaultEnabled": false, - "label": "Show splash screen", - "masterSwitch": true, - "name": "splashScreen" - }) - - ]; - - - constructor() { - - this.#testSwitches(); - - this.savePreferences(); - - } - - - getSwitch( switchName:string ) { - - return this.#featureSwitches.find( featureSwitch => featureSwitch.name === switchName ); - - } - - - #testSwitches() { - - for ( const featureSwitch of this.#featureSwitches ) { - - if ( featureSwitch.isEnabled() ) { - - if ( typeof featureSwitch.onEnabled === "function" ) { - featureSwitch.onEnabled(); - } - - } else { - - document.querySelectorAll( "[data-feature-switch='" + featureSwitch.name + "']" ).forEach( el => { - - if ( featureSwitch.removeArtifactsIfDisabled === false ) { - el.remove(); - } else { - el.classList.add( "hide" ); - } - - }); - - } - - document.body.classList.toggle( "feature-" + featureSwitch.name, featureSwitch.isEnabled() ); - - } - - } - - - savePreferences() { - - let preferences:any = {}; - - for ( const featureSwitch of this.#featureSwitches ) { - preferences[ featureSwitch.name ] = featureSwitch.isEnabled(); - } - - localStorage.setItem( "featureSwitches", JSON.stringify( preferences ) ); - - } - -} \ No newline at end of file From 8d5b1f50be345e7887b884a43d5570701c10d2de Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:57:55 +0100 Subject: [PATCH 18/30] Delete ToggleableFeature.ts --- client/src/ToggleableFeature.ts | 35 --------------------------------- 1 file changed, 35 deletions(-) delete mode 100644 client/src/ToggleableFeature.ts diff --git a/client/src/ToggleableFeature.ts b/client/src/ToggleableFeature.ts deleted file mode 100644 index 5873fb6e..00000000 --- a/client/src/ToggleableFeature.ts +++ /dev/null @@ -1,35 +0,0 @@ -export abstract class ToggleableFeature { - - #status:boolean = false; - - - constructor( defaultStatus:boolean ) { - - this.#status = defaultStatus; - - this.onStatusUpdate(); - - } - - - getStatus() : boolean { - return this.#status; - } - - - protected onStatusUpdate() {} - - - toggleStatus( force?:boolean ) : void { - - if ( force ) { - this.#status = force; - } else { - this.#status = !this.#status; - } - - this.onStatusUpdate(); - - } - -} \ No newline at end of file From b457a042ea67ec7953cc760f79de05d9578ae40f Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:58:51 +0100 Subject: [PATCH 19/30] Delete olympus.cpp --- src/Olympus/src/olympus.cpp | 152 ------------------------------------ 1 file changed, 152 deletions(-) delete mode 100644 src/Olympus/src/olympus.cpp diff --git a/src/Olympus/src/olympus.cpp b/src/Olympus/src/olympus.cpp deleted file mode 100644 index 67189855..00000000 --- a/src/Olympus/src/olympus.cpp +++ /dev/null @@ -1,152 +0,0 @@ -#include "framework.h" -#include "dcstools.h" -#include "logger.h" -#include "utils.h" - -/* 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_coreDeinit)(lua_State* L); -typedef int(__stdcall* f_coreFrame)(lua_State* L); -typedef int(__stdcall* f_coreMissionData)(lua_State* L); -f_coreInit coreInit = nullptr; -f_coreDeinit coreDeinit = nullptr; -f_coreFrame coreFrame = nullptr; -f_coreMissionData coreMissionData = nullptr; - -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"; - - log("Loading core.dll"); - hGetProcIDDLL = LoadLibrary(to_wstring(dllLocation).c_str()); - - if (!hGetProcIDDLL) { - LogError(L, "Error loading core DLL"); - goto error; - } - - log("Core DLL loaded successfully"); - - coreInit = (f_coreInit)GetProcAddress(hGetProcIDDLL, "coreInit"); - if (!coreInit) - { - LogError(L, "Error getting coreInit ProcAddress from DLL"); - goto error; - } - - coreDeinit = (f_coreDeinit)GetProcAddress(hGetProcIDDLL, "coreDeinit"); - if (!coreInit) - { - LogError(L, "Error getting coreDeinit ProcAddress from DLL"); - goto error; - } - - coreFrame = (f_coreFrame)GetProcAddress(hGetProcIDDLL, "coreFrame"); - if (!coreFrame) - { - LogError(L, "Error getting coreFrame ProcAddress from DLL"); - goto error; - } - - coreMissionData = (f_coreFrame)GetProcAddress(hGetProcIDDLL, "coreMissionData"); - if (!coreFrame) - { - LogError(L, "Error getting coreMissionData ProcAddress from DLL"); - goto error; - } - - coreInit(L); - - LogInfo(L, "Module loaded and started successfully."); - - return 0; - -error: - LogError(L, "Error while loading module, see Olympus.log in temporary folder for additional details."); - return 0; -} - -static int onSimulationFrame(lua_State* L) -{ - if (coreFrame) - { - coreFrame(L); - } - return 0; -} - -static int onSimulationStop(lua_State* L) -{ - log("onSimulationStop callback called successfully"); - if (hGetProcIDDLL) - { - log("Trying to unload core DLL"); - if (coreDeinit) - { - coreDeinit(L); - } - - if (FreeLibrary(hGetProcIDDLL)) - { - log("Core DLL unloaded successfully"); - } - else - { - LogError(L, "Error unloading DLL"); - goto error; - } - - coreInit = nullptr; - coreDeinit = nullptr; - coreFrame = nullptr; - coreMissionData = nullptr; - } - - hGetProcIDDLL = NULL; - - return 0; - -error: - LogError(L, "Error while unloading module, see Olympus.log in temporary folder for additional details."); - return 0; -} - -static int setMissionData(lua_State* L) -{ - if (coreMissionData) - { - coreMissionData(L); - } - return 0; -} - -static const luaL_Reg Map[] = { - {"onSimulationStart", onSimulationStart}, - {"onSimulationFrame", onSimulationFrame}, - {"onSimulationStop", onSimulationStop}, - {"setMissionData", setMissionData }, - {NULL, NULL} -}; - -extern "C" DllExport int luaopen_olympus(lua_State * L) -{ - luaL_register(L, "olympus", Map); - return 1; -} \ No newline at end of file From fd731d5da43857a428547d59bf3c88a1a5d0510a Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:58:54 +0100 Subject: [PATCH 20/30] Delete Olympus.filters --- src/Olympus/Olympus.filters | 29 ----------------------------- 1 file changed, 29 deletions(-) delete mode 100644 src/Olympus/Olympus.filters diff --git a/src/Olympus/Olympus.filters b/src/Olympus/Olympus.filters deleted file mode 100644 index 2bcbeefa..00000000 --- a/src/Olympus/Olympus.filters +++ /dev/null @@ -1,29 +0,0 @@ - - - - - {4FC737F1-C7A5-4376-A066-2A32D752A2FF} - cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx - - - {93995380-89BD-4b04-88EB-625FBE52EBFB} - h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd - - - - - inc - - - inc - - - - - src - - - src - - - \ No newline at end of file From 6f1f862f0750a5d6386a90f1306018c4fcf5dee4 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:58:57 +0100 Subject: [PATCH 21/30] Delete Olympus.vcxproj --- src/Olympus/Olympus.vcxproj | 120 ------------------------------------ 1 file changed, 120 deletions(-) delete mode 100644 src/Olympus/Olympus.vcxproj diff --git a/src/Olympus/Olympus.vcxproj b/src/Olympus/Olympus.vcxproj deleted file mode 100644 index 50e68d5c..00000000 --- a/src/Olympus/Olympus.vcxproj +++ /dev/null @@ -1,120 +0,0 @@ - - - - - Debug - x64 - - - Release - x64 - - - - - - - - {2b255368-39a0-431a-a6de-cc739ac70dc1} - - - {873ecabe-fcfe-4217-ac15-91959c3cf1c6} - - - {b85009ce-4a5c-4a5a-b85d-001b3a2651b2} - - - - 16.0 - Win32Proj - {5f3fc91e-1fbc-4223-8011-9708de913474} - Olympus - 10.0 - olympus - - - - DynamicLibrary - true - v143 - Unicode - - - DynamicLibrary - false - v143 - true - Unicode - - - - - - - - - - - - - - - false - .\..\..\bin\$(Platform)\$(Configuration)\ - - - false - .\..\..\bin\ - - - true - - - - Level3 - true - _CRT_SECURE_NO_WARNINGS; _DEBUG;OLYMPUS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - pch.h - include; ..\..\third-party\lua\include; ..\utils\include; ..\shared\include - stdcpp17 - AssemblyCode - - - Windows - true - false - lua.lib - ..\..\third-party\lua - - - - - Level3 - true - true - true - _CRT_SECURE_NO_WARNINGS; NDEBUG;OLYMPUS_EXPORTS;_WINDOWS;_USRDLL;%(PreprocessorDefinitions) - true - NotUsing - - - include;..\..\third-party\lua\include;..\utils\include;..\shared\include;..\dcstools\include;..\logger\include;..\luatools\include - stdcpp20 - NoListing - - - Windows - true - true - true - false - lua.lib - ..\..\third-party\lua - - - - - - \ No newline at end of file From d773aeb15929d3de87af3239b6cae35b39449ba5 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:59:02 +0100 Subject: [PATCH 22/30] Delete Olympus.vcxproj.filters --- src/Olympus/Olympus.vcxproj.filters | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 src/Olympus/Olympus.vcxproj.filters diff --git a/src/Olympus/Olympus.vcxproj.filters b/src/Olympus/Olympus.vcxproj.filters deleted file mode 100644 index fa32be80..00000000 --- a/src/Olympus/Olympus.vcxproj.filters +++ /dev/null @@ -1,16 +0,0 @@ - - - - - {c021f649-26ec-4040-abd4-13132def4a81} - - - {2809fbbc-77d2-465e-afef-230525a60c66} - - - - - Source Files - - - \ No newline at end of file From 319f1000aeb980d5a1f54620fa7b8a7a83df2c47 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:59:38 +0100 Subject: [PATCH 23/30] Rename Utils.h to utils.h --- src/utils/include/{Utils.h => utils.h} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/utils/include/{Utils.h => utils.h} (100%) diff --git a/src/utils/include/Utils.h b/src/utils/include/utils.h similarity index 100% rename from src/utils/include/Utils.h rename to src/utils/include/utils.h From da8d558ece65879253a5ceb9307a15905dfab99d Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 15:59:53 +0100 Subject: [PATCH 24/30] Rename Utils.cpp to utils.cpp --- src/utils/src/{Utils.cpp => utils.cpp} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/utils/src/{Utils.cpp => utils.cpp} (100%) diff --git a/src/utils/src/Utils.cpp b/src/utils/src/utils.cpp similarity index 100% rename from src/utils/src/Utils.cpp rename to src/utils/src/utils.cpp From 63af32c388541442e4807152b65b23fdae984a38 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 16:00:10 +0100 Subject: [PATCH 25/30] Delete Commands.h --- src/core/include/Commands.h | 275 ------------------------------------ 1 file changed, 275 deletions(-) delete mode 100644 src/core/include/Commands.h diff --git a/src/core/include/Commands.h b/src/core/include/Commands.h deleted file mode 100644 index c8ffbb21..00000000 --- a/src/core/include/Commands.h +++ /dev/null @@ -1,275 +0,0 @@ -#pragma once -#include "framework.h" -#include "luatools.h" -#include "utils.h" - -namespace CommandPriority { - enum CommandPriorities { LOW, MEDIUM, HIGH }; -}; - -namespace CommandType { - enum CommandTypes { NO_TYPE, MOVE, SMOKE, SPAWN_AIR, SPAWN_GROUND, CLONE, FOLLOW, RESET_TASK, SET_OPTION, SET_COMMAND, SET_TASK }; -}; - -namespace SetCommandType { - enum SetCommandTypes { - ROE = 0, - REACTION_ON_THREAT = 1, - RADAR_USING = 3, - FLARE_USING = 4, - FORMATION = 5, - RTB_ON_BINGO = 6, - SILENCE = 7, - RTB_ON_OUT_OF_AMMO = 10, - ECM_USING = 13, - PROHIBIT_AA = 14, - PROHIBIT_JETT = 15, - PROHIBIT_AB = 16, - PROHIBIT_AG = 17, - MISSILE_ATTACK = 18, - PROHIBIT_WP_PASS_REPORT = 19, - OPTION_RADIO_USAGE_CONTACT = 21, - OPTION_RADIO_USAGE_ENGAGE = 22, - OPTION_RADIO_USAGE_KILL = 23, - JETT_TANKS_IF_EMPTY = 25, - FORCED_ATTACK = 26 - }; -} - -namespace ROE { - enum ROEs { - WEAPON_FREE = 0, - OPEN_FIRE_WEAPON_FREE = 1, - OPEN_FIRE = 2, - RETURN_FIRE = 3, - WEAPON_HOLD = 4, - }; -} - -namespace ReactionToThreat { - enum ReactionToThreats { - NO_REACTION = 0, - PASSIVE_DEFENCE = 1, - EVADE_FIRE = 2, - BYPASS_AND_ESCAPE = 3, - ALLOW_ABORT_MISSION = 4 - }; -} - -/* Base command class */ -class Command -{ -public: - int getPriority() { return priority; } - int getType() { return type; } - virtual wstring getString(lua_State* L) = 0; - virtual int getLoad() = 0; - -protected: - int priority = CommandPriority::LOW; - int type = CommandType::NO_TYPE; -}; - -/* Simple low priority move command (from user click) */ -class Move : public Command -{ -public: - Move(int ID, Coords destination, double speed, double altitude, wstring unitCategory, wstring taskOptions): - ID(ID), - destination(destination), - speed(speed), - altitude(altitude), - unitCategory(unitCategory), - taskOptions(taskOptions) - { - priority = CommandPriority::HIGH; - type = CommandType::MOVE; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 5; } - -private: - const int ID; - const Coords destination; - const wstring unitCategory; - const double speed; - const double altitude; - const wstring taskOptions; -}; - -/* Smoke command */ -class Smoke : public Command -{ -public: - Smoke(wstring color, Coords location) : - color(color), - location(location) - { - priority = CommandPriority::LOW; - type = CommandType::SMOKE; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 5; } - -private: - const wstring color; - const Coords location; -}; - -/* Spawn ground unit command */ -class SpawnGroundUnit : public Command -{ -public: - SpawnGroundUnit(wstring coalition, wstring unitType, Coords location) : - coalition(coalition), - unitType(unitType), - location(location) - { - priority = CommandPriority::LOW; - type = CommandType::SPAWN_GROUND; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 100; } - -private: - const wstring coalition; - const wstring unitType; - const Coords location; -}; - -/* Spawn air unit command */ -class SpawnAircraft : public Command -{ -public: - SpawnAircraft(wstring coalition, wstring unitType, Coords location, wstring payloadName, wstring airbaseName) : - coalition(coalition), - unitType(unitType), - location(location), - payloadName(payloadName), - airbaseName(airbaseName) - { - priority = CommandPriority::LOW; - type = CommandType::SPAWN_AIR; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 100; } - -private: - const wstring coalition; - const wstring unitType; - const Coords location; - const wstring payloadName; - const wstring airbaseName; -}; - -/* Clone unit command */ -class Clone : public Command -{ -public: - Clone(int ID, Coords location) : - ID(ID), - location(location) - { - priority = CommandPriority::LOW; - type = CommandType::CLONE; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 100; } - -private: - const int ID; - const Coords location; -}; - -/* Delete unit command */ -class Delete : public Command -{ -public: - Delete(int ID) : - ID(ID) - { - priority = CommandPriority::HIGH; - type = CommandType::CLONE; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 20; } - -private: - const int ID; -}; - -/* Follow command */ -class SetTask : public Command -{ -public: - SetTask(int ID, wstring task) : - ID(ID), - task(task) - { - priority = CommandPriority::MEDIUM; - type = CommandType::FOLLOW; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 10; } - -private: - const int ID; - const wstring task; -}; - -/* Reset task command */ -class ResetTask : public Command -{ -public: - ResetTask(int ID) : - ID(ID) - { - priority = CommandPriority::HIGH; - type = CommandType::RESET_TASK; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 10; } - -private: - const int ID; -}; - -/* Set command */ -class SetCommand : public Command -{ -public: - SetCommand(int ID, wstring command) : - ID(ID), - command(command) - { - priority = CommandPriority::HIGH; - type = CommandType::RESET_TASK; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 10; } - -private: - const int ID; - const wstring command; -}; - -/* Set option command */ -class SetOption : public Command -{ -public: - SetOption(int ID, int optionID, int optionValue) : - ID(ID), - optionID(optionID), - optionValue(optionValue) - { - priority = CommandPriority::HIGH; - type = CommandType::RESET_TASK; - }; - virtual wstring getString(lua_State* L); - virtual int getLoad() { return 10; } - -private: - const int ID; - const int optionID; - const int optionValue; -}; \ No newline at end of file From 2a39073f501cdf327682823463e03a9f023e4c09 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 16:00:13 +0100 Subject: [PATCH 26/30] Delete Scheduler.h --- src/core/include/Scheduler.h | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 src/core/include/Scheduler.h diff --git a/src/core/include/Scheduler.h b/src/core/include/Scheduler.h deleted file mode 100644 index d5ebfcf6..00000000 --- a/src/core/include/Scheduler.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once -#include "framework.h" -#include "luatools.h" -#include "commands.h" - -class Scheduler -{ -public: - Scheduler(lua_State* L); - ~Scheduler(); - - void appendCommand(Command* command); - void execute(lua_State* L); - void handleRequest(wstring key, json::value value); - -private: - list commands; - int load; -}; - From f67125123b187ccc4a5f54463f5df3f08efa9885 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 16:00:18 +0100 Subject: [PATCH 27/30] Delete Unit.h --- src/core/include/Unit.h | 184 ---------------------------------------- 1 file changed, 184 deletions(-) delete mode 100644 src/core/include/Unit.h diff --git a/src/core/include/Unit.h b/src/core/include/Unit.h deleted file mode 100644 index b94f7b1a..00000000 --- a/src/core/include/Unit.h +++ /dev/null @@ -1,184 +0,0 @@ -#pragma once -#include "framework.h" -#include "utils.h" -#include "dcstools.h" -#include "luatools.h" -#include "measure.h" - -namespace State -{ - enum States - { - IDLE, - REACH_DESTINATION, - ATTACK, - WINGMAN, - FOLLOW, - LAND, - REFUEL, - AWACS, - EWR, - TANKER, - RUN_AWAY - }; -}; - -class Unit -{ -public: - Unit(json::value json, int ID); - ~Unit(); - - /********** Public methods **********/ - int getID() { return ID; } - void updateExportData(json::value json); - void updateMissionData(json::value json); - json::value getData(long long time); - - /********** Base data **********/ - void setAI(bool newAI) { AI = newAI; addMeasure(L"AI", json::value(newAI)); } - void setName(wstring newName) { name = newName; addMeasure(L"name", json::value(newName));} - void setUnitName(wstring newUnitName) { unitName = newUnitName; addMeasure(L"unitName", json::value(newUnitName));} - void setGroupName(wstring newGroupName) { groupName = newGroupName; addMeasure(L"groupName", json::value(newGroupName));} - void setAlive(bool newAlive) { alive = newAlive; addMeasure(L"alive", json::value(newAlive));} - void setType(json::value newType) { type = newType; addMeasure(L"type", newType);} - void setCountry(int newCountry) { country = newCountry; addMeasure(L"country", json::value(newCountry));} - bool getAI() { return AI; } - wstring getName() { return name; } - wstring getUnitName() { return unitName; } - wstring getGroupName() { return groupName; } - bool getAlive() { return alive; } - json::value getType() { return type; } - int getCountry() { return country; } - - /********** Flight data **********/ - void setLatitude(double newLatitude) {latitude = newLatitude; addMeasure(L"latitude", json::value(newLatitude));} - void setLongitude(double newLongitude) {longitude = newLongitude; addMeasure(L"longitude", json::value(newLongitude));} - void setAltitude(double newAltitude) {altitude = newAltitude; addMeasure(L"altitude", json::value(newAltitude));} - void setHeading(double newHeading) {heading = newHeading; addMeasure(L"heading", json::value(newHeading));} - void setSpeed(double newSpeed) {speed = newSpeed; addMeasure(L"speed", json::value(newSpeed));} - double getLatitude() { return latitude; } - double getLongitude() { return longitude; } - double getAltitude() { return altitude; } - double getHeading() { return heading; } - double getSpeed() { return speed; } - - /********** Mission data **********/ - void setFuel(double newFuel) { fuel = newFuel; addMeasure(L"fuel", json::value(newFuel));} - void setAmmo(json::value newAmmo) { ammo = newAmmo; addMeasure(L"ammo", json::value(newAmmo));} - void setTargets(json::value newTargets) {targets = newTargets; addMeasure(L"targets", json::value(newTargets));} - void setHasTask(bool newHasTask) { hasTask = newHasTask; addMeasure(L"hasTask", json::value(newHasTask));} - void setCoalitionID(int newCoalitionID); - void setFlags(json::value newFlags) { flags = newFlags; addMeasure(L"flags", json::value(newFlags));} - double getFuel() { return fuel; } - json::value getAmmo() { return ammo; } - json::value getTargets() { return targets; } - bool getHasTask() { return hasTask; } - wstring getCoalition() { return coalition; } - int getCoalitionID(); - json::value getFlags() { return flags; } - - /********** Formation data **********/ - void setIsLeader(bool newIsLeader); - void setIsWingman(bool newIsWingman); - void setLeader(Unit* newLeader); - void setWingmen(vector newWingmen); - void setFormation(wstring newFormation) { formation = newFormation; addMeasure(L"formation", json::value(formation));} - void setFormationOffset(Offset formationOffset); - bool getIsLeader() { return isLeader; } - bool getIsWingman() { return isWingman; } - Unit* getLeader() { return leader; } - vector getWingmen() { return wingmen; } - wstring getFormation() { return formation; } - Offset getFormationoffset() { return formationOffset; } - - /********** Task data **********/ - void setCurrentTask(wstring newCurrentTask) { currentTask = newCurrentTask;addMeasure(L"currentTask", json::value(newCurrentTask)); } - virtual void setTargetSpeed(double newTargetSpeed) { targetSpeed = newTargetSpeed; addMeasure(L"targetSpeed", json::value(newTargetSpeed));} - virtual void setTargetAltitude(double newTargetAltitude) { targetAltitude = newTargetAltitude; addMeasure(L"targetAltitude", json::value(newTargetAltitude));} //TODO fix, double definition - void setActiveDestination(Coords newActiveDestination) { activeDestination = newActiveDestination; addMeasure(L"activeDestination", json::value("")); } // TODO fix - void setActivePath(list newActivePath); - void setTargetID(int newTargetID) { targetID = newTargetID; addMeasure(L"targetID", json::value(newTargetID));} - wstring getCurrentTask() { return currentTask; } - virtual double getTargetSpeed() { return targetSpeed; }; - virtual double getTargetAltitude() { return targetAltitude; }; - Coords getActiveDestination() { return activeDestination; } - list getActivePath() { return activePath; } - int getTargetID() { return targetID; } - - /********** Options data **********/ - void setROE(wstring newROE); - void setReactionToThreat(wstring newReactionToThreat); - wstring getROE() { return ROE; } - wstring getReactionToThreat() {return reactionToThreat;} - - /********** Control functions **********/ - void landAt(Coords loc); - virtual void changeSpeed(wstring change){}; - virtual void changeAltitude(wstring change){}; - void resetActiveDestination(); - virtual void setState(int newState) { state = newState; }; - void resetTask(); - -protected: - int ID; - - map measures; - - /********** Base data **********/ - bool AI = false; - wstring name = L"undefined"; - wstring unitName = L"undefined"; - wstring groupName = L"undefined"; - bool alive = true; - json::value type = json::value::null(); - int country = NULL; - - /********** Flight data **********/ - double latitude = NULL; - double longitude = NULL; - double altitude = NULL; - double speed = NULL; - double heading = NULL; - - /********** Mission data **********/ - double fuel = 0; - json::value ammo = json::value::null(); - json::value targets = json::value::null(); - bool hasTask = false; - wstring coalition = L""; - json::value flags = json::value::null(); - - /********** Formation data **********/ - bool isLeader = false; - bool isWingman = false; - wstring formation = L""; - Unit *leader = nullptr; - vector wingmen; - Offset formationOffset = Offset(NULL); - - /********** Task data **********/ - wstring currentTask = L""; - double targetSpeed = 0; - double targetAltitude = 0; - list activePath; - Coords activeDestination = Coords(0); - int targetID = NULL; - - /********** Options data **********/ - wstring ROE = L""; - wstring reactionToThreat = L""; - - /********** State machine **********/ - int state = State::IDLE; - - /********** Other **********/ - Coords oldPosition = Coords(0); // Used to approximate speed - - /********** Functions **********/ - virtual wstring getCategory() { return L"No category"; }; - wstring getTargetName(); - bool isTargetAlive(); - virtual void AIloop() = 0; - void addMeasure(wstring key, json::value value); -}; From 878d4ecdc0c263ff92d2942fffeeb3143e32e0e6 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 16:00:32 +0100 Subject: [PATCH 28/30] Delete Commands.cpp --- src/core/src/Commands.cpp | 135 -------------------------------------- 1 file changed, 135 deletions(-) delete mode 100644 src/core/src/Commands.cpp diff --git a/src/core/src/Commands.cpp b/src/core/src/Commands.cpp deleted file mode 100644 index ef5a7535..00000000 --- a/src/core/src/Commands.cpp +++ /dev/null @@ -1,135 +0,0 @@ -#include "commands.h" -#include "logger.h" -#include "dcstools.h" - -/* Move command */ -wstring Move::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.move, " - << ID << ", " - << destination.lat << ", " - << destination.lng << ", " - << altitude << ", " - << speed << ", " - << "\"" << unitCategory << "\"" << ", " - << taskOptions; - return commandSS.str(); -} - -/* Smoke command */ -wstring Smoke::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.smoke, " - << "\"" << color << "\"" << ", " - << location.lat << ", " - << location.lng; - return commandSS.str(); -} - -/* Spawn ground command */ -wstring SpawnGroundUnit::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.spawnGroundUnit, " - << "\"" << coalition << "\"" << ", " - << "\"" << unitType << "\"" << ", " - << location.lat << ", " - << location.lng; - return commandSS.str(); -} - -/* Spawn air command */ -wstring SpawnAircraft::getString(lua_State* L) -{ - std::wostringstream optionsSS; - optionsSS.precision(10); - optionsSS << "{" - << "payloadName = \"" << payloadName << "\", " - << "airbaseName = \"" << airbaseName << "\"," - << "}"; - - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.spawnAircraft, " - << "\"" << coalition << "\"" << ", " - << "\"" << unitType << "\"" << ", " - << location.lat << ", " - << location.lng << "," - << optionsSS.str(); - return commandSS.str(); -} - -/* Clone unit command */ -wstring Clone::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.clone, " - << ID << ", " - << location.lat << ", " - << location.lng; - return commandSS.str(); -} - -/* Delete unit command */ -wstring Delete::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.delete, " - << ID; - return commandSS.str(); -} - -/* Set task command */ -wstring SetTask::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.setTask, " - << ID << "," - << task; - - return commandSS.str(); -} - -/* Reset task command */ -wstring ResetTask::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.resetTask, " - << ID; - - return commandSS.str(); -} - -/* Set command command */ -wstring SetCommand::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.setCommand, " - << ID << "," - << command; - - return commandSS.str(); -} - -/* Set option command */ -wstring SetOption::getString(lua_State* L) -{ - std::wostringstream commandSS; - commandSS.precision(10); - commandSS << "Olympus.setOption, " - << ID << "," - << optionID << "," - << optionValue; - - return commandSS.str(); -} \ No newline at end of file From 5d8b1062e8fb16b6066e2675f5005ac152876060 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 16:00:40 +0100 Subject: [PATCH 29/30] Delete Scheduler.cpp --- src/core/src/Scheduler.cpp | 263 ------------------------------------- 1 file changed, 263 deletions(-) delete mode 100644 src/core/src/Scheduler.cpp diff --git a/src/core/src/Scheduler.cpp b/src/core/src/Scheduler.cpp deleted file mode 100644 index 8e80f9bf..00000000 --- a/src/core/src/Scheduler.cpp +++ /dev/null @@ -1,263 +0,0 @@ -#include "scheduler.h" -#include "logger.h" -#include "dcstools.h" -#include "unitsManager.h" -#include "utils.h" -#include "unit.h" - -extern UnitsManager* unitsManager; - -Scheduler::Scheduler(lua_State* L): - load(0) -{ - LogInfo(L, "Scheduler constructor called successfully"); -} - -Scheduler::~Scheduler() -{ - -} - -void Scheduler::appendCommand(Command* command) -{ - commands.push_back(command); -} - -void Scheduler::execute(lua_State* L) -{ - /* Decrease the active computation load. New commands can be sent only if the load has reached 0. - This is needed to avoid server lag. */ - if (load > 0) { - load--; - return; - } - - int priority = CommandPriority::HIGH; - while (priority >= CommandPriority::LOW) - { - for (auto command : commands) - { - if (command->getPriority() == priority) - { - wstring commandString = L"Olympus.protectedCall(" + command->getString(L) + L")"; - if (dostring_in(L, "server", to_string(commandString))) - log(L"Error executing command " + commandString); - load = command->getLoad(); - commands.remove(command); - return; - } - } - priority--; - } -} - -void Scheduler::handleRequest(wstring key, json::value value) -{ - Command* command = nullptr; - - log(L"Received request with ID: " + key); - if (key.compare(L"setPath") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - { - wstring unitName = unit->getUnitName(); - json::value path = value[L"path"]; - list newPath; - for (int i = 1; i <= path.as_object().size(); i++) - { - wstring WP = to_wstring(i); - double lat = path[WP][L"lat"].as_double(); - double lng = path[WP][L"lng"].as_double(); - log(unitName + L" set path destination " + WP + L" (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); - Coords dest; dest.lat = lat; dest.lng = lng; - newPath.push_back(dest); - } - - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - { - unit->setActivePath(newPath); - unit->setState(State::REACH_DESTINATION); - log(unitName + L" new path set successfully"); - } - else - log(unitName + L" not found, request will be discarded"); - } - } - else if (key.compare(L"smoke") == 0) - { - wstring color = value[L"color"].as_string(); - double lat = value[L"location"][L"lat"].as_double(); - double lng = value[L"location"][L"lng"].as_double(); - log(L"Adding " + color + L" smoke at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); - Coords loc; loc.lat = lat; loc.lng = lng; - command = dynamic_cast(new Smoke(color, loc)); - } - else if (key.compare(L"spawnGround") == 0) - { - wstring coalition = value[L"coalition"].as_string(); - wstring type = value[L"type"].as_string(); - double lat = value[L"location"][L"lat"].as_double(); - double lng = value[L"location"][L"lng"].as_double(); - log(L"Spawning " + coalition + L" ground unit of type " + type + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L")"); - Coords loc; loc.lat = lat; loc.lng = lng; - command = dynamic_cast(new SpawnGroundUnit(coalition, type, loc)); - } - else if (key.compare(L"spawnAir") == 0) - { - wstring coalition = value[L"coalition"].as_string(); - wstring type = value[L"type"].as_string(); - double lat = value[L"location"][L"lat"].as_double(); - double lng = value[L"location"][L"lng"].as_double(); - Coords loc; loc.lat = lat; loc.lng = lng; - wstring payloadName = value[L"payloadName"].as_string(); - wstring airbaseName = value[L"airbaseName"].as_string(); - log(L"Spawning " + coalition + L" air unit of type " + type + L" with payload " + payloadName + L" at (" + to_wstring(lat) + L", " + to_wstring(lng) + L" " + airbaseName + L")"); - command = dynamic_cast(new SpawnAircraft(coalition, type, loc, payloadName, airbaseName)); - } - else if (key.compare(L"attackUnit") == 0) - { - int ID = value[L"ID"].as_integer(); - int targetID = value[L"targetID"].as_integer(); - - Unit* unit = unitsManager->getUnit(ID); - Unit* target = unitsManager->getUnit(targetID); - - wstring unitName; - wstring targetName; - - if (unit != nullptr) - unitName = unit->getUnitName(); - else - return; - - if (target != nullptr) - targetName = target->getUnitName(); - else - return; - - log(L"Unit " + unitName + L" attacking unit " + targetName); - unit->setTargetID(targetID); - unit->setState(State::ATTACK); - } - else if (key.compare(L"stopAttack") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - unit->setState(State::REACH_DESTINATION); - else - return; - } - else if (key.compare(L"changeSpeed") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - unit->changeSpeed(value[L"change"].as_string()); - } - else if (key.compare(L"changeAltitude") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - unit->changeAltitude(value[L"change"].as_string()); - } - else if (key.compare(L"setSpeed") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - unit->setTargetSpeed(value[L"speed"].as_double()); - } - else if (key.compare(L"setAltitude") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - if (unit != nullptr) - unit->setTargetAltitude(value[L"altitude"].as_double()); - } - else if (key.compare(L"cloneUnit") == 0) - { - int ID = value[L"ID"].as_integer(); - double lat = value[L"location"][L"lat"].as_double(); - double lng = value[L"location"][L"lng"].as_double(); - Coords loc; loc.lat = lat; loc.lng = lng; - command = dynamic_cast(new Clone(ID, loc)); - log(L"Cloning unit " + to_wstring(ID)); - } - else if (key.compare(L"setLeader") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - bool isLeader = value[L"isLeader"].as_bool(); - if (isLeader) - { - json::value wingmenIDs = value[L"wingmenIDs"]; - vector wingmen; - if (unit != nullptr) - { - for (auto itr = wingmenIDs.as_array().begin(); itr != wingmenIDs.as_array().end(); itr++) - { - Unit* wingman = unitsManager->getUnit(itr->as_integer()); - if (wingman != nullptr) - wingmen.push_back(wingman); - } - unit->setFormation(L"Line abreast"); - unit->setIsLeader(true); - unit->setWingmen(wingmen); - log(L"Setting " + unit->getName() + L" as formation leader"); - } - } - else { - unit->setIsLeader(false); - } - } - else if (key.compare(L"setFormation") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - wstring formation = value[L"formation"].as_string(); - unit->setFormation(formation); - } - else if (key.compare(L"setROE") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - wstring ROE = value[L"ROE"].as_string(); - unit->setROE(ROE); - } - else if (key.compare(L"setReactionToThreat") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - wstring reactionToThreat = value[L"reactionToThreat"].as_string(); - unit->setReactionToThreat(reactionToThreat); - } - else if (key.compare(L"landAt") == 0) - { - int ID = value[L"ID"].as_integer(); - Unit* unit = unitsManager->getUnit(ID); - double lat = value[L"location"][L"lat"].as_double(); - double lng = value[L"location"][L"lng"].as_double(); - Coords loc; loc.lat = lat; loc.lng = lng; - unit->landAt(loc); - } - else if (key.compare(L"deleteUnit") == 0) - { - int ID = value[L"ID"].as_integer(); - unitsManager->deleteUnit(ID); - } - else - { - log(L"Unknown command: " + key); - } - - if (command != nullptr) - { - appendCommand(command); - } -} - From 2b2dc087dae4fa6d6ccb666076ca44ff06c22075 Mon Sep 17 00:00:00 2001 From: Pax1601 Date: Thu, 16 Mar 2023 16:00:43 +0100 Subject: [PATCH 30/30] Delete Unit.cpp --- src/core/src/Unit.cpp | 322 ------------------------------------------ 1 file changed, 322 deletions(-) delete mode 100644 src/core/src/Unit.cpp diff --git a/src/core/src/Unit.cpp b/src/core/src/Unit.cpp deleted file mode 100644 index 09bb63bd..00000000 --- a/src/core/src/Unit.cpp +++ /dev/null @@ -1,322 +0,0 @@ -#include "unit.h" -#include "utils.h" -#include "logger.h" -#include "commands.h" -#include "scheduler.h" -#include "defines.h" -#include "unitsManager.h" - -#include -using namespace std::chrono; - -#include -using namespace GeographicLib; - -extern Scheduler* scheduler; -extern UnitsManager* unitsManager; - -Unit::Unit(json::value json, int ID) : - ID(ID) -{ - log("Creating unit with ID: " + to_string(ID)); -} - -Unit::~Unit() -{ - -} - -void Unit::addMeasure(wstring key, json::value value) -{ - milliseconds ms = duration_cast(system_clock::now().time_since_epoch()); - if (measures.find(key) == measures.end()) - measures[key] = new Measure(value, ms.count()); - else - { - if (measures[key]->getValue() != value) - { - measures[key]->setValue(value); - measures[key]->setTime(ms.count()); - } - } -} - -void Unit::updateExportData(json::value json) -{ - /* Compute speed (loGetWorldObjects does not provide speed, we compute it for better performance instead of relying on many lua calls) */ - if (oldPosition != NULL) - { - double dist = 0; - Geodesic::WGS84().Inverse(latitude, longitude, oldPosition.lat, oldPosition.lng, dist); - setSpeed(getSpeed() * 0.95 + (dist / UPDATE_TIME_INTERVAL) * 0.05); - } - oldPosition = Coords(latitude, longitude, altitude); - - if (json.has_string_field(L"Name")) - setName(json[L"Name"].as_string()); - if (json.has_string_field(L"UnitName")) - setUnitName(json[L"UnitName"].as_string()); - if (json.has_string_field(L"GroupName")) - setGroupName(json[L"GroupName"].as_string()); - if (json.has_object_field(L"Type")) - setType(json[L"Type"]); - if (json.has_number_field(L"Country")) - setCountry(json[L"Country"].as_number().to_int32()); - if (json.has_number_field(L"CoalitionID")) - setCoalitionID(json[L"CoalitionID"].as_number().to_int32()); - if (json.has_object_field(L"LatLongAlt")) - { - setLatitude(json[L"LatLongAlt"][L"Lat"].as_number().to_double()); - setLongitude(json[L"LatLongAlt"][L"Long"].as_number().to_double()); - setAltitude(json[L"LatLongAlt"][L"Alt"].as_number().to_double()); - } - if (json.has_number_field(L"Heading")) - setHeading(json[L"Heading"].as_number().to_double()); - if (json.has_object_field(L"Flags")) - setFlags(json[L"Flags"]); - - /* All units which contain the name "Olympus" are automatically under AI control */ - /* TODO: I don't really like using this method */ - setAI(getUnitName().find(L"Olympus") != wstring::npos); - - /* If the unit is alive and it is not a human, run the AI Loop that performs the requested commands and instructions (moving, attacking, etc) */ - if (getAI() && getAlive() && getFlags()[L"Human"].as_bool() == false) - AIloop(); -} - -void Unit::updateMissionData(json::value json) -{ - if (json.has_number_field(L"fuel")) - setFuel(int(json[L"fuel"].as_number().to_double() * 100)); - if (json.has_object_field(L"ammo")) - setAmmo(json[L"ammo"]); - if (json.has_object_field(L"targets")) - setTargets(json[L"targets"]); - if (json.has_boolean_field(L"hasTask")) - setHasTask(json[L"hasTask"].as_bool()); -} - -json::value Unit::getData(long long time) -{ - auto json = json::value::object(); - - /********** Base data **********/ - json[L"baseData"] = json::value::object(); - for (auto key : { L"AI", L"name", L"unitName", L"groupName", L"alive", L"category"}) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"baseData"][key] = measures[key]->getValue(); - } - - /********** Flight data **********/ - json[L"flightData"] = json::value::object(); - for (auto key : { L"latitude", L"longitude", L"altitude", L"speed", L"heading"}) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"flightData"][key] = measures[key]->getValue(); - } - - /********** Mission data **********/ - json[L"missionData"] = json::value::object(); - for (auto key : { L"fuel", L"ammo", L"targets", L"hasTask", L"coalition", L"flags"}) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"missionData"][key] = measures[key]->getValue(); - } - - /********** Formation data **********/ - json[L"formationData"] = json::value::object(); - for (auto key : { L"isLeader", L"isWingman", L"formation", L"wingmenIDs", L"leaderID" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"missionData"][key] = measures[key]->getValue(); - } - - /********** Task data **********/ - json[L"taskData"] = json::value::object(); - for (auto key : { L"currentTask", L"targetSpeed", L"targetAltitude", L"activePath" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"taskData"][key] = measures[key]->getValue(); - } - - /********** Options data **********/ - json[L"optionsData"] = json::value::object(); - for (auto key : { L"ROE", L"reactionToThreat" }) - { - if (measures.find(key) != measures.end() && measures[key]->getTime() > time) - json[L"optionsData"][key] = measures[key]->getValue(); - } - - return json; -} - -void Unit::setActivePath(list newPath) -{ - if (state != State::WINGMAN && state != State::FOLLOW) - { - activePath = newPath; - resetActiveDestination(); - } - - auto path = json::value::object(); - if (activePath.size() > 0) { - int count = 1; - for (auto& destination : activePath) - { - auto json = json::value::object(); - json[L"lat"] = destination.lat; - json[L"lng"] = destination.lng; - json[L"alt"] = destination.alt; - path[to_wstring(count++)] = json; - } - } - addMeasure(L"activePath", path); -} - -void Unit::setCoalitionID(int newCoalitionID) -{ - if (newCoalitionID == 0) - coalition = L"neutral"; - else if (newCoalitionID == 1) - coalition = L"red"; - else - coalition = L"blue"; - addMeasure(L"coalition", json::value(coalition)); -} - -int Unit::getCoalitionID() -{ - if (coalition == L"neutral") - return 0; - else if (coalition == L"red") - return 1; - else - return 2; -} - -void Unit::setLeader(Unit* newLeader) -{ - leader = newLeader; - if (leader != nullptr) - addMeasure(L"leaderID", json::value(leader->getID())); -} - -void Unit::setWingmen(vector newWingmen) { - wingmen = newWingmen; - auto wingmenIDs = json::value::object(); - int i = 0; - for (auto itr = wingmen.begin(); itr != wingmen.end(); itr++) - wingmenIDs[i++] = (*itr)->getID(); - addMeasure(L"wingmen", wingmenIDs); -} - -wstring Unit::getTargetName() -{ - if (isTargetAlive()) - { - Unit* target = unitsManager->getUnit(targetID); - if (target != nullptr) - return target->getUnitName(); - } - return L""; -} - -bool Unit::isTargetAlive() -{ - if (targetID == NULL) - return false; - - Unit* target = unitsManager->getUnit(targetID); - if (target != nullptr) - return target->alive; - else - return false; -} - -void Unit::resetActiveDestination() -{ - activeDestination = Coords(NULL); -} - -void Unit::resetTask() -{ - Command* command = dynamic_cast(new ResetTask(ID)); - scheduler->appendCommand(command); -} - -void Unit::setIsLeader(bool newIsLeader) { - isLeader = newIsLeader; - if (!isLeader) { - for (auto wingman : wingmen) - { - wingman->setFormation(L""); - wingman->setIsWingman(false); - wingman->setLeader(nullptr); - } - } - addMeasure(L"isLeader", json::value(newIsLeader)); -} - -void Unit::setIsWingman(bool newIsWingman) -{ - isWingman = newIsWingman; - if (isWingman) - setState(State::WINGMAN); - else - setState(State::IDLE); - - addMeasure(L"isWingman", json::value(isWingman)); -} - -void Unit::setFormationOffset(Offset newFormationOffset) -{ - formationOffset = newFormationOffset; - resetTask(); -} - -void Unit::setROE(wstring newROE) { - ROE = newROE; - int ROEEnum; - if (newROE.compare(L"Free") == 0) - ROEEnum = ROE::WEAPON_FREE; - else if (newROE.compare(L"Designated free") == 0) - ROEEnum = ROE::OPEN_FIRE_WEAPON_FREE; - else if (newROE.compare(L"Designated") == 0) - ROEEnum = ROE::OPEN_FIRE; - else if (newROE.compare(L"Return") == 0) - ROEEnum = ROE::RETURN_FIRE; - else if (newROE.compare(L"Hold") == 0) - ROEEnum = ROE::WEAPON_HOLD; - else - return; - Command* command = dynamic_cast(new SetOption(ID, SetCommandType::ROE, ROEEnum)); - scheduler->appendCommand(command); - addMeasure(L"ROE", json::value(newROE)); -} - -void Unit::setReactionToThreat(wstring newReactionToThreat) { - reactionToThreat = newReactionToThreat; - int reactionToThreatEnum; - if (newReactionToThreat.compare(L"None") == 0) - reactionToThreatEnum = ReactionToThreat::NO_REACTION; - else if (newReactionToThreat.compare(L"Passive") == 0) - reactionToThreatEnum = ReactionToThreat::PASSIVE_DEFENCE; - else if (newReactionToThreat.compare(L"Evade") == 0) - reactionToThreatEnum = ReactionToThreat::EVADE_FIRE; - else if (newReactionToThreat.compare(L"Escape") == 0) - reactionToThreatEnum = ReactionToThreat::BYPASS_AND_ESCAPE; - else if (newReactionToThreat.compare(L"Abort") == 0) - reactionToThreatEnum = ReactionToThreat::ALLOW_ABORT_MISSION; - else - return; - Command* command = dynamic_cast(new SetOption(ID, SetCommandType::REACTION_ON_THREAT, reactionToThreatEnum)); - scheduler->appendCommand(command); - addMeasure(L"reactionToThreat", json::value(newReactionToThreat)); -} - -void Unit::landAt(Coords loc) { - activePath.clear(); - activePath.push_back(loc); - setState(State::LAND); -} \ No newline at end of file