A2A Dispatcher fixes

- Increased engage distance.
This commit is contained in:
Frank 2019-12-17 00:09:24 +01:00
parent c3c984381e
commit 5b9978e390
3 changed files with 47 additions and 65 deletions

View File

@ -3045,8 +3045,7 @@ do -- AI_A2A_DISPATCHER
if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then
-- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the AttackerSet -- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the AttackerSet
if DefenderTask.Target == nil then if DefenderTask.Target == nil then
if DefenderTask.Fsm:Is( "Returning" ) if DefenderTask.Fsm:Is( "Returning" ) or DefenderTask.Fsm:Is( "Patrolling" ) then
or DefenderTask.Fsm:Is( "Patrolling" ) then
Friendlies = Friendlies or {} Friendlies = Friendlies or {}
Friendlies[Friendly] = Friendly Friendlies[Friendly] = Friendly
DefenderCount = DefenderCount + Friendly:GetSize() DefenderCount = DefenderCount + Friendly:GetSize()
@ -3315,19 +3314,20 @@ do -- AI_A2A_DISPATCHER
-- @param Functional.Detection#DETECTION_BASE.DetectedItem AttackerDetection Detected item. -- @param Functional.Detection#DETECTION_BASE.DetectedItem AttackerDetection Detected item.
-- @param #table Defenders Defenders table. -- @param #table Defenders Defenders table.
function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, AttackerDetection, Defenders ) function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, AttackerDetection, Defenders )
self:F("ENGAGING Detection ID="..tostring(AttackerDetection.ID))
self:F("ENGAGING "..tostring(AttackerDetection.Name))
if Defenders then if Defenders then
for DefenderID, Defender in pairs( Defenders ) do for DefenderID, Defender in pairs( Defenders ) do
local Fsm = self:GetDefenderTaskFsm( Defender ) local Fsm = self:GetDefenderTaskFsm( Defender )
Fsm:EngageRoute( AttackerDetection.Set ) -- Engage on the TargetSetUnit Fsm:EngageRoute( AttackerDetection.Set ) -- Engage on the TargetSetUnit
self:SetDefenderTaskTarget( Defender, AttackerDetection ) self:SetDefenderTaskTarget( Defender, AttackerDetection )
end end
end end
end end
@ -3341,7 +3341,7 @@ do -- AI_A2A_DISPATCHER
-- @param #table DefenderFriendlies Friendly defenders. -- @param #table DefenderFriendlies Friendly defenders.
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, AttackerDetection, DefendersMissing, DefenderFriendlies ) function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, AttackerDetection, DefendersMissing, DefenderFriendlies )
self:F("GCI "..tostring(AttackerDetection.Name)) self:F("GCI Detection ID="..tostring(AttackerDetection.ID))
self:F( { From, Event, To, AttackerDetection.Index, DefendersMissing, DefenderFriendlies } ) self:F( { From, Event, To, AttackerDetection.Index, DefendersMissing, DefenderFriendlies } )
@ -3606,8 +3606,7 @@ do -- AI_A2A_DISPATCHER
-- 2. There is sufficient fuel -- 2. There is sufficient fuel
-- 3. There is sufficient ammo -- 3. There is sufficient ammo
-- 4. The plane is not damaged -- 4. The plane is not damaged
if DefenderGroups and DetectedItem.IsDetected == true then if DefenderGroups and DetectedItem.IsDetected == true then
return DefenderGroups return DefenderGroups
end end
@ -3686,13 +3685,13 @@ do -- AI_A2A_DISPATCHER
local TaskReport = REPORT:New() local TaskReport = REPORT:New()
local Report = REPORT:New( "Tactical Overviews" ) local Report = REPORT:New( "Tactical Overview:" )
local DefenderGroupCount = 0 local DefenderGroupCount = 0
-- 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
for DetectedItemID, DetectedItem in UTILS.spairs( Detection:GetDetectedItems(), function( t, a, b ) return self:Order(t[a]) < self:Order(t[b]) end ) do for DetectedItemID, DetectedItem in UTILS.spairs( Detection:GetDetectedItems(), function( t, a, b ) return self:Order(t[a]) < self:Order(t[b]) end ) do
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT

View File

@ -334,9 +334,8 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function AI_AIR_ENGAGE:onafterEngage( AIGroup, From, Event, To ) function AI_AIR_ENGAGE:onafterEngage( AIGroup, From, Event, To )
-- TODO: This function is overwritten below!
self:HandleEvent( EVENTS.Dead ) self:HandleEvent( EVENTS.Dead )
end end
-- todo: need to fix this global function -- todo: need to fix this global function
@ -349,10 +348,10 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function AI_AIR_ENGAGE:onbeforeEngage( AIGroup, From, Event, To ) function AI_AIR_ENGAGE:onbeforeEngage( AIGroup, From, Event, To )
if self.Accomplished == true then if self.Accomplished == true then
return false return false
end end
return true
end end
--- onafter event handler for Abort event. --- onafter event handler for Abort event.
@ -405,14 +404,10 @@ end
--- @param Wrapper.Group#GROUP AIControllable --- @param Wrapper.Group#GROUP AIControllable
function AI_AIR_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit ) function AI_AIR_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit )
Fsm:I(string.format("AI_AIR_ENGAGE.___EngageRoute: %s", tostring(AIGroup:GetName())))
Fsm:I( { "AI_AIR_ENGAGE.___EngageRoute:", AIGroup:GetName() } )
if AIGroup:IsAlive() then if AIGroup and AIGroup:IsAlive() then
Fsm:__EngageRoute( Fsm.TaskDelay, AttackSetUnit ) Fsm:__EngageRoute( Fsm.TaskDelay or 0.1, AttackSetUnit )
--local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
--AIGroup:SetTask( Task )
end end
end end
@ -423,7 +418,6 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit ) function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
self:I( { DefenderGroup, From, Event, To, AttackSetUnit } ) self:I( { DefenderGroup, From, Event, To, AttackSetUnit } )
local DefenderGroupName = DefenderGroup:GetName() local DefenderGroupName = DefenderGroup:GetName()
@ -450,39 +444,33 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude. TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
if TargetDistance <= EngageDistance * 3 then -- TODO: A factor of * 3 is way too close. This causes the AI not to engange until merged sometimes!
if TargetDistance <= EngageDistance * 9 then
self:I(string.format("AI_AIR_ENGAGE onafterEngageRoute ==> __Engage - target distance = %.1f km", TargetDistance/1000))
self:__Engage( 0.1, AttackSetUnit ) self:__Engage( 0.1, AttackSetUnit )
else else
self:I(string.format("FF AI_AIR_ENGAGE onafterEngageRoute ==> Routing - target distance = %.1f km", TargetDistance/1000))
local EngageRoute = {} local EngageRoute = {}
local AttackTasks = {} local AttackTasks = {}
--- Calculate the target route point. --- Calculate the target route point.
local FromWP = DefenderCoord:WaypointAir( local FromWP = DefenderCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
self.PatrolAltType or "RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
EngageSpeed,
true
)
EngageRoute[#EngageRoute+1] = FromWP EngageRoute[#EngageRoute+1] = FromWP
self:SetTargetDistance( TargetCoord ) -- For RTB status check self:SetTargetDistance( TargetCoord ) -- For RTB status check
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) ) local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir( local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
self.PatrolAltType or "RADIO",
POINT_VEC3.RoutePointType.TurningPoint, local ToWP = ToCoord:WaypointAir(self.PatrolAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
POINT_VEC3.RoutePointAction.TurningPoint,
EngageSpeed,
true
)
EngageRoute[#EngageRoute+1] = ToWP EngageRoute[#EngageRoute+1] = ToWP
@ -492,11 +480,12 @@ function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
DefenderGroup:OptionROEReturnFire() DefenderGroup:OptionROEReturnFire()
DefenderGroup:OptionROTEvadeFire() DefenderGroup:OptionROTEvadeFire()
DefenderGroup:Route( EngageRoute, self.TaskDelay ) DefenderGroup:Route( EngageRoute, self.TaskDelay or 0.1 )
end end
end end
else else
-- TODO: This will make an A2A Dispatcher CAP flight to return rather than going back to patrolling!
self:I( DefenderGroupName .. ": No targets found -> Going RTB") self:I( DefenderGroupName .. ": No targets found -> Going RTB")
self:Return() self:Return()
end end
@ -506,10 +495,11 @@ end
--- @param Wrapper.Group#GROUP AIControllable --- @param Wrapper.Group#GROUP AIControllable
function AI_AIR_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit ) function AI_AIR_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit )
Fsm:I( { "AI_AIR_ENGAGE.___Engage:", AIGroup:GetName() } ) Fsm:I(string.format("AI_AIR_ENGAGE.___Engage: %s", tostring(AIGroup:GetName())))
if AIGroup:IsAlive() then if AIGroup and AIGroup:IsAlive() then
Fsm:__Engage( Fsm.TaskDelay, AttackSetUnit ) local delay=Fsm.TaskDelay or 0.1
Fsm:__Engage(delay, AttackSetUnit)
end end
end end
@ -520,7 +510,6 @@ end
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit ) function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} ) self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
local DefenderGroupName = DefenderGroup:GetName() local DefenderGroupName = DefenderGroup:GetName()
@ -532,7 +521,7 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
if AttackCount > 0 then if AttackCount > 0 then
if DefenderGroup:IsAlive() then if DefenderGroup and DefenderGroup:IsAlive() then
local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 ) local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 )
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed ) local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
@ -544,33 +533,25 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude. TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord ) local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 ) local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
local EngageRoute = {} local EngageRoute = {}
local AttackTasks = {} local AttackTasks = {}
local FromWP = DefenderCoord:WaypointAir( local FromWP = DefenderCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
self.EngageAltType or "RADIO",
POINT_VEC3.RoutePointType.TurningPoint,
POINT_VEC3.RoutePointAction.TurningPoint,
EngageSpeed,
true
)
EngageRoute[#EngageRoute+1] = FromWP EngageRoute[#EngageRoute+1] = FromWP
self:SetTargetDistance( TargetCoord ) -- For RTB status check self:SetTargetDistance( TargetCoord ) -- For RTB status check
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) ) local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir( local ToCoord=DefenderCoord:Translate( EngageDistance, FromEngageAngle, true )
self.EngageAltType or "RADIO",
POINT_VEC3.RoutePointType.TurningPoint, local ToWP = ToCoord:WaypointAir(self.EngageAltType or "RADIO", POINT_VEC3.RoutePointType.TurningPoint, POINT_VEC3.RoutePointAction.TurningPoint, EngageSpeed, true)
POINT_VEC3.RoutePointAction.TurningPoint,
EngageSpeed,
true
)
EngageRoute[#EngageRoute+1] = ToWP EngageRoute[#EngageRoute+1] = ToWP
if TargetDistance <= EngageDistance * 3 then -- TODO: A factor of * 3 this way too low. This causes the AI NOT to engage until very close or even merged sometimes. Some A2A missiles have a much longer range! Needs more frequent updates of the task!
if TargetDistance <= EngageDistance * 9 then
local AttackUnitTasks = self:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) -- Polymorphic local AttackUnitTasks = self:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude ) -- Polymorphic
@ -579,7 +560,8 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
self:Return() self:Return()
return return
else else
self:I( DefenderGroupName .. ": Engaging targets " ) local text=string.format("%s: Engaging targets at distance %.2f NM", DefenderGroupName, UTILS.MetersToNM(TargetDistance))
self:I(text)
DefenderGroup:OptionROEOpenFire() DefenderGroup:OptionROEOpenFire()
DefenderGroup:OptionROTEvadeFire() DefenderGroup:OptionROTEvadeFire()
DefenderGroup:OptionKeepWeaponsOnThreat() DefenderGroup:OptionKeepWeaponsOnThreat()
@ -591,10 +573,11 @@ function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetU
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___Engage", self, AttackSetUnit ) AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___Engage", self, AttackSetUnit )
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks ) EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
DefenderGroup:Route( EngageRoute, self.TaskDelay ) DefenderGroup:Route( EngageRoute, self.TaskDelay or 0.1 )
end end
else else
-- TODO: This will make an A2A Dispatcher CAP flight to return rather than going back to patrolling!
self:I( DefenderGroupName .. ": No targets found -> returning.") self:I( DefenderGroupName .. ": No targets found -> returning.")
self:Return() self:Return()
return return
@ -605,9 +588,9 @@ end
function AI_AIR_ENGAGE.Resume( AIEngage, Fsm ) function AI_AIR_ENGAGE.Resume( AIEngage, Fsm )
AIEngage:F( { "Resume:", AIEngage:GetName() } ) AIEngage:F( { "Resume:", AIEngage:GetName() } )
if AIEngage:IsAlive() then if AIEngage and AIEngage:IsAlive() then
Fsm:__Reset( Fsm.TaskDelay ) Fsm:__Reset( Fsm.TaskDelay or 0.1 )
Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit ) Fsm:__EngageRoute( Fsm.TaskDelay or 0.2, Fsm.AttackSetUnit )
end end
end end

View File

@ -421,7 +421,7 @@ end
-- @param #string To The To State string. -- @param #string To The To State string.
function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
if Controllable:IsAlive() then if Controllable and Controllable:IsAlive() then
local EngageRoute = {} local EngageRoute = {}