From 2c82513e548e7295f03b2e466d4cce74c6833ea7 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sun, 21 Dec 2025 15:38:14 +0100 Subject: [PATCH] #EASYGCICAP - Added INTEL Corridors --- Moose Development/Moose/Ops/EasyGCICAP.lua | 151 +++++++++++++++++++-- 1 file changed, 141 insertions(+), 10 deletions(-) diff --git a/Moose Development/Moose/Ops/EasyGCICAP.lua b/Moose Development/Moose/Ops/EasyGCICAP.lua index 8a902cad5..02a48aa1a 100644 --- a/Moose Development/Moose/Ops/EasyGCICAP.lua +++ b/Moose Development/Moose/Ops/EasyGCICAP.lua @@ -1,3 +1,12 @@ +--- **Ops** - Create your A2A Defenses. +-- +-- **Main Features:** +-- +-- * Automatically create and manage A2A defenses using an AirWing and Squadrons for one coalition +-- * Easy set-up +-- +-- === +-- ------------------------------------------------------------------------- -- Easy CAP/GCI Class, based on OPS classes ------------------------------------------------------------------------- @@ -109,7 +118,7 @@ -- ### Prerequisites -- -- You have to put a **STATIC WAREHOUSE** object on the airbase with the UNIT name according to the name of the airbase. **Do not put any other static type or it creates a conflict with the airbase name!** --- E.g. for Kuitaisi this has to have the unit name Kutaisi. This object symbolizes the AirWing HQ. +-- E.g. for Kutaisi this has to have the unit name Kutaisi. This object symbolizes the AirWing HQ. -- Next put a late activated template group for your CAP/GCI Squadron on the map. Last, put a zone on the map for the CAP operations, let's name it "Blue Zone 1". Size of the zone plays no role. -- Put an EW radar system on the map and name it aptly, like "Blue EWR". -- @@ -205,7 +214,7 @@ EASYGCICAP = { coalition = "blue", alias = nil, wings = {}, - Intel = nil, + Intel = nil, -- Ops.Intel#INTEL resurrection = 900, capspeed = 300, capalt = 25000, @@ -275,10 +284,11 @@ EASYGCICAP = { --- EASYGCICAP class version. -- @field #string version -EASYGCICAP.version="0.1.30" +EASYGCICAP.version="0.1.33" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO list +-- + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO: TBD @@ -350,6 +360,34 @@ function EASYGCICAP:New(Alias, AirbaseName, Coalition, EWRName) self:__Start(math.random(6,12)) + --- On Before "Start" event. + -- @function [parent=#EASYGCICAP] OnBeforeStart + -- @param #EASYGCICAP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "Start" event. + -- @function [parent=#EASYGCICAP] OnAfterStart + -- @param #EASYGCICAP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On Before "Status" event. + -- @function [parent=#EASYGCICAP] OnBeforeStatus + -- @param #EASYGCICAP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + + --- On After "Status" event. + -- @function [parent=#EASYGCICAP] OnAfterStatus + -- @param #EASYGCICAP self + -- @param #string From From state. + -- @param #string Event Event. + -- @param #string To To state. + return self end @@ -369,6 +407,28 @@ function EASYGCICAP:GetAirwing(AirbaseName) return nil end +--- Add an agent to the underlying INTEL detection - caution, we need to be started first for this to work! +-- Normally this isn't necessary when the Group name is correctly filled (see EWRName in `New()`). +-- @param #EASYGCICAP self +-- @param Wrapper.Group#GROUP Group The group object to be added as Intel Agent. +-- @return #EASYGCICAP self +function EASYGCICAP:AddAgent(Group) + self:T(self.lid.."AddAgent") + if Group:IsInstanceOf("GROUP") and self.Intel ~= nil then + self.Intel:AddAgent(Group) + if self.TankerInvisible == true then + Group:SetCommandInvisible(true) + Group:OptionROEHoldFire() + if Group:IsAir() then + Group:OptionROTEvadeFire() + else + Group:OptionDisperseOnAttack(30) + end + end + end + return self +end + --- Get a table of all managed AirWings -- @param #EASYGCICAP self -- @return #table Table of Ops.AirWing#AIRWING Airwings @@ -611,7 +671,6 @@ function EASYGCICAP:SetCapStartTimeVariation(Start, End) return self end - --- Set which target types CAP flights will prefer to engage, defaults to {"Air"} -- @param #EASYGCICAP self -- @param #table types Table of comma separated #string entries, defaults to {"Air"} (everything that flies and is not a weapon). Useful other options are e.g. {"Bombers"}, {"Fighters"}, @@ -656,7 +715,7 @@ function EASYGCICAP:_CreateAirwings() return self end ---- (internal) Create and add another AirWing to the manager +--- (Internal) Create and add another AirWing to the manager -- @param #EASYGCICAP self -- @param #string Airbasename -- @param #string Alias @@ -763,8 +822,13 @@ function EASYGCICAP:_AddAirwing(Airbasename, Alias) end end - if self.noalert5 > 0 then - local alert = AUFTRAG:NewALERT5(AUFTRAG.Type.INTERCEPT) + if self.noalert5 > 0 then + local alert + if self.ClassName == "EASYGCICAP" then + alert = AUFTRAG:NewALERT5(AUFTRAG.Type.INTERCEPT) + elseif self.ClassName == "EASYA2G" then + alert = AUFTRAG:NewALERT5(AUFTRAG.Type.BAI) + end alert:SetRequiredAssets(self.noalert5) alert:SetRepeat(99) CAP_Wing:AddMission(alert) @@ -1300,6 +1364,54 @@ function EASYGCICAP:AddConflictZone(Zone) return self end +--- Function to set corridor zones. +-- @param #EASYGCICAP self +-- @param Core.Set#SET_ZONE CorridorZones Can be handed in as SET\_ZONE or single ZONE object. +-- @return #EASYGCICAP self +function EASYGCICAP:SetCorridorZones(CorridorZones) + self:T(self.lid .. "SetCorridorZones") + if CorridorZones and CorridorZones:IsInstanceOf("SET_ZONE") then + self.corridorzones = CorridorZones + self.usecorridors = true + elseif CorridorZones and CorridorZones:IsInstanceOf("ZONE_BASE") then + if not self.corridorzones then self.corridorzones = SET_ZONE:New() end + self.corridorzones:AddZone(CorridorZones) + self.usecorridors = true + end + return self +end + +--- Function to add one corridor zone. +-- @param #EASYGCICAP self +-- @param Core.Zone#ZONE CorridorZone The ZONE object to be added. +-- @return #EASYGCICAP self +function EASYGCICAP:AddCorridorZone(CorridorZone) + self:T(self.lid .. "AddCorridorZone") + self:SetCorridorZones(CorridorZone) + return self +end + +--- Function to set corridor zone floor and ceiling in FEET. +-- @param #EASYGCICAP self +-- @param #number Floor Floor altitude ASL in feet. +-- @param #number Ceiling Ceiling altitude ASL in feet. +-- @return #EASYGCICAP self +function EASYGCICAP:SetCorridorZoneFloorAndCeiling(Floor,Ceiling) + self.corridorfloor = UTILS.FeetToMeters(Floor) + self.corridorceiling = UTILS.FeetToMeters(Ceiling) + return self +end + +--- Function to set corridor zone floor and ceiling in METERS. +-- @param #EASYGCICAP self +-- @param #number Floor Floor altitude ASL in meters. +-- @param #number Ceiling Ceiling altitude ASL in meters. +-- @return #EASYGCICAP self +function EASYGCICAP:SetCorridorZoneFloorAndCeilingMeters(Floor,Ceiling) + self.corridorfloor = Floor + self.corridorceiling = Ceiling + return self +end --- (Internal) Try to assign the intercept to a FlightGroup already in air and ready. -- @param #EASYGCICAP self @@ -1459,6 +1571,8 @@ function EASYGCICAP:_AssignIntercept(Cluster) if coord and conflictset:Count() > 0 and conflictset:IsCoordinateInZone(coord) then success = false end + else + success = true end return success end, @@ -1468,6 +1582,14 @@ function EASYGCICAP:_AssignIntercept(Cluster) ) end + InterceptAuftrag:AddConditionFailure( + function() + local failure = false + if InterceptAuftrag:CountOpsGroups()==0 and InterceptAuftrag:IsExecuting() then failure = true end + return failure + end + ) + table.insert(self.ListOfAuftrag,InterceptAuftrag) local assigned, rest = self:_TryAssignIntercept(ReadyFlightGroups,InterceptAuftrag,contact.group,wingsize) if not assigned then @@ -1500,6 +1622,14 @@ function EASYGCICAP:_StartIntel() BlueIntel:SetRejectZones(self.NoGoZoneSet) BlueIntel:SetConflictZones(self.ConflictZoneSet) BlueIntel:SetVerbosity(0) + + if self.usecorridors == true then + BlueIntel:SetCorridorZones(self.corridorzones) + if self.corridorfloor or self.corridorceiling then + BlueIntel:SetCorridorLimitsFeet(self.corridorfloor,self.corridorceiling) + end + end + BlueIntel:Start() if self.debug then @@ -1603,7 +1733,7 @@ function EASYGCICAP:onafterStatus(From,Event,To) tankermission = tankermission + _wing[1]:CountMissionsInQueue({AUFTRAG.Type.TANKER}) assets = assets + count instock = instock + count2 - local assetsonmission = _wing[1]:GetAssetsOnMission({AUFTRAG.Type.GCICAP,AUFTRAG.Type.PATROLRACETRACK}) + local assetsonmission = _wing[1]:GetAssetsOnMission({AUFTRAG.Type.ALERT5, AUFTRAG.Type.GCICAP,AUFTRAG.Type.PATROLRACETRACK}) -- update ready groups self.ReadyFlightGroups = nil self.ReadyFlightGroups = {} @@ -1614,7 +1744,8 @@ function EASYGCICAP:onafterStatus(From,Event,To) local name = FG:GetName() local engage = FG:IsEngaging() local hasmissiles = FG:IsOutOfMissiles() == nil and true or false - local ready = hasmissiles and FG:IsFuelGood() and FG:IsAirborne() + local isalert5 = (FG:GetMissionCurrent() ~= nil and FG:GetMissionCurrent().type == AUFTRAG.Type.ALERT5) and true or false + local ready = hasmissiles and FG:IsFuelGood() and (FG:IsAirborne() or isalert5) --self:T(string.format("Flightgroup %s Engaging = %s Ready = %s",tostring(name),tostring(engage),tostring(ready))) if ready then self.ReadyFlightGroups[name] = FG