This commit is contained in:
FlightControl 2018-11-05 21:26:47 +01:00
parent 3e3dfc83aa
commit 9d3796b605
5 changed files with 119 additions and 46 deletions

View File

@ -281,6 +281,14 @@ function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAl
return self return self
end end
--- @param Wrapper.Group#GROUP self
-- @param Core.Event#EVENTDATA EventData
function GROUP:OnEventTakeoff( EventData, Fsm )
Fsm:Takeoff()
self:UnHandleEvent( EVENTS.Takeoff )
end
--- onafter State Transition for Event Patrol. --- onafter State Transition for Event Patrol.
-- @param #AI_A2A_CAP self -- @param #AI_A2A_CAP self
-- @param Wrapper.Group#GROUP AICap The AI Group managed by the FSM. -- @param Wrapper.Group#GROUP AICap The AI Group managed by the FSM.

View File

@ -2798,6 +2798,7 @@ do -- AI_A2A_DISPATCHER
local TakeoffMethod = self:GetSquadronTakeoff( SquadronName ) local TakeoffMethod = self:GetSquadronTakeoff( SquadronName )
local Defender = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod, DefenderSquadron.TakeoffAltitude or self.DefenderDefault.TakeoffAltitude ) -- Wrapper.Group#GROUP local Defender = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod, DefenderSquadron.TakeoffAltitude or self.DefenderDefault.TakeoffAltitude ) -- Wrapper.Group#GROUP
self:AddDefenderToSquadron( DefenderSquadron, Defender, DefenderGrouping )
return Defender, DefenderGrouping return Defender, DefenderGrouping
end end

View File

@ -207,6 +207,13 @@ do -- AI_A2G_DISPATCHER
} }
--- List of defense coordinates.
-- @type AI_A2G_DISPATCHER.DefenseCoordinates
-- @map <#string,Core.Point#COORDINATE> A list of all defense coordinates mapped per defense coordinate name.
--- @field #AI_A2G_DISPATCHER.DefenseCoordinates DefenseCoordinates
AI_A2G_DISPATCHER.DefenseCoordinates = {}
--- Enumerator for spawns at airbases --- Enumerator for spawns at airbases
-- @type AI_A2G_DISPATCHER.Takeoff -- @type AI_A2G_DISPATCHER.Takeoff
-- @extends Wrapper.Group#GROUP.Takeoff -- @extends Wrapper.Group#GROUP.Takeoff
@ -263,7 +270,6 @@ do -- AI_A2G_DISPATCHER
-- self.Detection:InitDetectVisual( true ) -- self.Detection:InitDetectVisual( true )
-- self.Detection:SetRefreshTimeInterval( 30 ) -- self.Detection:SetRefreshTimeInterval( 30 )
self:SetEngageRadius()
self:SetDefenseRadius() self:SetDefenseRadius()
self:SetIntercept( 300 ) -- A default intercept delay time of 300 seconds. self:SetIntercept( 300 ) -- A default intercept delay time of 300 seconds.
self:SetDisengageRadius( 300000 ) -- The default Disengage Radius is 300 km. self:SetDisengageRadius( 300000 ) -- The default Disengage Radius is 300 km.
@ -501,6 +507,35 @@ do -- AI_A2G_DISPATCHER
end end
end end
do -- Manage the defensive behaviour
--- @param #AI_A2G_DISPATCHER self
-- @param #string DefenseCoordinateName The name of the coordinate to be defended by A2G defenses.
-- @param Core.Point#COORDINATE DefenseCoordinate The coordinate to be defended by A2G defenses.
function AI_A2G_DISPATCHER:AddDefenseCoordinate( DefenseCoordinateName, DefenseCoordinate )
self.DefenseCoordinates[DefenseCoordinateName] = DefenseCoordinate
end
--- @param #AI_A2G_DISPATCHER self
function AI_A2G_DISPATCHER:SetDefenseReactivityLow()
self.DefenseReactivity = 0.05
self.DefenseDistance = 20000
end
--- @param #AI_A2G_DISPATCHER self
function AI_A2G_DISPATCHER:SetDefenseReactivityMedium()
self.DefenseReactivity = 0.15
self.DefenseDistance = 20000
end
--- @param #AI_A2G_DISPATCHER self
function AI_A2G_DISPATCHER:SetDefenseReactivityHigh()
self.DefenseReactivity = 0.5
self.DefenseDistance = 20000
end
end
--- Define the radius to engage any target by airborne friendlies, which are executing cap or returning from an defense mission. --- Define the radius to engage any target by airborne friendlies, which are executing cap or returning from an defense mission.
-- If there is a target area detected and reported, then any friendlies that are airborne near this target area, -- If there is a target area detected and reported, then any friendlies that are airborne near this target area,
-- will be commanded to (re-)engage that target when available (if no other tasks were commanded). -- will be commanded to (re-)engage that target when available (if no other tasks were commanded).
@ -530,7 +565,7 @@ do -- AI_A2G_DISPATCHER
-- --
function AI_A2G_DISPATCHER:SetEngageRadius( EngageRadius ) function AI_A2G_DISPATCHER:SetEngageRadius( EngageRadius )
self.Detection:SetFriendliesRange( EngageRadius or 100000 ) --self.Detection:SetFriendliesRange( EngageRadius or 100000 )
return self return self
end end
@ -2408,22 +2443,25 @@ do -- AI_A2G_DISPATCHER
self:F( { DefenderSquadrons = self.DefenderSquadrons } ) self:F( { DefenderSquadrons = self.DefenderSquadrons } )
for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do
if DefenderSquadron[DefenseTaskType] then
local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE
local AttackerCoord = AttackerUnit:GetCoordinate() local AttackerCoord = AttackerUnit:GetCoordinate()
local InterceptCoord = AttackerDetection.InterceptCoord local InterceptCoord = AttackerDetection.InterceptCoord
self:F( { InterceptCoord = InterceptCoord } ) self:F( { InterceptCoord = InterceptCoord } )
if InterceptCoord then if InterceptCoord then
local InterceptDistance = SpawnCoord:Get2DDistance( InterceptCoord ) local InterceptDistance = SpawnCoord:Get2DDistance( InterceptCoord )
local AirbaseDistance = SpawnCoord:Get2DDistance( AttackerCoord ) local AirbaseDistance = SpawnCoord:Get2DDistance( AttackerCoord )
self:F( { InterceptDistance = InterceptDistance, AirbaseDistance = AirbaseDistance, InterceptCoord = InterceptCoord } ) self:F( { InterceptDistance = InterceptDistance, AirbaseDistance = AirbaseDistance, InterceptCoord = InterceptCoord } )
if ClosestDistance == 0 or InterceptDistance < ClosestDistance then
-- Only intercept if the distance to target is smaller or equal to the GciRadius limit. if ClosestDistance == 0 or InterceptDistance < ClosestDistance then
if AirbaseDistance <= self.DefenseRadius then
ClosestDistance = InterceptDistance -- Only intercept if the distance to target is smaller or equal to the GciRadius limit.
ClosestDefenderSquadronName = SquadronName if AirbaseDistance <= self.DefenseRadius then
ClosestDistance = InterceptDistance
ClosestDefenderSquadronName = SquadronName
end
end end
end end
end end
@ -2585,10 +2623,13 @@ do -- AI_A2G_DISPATCHER
local AttackerSet = DetectedItem.Set -- Core.Set#SET_UNIT local AttackerSet = DetectedItem.Set -- Core.Set#SET_UNIT
local AttackerCount = AttackerSet:Count() local AttackerCount = AttackerSet:Count()
local AttackerRadarCount = AttackerSet:HasSEAD()
local IsFriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT ) local IsFriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT )
local IsCas = ( AttackerSet:HasSEAD() == 0 ) and IsFriendliesNearBy -- Is the AttackerSet a CAS group? local IsCas = ( AttackerRadarCount == 0 ) and ( IsFriendliesNearBy == true ) -- Is the AttackerSet a CAS group?
if IsCas then self:F( { Friendlies = self.Detection:GetFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT ) } )
if IsCas == true then
-- First, count the active defenders, engaging the DetectedItem. -- First, count the active defenders, engaging the DetectedItem.
local DefenderCount = self:CountDefendersEngaged( DetectedItem ) local DefenderCount = self:CountDefendersEngaged( DetectedItem )
@ -2618,10 +2659,11 @@ do -- AI_A2G_DISPATCHER
local AttackerSet = DetectedItem.Set -- Core.Set#SET_UNIT local AttackerSet = DetectedItem.Set -- Core.Set#SET_UNIT
local AttackerCount = AttackerSet:Count() local AttackerCount = AttackerSet:Count()
local AttackerRadarCount = AttackerSet:HasSEAD()
local IsFriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT ) local IsFriendliesNearBy = self.Detection:IsFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT )
local IsBai = ( AttackerSet:HasSEAD() == 0 ) and not IsFriendliesNearBy -- Is the AttackerSet a BAI group? local IsBai = ( AttackerRadarCount == 0 ) and ( IsFriendliesNearBy == false ) -- Is the AttackerSet a BAI group?
if IsBai then if IsBai == true then
-- First, count the active defenders, engaging the DetectedItem. -- First, count the active defenders, engaging the DetectedItem.
local DefenderCount = self:CountDefendersEngaged( DetectedItem ) local DefenderCount = self:CountDefendersEngaged( DetectedItem )
@ -2684,6 +2726,7 @@ do -- AI_A2G_DISPATCHER
local Report = REPORT:New( "\nTactical Overview" ) local Report = REPORT:New( "\nTactical Overview" )
local DefenderGroupCount = 0 local DefenderGroupCount = 0
local Delay = 0 -- We need to implement a delay for each action because the spawning on airbases get confused if done too quick.
-- Now that all obsolete tasks are removed, loop through the detected targets. -- Now that all obsolete tasks are removed, loop through the detected targets.
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
@ -2700,27 +2743,54 @@ do -- AI_A2G_DISPATCHER
local DetectionIndex = DetectedItem.Index local DetectionIndex = DetectedItem.Index
local DetectedItemChanged = DetectedItem.Changed local DetectedItemChanged = DetectedItem.Changed
do local AttackerCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem )
local DefendersMissing, Friendlies = self:Evaluate_SEAD( DetectedItem ) -- Returns a SET_UNIT with the SEAD targets to be engaged...
if DefendersMissing and DefendersMissing > 0 then -- Calculate if for this DetectedItem if a defense needs to be initiated.
self:F( { SeadGroups = Friendlies } ) -- This calculation is based on the distance between the defense point and the attackers, and the defensiveness parameter.
self:DEFEND( DetectedItem, DefendersMissing, Friendlies, "SEAD" ) -- The attackers closest to the defense coordinates will be handled first, or course!
local DefenseCoordinate = nil
for DefenseCoordinateName, EvaluateCoordinate in pairs( self.DefenseCoordinates ) do
local EvaluateDistance = AttackerCoordinate:Get2DDistance( EvaluateCoordinate )
local DistanceProbability = ( self.DefenseDistance / EvaluateDistance * self.DefenseReactivity )
local DefenseProbability = math.random()
self:F({DistanceProbability=DistanceProbability,DefenseProbability=DefenseProbability})
if DefenseProbability <= DistanceProbability / ( 300 / 30 ) then
DefenseCoordinate = EvaluateCoordinate
break
end end
end end
do if DefenseCoordinate then
local DefendersMissing, Friendlies = self:Evaluate_CAS( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged... do
if DefendersMissing and DefendersMissing > 0 then local DefendersMissing, Friendlies = self:Evaluate_SEAD( DetectedItem ) -- Returns a SET_UNIT with the SEAD targets to be engaged...
self:F( { CasGroups = Friendlies } ) if DefendersMissing and DefendersMissing > 0 then
self:DEFEND( DetectedItem, DefendersMissing, Friendlies, "CAS" ) self:F( { SeadGroups = Friendlies } )
self:__DEFEND( Delay, DetectedItem, DefendersMissing, Friendlies, "SEAD", DefenseCoordinate )
Delay = Delay + 1
end
end end
end
do
do local DefendersMissing, Friendlies = self:Evaluate_CAS( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged...
local DefendersMissing, Friendlies = self:Evaluate_BAI( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged... if DefendersMissing and DefendersMissing > 0 then
if DefendersMissing and DefendersMissing > 0 then self:F( { CasGroups = Friendlies } )
self:F( { BaiGroups = Friendlies } ) self:__DEFEND( Delay, DetectedItem, DefendersMissing, Friendlies, "CAS", DefenseCoordinate )
self:DEFEND( DetectedItem, DefendersMissing, Friendlies, "BAI" ) Delay = Delay + 1
end
end
do
local DefendersMissing, Friendlies = self:Evaluate_BAI( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged...
if DefendersMissing and DefendersMissing > 0 then
self:F( { BaiGroups = Friendlies } )
self:__DEFEND( Delay, DetectedItem, DefendersMissing, Friendlies, "BAI", DefenseCoordinate )
Delay = Delay + 1
end
end end
end end
@ -3248,7 +3318,6 @@ do
local self = BASE:Inherit( self, AI_A2G_DISPATCHER:New( Detection ) ) -- #AI_A2G_GCICAP local self = BASE:Inherit( self, AI_A2G_DISPATCHER:New( Detection ) ) -- #AI_A2G_GCICAP
self:SetEngageRadius( EngageRadius )
self:SetGciRadius( GciRadius ) self:SetGciRadius( GciRadius )
-- Determine the coalition of the EWRNetwork, this will be the coalition of the GCICAP. -- Determine the coalition of the EWRNetwork, this will be the coalition of the GCICAP.

View File

@ -252,13 +252,6 @@ function AI_AIR:New( AIGroup )
return self return self
end end
--- @param Wrapper.Group#GROUP self
-- @param Core.Event#EVENTDATA EventData
function GROUP:OnEventTakeoff( EventData, Fsm )
Fsm:Takeoff()
self:UnHandleEvent( EVENTS.Takeoff )
end
function AI_AIR:SetDispatcher( Dispatcher ) function AI_AIR:SetDispatcher( Dispatcher )
self.Dispatcher = Dispatcher self.Dispatcher = Dispatcher
end end

View File

@ -327,6 +327,8 @@ do -- DETECTION_BASE
self:InitDetectIRST( nil ) self:InitDetectIRST( nil )
self:InitDetectDLINK( nil ) self:InitDetectDLINK( nil )
self:SetFriendliesRange( 6000 )
self:FilterCategories( { self:FilterCategories( {
Unit.Category.AIRPLANE, Unit.Category.AIRPLANE,
Unit.Category.GROUND_UNIT, Unit.Category.GROUND_UNIT,