diff --git a/Moose Development/Moose/Core/Message.lua b/Moose Development/Moose/Core/Message.lua index 45c9cd968..764f33602 100644 --- a/Moose Development/Moose/Core/Message.lua +++ b/Moose Development/Moose/Core/Message.lua @@ -52,7 +52,7 @@ -- === -- -- ### Author: **FlightControl** --- ### Contributions: +-- ### Contributions: **Applevangelist** -- -- === -- @@ -371,7 +371,9 @@ function MESSAGE:ToCoalition( CoalitionSide, Settings ) trigger.action.outTextForCoalition( CoalitionSide, self.MessageText:gsub( "\n$", "" ):gsub( "\n$", "" ), self.MessageDuration, self.ClearScreen ) end end - + + self.CoalitionSide = CoalitionSide + return self end @@ -454,3 +456,154 @@ function MESSAGE:ToLogIf( Condition ) end return self end + +_MESSAGESRS = {} + +--- Set up MESSAGE generally to allow Text-To-Speech via SRS and TTS functions. +-- @param #string PathToSRS Path to SRS Folder, defaults to "C:\\\\Program Files\\\\DCS-SimpleRadio-Standalone". +-- @param #number Port Port number of SRS, defaults to 5002. +-- @param #string PathToCredentials (optional) Path to credentials file for e.g. Google. +-- @param #number Frequency Frequency in MHz. Can also be given as a #table of frequencies. +-- @param #number Modulation Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. +-- @param #string Gender (optional) Gender, i.e. "male" or "female", defaults to "male". +-- @param #string Culture (optional) Culture, e.g. "en-US", defaults to "en-GB" +-- @param #string Voice (optional) Voice. Will override gender and culture settings, e.g. MSRS.Voices.Microsoft.Hazel or MSRS.Voices.Google.Standard.de_DE_Standard_D. Hint on Microsoft voices - working voices are limited to Hedda, Hazel, David, Zira and Hortense. **Must** be installed on your Desktop or Server! +-- @param #number Coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Defaults to coalition.side.NEUTRAL. +-- @param #number Volume (optional) Volume, can be between 0.0 and 1.0 (loudest). +-- @param #string Label (optional) Label, defaults to "MESSAGE" or the Message Category set. +-- @param Core.Point#COORDINATE Coordinate (optional) Coordinate this messages originates from. +-- @usage +-- -- Mind the dot here, not using the colon this time around! +-- -- Needed once only +-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE) +-- -- later on in your code +-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() +-- +function MESSAGE.SetMSRS(PathToSRS,Port,PathToCredentials,Frequency,Modulation,Gender,Culture,Voice,Coalition,Volume,Label,Coordinate) + local path = PathToSRS or "C:\\Program Files\\DCS-SimpleRadio-Standalone" + _MESSAGESRS.MSRS = MSRS:New(path,Frequency,Modulation,Volume) + _MESSAGESRS.MSRS:SetCoalition(Coalition) + _MESSAGESRS.MSRS:SetCoordinate(Coordinate) + _MESSAGESRS.MSRS:SetCulture(Culture) + _MESSAGESRS.MSRS:SetFrequencies(Frequency) + _MESSAGESRS.MSRS:SetGender(Gender) + _MESSAGESRS.MSRS:SetGoogle(PathToCredentials) + _MESSAGESRS.MSRS:SetLabel(Label or "MESSAGE") + _MESSAGESRS.MSRS:SetModulations(Modulation) + _MESSAGESRS.MSRS:SetPath(PathToSRS) + _MESSAGESRS.MSRS:SetPort(Port) + _MESSAGESRS.MSRS:SetVolume(Volume) + _MESSAGESRS.MSRS:SetVoice(Voice) + _MESSAGESRS.SRSQ = MSRSQUEUE:New(Label or "MESSAGE") +end + +--- Sends a message via SRS. +-- @param #MESSAGE self +-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #number coalition (optional) Coalition, can be coalition.side.RED, coalition.side.BLUE or coalition.side.NEUTRAL. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @return #MESSAGE self +-- @usage +-- -- Mind the dot here, not using the colon this time around! +-- -- Needed once only +-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE) +-- -- later on in your code +-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRS() +-- +function MESSAGE:ToSRS(frequency,modulation,gender,culture,voice,coalition,volume,coordinate) + if _MESSAGESRS.SRSQ then + _MESSAGESRS.MSRS:SetLabel(self.MessageCategory or _MESSAGESRS.MSRS.Label or "MESSAGE") + if gender then + _MESSAGESRS.MSRS:SetGender(gender) + end + if coalition then + _MESSAGESRS.MSRS:SetCoalition(coalition) + end + if culture then + _MESSAGESRS.MSRS:SetCulture(culture) + end + if volume then + _MESSAGESRS.MSRS:SetVolume(volume) + end + if coordinate then + _MESSAGESRS.MSRS:SetCoordinate(coordinate) + end + if voice then + _MESSAGESRS.MSRS:SetVoice(voice) + end + _MESSAGESRS.SRSQ:NewTransmission(self.MessageText,nil,_MESSAGESRS.MSRS,nil,1,nil,nil,nil,frequency,modulation) + end + return self +end + +--- Sends a message via SRS on the blue coalition side. +-- @param #MESSAGE self +-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @return #MESSAGE self +-- @usage +-- -- Mind the dot here, not using the colon this time around! +-- -- Needed once only +-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.BLUE) +-- -- later on in your code +-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSBlue() +-- +function MESSAGE:ToSRSBlue(frequency,modulation,gender,culture,voice,volume,coordinate) + self:ToSRS(frequency,modulation,gender,culture,voice,coalition.side.BLUE,volume,coordinate) + return self +end + +--- Sends a message via SRS on the red coalition side. +-- @param #MESSAGE self +-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @return #MESSAGE self +-- @usage +-- -- Mind the dot here, not using the colon this time around! +-- -- Needed once only +-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.RED) +-- -- later on in your code +-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSRed() +-- +function MESSAGE:ToSRSRed(frequency,modulation,gender,culture,voice,volume,coordinate) + self:ToSRS(frequency,modulation,gender,culture,voice,coalition.side.RED,volume,coordinate) + return self +end + +--- Sends a message via SRS to all - via the neutral coalition side. +-- @param #MESSAGE self +-- @param #number frequency (optional) Frequency in MHz. Can also be given as a #table of frequencies. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #number modulation (optional) Modulation, i.e. radio.modulation.AM or radio.modulation.FM. Can also be given as a #table of modulations. Only needed if you want to override defaults set with `MESSAGE.SetMSRS()` for this one setting. +-- @param #string gender (optional) Gender, i.e. "male" or "female". Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string culture (optional) Culture, e.g. "en-US. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #string voice (optional) Voice. Will override gender and culture settings. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param #number volume (optional) Volume, can be between 0.0 and 1.0 (loudest). Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @param Core.Point#COORDINATE coordinate (optional) Coordinate this messages originates from. Only needed if you want to change defaults set with `MESSAGE.SetMSRS()`. +-- @return #MESSAGE self +-- @usage +-- -- Mind the dot here, not using the colon this time around! +-- -- Needed once only +-- MESSAGE.SetMSRS("D:\\Program Files\\DCS-SimpleRadio-Standalone",5012,nil,127,radio.modulation.FM,"female","en-US",nil,coalition.side.NEUTRAL) +-- -- later on in your code +-- MESSAGE:New("Test message!",15,"SPAWN"):ToSRSAll() +-- +function MESSAGE:ToSRSAll(frequency,modulation,gender,culture,voice,volume,coordinate) + self:ToSRS(frequency,modulation,gender,culture,voice,coalition.side.NEUTRAL,volume,coordinate) + return self +end + diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index bf98911ef..dac994af1 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -6052,7 +6052,29 @@ do -- SET_ZONE return self end - + + --- Get the average aggregated coordinate of this set of zones. + -- @param #SET_ZONE self + -- @return Core.Point#COORDINATE + function SET_ZONE:GetAverageCoordinate() + local x,y,z = 0,0,0 + local count = 0 + for _,_zone in pairs(self.Set) do + local zone=_zone --Core.Zone#ZONE + local vec3 = zone:GetVec3() + x = x + vec3.x + y = y + vec3.y + z = z + vec3.z + count = count + 1 + end + if count > 1 then + x = x/count + y = y/count + z = z/count + end + local coord = COORDINATE:New(x,y,z) + return coord + end --- Private function. -- @param #SET_ZONE self diff --git a/Moose Development/Moose/Functional/Fox.lua b/Moose Development/Moose/Functional/Fox.lua index 5d2e35865..4d5a418e0 100644 --- a/Moose Development/Moose/Functional/Fox.lua +++ b/Moose Development/Moose/Functional/Fox.lua @@ -113,14 +113,9 @@ -- -- Start missile trainer. -- fox:Start() -- --- # Fine Tuning --- --- Todo! --- --- # Special Events --- --- Todo! +-- # Notes -- +-- The script needs to be running before you enter an airplane slot. If FOX is not available to you, go back to observers and then join a slot again. -- -- @field #FOX FOX = { diff --git a/Moose Development/Moose/Functional/MissileTrainer.lua b/Moose Development/Moose/Functional/MissileTrainer.lua index 2551ac825..a006d9550 100644 --- a/Moose Development/Moose/Functional/MissileTrainer.lua +++ b/Moose Development/Moose/Functional/MissileTrainer.lua @@ -50,6 +50,11 @@ -- * **100 meter**: Destroys the missile when the distance to the aircraft is below or equal to 100 meter. -- * **150 meter**: Destroys the missile when the distance to the aircraft is below or equal to 150 meter. -- * **200 meter**: Destroys the missile when the distance to the aircraft is below or equal to 200 meter. +-- +-- # Developer Note +-- +-- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE. +-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality. -- -- === -- @@ -101,7 +106,7 @@ -- # Developer Note -- -- Note while this class still works, it is no longer supported as the original author stopped active development of MOOSE. --- Therefore, this class is considered to be deprecated and superseded by the @{Functional.Fox#FOX} class, which provides the same functionality. +-- Therefore, this class is considered to be deprecated and superseded by the [Functional.Fox](https://flightcontrol-master.github.io/MOOSE_DOCS_DEVELOP/Documentation/Functional.Fox.html) class, which provides the same functionality. -- -- @field #MISSILETRAINER MISSILETRAINER = { diff --git a/Moose Development/Moose/Ops/ATIS.lua b/Moose Development/Moose/Ops/ATIS.lua index e0aea4bbd..8f110b07f 100644 --- a/Moose Development/Moose/Ops/ATIS.lua +++ b/Moose Development/Moose/Ops/ATIS.lua @@ -253,8 +253,7 @@ -- # Sound Files -- -- More than 180 individual sound files have been created using a text-to-speech program. All ATIS information is given with en-US accent. --- --- Check out the pinned messages in the Moose discord #ops-atis channel. +-- You can find the sound files [here](https://github.com/FlightControl-Master/MOOSE_SOUND/releases). Also check out the pinned messages in the Moose discord #ops-atis channel. -- -- To include the files, open the mission (.miz) file with, *e.g.*, 7-zip. Then just drag-n-drop the file into the miz. -- diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index 4cfbe36a7..ed166e23d 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -34,14 +34,17 @@ -- @field Core.Set#SET_ZONE zonesetCAP Set of CAP zones. -- @field Core.Set#SET_ZONE zonesetTANKER Set of TANKER zones. -- @field Core.Set#SET_ZONE zonesetAWACS Set of AWACS zones. +-- @field Core.Set#SET_ZONE zonesetRECON Set of RECON zones. -- @field #number nflightsCAP Number of CAP flights constantly in the air. -- @field #number nflightsAWACS Number of AWACS flights constantly in the air. -- @field #number nflightsTANKERboom Number of TANKER flights with BOOM constantly in the air. -- @field #number nflightsTANKERprobe Number of TANKER flights with PROBE constantly in the air. -- @field #number nflightsRescueHelo Number of Rescue helo flights constantly in the air. +-- @field #number nflightsRecon Number of Recon flights constantly in the air. -- @field #table pointsCAP Table of CAP points. -- @field #table pointsTANKER Table of Tanker points. -- @field #table pointsAWACS Table of AWACS points. +-- @field #table pointsRecon Table of RECON points. -- @field #boolean markpoints Display markers on the F10 map. -- @field Ops.Airboss#AIRBOSS airboss Airboss attached to this wing. -- @@ -123,6 +126,7 @@ AIRWING = { pointsCAP = {}, pointsTANKER = {}, pointsAWACS = {}, + pointsRecon = {}, markpoints = false, } @@ -175,7 +179,7 @@ AIRWING = { --- AIRWING class version. -- @field #string version -AIRWING.version="0.9.2" +AIRWING.version="0.9.3" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -219,6 +223,7 @@ function AIRWING:New(warehousename, airwingname) -- Defaults: self.nflightsCAP=0 self.nflightsAWACS=0 + self.nflightsRecon=0 self.nflightsTANKERboom=0 self.nflightsTANKERprobe=0 self.nflightsRecoveryTanker=0 @@ -734,6 +739,15 @@ function AIRWING:SetNumberAWACS(n) return self end +--- Set number of RECON flights constantly in the air. +-- @param #AIRWING self +-- @param #number n Number of flights. Default 1. +-- @return #AIRWING self +function AIRWING:SetNumberRecon(n) + self.nflightsRecon=n or 1 + return self +end + --- Set number of Rescue helo flights constantly in the air. -- @param #AIRWING self -- @param #number n Number of flights. Default 1. @@ -819,6 +833,23 @@ function AIRWING:AddPatrolPointCAP(Coordinate, Altitude, Speed, Heading, LegLeng return self end +--- Add a patrol Point for RECON missions. +-- @param #AIRWING self +-- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. +-- @param #number Altitude Orbit altitude in feet. +-- @param #number Speed Orbit speed in knots. +-- @param #number Heading Heading in degrees. +-- @param #number LegLength Length of race-track orbit in NM. +-- @return #AIRWING self +function AIRWING:AddPatrolPointRecon(Coordinate, Altitude, Speed, Heading, LegLength) + + local patrolpoint=self:NewPatrolPoint("RECON", Coordinate, Altitude, Speed, Heading, LegLength) + + table.insert(self.pointsRecon, patrolpoint) + + return self +end + --- Add a patrol Point for TANKER missions. -- @param #AIRWING self -- @param Core.Point#COORDINATE Coordinate Coordinate of the patrol point. @@ -971,6 +1002,9 @@ function AIRWING:onafterStatus(From, Event, To) -- Check Rescue Helo missions. self:CheckRescuhelo() + -- Check Recon missions. + self:CheckRECON() + ---------------- -- Transport --- ---------------- @@ -1111,6 +1145,58 @@ function AIRWING:CheckCAP() return self end +--- Check how many RECON missions are assigned and add number of missing missions. +-- @param #AIRWING self +-- @return #AIRWING self +function AIRWING:CheckRECON() + + local Ncap=0 --self:CountMissionsInQueue({AUFTRAG.Type.GCICAP, AUFTRAG.Type.INTERCEPT}) + + -- Count CAP missions. + for _,_mission in pairs(self.missionqueue) do + local mission=_mission --Ops.Auftrag#AUFTRAG + + if mission:IsNotOver() and mission.type==AUFTRAG.Type.RECON and mission.patroldata then + Ncap=Ncap+1 + end + + end + + --self:I(self.lid.."Number of active RECON Missions: "..Ncap) + + for i=1,self.nflightsRecon-Ncap do + + --self:I(self.lid.."Creating RECON Missions: "..i) + + local patrol=self:_GetPatrolData(self.pointsRecon) + + local altitude=patrol.altitude --+1000*patrol.noccupied + + local ZoneSet = SET_ZONE:New() + local Zone = ZONE_RADIUS:New(self.alias.." Recon "..math.random(1,10000),patrol.coord:GetVec2(),UTILS.NMToMeters(patrol.leg/2)) + + ZoneSet:AddZone(Zone) + + if self.Debug then + Zone:DrawZone(self.coalition,{0,0,1},Alpha,FillColor,FillAlpha,2,true) + end + + local missionRECON=AUFTRAG:NewRECON(ZoneSet,patrol.speed,patrol.altitude,true) + + missionRECON.patroldata=patrol + missionRECON.categories={AUFTRAG.Category.AIRCRAFT} + + patrol.noccupied=patrol.noccupied+1 + + if self.markpoints then AIRWING.UpdatePatrolPointMarker(patrol) end + + self:AddMission(missionRECON) + + end + + return self +end + --- Check how many TANKER missions are assigned and add number of missing missions. -- @param #AIRWING self -- @return #AIRWING self diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 46b957dd7..b501813c8 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -1339,9 +1339,9 @@ function AUFTRAG:NewCAP(ZoneCAP, Altitude, Speed, Coordinate, Heading, Leg, Targ return mission end ---- **[AIR]** Create a CAP mission on a group. +--- **[AIR]** Create a CAP mission over a (moving) group. -- @param #AUFTRAG self --- @param Wrapper.Group#GROUP Grp. +-- @param Wrapper.Group#GROUP Grp The grp to perform the CAP over. -- @param #number Altitude Orbit altitude in feet. Default is 6,000 ft. -- @param #number Speed Orbit speed in knots. Default 250 KIAS. -- @param #number RelHeading Relative heading [0, 360) of race-track pattern in degrees wrt heading of the carrier. Default is heading of the carrier. @@ -2229,7 +2229,9 @@ function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly, Forma local mission=AUFTRAG:New(AUFTRAG.Type.RECON) mission:_TargetFromObject(ZoneSet) - + + mission.missionZoneSet = ZoneSet + mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.RECON) mission.optionROE=ENUMS.ROE.WeaponHold @@ -2669,7 +2671,7 @@ function AUFTRAG:NewAUTO(EngageGroup) elseif auftrag==AUFTRAG.Type.ORBIT then mission=AUFTRAG:NewORBIT(Coordinate,Altitude,Speed,Heading,Leg) elseif auftrag==AUFTRAG.Type.RECON then - -- Not implemented yet. + mission=AUFTRAG:NewRECON(ZoneSet,Speed,Altitude,Adinfinitum,Randomly,Formation) elseif auftrag==AUFTRAG.Type.RESCUEHELO then mission=AUFTRAG:NewRESCUEHELO(Carrier) elseif auftrag==AUFTRAG.Type.SEAD then @@ -5362,6 +5364,10 @@ function AUFTRAG:GetTargetCoordinate() -- Special case where we defined a return self.transportPickup + + elseif self.missionZoneSet and self.type == AUFTRAG.Type.RECON then + + return self.missionZoneSet:GetAverageCoordinate() elseif self.engageTarget then diff --git a/Moose Development/Moose/Ops/CSAR.lua b/Moose Development/Moose/Ops/CSAR.lua index f9ec9e5f5..9d23a86e1 100644 --- a/Moose Development/Moose/Ops/CSAR.lua +++ b/Moose Development/Moose/Ops/CSAR.lua @@ -61,6 +61,8 @@ -- You need to load an .ogg soundfile for the pilot\'s beacons into the mission, e.g. "beacon.ogg", use a once trigger, "sound to country" for that. -- Create a late-activated single infantry unit as template in the mission editor and name it e.g. "Downed Pilot". -- +-- Example sound files are here: [Moose Sound](https://github.com/FlightControl-Master/MOOSE_SOUND/tree/master/CTLD%20CSAR) +-- -- ## 1. Basic Setup -- -- A basic setup example is the following: diff --git a/Moose Development/Moose/Ops/CTLD.lua b/Moose Development/Moose/Ops/CTLD.lua index 7e79bdbc8..8c77f8eb8 100644 --- a/Moose Development/Moose/Ops/CTLD.lua +++ b/Moose Development/Moose/Ops/CTLD.lua @@ -616,6 +616,8 @@ do -- You need to load an .ogg soundfile for the pilot\'s beacons into the mission, e.g. "beacon.ogg", use a once trigger, "sound to country" for that. -- Create the late-activated troops, vehicles, that will make up your deployable forces. -- +-- Example sound files are here: [Moose Sound](https://github.com/FlightControl-Master/MOOSE_SOUND/tree/master/CTLD%20CSAR) +-- -- ## 1. Basic Setup -- -- ## 1.1 Create and start a CTLD instance diff --git a/Moose Development/Moose/Ops/EasyGCICAP.lua b/Moose Development/Moose/Ops/EasyGCICAP.lua index 5d1d4c0a8..248318fe7 100644 --- a/Moose Development/Moose/Ops/EasyGCICAP.lua +++ b/Moose Development/Moose/Ops/EasyGCICAP.lua @@ -55,12 +55,15 @@ -- @field #table ManagedSQ -- @field #table ManagedCP -- @field #table ManagedTK +-- @field #table ManagedEWR +-- @field #table ManagedREC -- @field #number MaxAliveMissions -- @field #boolean debug -- @field #number repeatsonfailure -- @field Core.Set#SET_ZONE GoZoneSet -- @field Core.Set#SET_ZONE NoGoZoneSet -- @field #boolean Monitor +-- @field #boolean TankerInvisible -- @extends Core.Fsm#FSM --- *“Airspeed, altitude, and brains. Two are always needed to successfully complete the flight.”* -- Unknown. @@ -137,8 +140,15 @@ -- -- **Note** If you need different tanker types, i.e. Boom and Drogue, set them up at different AirWings! -- -- Add a tanker point -- mywing:AddPatrolPointTanker(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone Tanker"):GetCoordinate(),20000,280,270,50) --- -- Add a tanker squad --- mywing:AddTankerSquadron("Blue Tanker","Tanker Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.EXCELLENT,602) +-- -- Add an AWACS squad - Radio 251 AM, TACAN 51Y +-- mywing:AddTankerSquadron("Blue Tanker","Tanker Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.EXCELLENT,602,nil,251,radio.modulation.AM,51) +-- +-- ### Add an AWACS (optional) +-- +-- -- Add an AWACS point +-- mywing:AddPatrolPointAwacs(AIRBASE.Caucasus.Kutaisi,ZONE:FindByName("Blue Zone AWACS"):GetCoordinate(),25000,300,270,50) +-- -- Add a tanker squad - Radio 251 AM, TACAN 51Y +-- mywing:AddAWACSSquadron("Blue AWACS","AWACS Ops Kutaisi",AIRBASE.Caucasus.Kutaisi,20,AI.Skill.AVERAGE,702,nil,271,radio.modulation.AM) -- -- # Fine-Tuning -- @@ -153,8 +163,14 @@ -- * @{#EASYGCICAP.SetDefaultMissionRange}: Set how many NM the planes can go from the home base, defaults to 100. -- * @{#EASYGCICAP.SetDefaultNumberAlter5Standby}: Set how many planes will be spawned on cold standby (Alert5), default 2. -- * @{#EASYGCICAP.SetDefaultEngageRange}: Set max engage range for CAP flights if they detect intruders, defaults to 50. --- * @{#EASYGCICAP.SetMaxAliveMissions}: Set max parallel missions can be done (CAP+GCI+Alert5+Tanker), defaults to 6. +-- * @{#EASYGCICAP.SetMaxAliveMissions}: Set max parallel missions can be done (CAP+GCI+Alert5+Tanker+AWACS), defaults to 8. -- * @{#EASYGCICAP.SetDefaultRepeatOnFailure}: Set max repeats on failure for intercepting/killing intruders, defaults to 3. +-- * @{#EASYGCICAP.SetTankerAndAWACSInvisible}: Set Tanker and AWACS to be invisible to enemy AI eyes. Is set to `true` by default. +-- +-- ## Debug and Monitor +-- +-- mywing.debug = true -- log information +-- mywing.Monitor = true -- show some statistics on screen -- -- -- @field #EASYGCICAP @@ -181,13 +197,16 @@ EASYGCICAP = { ManagedSQ = {}, ManagedCP = {}, ManagedTK = {}, - MaxAliveMissions = 6, + ManagedEWR = {}, + ManagedREC = {}, + MaxAliveMissions = 8, debug = false, engagerange = 50, repeatsonfailure = 3, GoZoneSet = nil, NoGoZoneSet = nil, Monitor = false, + TankerInvisible = true, } --- Internal Squadron data type @@ -200,6 +219,11 @@ EASYGCICAP = { -- @field #string Modex -- @field #string Livery -- @field #boolean Tanker +-- @field #boolean AWACS +-- @field #boolean RECON +-- @field #number Frequency +-- @field #number Modulation +-- @field #number TACAN --- Internal Wing data type -- @type EASYGCICAP.Wing @@ -218,7 +242,7 @@ EASYGCICAP = { --- EASYGCICAP class version. -- @field #string version -EASYGCICAP.version="0.0.7" +EASYGCICAP.version="0.0.8" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -260,10 +284,11 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName) self.capgrouping = 2 self.missionrange = 100 self.noaltert5 = 2 - self.MaxAliveMissions = 6 + self.MaxAliveMissions = 8 self.engagerange = 50 self.repeatsonfailure = 3 self.Monitor = false + self.TankerInvisible = true -- Set some string id for output to DCS.log file. self.lid=string.format("EASYGCICAP %s | ", self.alias) @@ -289,13 +314,23 @@ end ------------------------------------------------------------------------- +--- Set Tanker and AWACS to be invisible to enemy AI eyes +-- @param #EASYGCICAP self +-- @param #boolean Switch Set to true or false, by default this is set to true already +-- @return #EASYGCICAP self +function EASYGCICAP:SetTankerAndAWACSInvisible(Switch) + self:T(self.lid.."SetTankerAndAWACSInvisible") + self.TankerInvisible = Switch + return self +end + --- Set Maximum of alive missions to stop airplanes spamming the map -- @param #EASYGCICAP self -- @param #number Maxiumum Maxmimum number of parallel missions allowed. Count is Cap-Missions + Intercept-Missions + Alert5-Missionsm default is 6 -- @return #EASYGCICAP self function EASYGCICAP:SetMaxAliveMissions(Maxiumum) self:T(self.lid.."SetDefaultResurrection") - self.MaxAliveMissions = Maxiumum or 6 + self.MaxAliveMissions = Maxiumum or 8 return self end @@ -443,13 +478,22 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias) -- Create Airwing local CAP_Wing = AIRWING:New(Airbasename,Alias) + CAP_Wing:SetVerbosityLevel(3) CAP_Wing:SetReportOff() CAP_Wing:SetMarker(false) CAP_Wing:SetAirbase(AIRBASE:FindByName(Airbasename)) CAP_Wing:SetRespawnAfterDestroyed() CAP_Wing:SetNumberCAP(self.capgrouping) - CAP_Wing:SetNumberTankerBoom(1) - CAP_Wing:SetNumberTankerProbe(1) + if #self.ManagedTK > 0 then + CAP_Wing:SetNumberTankerBoom(1) + CAP_Wing:SetNumberTankerProbe(1) + end + if #self.ManagedAW > 0 then + CAP_Wing:SetNumberAWACS(1) + end + if #self.ManagedREC > 0 then + CAP_Wing:SetNumberRecon(1) + end --local PatrolCoordinateKutaisi = ZONE:New(CapZoneName):GetCoordinate() --CAP_Wing:AddPatrolPointCAP(PatrolCoordinateKutaisi,self.capalt,UTILS.KnotsToAltKIAS(self.capspeed,self.capalt),self.capdir,self.capleg) CAP_Wing:SetTakeoffHot() @@ -459,20 +503,33 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias) local Intel = self.Intel + local TankerInvisible = self.TankerInvisible + function CAP_Wing:OnAfterFlightOnMission(From, Event, To, Flightgroup, Mission) local flightgroup = Flightgroup -- Ops.FlightGroup#FLIGHTGROUP --flightgroup:SetDespawnAfterLanding() flightgroup:SetDespawnAfterHolding() flightgroup:SetDestinationbase(AIRBASE:FindByName(Airbasename)) flightgroup:GetGroup():CommandEPLRS(true,5) - flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet) - flightgroup:GetGroup():OptionROTEvadeFire() - flightgroup:SetOutOfAAMRTB() + if Mission.type ~= AUFTRAG.Type.TANKER and Mission.type ~= AUFTRAG.Type.AWACS and Mission.type ~= AUFTRAG.Type.RECON then + flightgroup:SetDetection(true) + flightgroup:SetEngageDetectedOn(self.engagerange,{"Air"},self.GoZoneSet,self.NoGoZoneSet) + flightgroup:SetOutOfAAMRTB() + end + if Mission.type == AUFTRAG.Type.TANKER or Mission.type == AUFTRAG.Type.AWACS or Mission.type == AUFTRAG.Type.RECON then + if TankerInvisible then + flightgroup:GetGroup():SetCommandInvisible(true) + end + if Mission.type == AUFTRAG.Type.RECON then + flightgroup:SetDetection(true) + end + end + flightgroup:GetGroup():OptionROTEvadeFire() flightgroup:SetFuelLowRTB(true) Intel:AddAgent(flightgroup) - --function flightgroup:OnAfterHolding(From,Event,To) - --self:ClearToLand(5) - --end + function flightgroup:OnAfterHolding(From,Event,To) + self:ClearToLand(5) + end end @@ -513,6 +570,31 @@ function EASYGCICAP:AddPatrolPointCAP(AirbaseName,Coordinate,Altitude,Speed,Head return self end +--- Add a RECON patrol point to a Wing +-- @param #EASYGCICAP self +-- @param #string AirbaseName Name of the Wing's airbase +-- @param Core.Point#COORDINATE Coordinate. +-- @param #number Altitude Defaults to 25000 feet. +-- @param #number Speed Defaults to 300 knots. +-- @param #number Heading Defaults to 90 degrees (East). +-- @param #number LegLength Defaults to 15 NM. +-- @return #EASYGCICAP self +function EASYGCICAP:AddPatrolPointRecon(AirbaseName,Coordinate,Altitude,Speed,Heading,LegLength) + self:T(self.lid.."AddPatrolPointRecon "..Coordinate:ToStringLLDDM()) + local EntryCAP = {} -- #EASYGCICAP.CapPoint + EntryCAP.AirbaseName = AirbaseName + EntryCAP.Coordinate = Coordinate + EntryCAP.Altitude = Altitude or 25000 + EntryCAP.Speed = Speed or 300 + EntryCAP.Heading = Heading or 90 + EntryCAP.LegLength = LegLength or 15 + self.ManagedREC[#self.ManagedREC+1] = EntryCAP + if self.debug then + local mark = MARKER:New(Coordinate,self.lid.."Patrol Point Recon"):ToAll() + end + return self +end + --- Add a TANKER patrol point to a Wing -- @param #EASYGCICAP self -- @param #string AirbaseName Name of the Wing's airbase @@ -538,6 +620,31 @@ function EASYGCICAP:AddPatrolPointTanker(AirbaseName,Coordinate,Altitude,Speed,H return self end +--- Add an AWACS patrol point to a Wing +-- @param #EASYGCICAP self +-- @param #string AirbaseName Name of the Wing's airbase +-- @param Core.Point#COORDINATE Coordinate. +-- @param #number Altitude Defaults to 25000 feet. +-- @param #number Speed Defaults to 300 knots. +-- @param #number Heading Defaults to 90 degrees (East). +-- @param #number LegLength Defaults to 15 NM. +-- @return #EASYGCICAP self +function EASYGCICAP:AddPatrolPointAwacs(AirbaseName,Coordinate,Altitude,Speed,Heading,LegLength) + self:T(self.lid.."AddPatrolPointAwacs "..Coordinate:ToStringLLDDM()) + local EntryCAP = {} -- #EASYGCICAP.CapPoint + EntryCAP.AirbaseName = AirbaseName + EntryCAP.Coordinate = Coordinate + EntryCAP.Altitude = Altitude or 25000 + EntryCAP.Speed = Speed or 300 + EntryCAP.Heading = Heading or 90 + EntryCAP.LegLength = LegLength or 15 + self.ManagedEWR[#self.ManagedEWR+1] = EntryCAP + if self.debug then + local mark = MARKER:New(Coordinate,self.lid.."Patrol Point AWACS"):ToAll() + end + return self +end + --- (Internal) Set actual Tanker Points from the list -- @param #EASYGCICAP self -- @return #EASYGCICAP self @@ -557,6 +664,25 @@ function EASYGCICAP:_SetTankerPatrolPoints() return self end +--- (Internal) Set actual Awacs Points from the list +-- @param #EASYGCICAP self +-- @return #EASYGCICAP self +function EASYGCICAP:_SetAwacsPatrolPoints() + self:T(self.lid.."_SetAwacsPatrolPoints") + for _,_data in pairs(self.ManagedEWR) do + local data = _data --#EASYGCICAP.CapPoint + local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING + local Coordinate = data.Coordinate + local Altitude = data.Altitude + local Speed = data.Speed + local Heading = data.Heading + local LegLength = data.LegLength + Wing:AddPatrolPointAWACS(Coordinate,Altitude,Speed,Heading,LegLength) + end + + return self +end + --- (Internal) Set actual PatrolPoints from the list -- @param #EASYGCICAP self -- @return #EASYGCICAP self @@ -576,25 +702,22 @@ function EASYGCICAP:_SetCAPPatrolPoints() return self end ---- (Internal) Add a CAP patrol point to a Wing +--- (Internal) Set actual PatrolPoints from the list -- @param #EASYGCICAP self --- @param #string AirbaseName Name of the Wing's airbase --- @param Core.Point#COORDINATE Coordinate. --- @param #number Altitude Defaults to 25000 feet. --- @param #number Speed Defaults to 300 knots. --- @param #number Heading Defaults to 90 degrees (East). --- @param #number LegLength Defaults to 15 NM. --- @return #EASYGCICAP self -function EASYGCICAP:_AddPatrolPointCAP(AirbaseName,Coordinate,Altitude,Speed,Heading,LegLength) - self:T(self.lid.."_AddPatrolPointCAP") - local airbasename = AirbaseName or self.airbasename - local coordinate = Coordinate - local Altitude = Altitude or 25000 - local Speed = Speed or 300 - local Heading = Heading or 90 - local LegLength = LegLength or 15 - local wing = self.wings[airbasename][1] -- Ops.AirWing#AIRWING - wing:AddPatrolPointCAP(coordinate,Altitude,Speed,Heading,LegLength) +-- @return #EASYGCICAP self +function EASYGCICAP:_SetReconPatrolPoints() + self:T(self.lid.."_SetReconPatrolPoints") + for _,_data in pairs(self.ManagedREC) do + local data = _data --#EASYGCICAP.CapPoint + local Wing = self.wings[data.AirbaseName][1] -- Ops.AirWing#AIRWING + local Coordinate = data.Coordinate + local Altitude = data.Altitude + local Speed = data.Speed + local Heading = data.Heading + local LegLength = data.LegLength + Wing:AddPatrolPointRecon(Coordinate,Altitude,Speed,Heading,LegLength) + end + return self end @@ -612,8 +735,15 @@ function EASYGCICAP:_CreateSquads() local Skill = squad.Skill local Modex = squad.Modex local Livery = squad.Livery + local Frequeny = squad.Frequency + local Modulation = squad.Modulation + local TACAN = squad.TACAN if squad.Tanker then - self:_AddTankerSquadron(TemplateName,SquadName,AirbaseName,AirFrames,Skill,Modex,Livery) + self:_AddTankerSquadron(TemplateName,SquadName,AirbaseName,AirFrames,Skill,Modex,Livery,Frequeny,Modulation,TACAN) + elseif squad.AWACS then + self:_AddAWACSSquadron(TemplateName,SquadName,AirbaseName,AirFrames,Skill,Modex,Livery,Frequeny,Modulation) + elseif squad.RECON then + self:_AddReconSquadron(TemplateName,SquadName,AirbaseName,AirFrames,Skill,Modex,Livery) else self:_AddSquadron(TemplateName,SquadName,AirbaseName,AirFrames,Skill,Modex,Livery) end @@ -648,7 +778,7 @@ function EASYGCICAP:AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames, return self end ---- Add a Tanker Squadron to an Airwing of the manager +--- Add a Recon Squadron to an Airwing of the manager -- @param #EASYGCICAP self -- @param #string TemplateName Name of the group template. -- @param #string SquadName Squadron name - must be unique! @@ -658,8 +788,8 @@ end -- @param #string Modex (optional) Modex to be used,e.g. 402. -- @param #string Livery (optional) Livery name to be used. -- @return #EASYGCICAP self -function EASYGCICAP:AddTankerSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery) - self:T(self.lid.."AddTankerSquadron "..SquadName) +function EASYGCICAP:AddReconSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery) + self:T(self.lid.."AddReconSquadron "..SquadName) -- Add Squadron Data local EntrySQ = {} -- #EASYGCICAP.Squad EntrySQ.TemplateName = TemplateName @@ -669,6 +799,40 @@ function EASYGCICAP:AddTankerSquadron(TemplateName, SquadName, AirbaseName, AirF EntrySQ.Skill = Skill or AI.Skill.AVERAGE EntrySQ.Modex = Modex or 402 EntrySQ.Livery = Livery + EntrySQ.RECON = true + + self.ManagedSQ[SquadName] = EntrySQ + + return self +end + +--- Add a Tanker Squadron to an Airwing of the manager +-- @param #EASYGCICAP self +-- @param #string TemplateName Name of the group template. +-- @param #string SquadName Squadron name - must be unique! +-- @param #string AirbaseName Name of the airbase the airwing resides on, e.g. AIRBASE.Caucasus.Kutaisi +-- @param #number AirFrames Number of available airframes, e.g. 20. +-- @param #string Skill(optional) Skill level, e.g. AI.Skill.AVERAGE +-- @param #string Modex (optional) Modex to be used,e.g. 402. +-- @param #string Livery (optional) Livery name to be used. +-- @param #number Frequency (optional) Radio Frequency to be used. +-- @param #number Modulation (optional) Radio Modulation to be used, e.g. radio.modulation.AM or radio.modulation.FM +-- @param #number TACAN (optional) TACAN channel, e.g. 71, resulting in Channel 71Y +-- @return #EASYGCICAP self +function EASYGCICAP:AddTankerSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery, Frequency, Modulation, TACAN) + self:T(self.lid.."AddTankerSquadron "..SquadName) + -- Add Squadron Data + local EntrySQ = {} -- #EASYGCICAP.Squad + EntrySQ.TemplateName = TemplateName + EntrySQ.SquadName = SquadName + EntrySQ.AirbaseName = AirbaseName + EntrySQ.AirFrames = AirFrames or 20 + EntrySQ.Skill = Skill or AI.Skill.AVERAGE + EntrySQ.Modex = Modex or 602 + EntrySQ.Livery = Livery + EntrySQ.Frequency = Frequency + EntrySQ.Modulation = Livery + EntrySQ.TACAN = TACAN EntrySQ.Tanker = true self.ManagedSQ[SquadName] = EntrySQ @@ -676,6 +840,38 @@ function EASYGCICAP:AddTankerSquadron(TemplateName, SquadName, AirbaseName, AirF return self end +--- Add an AWACS Squadron to an Airwing of the manager +-- @param #EASYGCICAP self +-- @param #string TemplateName Name of the group template. +-- @param #string SquadName Squadron name - must be unique! +-- @param #string AirbaseName Name of the airbase the airwing resides on, e.g. AIRBASE.Caucasus.Kutaisi +-- @param #number AirFrames Number of available airframes, e.g. 20. +-- @param #string Skill(optional) Skill level, e.g. AI.Skill.AVERAGE +-- @param #string Modex (optional) Modex to be used,e.g. 402. +-- @param #string Livery (optional) Livery name to be used. +-- @param #number Frequency (optional) Radio Frequency to be used. +-- @param #number Modulation (optional) Radio Modulation to be used, e.g. radio.modulation.AM or radio.modulation.FM +-- @return #EASYGCICAP self +function EASYGCICAP:AddAWACSSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery, Frequency, Modulation) + self:T(self.lid.."AddAWACSSquadron "..SquadName) + -- Add Squadron Data + local EntrySQ = {} -- #EASYGCICAP.Squad + EntrySQ.TemplateName = TemplateName + EntrySQ.SquadName = SquadName + EntrySQ.AirbaseName = AirbaseName + EntrySQ.AirFrames = AirFrames or 20 + EntrySQ.Skill = Skill or AI.Skill.AVERAGE + EntrySQ.Modex = Modex or 702 + EntrySQ.Livery = Livery + EntrySQ.Frequency = Frequency + EntrySQ.Modulation = Livery + EntrySQ.AWACS = true + + self.ManagedSQ[SquadName] = EntrySQ + + return self +end + --- (Internal) Add a Squadron to an Airwing of the manager -- @param #EASYGCICAP self -- @param #string TemplateName Name of the group template. @@ -685,8 +881,10 @@ end -- @param #string Skill(optional) Skill level, e.g. AI.Skill.AVERAGE -- @param #string Modex (optional) Modex to be used,e.g. 402. -- @param #string Livery (optional) Livery name to be used. +-- @param #number Frequency (optional) Radio Frequency to be used. +-- @param #number Modulation (optional) Radio Modulation to be used, e.g. radio.modulation.AM or radio.modulation.FM -- @return #EASYGCICAP self -function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery) +function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery, Frequency, Modulation) self:T(self.lid.."_AddSquadron "..SquadName) -- Add Squadrons local Squadron_One = SQUADRON:New(TemplateName,AirFrames,SquadName) @@ -707,7 +905,7 @@ function EASYGCICAP:_AddSquadron(TemplateName, SquadName, AirbaseName, AirFrames return self end ---- (Internal) Add a Tanker Squadron to an Airwing of the manager +--- (Internal) Add a Recon Squadron to an Airwing of the manager -- @param #EASYGCICAP self -- @param #string TemplateName Name of the group template. -- @param #string SquadName Squadron name - must be unique! @@ -717,11 +915,11 @@ end -- @param #string Modex (optional) Modex to be used,e.g. 402. -- @param #string Livery (optional) Livery name to be used. -- @return #EASYGCICAP self -function EASYGCICAP:_AddTankerSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery) - self:T(self.lid.."_AddTankerSquadron "..SquadName) +function EASYGCICAP:_AddReconSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery) + self:T(self.lid.."_AddReconSquadron "..SquadName) -- Add Squadrons local Squadron_One = SQUADRON:New(TemplateName,AirFrames,SquadName) - Squadron_One:AddMissionCapability({AUFTRAG.Type.TANKER}) + Squadron_One:AddMissionCapability({AUFTRAG.Type.RECON}) --Squadron_One:SetFuelLowRefuel(true) Squadron_One:SetFuelLowThreshold(0.3) Squadron_One:SetTurnoverTime(10,20) @@ -732,12 +930,81 @@ function EASYGCICAP:_AddTankerSquadron(TemplateName, SquadName, AirbaseName, Air local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING + wing:AddSquadron(Squadron_One) + wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.RECON},75) + + return self +end + +--- (Internal) Add a Tanker Squadron to an Airwing of the manager +-- @param #EASYGCICAP self +-- @param #string TemplateName Name of the group template. +-- @param #string SquadName Squadron name - must be unique! +-- @param #string AirbaseName Name of the airbase the airwing resides on, e.g. AIRBASE.Caucasus.Kutaisi +-- @param #number AirFrames Number of available airframes, e.g. 20. +-- @param #string Skill(optional) Skill level, e.g. AI.Skill.AVERAGE +-- @param #string Modex (optional) Modex to be used,e.g. 402. +-- @param #string Livery (optional) Livery name to be used. +-- @param #number Frequency (optional) Radio frequency of the Tanker +-- @param #number Modulation (Optional) Radio modulation of the Tanker +-- @param #number TACAN (Optional) TACAN Channel to be used, will always be an "Y" channel +-- @return #EASYGCICAP self +function EASYGCICAP:_AddTankerSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery, Frequency, Modulation, TACAN) + self:T(self.lid.."_AddTankerSquadron "..SquadName) + -- Add Squadrons + local Squadron_One = SQUADRON:New(TemplateName,AirFrames,SquadName) + Squadron_One:AddMissionCapability({AUFTRAG.Type.TANKER}) + --Squadron_One:SetFuelLowRefuel(true) + Squadron_One:SetFuelLowThreshold(0.3) + Squadron_One:SetTurnoverTime(10,20) + Squadron_One:SetModex(Modex) + Squadron_One:SetLivery(Livery) + Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) + Squadron_One:SetMissionRange(self.missionrange) + Squadron_One:SetRadio(Frequency,Modulation) + Squadron_One:AddTacanChannel(TACAN,TACAN) + + local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING + wing:AddSquadron(Squadron_One) wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.TANKER},75) return self end +--- (Internal) Add a AWACS Squadron to an Airwing of the manager +-- @param #EASYGCICAP self +-- @param #string TemplateName Name of the group template. +-- @param #string SquadName Squadron name - must be unique! +-- @param #string AirbaseName Name of the airbase the airwing resides on, e.g. AIRBASE.Caucasus.Kutaisi +-- @param #number AirFrames Number of available airframes, e.g. 20. +-- @param #string Skill(optional) Skill level, e.g. AI.Skill.AVERAGE +-- @param #string Modex (optional) Modex to be used,e.g. 402. +-- @param #string Livery (optional) Livery name to be used. +-- @param #number Frequency (optional) Radio frequency of the AWACS +-- @param #number Modulation (Optional) Radio modulation of the AWACS +-- @return #EASYGCICAP self +function EASYGCICAP:_AddAWACSSquadron(TemplateName, SquadName, AirbaseName, AirFrames, Skill, Modex, Livery, Frequency, Modulation) + self:T(self.lid.."_AddAWACSSquadron "..SquadName) + -- Add Squadrons + local Squadron_One = SQUADRON:New(TemplateName,AirFrames,SquadName) + Squadron_One:AddMissionCapability({AUFTRAG.Type.AWACS}) + --Squadron_One:SetFuelLowRefuel(true) + Squadron_One:SetFuelLowThreshold(0.3) + Squadron_One:SetTurnoverTime(10,20) + Squadron_One:SetModex(Modex) + Squadron_One:SetLivery(Livery) + Squadron_One:SetSkill(Skill or AI.Skill.AVERAGE) + Squadron_One:SetMissionRange(self.missionrange) + Squadron_One:SetRadio(Frequency,Modulation) + local wing = self.wings[AirbaseName][1] -- Ops.AirWing#AIRWING + + wing:AddSquadron(Squadron_One) + wing:NewPayload(TemplateName,-1,{AUFTRAG.Type.AWACS},75) + + return self +end + --- Add a zone to the accepted zones set. -- @param #EASYGCICAP self -- @param Core.Zone#ZONE_BASE Zone @@ -809,7 +1076,12 @@ function EASYGCICAP:_StartIntel() local clustersize = self:ClusterCountUnits(Cluster) or 1 local wingsize = math.abs(overhead * (clustersize+1)) if wingsize > maxsize then wingsize = maxsize end - if (not Cluster.mission) and (wingsize > 0) then + -- existing mission, and if so - done? + local retrymission = true + if Cluster.mission and (not Cluster.mission:IsOver()) then + retrymission = false + end + if (retrymission) and (wingsize >= 1) then MESSAGE:New(string.format("**** %s Interceptors need wingsize %d", UTILS.GetCoalitionName(self.coalition), wingsize),15,"CAPGCI"):ToAllIf(self.debug):ToLog() for _,_data in pairs (wings) do local airwing = _data[1] -- Ops.AirWing#AIRWING @@ -920,6 +1192,8 @@ function EASYGCICAP:onafterStart(From,Event,To) self:_CreateSquads() self:_SetCAPPatrolPoints() self:_SetTankerPatrolPoints() + self:_SetAwacsPatrolPoints() + self:_SetReconPatrolPoints() self:__Status(-10) return self end @@ -957,20 +1231,27 @@ function EASYGCICAP:onafterStatus(From,Event,To) local caps = counttable(self.ManagedCP) local assets = 0 local instock = 0 + local capmission = 0 + local interceptmission = 0 + local reconmission = 0 for _,_wing in pairs(self.wings) do local count = _wing[1]:CountAssetsOnMission(MissionTypes,Cohort) local count2 = _wing[1]:CountAssets(true,MissionTypes,Attributes) + capmission = capmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.GCICAP}) + interceptmission = interceptmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.INTERCEPT}) + reconmission = reconmission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.RECON}) assets = assets + count instock = instock + count2 end - if self.debug then - self:I(self.lid.."Wings: "..wings.." | Squads: "..squads.." | CapPoints: "..caps.." | Assets on Mission: "..assets.." | Assets in Stock: "..instock) - end if self.Monitor then local threatcount = #self.Intel.Clusters or 0 local text = "GCICAP "..self.alias text = text.."\nWings: "..wings.."\nSquads: "..squads.."\nCapPoints: "..caps.."\nAssets on Mission: "..assets.."\nAssets in Stock: "..instock - text = text.."\nThreats:"..threatcount + text = text.."\nThreats: "..threatcount + text = text.."\nMissions: "..capmission+interceptmission + text = text.."\n - CAP: "..capmission + text = text.."\n - Intercept: "..interceptmission + text = text.."\n - Recon: "..reconmission MESSAGE:New(text,15,"GCICAP"):ToAll():ToLogIf(self.debug) end self:__Status(30)