First working version

This commit is contained in:
FlightControl_Master
2017-07-31 12:04:27 +02:00
parent 87634969b3
commit 85bd3a1c33
10 changed files with 476 additions and 61 deletions

View File

@@ -72,6 +72,7 @@ function AI_A2A:New( AIGroup )
self:SetFuelThreshold( .2, 60 )
self:SetDamageThreshold( 0.4 )
self:SetDisengageRadius( 70000 )
self:SetStartState( "Stopped" )
@@ -295,6 +296,15 @@ function AI_A2A:SetHomeAirbase( HomeAirbase )
end
--- Sets the disengage range, that when engaging a target beyond the specified range, the engagement will be cancelled and the plane will RTB.
-- @param #AI_A2A self
-- @param #number DisengageRadius The disengage range.
-- @return #AI_A2A self
function AI_A2A:SetDisengageRadius( DisengageRadius )
self:F2( { DisengageRadius } )
self.DisengageRadius = DisengageRadius
end
--- Set the status checking off.
-- @param #AI_A2A self
@@ -378,6 +388,16 @@ function AI_A2A:onafterStatus()
local RTB = false
local DistanceFromHomeBase = self.HomeAirbase:GetCoordinate():Get2DDistance( self.Controllable:GetCoordinate() )
self:F({DistanceFromHomeBase=DistanceFromHomeBase})
if DistanceFromHomeBase > self.DisengageRadius then
self:E( self.Controllable:GetName() .. " is too far from home base, RTB!" )
self:Home()
RTB = true
end
local Fuel = self.Controllable:GetUnit(1):GetFuel()
self:F({Fuel=Fuel})
if Fuel < self.PatrolFuelThresholdPercentage then

View File

@@ -641,7 +641,9 @@ do -- AI_A2A_DISPATCHER
--
-- Use the method @{#AI_A2A_DISPATCHER.SetDefaultDamageThreshold}() to set the **default damage treshold** of spawned airplanes for all squadrons.
--
-- ## 10.7. Default CAP Time Interval.
-- ## 10.7. Default settings for CAP.
--
-- ### 10.7.1. Default CAP Time Interval.
--
-- CAP is time driven, and will evaluate in random time intervals if a new CAP needs to be spawned.
-- The **default CAP time interval** is between **180** and **600** seconds.
@@ -649,7 +651,7 @@ do -- AI_A2A_DISPATCHER
-- Use the method @{#AI_A2A_DISPATCHER.SetDefaultCapTimeInterval}() to set the **default CAP time interval** of spawned airplanes for all squadrons.
-- Note that you can still change the CAP limit and CAP time intervals for each CAP individually using the @{#AI_A2A_DISPATCHER.SetSquadronCapTimeInterval}() method.
--
-- ## 10.8. Default CAP limit.
-- ### 10.7.2. Default CAP limit.
--
-- Multiple CAP can be airborne at the same time for one squadron, which is controlled by the **CAP limit**.
-- The **default CAP limit** is 1 CAP per squadron to be airborne at the same time.
@@ -659,6 +661,27 @@ do -- AI_A2A_DISPATCHER
-- Use the method @{#AI_A2A_DISPATCHER.SetDefaultCapTimeInterval}() to set the **default CAP time interval** of spawned airplanes for all squadrons.
-- Note that you can still change the CAP limit and CAP time intervals for each CAP individually using the @{#AI_A2A_DISPATCHER.SetSquadronCapTimeInterval}() method.
--
-- ## 10.8. Default settings for GCI.
--
-- ## 10.8.1. Optimal intercept point.
--
-- When intruders are detected, the intrusion path of the attackers can be monitored by the EWR.
-- Although defender planes might be on standby at the airbase, it can still take some time to get the defenses up in the air if there aren't any defenses airborne.
-- This time can easily take 2 to 3 minutes, and even then the defenders still need to fly towards the target, which takes also time.
--
-- Therefore, an optimal **intercept point** is calculated which takes a couple of parameters:
--
-- * The average bearing of the intruders for an amount of seconds.
-- * The average speed of the intruders for an amount of seconds.
-- * The altitude of the intruders.
-- * An assumed time it takes to get planes operational at the airbase.
-- * The intercept speed, which is given as a parameter for each squadron or set by default for all squadrons.
--
-- The **intercept point** will determine:
--
-- * If there are any friendlies close to engage the target. These can be defenders performing CAP or defenders in RTB.
-- * The optimal airbase from where defenders will takeoff for gci.
--
-- ## 11. Q & A:
--
-- ### 11.1. Which countries will be selected for each coalition?
@@ -751,6 +774,8 @@ do -- AI_A2A_DISPATCHER
self:SetDefaultDamageThreshold( 0.4 ) -- When 40% of damage, go RTB.
self:SetDefaultCapTimeInterval( 180, 600 ) -- Between 180 and 600 seconds.
self:SetDefaultCapLimit( 1 ) -- Maximum one CAP per squadron.
self:SetIntercept( 300 ) -- A default intercept delay time of 300 seconds.
self:SetDisengageRadius( 100000 ) -- The default disengage radius is 100 km.
self:AddTransition( "Started", "Assign", "Started" )
@@ -939,6 +964,26 @@ do -- AI_A2A_DISPATCHER
return self
end
--- Define the radius to disengage any target when the distance to the home base is larger than the specified meters.
-- @param #AI_A2A_DISPATCHER self
-- @param #number DisengageRadius (Optional, Default = 100000) The radius to disengage a target when too far from the home base.
-- @return #AI_A2A_DISPATCHER
-- @usage
--
-- -- Set 50km as the disengage radius.
-- Dispatcher:SetDisengageRadius( 50000 )
--
-- -- Set 100km as the disengage radius.
-- Dispatcher:SetDisngageRadius() -- 100000 is the default value.
--
function AI_A2A_DISPATCHER:SetDisengageRadius( DisengageRadius )
self.DisengageRadius = DisengageRadius
return self
end
--- Define the radius to check if a target can be engaged by an ground controlled intercept.
-- So, if there is a target area detected and reported,
@@ -1092,7 +1137,7 @@ do -- AI_A2A_DISPATCHER
self.DefenderDefault.CapMaxSeconds = CapMaxSeconds
return self
end
end
--- Set the default CAP limit for squadrons, which will be used to determine how many CAP can be airborne at the same time for the squadron.
@@ -1116,13 +1161,24 @@ do -- AI_A2A_DISPATCHER
end
function AI_A2A_DISPATCHER:SetIntercept( InterceptDelay )
self.DefenderDefault.InterceptDelay = InterceptDelay
local Detection = self.Detection -- Functional.Detection#DETECTION_AREAS
Detection:SetIntercept( true, InterceptDelay )
return self
end
--- Calculates which AI friendlies are nearby the area
-- @param #AI_A2A_DISPATCHER self
-- @param DetectedItem
-- @return #number, Core.CommandCenter#REPORT
function AI_A2A_DISPATCHER:GetAIFriendliesNearBy( DetectedItem )
local FriendliesNearBy = self.Detection:GetFriendliesDistance( DetectedItem )
local FriendliesNearBy = self.Detection:GetFriendliesNearBy( DetectedItem )
return FriendliesNearBy
end
@@ -2270,6 +2326,7 @@ do -- AI_A2A_DISPATCHER
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
Fsm:SetFuelThreshold( self.DefenderDefault.FuelThreshold, 60 )
Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
Fsm:SetDisengageRadius( self.DisengageRadius )
Fsm:Start()
Fsm:__Patrol( 2 )
@@ -2322,17 +2379,18 @@ do -- AI_A2A_DISPATCHER
---
-- @param #AI_A2A_DISPATCHER self
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, Target, DefendersMissing, AIGroups )
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, DetectedItem, DefendersMissing, Friendlies )
local AttackerCount = Target.Set:Count()
local AttackerSet = DetectedItem.Set
local AttackerCount = AttackerSet:Count()
local DefendersCount = 0
for AIGroupID, AIGroup in pairs( AIGroups or {} ) do
for DefenderID, AIGroup in pairs( Friendlies or {} ) do
local Fsm = self:GetDefenderTaskFsm( AIGroup )
Fsm:__Engage( 1, Target.Set ) -- Engage on the TargetSetUnit
Fsm:__Engage( 1, AttackerSet ) -- Engage on the TargetSetUnit
self:SetDefenderTaskTarget( AIGroup, Target )
self:SetDefenderTaskTarget( AIGroup, DetectedItem )
DefendersCount = DefendersCount + AIGroup:GetSize()
end
@@ -2349,9 +2407,11 @@ do -- AI_A2A_DISPATCHER
self:E( { DefenderSquadron } )
local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE
local TargetCoord = Target.Set:GetFirst():GetCoordinate()
--local TargetCoord = AttackerSet:GetFirst():GetCoordinate()
local TargetCoord = DetectedItem.InterceptCoord
if TargetCoord then
local Distance = SpawnCoord:Get2DDistance( TargetCoord )
self:F( { Distance = Distance, TargetCoord = TargetCoord } )
if ClosestDistance == 0 or Distance < ClosestDistance then
@@ -2402,11 +2462,12 @@ do -- AI_A2A_DISPATCHER
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
Fsm:SetFuelThreshold( self.DefenderDefault.FuelThreshold, 60 )
Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
Fsm:SetDisengageRadius( self.DisengageRadius )
Fsm:Start()
Fsm:__Engage( 2, Target.Set ) -- Engage on the TargetSetUnit
Fsm:__Engage( 2, DetectedItem.Set ) -- Engage on the TargetSetUnit
self:SetDefenderTask( DefenderGCI, "GCI", Fsm, Target )
self:SetDefenderTask( DefenderGCI, "GCI", Fsm, DetectedItem )
function Fsm:onafterRTB( Defender, From, Event, To )
@@ -2475,20 +2536,20 @@ do -- AI_A2A_DISPATCHER
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set.
function AI_A2A_DISPATCHER:EvaluateGCI( Target )
self:F( { Target.ItemID } )
function AI_A2A_DISPATCHER:EvaluateGCI( DetectedItem )
self:F( { DetectedItem.ItemID } )
local AttackerSet = Target.Set
local AttackerSet = DetectedItem.Set
local AttackerCount = AttackerSet:Count()
-- First, count the active AIGroups Units, targetting the DetectedSet
local DefenderCount = self:CountDefendersEngaged( Target )
local DefenderCount = self:CountDefendersEngaged( DetectedItem )
local DefendersMissing = AttackerCount - DefenderCount
self:F( { AttackerCount = AttackerCount, DefenderCount = DefenderCount, DefendersMissing = DefendersMissing } )
local Friendlies = self:CountDefendersToBeEngaged( Target, DefenderCount )
local Friendlies = self:CountDefendersToBeEngaged( DetectedItem, DefenderCount )
if Target.IsDetected == true then
if DetectedItem.IsDetected == true then
return DefendersMissing, Friendlies
end

View File

@@ -940,6 +940,24 @@ do -- DETECTION_BASE
end
do -- Intercept Point
--- Set the parameters to calculate to optimal intercept point.
-- @param #DETECTION_BASE self
-- @param #boolean Intercept Intercept is true if an intercept point is calculated. Intercept is false if it is disabled. The default Intercept is false.
-- @param #number IntereptDelay If Intercept is true, then InterceptDelay is the average time it takes to get airplanes airborne.
-- @return #DETECTION_BASE self
function DETECTION_BASE:SetIntercept( Intercept, InterceptDelay )
self:F2()
self.Intercept = Intercept
self.InterceptDelay = InterceptDelay
return self
end
end
do -- Accept / Reject detected units
--- Accept detections if within a range in meters.
@@ -1130,9 +1148,9 @@ do -- DETECTION_BASE
return DetectedItem.FriendliesNearBy
end
--- Returns friendly units nearby the FAC units sorted per distance ...
--- Returns the distance used to identify friendlies near the deteted item ...
-- @param #DETECTION_BASE self
-- @return #map<#number,Wrapper.Unit#UNIT> The map of Friendly UNITs.
-- @return #number The distance.
function DETECTION_BASE:GetFriendliesDistance( DetectedItem )
return DetectedItem.FriendliesDistance
@@ -1161,7 +1179,8 @@ do -- DETECTION_BASE
local DetectedItem = ReportGroupData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = ReportGroupData.DetectedItem.Set
local DetectedUnit = DetectedSet:GetFirst()
local DetectedUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
local InterceptCoord = ReportGroupData.InterceptCoord or DetectedUnit:GetCoordinate()
DetectedItem.FriendliesNearBy = nil
@@ -1171,7 +1190,7 @@ do -- DETECTION_BASE
local SphereSearch = {
id = world.VolumeType.SPHERE,
params = {
point = DetectedUnit:GetVec3(),
point = InterceptCoord:GetVec3(),
radius = self.FriendliesRange,
}
@@ -1185,7 +1204,8 @@ do -- DETECTION_BASE
local DetectedItem = ReportGroupData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = ReportGroupData.DetectedItem.Set
local DetectedUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
local CenterCoord = DetectedUnit:GetCoordinate()
local InterceptCoord = ReportGroupData.InterceptCoord or DetectedUnit:GetCoordinate()
local DetectedUnitCoord = DetectedUnit:GetCoordinate()
local ReportSetGroup = ReportGroupData.ReportSetGroup
local EnemyCoalition = DetectedUnit:GetCoalition()
@@ -1203,7 +1223,7 @@ do -- DETECTION_BASE
local FriendlyUnit = UNIT:Find( FoundDCSUnit )
local FriendlyUnitName = FriendlyUnit:GetName()
DetectedItem.FriendliesNearBy[FriendlyUnitName] = FriendlyUnit
local Distance = CenterCoord:Get2DDistance( FriendlyUnit:GetCoordinate() )
local Distance = InterceptCoord:Get2DDistance( FriendlyUnit:GetCoordinate() )
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {}
DetectedItem.FriendliesDistance[Distance] = FriendlyUnit
return true
@@ -1233,8 +1253,8 @@ do -- DETECTION_BASE
DetectedItem.FriendliesNearBy = DetectedItem.FriendliesNearBy or {}
DetectedItem.FriendliesNearBy[PlayerUnitName] = PlayerUnit
local CenterCoord = DetectedUnit:GetCoordinate()
local Distance = CenterCoord:Get2DDistance( PlayerUnit:GetCoordinate() )
--local CenterCoord = DetectedUnit:GetCoordinate()
local Distance = InterceptCoord:Get2DDistance( PlayerUnit:GetCoordinate() )
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {}
DetectedItem.FriendliesDistance[Distance] = PlayerUnit
end
@@ -2287,6 +2307,30 @@ do -- DETECTION_AREAS
end
--- Calculate the optimal intercept point of the DetectedItem.
-- @param #DETECTION_AREAS self
-- @param #DETECTION_BASE.DetectedItem DetectedItem
function DETECTION_AREAS:CalculateIntercept( DetectedItem )
if self.Intercept then
local DetectedSet = DetectedItem.Set
local DetectedUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
local UnitSpeed = DetectedUnit:GetVelocityMPS()
local UnitHeading = DetectedUnit:GetHeading()
local UnitCoord = DetectedUnit:GetCoordinate()
local TranslateDistance = UnitSpeed * self.InterceptDelay
local InterceptCoord = UnitCoord:Translate( TranslateDistance, UnitHeading )
DetectedItem.InterceptCoord = InterceptCoord
else
DetectedItem.InterceptCoord = nil
end
end
--- Find the nearest FAC of the DetectedItem.
-- @param #DETECTION_AREAS self
-- @param #DETECTION_BASE.DetectedItem DetectedItem
@@ -2605,6 +2649,8 @@ do -- DETECTION_AREAS
local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set
local DetectedZone = DetectedItem.Zone
self:CalculateIntercept( DetectedItem )
self:ReportFriendliesNearBy( { DetectedItem = DetectedItem, ReportSetGroup = self.DetectionSetGroup } ) -- Fill the Friendlies table
self:CalculateThreatLevelA2G( DetectedItem ) -- Calculate A2G threat level