Updated defects in dispatcher

This commit is contained in:
FlightControl_Master 2017-08-01 17:35:53 +02:00
parent 9ec29f607f
commit 9054a493f9
6 changed files with 160 additions and 43 deletions

View File

@ -222,6 +222,7 @@ function AI_A2A:New( AIGroup )
self:AddTransition( "*", "Return", "Returning" )
self:AddTransition( "*", "Hold", "Holding" )
self:AddTransition( "*", "Home", "Home" )
self:AddTransition( "*", "LostControl", "LostControl" )
self:AddTransition( "*", "Fuel", "Fuel" )
@ -382,21 +383,34 @@ end
--- @param #AI_A2A self
function AI_A2A:onafterStatus()
self:F()
self:F( " Checking Status" )
if self.Controllable and self.Controllable:IsAlive() then
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
if not self:Is( "Holding" ) and not self:Is( "Returning" ) then
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:Hold( 300 )
RTB = false
end
end
if self:Is( "Damaged" ) or self:Is( "LostControl" ) then
if DistanceFromHomeBase < 5000 then
self:E( self.Controllable:GetName() .. " is too far from home base, RTB!" )
self:Home( "Destroy" )
end
end
local Fuel = self.Controllable:GetUnit(1):GetFuel()
self:F({Fuel=Fuel})
@ -427,10 +441,15 @@ function AI_A2A:onafterStatus()
-- Check if planes went RTB and are out of control.
if self.Controllable:HasTask() == false then
if not self:Is( "Started" ) and
not self:Is( "Stopped" ) then
not self:Is( "Stopped" ) and
not self:Is( "Home" ) then
if self.IdleCount >= 2 then
self:E( self.Controllable:GetName() .. " control lost! " )
self:LostControl()
if Damage ~= InitialLife then
self:Damaged()
else
self:E( self.Controllable:GetName() .. " control lost! " )
self:LostControl()
end
else
self.IdleCount = self.IdleCount + 1
end
@ -438,7 +457,7 @@ function AI_A2A:onafterStatus()
else
self.IdleCount = 0
end
if RTB == true then
self:__RTB( 0.5 )
end
@ -451,11 +470,30 @@ end
--- @param Wrapper.Group#GROUP AIGroup
function AI_A2A.RTBRoute( AIGroup )
AIGroup:E( { "RTBRoute:", AIGroup:GetName() } )
local _AI_A2A = AIGroup:GetState( AIGroup, "AI_A2A" ) -- #AI_A2A
_AI_A2A:__RTB( 0.5 )
AIGroup:E( { "AI_A2A.RTBRoute:", AIGroup:GetName() } )
if AIGroup:IsAlive() then
local _AI_A2A = AIGroup:GetState( AIGroup, "AI_A2A" ) -- #AI_A2A
_AI_A2A:__RTB( 0.5 )
local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
AIGroup:SetTask( Task )
end
end
--- @param Wrapper.Group#GROUP AIGroup
function AI_A2A.RTBHold( AIGroup )
AIGroup:E( { "AI_A2A.RTBHold:", AIGroup:GetName() } )
if AIGroup:IsAlive() then
local _AI_A2A = AIGroup:GetState( AIGroup, "AI_A2A" ) -- #AI_A2A
_AI_A2A:__RTB( 0.5 )
_AI_A2A:Return()
local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
AIGroup:SetTask( Task )
end
end
--- @param #AI_A2A self
@ -468,8 +506,6 @@ function AI_A2A:onafterRTB( AIGroup, From, Event, To )
self:E( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" )
self.CheckStatus = false
self:ClearTargetDistance()
AIGroup:ClearTasks()
@ -486,6 +522,7 @@ function AI_A2A:onafterRTB( AIGroup, From, Event, To )
local ToAirbaseCoord = CurrentCoord:Translate( 5000, ToAirbaseAngle )
if Distance < 5000 then
self:E( "RTB and near the airbase!" )
self:Home()
return
end
@ -501,6 +538,7 @@ function AI_A2A:onafterRTB( AIGroup, From, Event, To )
self:F( { Angle = ToAirbaseAngle, ToTargetSpeed = ToTargetSpeed } )
self:T2( { self.MinSpeed, self.MaxSpeed, ToTargetSpeed } )
EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
AIGroup:OptionROEHoldFire()
@ -511,12 +549,13 @@ function AI_A2A:onafterRTB( AIGroup, From, Event, To )
local Tasks = {}
Tasks[#Tasks+1] = AIGroup:TaskFunction( 1, 1, "AI_A2A.RTBRoute" )
EngageRoute[1].task = AIGroup:TaskCombo( Tasks )
Tasks[#Tasks+1] = AIGroup:TaskOrbitCircle( 4000, 350 )
EngageRoute[#EngageRoute].task = AIGroup:TaskCombo( Tasks )
AIGroup:SetState( AIGroup, "AI_A2A", self )
--- NOW ROUTE THE GROUP!
AIGroup:WayPointExecute( 1, 0 )
AIGroup:SetTask( AIGroup:TaskRoute( EngageRoute ), 1 )
end
@ -533,6 +572,30 @@ function AI_A2A:onafterHome( AIGroup, From, Event, To )
end
end
--- @param #AI_A2A self
-- @param Wrapper.Group#GROUP AIGroup
function AI_A2A:onafterHold( AIGroup, From, Event, To, HoldTime )
self:F( { AIGroup, From, Event, To } )
self:E( "Group " .. self.Controllable:GetName() .. " ... Holding! ( " .. self:GetState() .. " )" )
if AIGroup and AIGroup:IsAlive() then
local OrbitTask = AIGroup:TaskOrbitCircle( math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ), self.PatrolMinSpeed )
local TimedOrbitTask = AIGroup:TaskControlled( OrbitTask, AIGroup:TaskCondition( nil, nil, nil, nil, HoldTime , nil ) )
local RTBTask = AIGroup:TaskFunction( 1, 1, "AI_A2A.RTBHold" )
local OrbitHoldTask = AIGroup:TaskOrbitCircle( 4000, self.PatrolMinSpeed )
AIGroup:SetState( AIGroup, "AI_A2A", self )
AIGroup:SetTask( AIGroup:TaskCombo( { TimedOrbitTask, RTBTask, OrbitHoldTask } ), 0 )
end
end

View File

@ -350,8 +350,15 @@ end
--- @param Wrapper.Group#GROUP AIGroup
function AI_A2A_CAP.AttackRoute( AIGroup )
local EngageZone = AIGroup:GetState( AIGroup, "AI_A2A_CAP" ) -- AI.AI_Cap#AI_A2A_CAP
EngageZone:__Engage( 0.5 )
AIGroup:E( { "AI_A2A_CAP.AttackRoute:", AIGroup:GetName() } )
if AIGroup:IsAlive() then
local _AI_A2A_CAP = AIGroup:GetState( AIGroup, "AI_A2A_CAP" ) -- AI.AI_Cap#AI_A2A_CAP
_AI_A2A_CAP:__Engage( 0.5 )
local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
AIGroup:SetTask( Task )
end
end
--- @param #AI_A2A_CAP self
@ -438,17 +445,17 @@ function AI_A2A_CAP:onafterEngage( AIGroup, From, Event, To, AttackSetUnit )
AIGroup:OptionROEOpenFire()
AIGroup:OptionROTPassiveDefense()
AttackTasks[#AttackTasks+1] = AIGroup:TaskFunction( 1, #AttackTasks, "AI_A2A_CAP.AttackRoute" )
AttackTasks[#AttackTasks+1] = AIGroup:TaskFunction( 1, 1, "AI_A2A_CAP.AttackRoute" )
AttackTasks[#AttackTasks+1] = AIGroup:TaskOrbitCircle( 4000, self.PatrolMinSpeed )
EngageRoute[#EngageRoute].task = AIGroup:TaskCombo( AttackTasks )
EngageRoute[1].task = AIGroup:TaskCombo( AttackTasks )
--- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
AIGroup:SetState( AIGroup, "AI_A2A_CAP", self )
end
--- NOW ROUTE THE GROUP!
AIGroup:WayPointExecute( 1, 0 )
AIGroup:SetTask( AIGroup:TaskRoute( EngageRoute ), 1 )
end
else
self:E("No targets found -> Going back to Patrolling")

View File

@ -460,6 +460,8 @@ do -- AI_A2A_DISPATCHER
-- For example with a group setting of 2, if 3 targets are detected and cannot be engaged by CAP or any airborne flight,
-- a GCI needs to be started, the GCI flights will be grouped as follows: Group 1 of 2 flights and Group 2 of one flight!
--
-- Even more ... If one target has been detected, and the overhead is 1.5, grouping is 1, then two groups of planes will be spawned, with one unit each!
--
-- The **grouping value is set for a Squadron**, and can be **dynamically adjusted** during mission execution, so to adjust the defense flights grouping when the tactical situation changes.
--
-- ### 6.4. Overhead and Balance the effectiveness of the air defenses in case of GCI
@ -484,6 +486,8 @@ do -- AI_A2A_DISPATCHER
-- The amount of defending units is calculated by multiplying the amount of detected attacking planes as part of the detected group
-- multiplied by the Overhead and rounded up to the smallest integer.
--
-- For example ... If one target has been detected, and the overhead is 1.5, grouping is 1, then two groups of planes will be spawned, with one unit each!
--
-- The **overhead value is set for a Squadron**, and can be **dynamically adjusted** during mission execution, so to adjust the defense overhead when the tactical situation changes.
--
-- ## 7. Setup a squadron for CAP
@ -2163,11 +2167,11 @@ do -- AI_A2A_DISPATCHER
--- @param #AI_A2A_DISPATCHER self
function AI_A2A_DISPATCHER:AddDefenderToSquadron( Squadron, Defender )
function AI_A2A_DISPATCHER:AddDefenderToSquadron( Squadron, Defender, Size )
self.Defenders = self.Defenders or {}
local DefenderName = Defender:GetName()
self.Defenders[ DefenderName ] = Squadron
Squadron.Resources = Squadron.Resources - Defender:GetSize()
Squadron.Resources = Squadron.Resources - Size
self:F( { DefenderName = DefenderName, SquadronResources = Squadron.Resources } )
end
@ -2324,7 +2328,7 @@ do -- AI_A2A_DISPATCHER
local TakeoffMethod = self:GetSquadronTakeoff( SquadronName )
local DefenderCAP = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod )
self:AddDefenderToSquadron( DefenderSquadron, DefenderCAP )
self:AddDefenderToSquadron( DefenderSquadron, DefenderCAP, DefenderGrouping )
if DefenderCAP then
@ -2367,13 +2371,19 @@ do -- AI_A2A_DISPATCHER
end
--- @param #AI_A2A_DISPATCHER self
function Fsm:onafterHome( Defender, From, Event, To )
function Fsm:onafterHome( Defender, From, Event, To, Action )
self:F({"CAP Home"})
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local AIGroup = self:GetControllable()
local Squadron = Dispatcher:GetSquadronFromDefender( AIGroup )
if Action and Action == "Destroy" then
Dispatcher:RemoveDefenderFromSquadron( Squadron, AIGroup )
AIGroup:Destroy()
end
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
Dispatcher:RemoveDefenderFromSquadron( Squadron, AIGroup )
AIGroup:Destroy()
@ -2412,7 +2422,7 @@ do -- AI_A2A_DISPATCHER
for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do
for InterceptID, Intercept in pairs( DefenderSquadron.Gci or {} ) do
self:E( { DefenderSquadron } )
--self:E( { DefenderSquadron } )
local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE
--local TargetCoord = AttackerSet:GetFirst():GetCoordinate()
local TargetCoord = DetectedItem.InterceptCoord
@ -2453,23 +2463,24 @@ do -- AI_A2A_DISPATCHER
while ( DefendersNeeded > 0 ) do
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] -- Functional.Spawn#SPAWN
local DefenderGrouping = ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded
if DefenderGrouping then
Spawn:InitGrouping( ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded )
Spawn:InitGrouping( DefenderGrouping )
else
Spawn:InitGrouping()
end
local TakeoffMethod = self:GetSquadronTakeoff( ClosestDefenderSquadronName )
local DefenderGCI = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod )
local DefenderGCI = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod ) -- Wrapper.Group#GROUP
self:F( { GCIDefender = DefenderGCI:GetName() } )
DefendersNeeded = DefendersNeeded - DefenderGCI:GetSize()
DefendersNeeded = DefendersNeeded - DefenderGrouping
self:AddDefenderToSquadron( DefenderSquadron, DefenderGCI )
self:AddDefenderToSquadron( DefenderSquadron, DefenderGCI, DefenderGrouping )
if DefenderGCI then
DefendersCount = DefendersCount - DefenderGCI:GetSize()
DefendersCount = DefendersCount - DefenderGrouping
local Fsm = AI_A2A_GCI:New( DefenderGCI, Gci.EngageMinSpeed, Gci.EngageMaxSpeed )
Fsm:SetDispatcher( self )
@ -2492,15 +2503,35 @@ do -- AI_A2A_DISPATCHER
local AIGroup = self:GetControllable()
Dispatcher:ClearDefenderTaskTarget( AIGroup )
end
--- @param #AI_A2A_DISPATCHER self
function Fsm:onafterLostControl( Defender, From, Event, To )
self:F({"GCI Home"})
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local AIGroup = self:GetControllable() -- Wrapper.Group#GROUP
local Squadron = Dispatcher:GetSquadronFromDefender( AIGroup )
if AIGroup:IsAboveRunway() then
Dispatcher:RemoveDefenderFromSquadron( Squadron, AIGroup )
AIGroup:Destroy()
end
end
--- @param #AI_A2A_DISPATCHER self
function Fsm:onafterHome( Defender, From, Event, To )
function Fsm:onafterHome( Defender, From, Event, To, Action )
self:F({"GCI Home"})
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local AIGroup = self:GetControllable()
local Squadron = Dispatcher:GetSquadronFromDefender( AIGroup )
if Action and Action == "Destroy" then
Dispatcher:RemoveDefenderFromSquadron( Squadron, AIGroup )
AIGroup:Destroy()
end
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
Dispatcher:RemoveDefenderFromSquadron( Squadron, AIGroup )
AIGroup:Destroy()
@ -2662,7 +2693,16 @@ do -- AI_A2A_DISPATCHER
local Defender = Defender -- Wrapper.Group#GROUP
if not DefenderTask.Target then
local DefenderHasTask = Defender:HasTask()
Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) %s", Defender:GetName(), DefenderTask.Type, DefenderTask.Fsm:GetState(), Defender:GetSize(), Defender:HasTask() == true and "Executing" or "Idle" ) )
local Fuel = Defender:GetUnit(1):GetFuel() * 100
local Damage = Defender:GetLife() / Defender:GetLife0() * 100
Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s",
Defender:GetName(),
DefenderTask.Type,
DefenderTask.Fsm:GetState(),
Defender:GetSize(),
Fuel,
Damage,
Defender:HasTask() == true and "Executing" or "Idle" ) )
end
end
Report:Add( string.format( "\n - %d Tasks", TaskCount ) )

View File

@ -311,11 +311,17 @@ end
-- todo: need to fix this global function
--- @param Wrapper.Group#GROUP AIControllable
function AI_A2A_GCI.InterceptRoute( AIControllable )
function AI_A2A_GCI.InterceptRoute( AIGroup )
local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_A2A_GCI
EngageZone:E( "NewEngageRoute" )
EngageZone:__Engage( 0.5 )
AIGroup:E( { "AI_A2A_GCI.InterceptRoute:", AIGroup:GetName() } )
if AIGroup:IsAlive() then
local _AI_A2A_GCI = AIGroup:GetState( AIGroup, "AI_A2A_GCI" ) -- AI.AI_Cap#AI_A2A_GCI
_AI_A2A_GCI:__Engage( 0.5 )
local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
AIGroup:SetTask( Task )
end
end
--- @param #AI_A2A_GCI self
@ -411,16 +417,17 @@ function AI_A2A_GCI:onafterEngage( AIGroup, From, Event, To, AttackSetUnit )
AIGroup:OptionROEOpenFire()
AIGroup:OptionROTPassiveDefense()
AttackTasks[#AttackTasks+1] = AIGroup:TaskFunction( 1, #AttackTasks, "AI_A2A_GCI.InterceptRoute" )
AttackTasks[#AttackTasks+1] = AIGroup:TaskFunction( 1, 1, "AI_A2A_GCI.InterceptRoute" )
AttackTasks[#AttackTasks+1] = AIGroup:TaskOrbitCircle( 4000, self.EngageMinSpeed )
EngageRoute[#EngageRoute].task = AIGroup:TaskCombo( AttackTasks )
--- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
AIGroup:SetState( AIGroup, "EngageZone", self )
AIGroup:SetState( AIGroup, "AI_A2A_GCI", self )
end
--- NOW ROUTE THE GROUP!
AIGroup:WayPointExecute( 1, 0 )
--AIGroup:ClearTasks()
AIGroup:SetTask( AIGroup:TaskRoute( EngageRoute ), 1 )
end
else

View File

@ -62,7 +62,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr
-- Initialize the ObjectSchedulers array, which is a weakly coupled table.
-- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array.
self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } )
self.ObjectSchedulers = self.ObjectSchedulers or {} -- setmetatable( {}, { __mode = "v" } )
if Scheduler.MasterObject then
self.ObjectSchedulers[self.CallID] = Scheduler

View File

@ -340,7 +340,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime )
-- Therefore we schedule the functions to set the mission and options for the Controllable.
-- Controller.setTask( Controller, DCSTask )
if not WaitTime then
if not WaitTime or WaitTime == 0 then
Controller:setTask( DCSTask )
else
self.TaskScheduler:Schedule( Controller, Controller.setTask, { DCSTask }, WaitTime )