mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
API V2 of the A2A and A2G dispatchers. Now a more fine grained attack is possible. You can now tweak the altitude and speed when units engage the target. Especially useful for ground attacks when SEAD, CAS or BAI.You can model low altitude approaches. Added 2 new test missions under the IAD - A2G API v2. Please report any bugs.
This commit is contained in:
parent
8c54b7298d
commit
c579aad606
@ -1,737 +0,0 @@
|
||||
--- **AI** -- (R2.2) - Models the process of air operations for airplanes.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI.AI_A2A
|
||||
-- @image MOOSE.JPG
|
||||
|
||||
--BASE:TraceClass("AI_A2A")
|
||||
|
||||
|
||||
--- @type AI_A2A
|
||||
-- @extends Core.Fsm#FSM_CONTROLLABLE
|
||||
|
||||
--- The AI_A2A class implements the core functions to operate an AI @{Wrapper.Group} A2A tasking.
|
||||
--
|
||||
--
|
||||
-- ## AI_A2A constructor
|
||||
--
|
||||
-- * @{#AI_A2A.New}(): Creates a new AI_A2A object.
|
||||
--
|
||||
-- ## 2. AI_A2A is a FSM
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ### 2.1. AI_A2A States
|
||||
--
|
||||
-- * **None** ( Group ): The process is not started yet.
|
||||
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
|
||||
-- * **Returning** ( Group ): The AI is returning to Base.
|
||||
-- * **Stopped** ( Group ): The process is stopped.
|
||||
-- * **Crashed** ( Group ): The AI has crashed or is dead.
|
||||
--
|
||||
-- ### 2.2. AI_A2A Events
|
||||
--
|
||||
-- * **Start** ( Group ): Start the process.
|
||||
-- * **Stop** ( Group ): Stop the process.
|
||||
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **RTB** ( Group ): Route the AI to the home base.
|
||||
-- * **Detect** ( Group ): The AI is detecting targets.
|
||||
-- * **Detected** ( Group ): The AI has detected new targets.
|
||||
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ## 3. Set or Get the AI controllable
|
||||
--
|
||||
-- * @{#AI_A2A.SetControllable}(): Set the AIControllable.
|
||||
-- * @{#AI_A2A.GetControllable}(): Get the AIControllable.
|
||||
--
|
||||
-- @field #AI_A2A
|
||||
AI_A2A = {
|
||||
ClassName = "AI_A2A",
|
||||
}
|
||||
|
||||
--- Creates a new AI_A2A object
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The GROUP object to receive the A2A Process.
|
||||
-- @return #AI_A2A
|
||||
function AI_A2A:New( AIGroup )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_A2A
|
||||
|
||||
self:SetControllable( AIGroup )
|
||||
|
||||
self:SetFuelThreshold( .2, 60 )
|
||||
self:SetDamageThreshold( 0.4 )
|
||||
self:SetDisengageRadius( 70000 )
|
||||
|
||||
self:SetStartState( "Stopped" )
|
||||
|
||||
self:AddTransition( "*", "Start", "Started" )
|
||||
|
||||
--- Start Handler OnBefore for AI_A2A
|
||||
-- @function [parent=#AI_A2A] OnBeforeStart
|
||||
-- @param #AI_A2A self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Start Handler OnAfter for AI_A2A
|
||||
-- @function [parent=#AI_A2A] OnAfterStart
|
||||
-- @param #AI_A2A self
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Start Trigger for AI_A2A
|
||||
-- @function [parent=#AI_A2A] Start
|
||||
-- @param #AI_A2A self
|
||||
|
||||
--- Start Asynchronous Trigger for AI_A2A
|
||||
-- @function [parent=#AI_A2A] __Start
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number Delay
|
||||
|
||||
self:AddTransition( "*", "Stop", "Stopped" )
|
||||
|
||||
--- OnLeave Transition Handler for State Stopped.
|
||||
-- @function [parent=#AI_A2A] OnLeaveStopped
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Stopped.
|
||||
-- @function [parent=#AI_A2A] OnEnterStopped
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- OnBefore Transition Handler for Event Stop.
|
||||
-- @function [parent=#AI_A2A] OnBeforeStop
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Stop.
|
||||
-- @function [parent=#AI_A2A] OnAfterStop
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Stop.
|
||||
-- @function [parent=#AI_A2A] Stop
|
||||
-- @param #AI_A2A self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Stop.
|
||||
-- @function [parent=#AI_A2A] __Stop
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "*", "Status", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A.
|
||||
|
||||
--- OnBefore Transition Handler for Event Status.
|
||||
-- @function [parent=#AI_A2A] OnBeforeStatus
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Status.
|
||||
-- @function [parent=#AI_A2A] OnAfterStatus
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Status.
|
||||
-- @function [parent=#AI_A2A] Status
|
||||
-- @param #AI_A2A self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Status.
|
||||
-- @function [parent=#AI_A2A] __Status
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "*", "RTB", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A.
|
||||
|
||||
--- OnBefore Transition Handler for Event RTB.
|
||||
-- @function [parent=#AI_A2A] OnBeforeRTB
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event RTB.
|
||||
-- @function [parent=#AI_A2A] OnAfterRTB
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event RTB.
|
||||
-- @function [parent=#AI_A2A] RTB
|
||||
-- @param #AI_A2A self
|
||||
|
||||
--- Asynchronous Event Trigger for Event RTB.
|
||||
-- @function [parent=#AI_A2A] __RTB
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
--- OnLeave Transition Handler for State Returning.
|
||||
-- @function [parent=#AI_A2A] OnLeaveReturning
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Returning.
|
||||
-- @function [parent=#AI_A2A] OnEnterReturning
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
self:AddTransition( "Patrolling", "Refuel", "Refuelling" )
|
||||
|
||||
--- Refuel Handler OnBefore for AI_A2A
|
||||
-- @function [parent=#AI_A2A] OnBeforeRefuel
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
-- @return #boolean
|
||||
|
||||
--- Refuel Handler OnAfter for AI_A2A
|
||||
-- @function [parent=#AI_A2A] OnAfterRefuel
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From
|
||||
-- @param #string Event
|
||||
-- @param #string To
|
||||
|
||||
--- Refuel Trigger for AI_A2A
|
||||
-- @function [parent=#AI_A2A] Refuel
|
||||
-- @param #AI_A2A self
|
||||
|
||||
--- Refuel Asynchronous Trigger for AI_A2A
|
||||
-- @function [parent=#AI_A2A] __Refuel
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number Delay
|
||||
|
||||
self:AddTransition( "*", "Takeoff", "Airborne" )
|
||||
self:AddTransition( "*", "Return", "Returning" )
|
||||
self:AddTransition( "*", "Hold", "Holding" )
|
||||
self:AddTransition( "*", "Home", "Home" )
|
||||
self:AddTransition( "*", "LostControl", "LostControl" )
|
||||
self:AddTransition( "*", "Fuel", "Fuel" )
|
||||
self:AddTransition( "*", "Damaged", "Damaged" )
|
||||
self:AddTransition( "*", "Eject", "*" )
|
||||
self:AddTransition( "*", "Crash", "Crashed" )
|
||||
self:AddTransition( "*", "PilotDead", "*" )
|
||||
|
||||
self.IdleCount = 0
|
||||
|
||||
return self
|
||||
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_A2A:SetDispatcher( Dispatcher )
|
||||
self.Dispatcher = Dispatcher
|
||||
end
|
||||
|
||||
function AI_A2A:GetDispatcher()
|
||||
return self.Dispatcher
|
||||
end
|
||||
|
||||
function AI_A2A:SetTargetDistance( Coordinate )
|
||||
|
||||
local CurrentCoord = self.Controllable:GetCoordinate()
|
||||
self.TargetDistance = CurrentCoord:Get2DDistance( Coordinate )
|
||||
|
||||
self.ClosestTargetDistance = ( not self.ClosestTargetDistance or self.ClosestTargetDistance > self.TargetDistance ) and self.TargetDistance or self.ClosestTargetDistance
|
||||
end
|
||||
|
||||
|
||||
function AI_A2A:ClearTargetDistance()
|
||||
|
||||
self.TargetDistance = nil
|
||||
self.ClosestTargetDistance = nil
|
||||
end
|
||||
|
||||
|
||||
--- Sets (modifies) the minimum and maximum speed of the patrol.
|
||||
-- @param #AI_A2A self
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Controllable} in km/h.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed )
|
||||
self:F2( { PatrolMinSpeed, PatrolMaxSpeed } )
|
||||
|
||||
self.PatrolMinSpeed = PatrolMinSpeed
|
||||
self.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
end
|
||||
|
||||
|
||||
--- Sets the floor and ceiling altitude of the patrol.
|
||||
-- @param #AI_A2A self
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
|
||||
self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } )
|
||||
|
||||
self.PatrolFloorAltitude = PatrolFloorAltitude
|
||||
self.PatrolCeilingAltitude = PatrolCeilingAltitude
|
||||
end
|
||||
|
||||
|
||||
--- Sets the home airbase.
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Airbase#AIRBASE HomeAirbase
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetHomeAirbase( HomeAirbase )
|
||||
self:F2( { HomeAirbase } )
|
||||
|
||||
self.HomeAirbase = HomeAirbase
|
||||
end
|
||||
|
||||
--- Sets to refuel at the given tanker.
|
||||
-- @param #AI_A2A self
|
||||
-- @param Wrapper.Group#GROUP TankerName The group name of the tanker as defined within the Mission Editor or spawned.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetTanker( TankerName )
|
||||
self:F2( { TankerName } )
|
||||
|
||||
self.TankerName = TankerName
|
||||
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
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetStatusOff()
|
||||
self:F2()
|
||||
|
||||
self.CheckStatus = false
|
||||
end
|
||||
|
||||
|
||||
--- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base.
|
||||
-- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated.
|
||||
-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_A2A.
|
||||
-- Once the time is finished, the old AI will return to the base.
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number PatrolFuelThresholdPercentage The treshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel.
|
||||
-- @param #number PatrolOutOfFuelOrbitTime The amount of seconds the out of fuel AIControllable will orbit before returning to the base.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetFuelThreshold( PatrolFuelThresholdPercentage, PatrolOutOfFuelOrbitTime )
|
||||
|
||||
self.PatrolFuelThresholdPercentage = PatrolFuelThresholdPercentage
|
||||
self.PatrolOutOfFuelOrbitTime = PatrolOutOfFuelOrbitTime
|
||||
|
||||
self.Controllable:OptionRTBBingoFuel( false )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- When the AI is damaged beyond a certain treshold, it is required that the AI returns to the home base.
|
||||
-- However, damage cannot be foreseen early on.
|
||||
-- Therefore, when the damage treshold is reached,
|
||||
-- the AI will return immediately to the home base (RTB).
|
||||
-- Note that for groups, the average damage of the complete group will be calculated.
|
||||
-- So, in a group of 4 airplanes, 2 lost and 2 with damage 0.2, the damage treshold will be 0.25.
|
||||
-- @param #AI_A2A self
|
||||
-- @param #number PatrolDamageThreshold The treshold in percentage (between 0 and 1) when the AI is considered to be damaged.
|
||||
-- @return #AI_A2A self
|
||||
function AI_A2A:SetDamageThreshold( PatrolDamageThreshold )
|
||||
|
||||
self.PatrolManageDamage = true
|
||||
self.PatrolDamageThreshold = PatrolDamageThreshold
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings.
|
||||
-- @param #AI_A2A self
|
||||
-- @return #AI_A2A self
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A:onafterStart( Controllable, From, Event, To )
|
||||
|
||||
self:__Status( 10 ) -- Check status status every 30 seconds.
|
||||
|
||||
self:HandleEvent( EVENTS.PilotDead, self.OnPilotDead )
|
||||
self:HandleEvent( EVENTS.Crash, self.OnCrash )
|
||||
self:HandleEvent( EVENTS.Ejection, self.OnEjection )
|
||||
|
||||
Controllable:OptionROEHoldFire()
|
||||
Controllable:OptionROTVertical()
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #AI_A2A self
|
||||
function AI_A2A:onbeforeStatus()
|
||||
|
||||
return self.CheckStatus
|
||||
end
|
||||
|
||||
--- @param #AI_A2A self
|
||||
function AI_A2A:onafterStatus()
|
||||
|
||||
if self.Controllable and self.Controllable:IsAlive() then
|
||||
|
||||
local RTB = false
|
||||
|
||||
local DistanceFromHomeBase = self.HomeAirbase:GetCoordinate():Get2DDistance( self.Controllable:GetCoordinate() )
|
||||
|
||||
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:I( self.Controllable:GetName() .. " is too far from home base, RTB!" )
|
||||
self:Hold( 300 )
|
||||
RTB = false
|
||||
end
|
||||
end
|
||||
|
||||
-- I think this code is not requirement anymore after release 2.5.
|
||||
-- if self:Is( "Fuel" ) or self:Is( "Damaged" ) or self:Is( "LostControl" ) then
|
||||
-- if DistanceFromHomeBase < 5000 then
|
||||
-- self:E( self.Controllable:GetName() .. " is near the home base, RTB!" )
|
||||
-- self:Home( "Destroy" )
|
||||
-- end
|
||||
-- end
|
||||
|
||||
|
||||
if not self:Is( "Fuel" ) and not self:Is( "Home" ) then
|
||||
local Fuel = self.Controllable:GetFuelMin()
|
||||
self:F({Fuel=Fuel, PatrolFuelThresholdPercentage=self.PatrolFuelThresholdPercentage})
|
||||
if Fuel < self.PatrolFuelThresholdPercentage then
|
||||
if self.TankerName then
|
||||
self:I( self.Controllable:GetName() .. " is out of fuel: " .. Fuel .. " ... Refuelling at Tanker!" )
|
||||
self:Refuel()
|
||||
else
|
||||
self:I( self.Controllable:GetName() .. " is out of fuel: " .. Fuel .. " ... RTB!" )
|
||||
local OldAIControllable = self.Controllable
|
||||
|
||||
local OrbitTask = OldAIControllable:TaskOrbitCircle( math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ), self.PatrolMinSpeed )
|
||||
local TimedOrbitTask = OldAIControllable:TaskControlled( OrbitTask, OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil ) )
|
||||
OldAIControllable:SetTask( TimedOrbitTask, 10 )
|
||||
|
||||
self:Fuel()
|
||||
RTB = true
|
||||
end
|
||||
else
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO: Check GROUP damage function.
|
||||
local Damage = self.Controllable:GetLife()
|
||||
local InitialLife = self.Controllable:GetLife0()
|
||||
self:F( { Damage = Damage, InitialLife = InitialLife, DamageThreshold = self.PatrolDamageThreshold } )
|
||||
if ( Damage / InitialLife ) < self.PatrolDamageThreshold then
|
||||
self:I( self.Controllable:GetName() .. " is damaged: " .. Damage .. " ... RTB!" )
|
||||
self:Damaged()
|
||||
RTB = true
|
||||
self:SetStatusOff()
|
||||
end
|
||||
|
||||
-- Check if planes went RTB and are out of control.
|
||||
-- We only check if planes are out of control, when they are in duty.
|
||||
if self.Controllable:HasTask() == false then
|
||||
if not self:Is( "Started" ) and
|
||||
not self:Is( "Stopped" ) and
|
||||
not self:Is( "Fuel" ) and
|
||||
not self:Is( "Damaged" ) and
|
||||
not self:Is( "Home" ) then
|
||||
if self.IdleCount >= 3 then
|
||||
if Damage ~= InitialLife then
|
||||
self:Damaged()
|
||||
else
|
||||
self:I( self.Controllable:GetName() .. " control lost! " )
|
||||
self:LostControl()
|
||||
end
|
||||
else
|
||||
self.IdleCount = self.IdleCount + 1
|
||||
end
|
||||
end
|
||||
else
|
||||
self.IdleCount = 0
|
||||
end
|
||||
|
||||
if RTB == true then
|
||||
self:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
if not self:Is("Home") then
|
||||
self:__Status( 10 )
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A.RTBRoute( AIGroup, Fsm )
|
||||
|
||||
AIGroup:F( { "AI_A2A.RTBRoute:", AIGroup:GetName() } )
|
||||
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A.RTBHold( AIGroup, Fsm )
|
||||
|
||||
AIGroup:F( { "AI_A2A.RTBHold:", AIGroup:GetName() } )
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__RTB( 0.5 )
|
||||
Fsm:Return()
|
||||
local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
|
||||
AIGroup:SetTask( Task )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A:onafterRTB( AIGroup, From, Event, To )
|
||||
self:F( { AIGroup, From, Event, To } )
|
||||
|
||||
|
||||
if AIGroup and AIGroup:IsAlive() then
|
||||
|
||||
self:I( "Group " .. AIGroup:GetName() .. " ... RTB! ( " .. self:GetState() .. " )" )
|
||||
|
||||
self:ClearTargetDistance()
|
||||
AIGroup:ClearTasks()
|
||||
|
||||
local EngageRoute = {}
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
local CurrentCoord = AIGroup:GetCoordinate()
|
||||
local ToTargetCoord = self.HomeAirbase:GetCoordinate()
|
||||
local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||
local ToAirbaseAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) )
|
||||
|
||||
local Distance = CurrentCoord:Get2DDistance( ToTargetCoord )
|
||||
|
||||
local ToAirbaseCoord = CurrentCoord:Translate( 5000, ToAirbaseAngle )
|
||||
if Distance < 5000 then
|
||||
self:I( "RTB and near the airbase!" )
|
||||
self:Home()
|
||||
return
|
||||
end
|
||||
--- Create a route point of type air.
|
||||
local ToRTBRoutePoint = ToAirbaseCoord:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
self:F( { Angle = ToAirbaseAngle, ToTargetSpeed = ToTargetSpeed } )
|
||||
self:T2( { self.MinSpeed, self.MaxSpeed, ToTargetSpeed } )
|
||||
|
||||
EngageRoute[#EngageRoute+1] = ToRTBRoutePoint
|
||||
EngageRoute[#EngageRoute+1] = ToRTBRoutePoint
|
||||
|
||||
AIGroup:OptionROEHoldFire()
|
||||
AIGroup:OptionROTEvadeFire()
|
||||
|
||||
--- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
|
||||
AIGroup:WayPointInitialize( EngageRoute )
|
||||
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = AIGroup:TaskFunction( "AI_A2A.RTBRoute", self )
|
||||
EngageRoute[#EngageRoute].task = AIGroup:TaskCombo( Tasks )
|
||||
|
||||
--- NOW ROUTE THE GROUP!
|
||||
AIGroup:Route( EngageRoute, 0.5 )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_A2A self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A:onafterHome( AIGroup, From, Event, To )
|
||||
self:F( { AIGroup, From, Event, To } )
|
||||
|
||||
self:I( "Group " .. self.Controllable:GetName() .. " ... Home! ( " .. self:GetState() .. " )" )
|
||||
|
||||
if AIGroup and AIGroup:IsAlive() then
|
||||
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:I( "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( "AI_A2A.RTBHold", self )
|
||||
|
||||
local OrbitHoldTask = AIGroup:TaskOrbitCircle( 4000, self.PatrolMinSpeed )
|
||||
|
||||
--AIGroup:SetState( AIGroup, "AI_A2A", self )
|
||||
|
||||
AIGroup:SetTask( AIGroup:TaskCombo( { TimedOrbitTask, RTBTask, OrbitHoldTask } ), 1 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A.Resume( AIGroup, Fsm )
|
||||
|
||||
AIGroup:I( { "AI_A2A.Resume:", AIGroup:GetName() } )
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param #AI_A2A self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A:onafterRefuel( AIGroup, From, Event, To )
|
||||
self:F( { AIGroup, From, Event, To } )
|
||||
|
||||
self:I( "Group " .. self.Controllable:GetName() .. " ... Refuelling! ( " .. self:GetState() .. " )" )
|
||||
|
||||
if AIGroup and AIGroup:IsAlive() then
|
||||
local Tanker = GROUP:FindByName( self.TankerName )
|
||||
if Tanker:IsAlive() and Tanker:IsAirPlane() then
|
||||
|
||||
local RefuelRoute = {}
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
local CurrentCoord = AIGroup:GetCoordinate()
|
||||
local ToRefuelCoord = Tanker:GetCoordinate()
|
||||
local ToRefuelSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToRefuelRoutePoint = CurrentCoord:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
ToRefuelSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
self:F( { ToRefuelSpeed = ToRefuelSpeed } )
|
||||
|
||||
RefuelRoute[#RefuelRoute+1] = ToRefuelRoutePoint
|
||||
RefuelRoute[#RefuelRoute+1] = ToRefuelRoutePoint
|
||||
|
||||
AIGroup:OptionROEHoldFire()
|
||||
AIGroup:OptionROTEvadeFire()
|
||||
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = AIGroup:TaskRefueling()
|
||||
Tasks[#Tasks+1] = AIGroup:TaskFunction( self:GetClassName() .. ".Resume", self )
|
||||
RefuelRoute[#RefuelRoute].task = AIGroup:TaskCombo( Tasks )
|
||||
|
||||
AIGroup:Route( RefuelRoute, 0.5 )
|
||||
else
|
||||
self:RTB()
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- @param #AI_A2A self
|
||||
function AI_A2A:onafterDead()
|
||||
self:SetStatusOff()
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A:OnCrash( EventData )
|
||||
|
||||
if self.Controllable:IsAlive() and EventData.IniDCSGroupName == self.Controllable:GetName() then
|
||||
self:I( self.Controllable:GetUnits() )
|
||||
if #self.Controllable:GetUnits() == 1 then
|
||||
self:__Crash( 1, EventData )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A:OnEjection( EventData )
|
||||
|
||||
if self.Controllable:IsAlive() and EventData.IniDCSGroupName == self.Controllable:GetName() then
|
||||
self:__Eject( 1, EventData )
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A:OnPilotDead( EventData )
|
||||
|
||||
if self.Controllable:IsAlive() and EventData.IniDCSGroupName == self.Controllable:GetName() then
|
||||
self:__PilotDead( 1, EventData )
|
||||
end
|
||||
end
|
||||
@ -10,7 +10,8 @@
|
||||
-- @image AI_Combat_Air_Patrol.JPG
|
||||
|
||||
--- @type AI_A2A_CAP
|
||||
-- @extends AI.AI_A2A_Patrol#AI_A2A_PATROL
|
||||
-- @extends AI.AI_Air_Patrol#AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air_Engage#AI_AIR_ENGAGE
|
||||
|
||||
|
||||
--- The AI_A2A_CAP class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
||||
@ -97,6 +98,36 @@ AI_A2A_CAP = {
|
||||
ClassName = "AI_A2A_CAP",
|
||||
}
|
||||
|
||||
--- Creates a new AI_A2A_CAP object
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @return #AI_A2A_CAP
|
||||
function AI_A2A_CAP:New2( AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType )
|
||||
|
||||
-- Multiple inheritance ... :-)
|
||||
local AI_Air = AI_AIR:New( AICap )
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AICap, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||
|
||||
self:SetFuelThreshold( .2, 60 )
|
||||
self:SetDamageThreshold( 0.4 )
|
||||
self:SetDisengageRadius( 70000 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a new AI_A2A_CAP object
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap
|
||||
@ -111,176 +142,8 @@ AI_A2A_CAP = {
|
||||
-- @return #AI_A2A_CAP
|
||||
function AI_A2A_CAP:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, PatrolAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2A_PATROL:New( AICap, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2A_CAP
|
||||
return self:New2( AICap, EngageMinSpeed, EngageMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolZone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, PatrolAltType )
|
||||
|
||||
self.Accomplished = false
|
||||
self.Engaging = false
|
||||
|
||||
self.EngageMinSpeed = EngageMinSpeed
|
||||
self.EngageMaxSpeed = EngageMaxSpeed
|
||||
|
||||
self:AddTransition( { "Patrolling", "Engaging", "Returning", "Airborne" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_CAP.
|
||||
|
||||
--- OnBefore Transition Handler for Event Engage.
|
||||
-- @function [parent=#AI_A2A_CAP] OnBeforeEngage
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Engage.
|
||||
-- @function [parent=#AI_A2A_CAP] OnAfterEngage
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_A2A_CAP] Engage
|
||||
-- @param #AI_A2A_CAP self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_A2A_CAP] __Engage
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
--- OnLeave Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2A_CAP] OnLeaveEngaging
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2A_CAP] OnEnterEngaging
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_CAP.
|
||||
|
||||
--- OnBefore Transition Handler for Event Fired.
|
||||
-- @function [parent=#AI_A2A_CAP] OnBeforeFired
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Fired.
|
||||
-- @function [parent=#AI_A2A_CAP] OnAfterFired
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Fired.
|
||||
-- @function [parent=#AI_A2A_CAP] Fired
|
||||
-- @param #AI_A2A_CAP self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Fired.
|
||||
-- @function [parent=#AI_A2A_CAP] __Fired
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_CAP.
|
||||
|
||||
--- OnBefore Transition Handler for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_CAP] OnBeforeDestroy
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_CAP] OnAfterDestroy
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_CAP] Destroy
|
||||
-- @param #AI_A2A_CAP self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_CAP] __Destroy
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
|
||||
self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_CAP.
|
||||
|
||||
--- OnBefore Transition Handler for Event Abort.
|
||||
-- @function [parent=#AI_A2A_CAP] OnBeforeAbort
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Abort.
|
||||
-- @function [parent=#AI_A2A_CAP] OnAfterAbort
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Abort.
|
||||
-- @function [parent=#AI_A2A_CAP] Abort
|
||||
-- @param #AI_A2A_CAP self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Abort.
|
||||
-- @function [parent=#AI_A2A_CAP] __Abort
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_CAP.
|
||||
|
||||
--- OnBefore Transition Handler for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_CAP] OnBeforeAccomplish
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_CAP] OnAfterAccomplish
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_CAP] Accomplish
|
||||
-- @param #AI_A2A_CAP self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_CAP] __Accomplish
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( { "Patrolling", "Engaging" }, "Refuel", "Refuelling" )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- onafter State Transition for Event Patrol.
|
||||
@ -291,7 +154,7 @@ end
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onafterStart( AICap, From, Event, To )
|
||||
|
||||
self:GetParent( self ).onafterStart( self, AICap, From, Event, To )
|
||||
self:GetParent( self, AI_A2A_CAP ).onafterStart( self, AICap, From, Event, To )
|
||||
AICap:HandleEvent( EVENTS.Takeoff, nil, self )
|
||||
|
||||
end
|
||||
@ -324,168 +187,26 @@ function AI_A2A_CAP:SetEngageRange( EngageRange )
|
||||
end
|
||||
end
|
||||
|
||||
--- onafter State Transition for Event Patrol.
|
||||
--- Evaluate the attack and create an AttackUnitTask list.
|
||||
-- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onafterPatrol( AICap, From, Event, To )
|
||||
-- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack.
|
||||
-- @param Wrappper.Group#GROUP DefenderGroup The group of defenders.
|
||||
-- @param #number EngageAltitude The altitude to engage the targets.
|
||||
-- @return #AI_A2A_CAP self
|
||||
function AI_A2A_CAP:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude )
|
||||
|
||||
-- Call the parent Start event handler
|
||||
self:GetParent(self).onafterPatrol( self, AICap, From, Event, To )
|
||||
self:HandleEvent( EVENTS.Dead )
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
end
|
||||
|
||||
-- todo: need to fix this global function
|
||||
|
||||
--- @param Wrapper.Group#GROUP AICap
|
||||
function AI_A2A_CAP.AttackRoute( AICap, Fsm )
|
||||
|
||||
AICap:F( { "AI_A2A_CAP.AttackRoute:", AICap:GetName() } )
|
||||
|
||||
if AICap:IsAlive() then
|
||||
Fsm:__Engage( 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onbeforeEngage( AICap, From, Event, To )
|
||||
|
||||
if self.Accomplished == true then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onafterAbort( AICap, From, Event, To )
|
||||
AICap:ClearTasks()
|
||||
self:__Route( 0.5 )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The AICap Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onafterEngage( AICap, From, Event, To, AttackSetUnit )
|
||||
|
||||
self:F( { AICap, From, Event, To, AttackSetUnit} )
|
||||
|
||||
self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT
|
||||
|
||||
local FirstAttackUnit = self.AttackSetUnit:GetFirst() -- Wrapper.Unit#UNIT
|
||||
|
||||
if FirstAttackUnit and FirstAttackUnit:IsAlive() then -- If there is no attacker anymore, stop the engagement.
|
||||
|
||||
if AICap and AICap:IsAlive() then
|
||||
|
||||
local EngageRoute = {}
|
||||
|
||||
--- Calculate the target route point.
|
||||
local CurrentCoord = AICap:GetCoordinate()
|
||||
local ToTargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate()
|
||||
local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||
local ToInterceptAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToPatrolRoutePoint = CurrentCoord:Translate( 5000, ToInterceptAngle ):WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
self:F( { Angle = ToInterceptAngle, ToTargetSpeed = ToTargetSpeed } )
|
||||
self:T2( { self.MinSpeed, self.MaxSpeed, ToTargetSpeed } )
|
||||
|
||||
EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
|
||||
EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
|
||||
|
||||
local AttackTasks = {}
|
||||
|
||||
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
|
||||
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
|
||||
self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
|
||||
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
|
||||
-- Maybe the detected set also contains
|
||||
AttackTasks[#AttackTasks+1] = AICap:TaskAttackUnit( AttackUnit )
|
||||
end
|
||||
end
|
||||
|
||||
if #AttackTasks == 0 then
|
||||
self:E("No targets found -> Going back to Patrolling")
|
||||
self:__Abort( 0.5 )
|
||||
else
|
||||
AICap:OptionROEOpenFire()
|
||||
AICap:OptionROTEvadeFire()
|
||||
|
||||
AttackTasks[#AttackTasks+1] = AICap:TaskFunction( "AI_A2A_CAP.AttackRoute", self )
|
||||
EngageRoute[#EngageRoute].task = AICap:TaskCombo( AttackTasks )
|
||||
end
|
||||
|
||||
AICap:Route( EngageRoute, 0.5 )
|
||||
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
|
||||
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
|
||||
self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
|
||||
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
|
||||
-- Maybe the detected set also contains
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit )
|
||||
end
|
||||
else
|
||||
self:E("No targets found -> Going back to Patrolling")
|
||||
self:__Abort( 0.5 )
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_CAP:onafterAccomplish( AICap, From, Event, To )
|
||||
self.Accomplished = true
|
||||
self:SetDetectionOff()
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_CAP self
|
||||
-- @param Wrapper.Group#GROUP AICap The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_CAP:onafterDestroy( AICap, From, Event, To, EventData )
|
||||
|
||||
if EventData.IniUnit then
|
||||
self.AttackUnits[EventData.IniUnit] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_CAP self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_CAP:OnEventDead( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
if EventData.IniDCSUnit then
|
||||
if self.AttackUnits and self.AttackUnits[EventData.IniUnit] then
|
||||
self:__Destroy( 1, EventData )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AICap
|
||||
function AI_A2A_CAP.Resume( AICap, Fsm )
|
||||
|
||||
AICap:I( { "AI_A2A_CAP.Resume:", AICap:GetName() } )
|
||||
if AICap:IsAlive() then
|
||||
Fsm:__Reset( 1 )
|
||||
Fsm:__Route( 5 )
|
||||
end
|
||||
|
||||
return AttackUnitTasks
|
||||
end
|
||||
|
||||
|
||||
@ -1770,13 +1770,87 @@ do -- AI_A2A_DISPATCHER
|
||||
--- Set a CAP for a Squadron.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed.
|
||||
-- @param #number FloorAltitude The minimum altitude at which the cap can be executed.
|
||||
-- @param #number CeilingAltitude the maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed.
|
||||
-- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed.
|
||||
-- @param #number EngageMinSpeed The minimum speed at which the engage can be executed.
|
||||
-- @param #number EngageMaxSpeed The maximum speed at which the engage can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param #number EngageAltType The altitude type to engage, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed.
|
||||
-- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed.
|
||||
-- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed.
|
||||
-- @param #number PatrolFloorAltitude The minimum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolCeilingAltitude the maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolAltType The altitude type to patrol, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- CAP Squadron execution.
|
||||
-- CAPZoneEast = ZONE_POLYGON:New( "CAP Zone East", GROUP:FindByName( "CAP Zone East" ) )
|
||||
-- -- Setup a CAP, engaging between 800 and 900 km/h, altitude 30 (above the sea), radio altitude measurement,
|
||||
-- -- patrolling speed between 500 and 600 km/h, altitude between 4000 and 10000 meters, barometric altitude measurement.
|
||||
-- A2ADispatcher:SetSquadronCapV2( "Mineralnye", 800, 900, 30, 30, "RADIO", CAPZoneEast, 500, 600, 4000, 10000, "BARO" )
|
||||
-- A2ADispatcher:SetSquadronCapInterval( "Mineralnye", 2, 30, 60, 1 )
|
||||
--
|
||||
-- CAPZoneWest = ZONE_POLYGON:New( "CAP Zone West", GROUP:FindByName( "CAP Zone West" ) )
|
||||
-- -- Setup a CAP, engaging between 800 and 1200 km/h, altitude between 4000 and 10000 meters, radio altitude measurement,
|
||||
-- -- patrolling speed between 600 and 800 km/h, altitude between 4000 and 8000, barometric altitude measurement.
|
||||
-- A2ADispatcher:SetSquadronCapV2( "Sochi", 800, 1200, 2000, 3000, "RADIO", CAPZoneWest, 600, 800, 4000, 8000, "BARO" )
|
||||
-- A2ADispatcher:SetSquadronCapInterval( "Sochi", 2, 30, 120, 1 )
|
||||
--
|
||||
-- CAPZoneMiddle = ZONE:New( "CAP Zone Middle")
|
||||
-- -- Setup a CAP, engaging between 800 and 1200 km/h, altitude between 5000 and 8000 meters, barometric altitude measurement,
|
||||
-- -- patrolling speed between 600 and 800 km/h, altitude between 4000 and 8000, radio altitude.
|
||||
-- A2ADispatcher:SetSquadronCapV2( "Maykop", 800, 1200, 5000, 8000, "BARO", CAPZoneMiddle, 600, 800, 4000, 8000, "RADIO" )
|
||||
-- A2ADispatcher:SetSquadronCapInterval( "Maykop", 2, 30, 120, 1 )
|
||||
--
|
||||
function AI_A2A_DISPATCHER:SetSquadronCap2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType )
|
||||
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
local Cap = self.DefenderSquadrons[SquadronName].Cap
|
||||
Cap.Name = SquadronName
|
||||
Cap.EngageMinSpeed = EngageMinSpeed
|
||||
Cap.EngageMaxSpeed = EngageMaxSpeed
|
||||
Cap.EngageFloorAltitude = EngageFloorAltitude
|
||||
Cap.EngageCeilingAltitude = EngageCeilingAltitude
|
||||
Cap.Zone = Zone
|
||||
Cap.PatrolMinSpeed = PatrolMinSpeed
|
||||
Cap.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
Cap.PatrolFloorAltitude = PatrolFloorAltitude
|
||||
Cap.PatrolCeilingAltitude = PatrolCeilingAltitude
|
||||
Cap.PatrolAltType = PatrolAltType
|
||||
Cap.EngageAltType = EngageAltType
|
||||
|
||||
self:SetSquadronCapInterval( SquadronName, self.DefenderDefault.CapLimit, self.DefenderDefault.CapMinSeconds, self.DefenderDefault.CapMaxSeconds, 1 )
|
||||
|
||||
self:I( { CAP = { SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageAltType } } )
|
||||
|
||||
-- Add the CAP to the EWR network.
|
||||
|
||||
local RecceSet = self.Detection:GetDetectionSet()
|
||||
RecceSet:FilterPrefixes( DefenderSquadron.TemplatePrefixes )
|
||||
RecceSet:FilterStart()
|
||||
|
||||
self.Detection:SetFriendlyPrefixes( DefenderSquadron.TemplatePrefixes )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set a CAP for a Squadron.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed The minimum speed at which the engage can be executed.
|
||||
-- @param #number EngageMaxSpeed The maximum speed at which the engage can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the CAP will be executed.
|
||||
-- @param #number PatrolFloorAltitude The minimum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolCeilingAltitude the maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolMinSpeed The minimum speed at which the cap can be executed.
|
||||
-- @param #number PatrolMaxSpeed The maximum speed at which the cap can be executed.
|
||||
-- @param #number AltType The altitude type, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
-- @usage
|
||||
@ -1794,37 +1868,9 @@ do -- AI_A2A_DISPATCHER
|
||||
-- A2ADispatcher:SetSquadronCap( "Maykop", CAPZoneMiddle, 4000, 8000, 600, 800, 800, 1200, "RADIO" )
|
||||
-- A2ADispatcher:SetSquadronCapInterval( "Sochi", 2, 30, 120, 1 )
|
||||
--
|
||||
function AI_A2A_DISPATCHER:SetSquadronCap( SquadronName, Zone, FloorAltitude, CeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, AltType )
|
||||
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
function AI_A2A_DISPATCHER:SetSquadronCap( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, EngageMinSpeed, EngageMaxSpeed, AltType )
|
||||
|
||||
local Cap = self.DefenderSquadrons[SquadronName].Cap
|
||||
Cap.Name = SquadronName
|
||||
Cap.Zone = Zone
|
||||
Cap.FloorAltitude = FloorAltitude
|
||||
Cap.CeilingAltitude = CeilingAltitude
|
||||
Cap.PatrolMinSpeed = PatrolMinSpeed
|
||||
Cap.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
Cap.EngageMinSpeed = EngageMinSpeed
|
||||
Cap.EngageMaxSpeed = EngageMaxSpeed
|
||||
Cap.AltType = AltType
|
||||
|
||||
self:SetSquadronCapInterval( SquadronName, self.DefenderDefault.CapLimit, self.DefenderDefault.CapMinSeconds, self.DefenderDefault.CapMaxSeconds, 1 )
|
||||
|
||||
self:F( { CAP = { SquadronName, Zone, FloorAltitude, CeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, AltType } } )
|
||||
|
||||
-- Add the CAP to the EWR network.
|
||||
|
||||
local RecceSet = self.Detection:GetDetectionSet()
|
||||
RecceSet:FilterPrefixes( DefenderSquadron.TemplatePrefixes )
|
||||
RecceSet:FilterStart()
|
||||
|
||||
self.Detection:SetFriendlyPrefixes( DefenderSquadron.TemplatePrefixes )
|
||||
|
||||
return self
|
||||
return self:SetSquadronCap2( SquadronName, EngageMinSpeed, EngageMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, AltType, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, AltType )
|
||||
end
|
||||
|
||||
--- Set the squadron CAP parameters.
|
||||
@ -2012,6 +2058,37 @@ do -- AI_A2A_DISPATCHER
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Set squadron GCI.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed The minimum speed [km/h] at which the GCI can be executed.
|
||||
-- @param #number EngageMaxSpeed The maximum speed [km/h] at which the GCI can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @usage
|
||||
--
|
||||
-- -- GCI Squadron execution.
|
||||
-- A2ADispatcher:SetSquadronGci2( "Mozdok", 900, 1200, 5000, 5000, "BARO" )
|
||||
-- A2ADispatcher:SetSquadronGci2( "Novo", 900, 2100, 30, 30, "RADIO" )
|
||||
-- A2ADispatcher:SetSquadronGci2( "Maykop", 900, 1200, 100, 300, "RADIO" )
|
||||
--
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
function AI_A2A_DISPATCHER:SetSquadronGci2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Gci = self.DefenderSquadrons[SquadronName].Gci or {}
|
||||
|
||||
local Intercept = self.DefenderSquadrons[SquadronName].Gci
|
||||
Intercept.Name = SquadronName
|
||||
Intercept.EngageMinSpeed = EngageMinSpeed
|
||||
Intercept.EngageMaxSpeed = EngageMaxSpeed
|
||||
Intercept.EngageFloorAltitude = EngageFloorAltitude
|
||||
Intercept.EngageCeilingAltitude = EngageCeilingAltitude
|
||||
Intercept.EngageAltType = EngageAltType
|
||||
|
||||
self:I( { GCI = { SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
end
|
||||
|
||||
--- Set squadron GCI.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
@ -3080,7 +3157,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
if DefenderCAP then
|
||||
|
||||
local Fsm = AI_A2A_CAP:New( DefenderCAP, Cap.Zone, Cap.FloorAltitude, Cap.CeilingAltitude, Cap.PatrolMinSpeed, Cap.PatrolMaxSpeed, Cap.EngageMinSpeed, Cap.EngageMaxSpeed, Cap.AltType )
|
||||
local Fsm = AI_A2A_CAP:New2( DefenderCAP, Cap.EngageMinSpeed, Cap.EngageMaxSpeed, Cap.EngageFloorAltitude, Cap.EngageCeilingAltitude, Cap.EngageAltType, Cap.Zone, Cap.PatrolMinSpeed, Cap.PatrolMaxSpeed, Cap.PatrolFloorAltitude, Cap.PatrolCeilingAltitude, Cap.PatrolAltType )
|
||||
Fsm:SetDispatcher( self )
|
||||
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||
@ -3101,7 +3178,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self:SetDefenderTask( SquadronName, DefenderCAP, "CAP", Fsm )
|
||||
|
||||
function Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
|
||||
self:F({"CAP Birth", DefenderGroup:GetName()})
|
||||
self:F({"CAP Takeoff", DefenderGroup:GetName()})
|
||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign()
|
||||
@ -3113,7 +3190,7 @@ do -- AI_A2A_DISPATCHER
|
||||
Fsm:__Patrol( 2 ) -- Start Patrolling
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
||||
|
||||
self:F({"CAP RTB", DefenderGroup:GetName()})
|
||||
@ -3169,7 +3246,7 @@ do -- AI_A2A_DISPATCHER
|
||||
for DefenderID, Defender in pairs( Defenders ) do
|
||||
|
||||
local Fsm = self:GetDefenderTaskFsm( Defender )
|
||||
Fsm:__Engage( 1, AttackerDetection.Set ) -- Engage on the TargetSetUnit
|
||||
Fsm:__EngageRoute( 1, AttackerDetection.Set ) -- Engage on the TargetSetUnit
|
||||
|
||||
self:SetDefenderTaskTarget( Defender, AttackerDetection )
|
||||
|
||||
@ -3201,7 +3278,7 @@ do -- AI_A2A_DISPATCHER
|
||||
for DefenderID, DefenderGroup in pairs( DefenderFriendlies or {} ) do
|
||||
|
||||
local Fsm = self:GetDefenderTaskFsm( DefenderGroup )
|
||||
Fsm:__Engage( 1, AttackerSet ) -- Engage on the TargetSetUnit
|
||||
Fsm:__EngageRoute( 1, AttackerSet ) -- Engage on the TargetSetUnit
|
||||
|
||||
self:SetDefenderTaskTarget( DefenderGroup, AttackerDetection )
|
||||
|
||||
@ -3283,7 +3360,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
DefenderCount = DefenderCount - DefenderGrouping / DefenderOverhead
|
||||
|
||||
local Fsm = AI_A2A_GCI:New( DefenderGCI, Gci.EngageMinSpeed, Gci.EngageMaxSpeed )
|
||||
local Fsm = AI_A2A_GCI:New2( DefenderGCI, Gci.EngageMinSpeed, Gci.EngageMaxSpeed, Gci.EngageFloorAltitude, Gci.EngageCeilingAltitude, Gci.EngageAltType )
|
||||
Fsm:SetDispatcher( self )
|
||||
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||
@ -3306,10 +3383,27 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
if DefenderTarget then
|
||||
Dispatcher:MessageToPlayers( DefenderName .. " wheels up.", DefenderGroup )
|
||||
Fsm:__Engage( 2, DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
||||
--Fsm:__Engage( 2, DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
||||
Fsm:EngageRoute( DefenderTarget.Set ) -- Engage on the TargetSetUnit
|
||||
end
|
||||
end
|
||||
|
||||
function Fsm:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
self:F({"GCI Route", DefenderGroup:GetName()})
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign()
|
||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||
|
||||
if Squadron then
|
||||
local FirstUnit = AttackSetUnit:GetFirst()
|
||||
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
||||
|
||||
Dispatcher:MessageToPlayers( DefenderName .. ", intercepting bogeys at " .. Coordinate:ToStringA2A( DefenderGroup ), DefenderGroup )
|
||||
end
|
||||
self:GetParent( Fsm ).onafterEngageRoute( self, DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
end
|
||||
|
||||
function Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
||||
self:F({"GCI RTB", DefenderGroup:GetName()})
|
||||
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
|
||||
|
||||
@ -105,185 +105,39 @@ AI_A2A_GCI = {
|
||||
--- Creates a new AI_A2A_GCI object
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @return #AI_A2A_GCI
|
||||
function AI_A2A_GCI:New( AIIntercept, EngageMinSpeed, EngageMaxSpeed )
|
||||
function AI_A2A_GCI:New2( AIIntercept, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2A:New( AIIntercept ) ) -- #AI_A2A_GCI
|
||||
|
||||
self.Accomplished = false
|
||||
self.Engaging = false
|
||||
local AI_Air = AI_AIR:New( AIIntercept )
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air, AIIntercept, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage ) -- #AI_A2A_GCI
|
||||
|
||||
self.EngageMinSpeed = EngageMinSpeed
|
||||
self.EngageMaxSpeed = EngageMaxSpeed
|
||||
self.PatrolMinSpeed = EngageMinSpeed
|
||||
self.PatrolMaxSpeed = EngageMaxSpeed
|
||||
|
||||
self.PatrolAltType = "RADIO"
|
||||
|
||||
self:AddTransition( { "Started", "Engaging", "Returning", "Airborne" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_GCI.
|
||||
|
||||
--- OnBefore Transition Handler for Event Engage.
|
||||
-- @function [parent=#AI_A2A_GCI] OnBeforeEngage
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Engage.
|
||||
-- @function [parent=#AI_A2A_GCI] OnAfterEngage
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_A2A_GCI] Engage
|
||||
-- @param #AI_A2A_GCI self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_A2A_GCI] __Engage
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
--- OnLeave Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2A_GCI] OnLeaveEngaging
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2A_GCI] OnEnterEngaging
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_GCI.
|
||||
|
||||
--- OnBefore Transition Handler for Event Fired.
|
||||
-- @function [parent=#AI_A2A_GCI] OnBeforeFired
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Fired.
|
||||
-- @function [parent=#AI_A2A_GCI] OnAfterFired
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Fired.
|
||||
-- @function [parent=#AI_A2A_GCI] Fired
|
||||
-- @param #AI_A2A_GCI self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Fired.
|
||||
-- @function [parent=#AI_A2A_GCI] __Fired
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_GCI.
|
||||
|
||||
--- OnBefore Transition Handler for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_GCI] OnBeforeDestroy
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_GCI] OnAfterDestroy
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_GCI] Destroy
|
||||
-- @param #AI_A2A_GCI self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Destroy.
|
||||
-- @function [parent=#AI_A2A_GCI] __Destroy
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
|
||||
self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_GCI.
|
||||
|
||||
--- OnBefore Transition Handler for Event Abort.
|
||||
-- @function [parent=#AI_A2A_GCI] OnBeforeAbort
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Abort.
|
||||
-- @function [parent=#AI_A2A_GCI] OnAfterAbort
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Abort.
|
||||
-- @function [parent=#AI_A2A_GCI] Abort
|
||||
-- @param #AI_A2A_GCI self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Abort.
|
||||
-- @function [parent=#AI_A2A_GCI] __Abort
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2A_GCI.
|
||||
|
||||
--- OnBefore Transition Handler for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_GCI] OnBeforeAccomplish
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_GCI] OnAfterAccomplish
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_GCI] Accomplish
|
||||
-- @param #AI_A2A_GCI self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Accomplish.
|
||||
-- @function [parent=#AI_A2A_GCI] __Accomplish
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( { "Patrolling", "Engaging" }, "Refuel", "Refuelling" )
|
||||
self:SetFuelThreshold( .2, 60 )
|
||||
self:SetDamageThreshold( 0.4 )
|
||||
self:SetDisengageRadius( 70000 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a new AI_A2A_GCI object
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @return #AI_A2A_GCI
|
||||
function AI_A2A_GCI:New( AIIntercept, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
return self:New2( AIIntercept, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
end
|
||||
|
||||
--- onafter State Transition for Event Patrol.
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The AI Group managed by the FSM.
|
||||
@ -292,173 +146,33 @@ end
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onafterStart( AIIntercept, From, Event, To )
|
||||
|
||||
self:GetParent( self ).onafterStart( self, AIIntercept, From, Event, To )
|
||||
AIIntercept:HandleEvent( EVENTS.Takeoff, nil, self )
|
||||
|
||||
self:GetParent( self, AI_A2A_GCI ).onafterStart( self, AIIntercept, From, Event, To )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- onafter State Transition for Event Patrol.
|
||||
--- Evaluate the attack and create an AttackUnitTask list.
|
||||
-- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onafterEngage( AIIntercept, From, Event, To )
|
||||
-- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack.
|
||||
-- @param Wrappper.Group#GROUP DefenderGroup The group of defenders.
|
||||
-- @param #number EngageAltitude The altitude to engage the targets.
|
||||
-- @return #AI_A2A_GCI self
|
||||
function AI_A2A_GCI:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude )
|
||||
|
||||
self:HandleEvent( EVENTS.Dead )
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
end
|
||||
|
||||
-- todo: need to fix this global function
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIControllable
|
||||
function AI_A2A_GCI.InterceptRoute( AIIntercept, Fsm )
|
||||
|
||||
AIIntercept:F( { "AI_A2A_GCI.InterceptRoute:", AIIntercept:GetName() } )
|
||||
|
||||
if AIIntercept:IsAlive() then
|
||||
Fsm:__Engage( 0.5 )
|
||||
|
||||
--local Task = AIIntercept:TaskOrbitCircle( 4000, 400 )
|
||||
--AIIntercept:SetTask( Task )
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onbeforeEngage( AIIntercept, From, Event, To )
|
||||
|
||||
if self.Accomplished == true then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onafterAbort( AIIntercept, From, Event, To )
|
||||
AIIntercept:ClearTasks()
|
||||
self:Return()
|
||||
self:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The GroupGroup managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onafterEngage( AIIntercept, From, Event, To, AttackSetUnit )
|
||||
|
||||
self:F( { AIIntercept, From, Event, To, AttackSetUnit} )
|
||||
|
||||
self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT
|
||||
|
||||
local FirstAttackUnit = self.AttackSetUnit:GetFirst()
|
||||
|
||||
if FirstAttackUnit and FirstAttackUnit:IsAlive() then
|
||||
|
||||
if AIIntercept:IsAlive() then
|
||||
|
||||
local EngageRoute = {}
|
||||
|
||||
local CurrentCoord = AIIntercept:GetCoordinate()
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
local CurrentCoord = AIIntercept:GetCoordinate()
|
||||
|
||||
local ToTargetCoord = self.AttackSetUnit:GetFirst():GetCoordinate()
|
||||
self:SetTargetDistance( ToTargetCoord ) -- For RTB status check
|
||||
|
||||
local ToTargetSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||
local ToInterceptAngle = CurrentCoord:GetAngleDegrees( CurrentCoord:GetDirectionVec3( ToTargetCoord ) )
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToPatrolRoutePoint = CurrentCoord:Translate( 15000, ToInterceptAngle ):WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
self:F( { Angle = ToInterceptAngle, ToTargetSpeed = ToTargetSpeed } )
|
||||
self:F( { self.EngageMinSpeed, self.EngageMaxSpeed, ToTargetSpeed } )
|
||||
|
||||
EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
|
||||
EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
|
||||
|
||||
local AttackTasks = {}
|
||||
|
||||
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
|
||||
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
|
||||
self:T( { "Intercepting Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
||||
AttackTasks[#AttackTasks+1] = AIIntercept:TaskAttackUnit( AttackUnit )
|
||||
end
|
||||
end
|
||||
|
||||
if #AttackTasks == 0 then
|
||||
self:E("No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( 0.5 )
|
||||
else
|
||||
AIIntercept:OptionROEOpenFire()
|
||||
AIIntercept:OptionROTEvadeFire()
|
||||
|
||||
AttackTasks[#AttackTasks+1] = AIIntercept:TaskFunction( "AI_A2A_GCI.InterceptRoute", self )
|
||||
EngageRoute[#EngageRoute].task = AIIntercept:TaskCombo( AttackTasks )
|
||||
end
|
||||
|
||||
AIIntercept:Route( EngageRoute, 0.5 )
|
||||
|
||||
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
|
||||
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
|
||||
self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
|
||||
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
|
||||
-- Maybe the detected set also contains
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit )
|
||||
end
|
||||
else
|
||||
self:E("No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
return AttackUnitTasks
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2A_GCI:onafterAccomplish( AIIntercept, From, Event, To )
|
||||
self.Accomplished = true
|
||||
self:SetDetectionOff()
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_GCI self
|
||||
-- @param Wrapper.Group#GROUP AIIntercept The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_GCI:onafterDestroy( AIIntercept, From, Event, To, EventData )
|
||||
|
||||
if EventData.IniUnit then
|
||||
self.AttackUnits[EventData.IniUnit] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_GCI self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_GCI:OnEventDead( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
if EventData.IniDCSUnit then
|
||||
if self.AttackUnits and self.AttackUnits[EventData.IniUnit] then
|
||||
self:__Destroy( 1, EventData )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@ -136,8 +136,14 @@ AI_A2A_PATROL = {
|
||||
-- PatrolArea = AI_A2A_PATROL:New( PatrolZone, 3000, 6000, 600, 900 )
|
||||
function AI_A2A_PATROL:New( AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2A:New( AIPatrol ) ) -- #AI_A2A_PATROL
|
||||
local AI_Air = AI_AIR:New( AIPatrol )
|
||||
local AI_Air_Patrol = AI_A2A_PATROL:New( AI_Air, AIPatrol, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Patrol ) -- #AI_A2A_PATROL
|
||||
|
||||
self:SetFuelThreshold( .2, 60 )
|
||||
self:SetDamageThreshold( 0.4 )
|
||||
self:SetDisengageRadius( 70000 )
|
||||
|
||||
|
||||
self.PatrolZone = PatrolZone
|
||||
self.PatrolFloorAltitude = PatrolFloorAltitude
|
||||
@ -257,35 +263,6 @@ function AI_A2A_PATROL:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude )
|
||||
self.PatrolCeilingAltitude = PatrolCeilingAltitude
|
||||
end
|
||||
|
||||
--- Set race track parameters. CAP flights will perform race track patterns rather than randomly patrolling the zone.
|
||||
-- @param #AI_A2A_PATROL self
|
||||
-- @param #number LegMin Min Length of the race track leg in meters. Default 10,000 m.
|
||||
-- @param #number LegMax Max length of the race track leg in meters. Default 15,000 m.
|
||||
-- @param #number HeadingMin Min heading of the race track in degrees. Default 0 deg, i.e. from South to North.
|
||||
-- @param #number HeadingMax Max heading of the race track in degrees. Default 180 deg, i.e. from South to North.
|
||||
-- @param #number DurationMin (Optional) Min duration before switching the orbit position. Default is keep same orbit until RTB or engage.
|
||||
-- @param #number DurationMax (Optional) Max duration before switching the orbit position. Default is keep same orbit until RTB or engage.
|
||||
-- @param #table CapCoordinates Table of coordinates of first race track point. Second point is determined by leg length and heading.
|
||||
-- @return #AI_A2A_PATROL self
|
||||
function AI_A2A_PATROL:SetRaceTrackPattern(LegMin, LegMax, HeadingMin, HeadingMax, DurationMin, DurationMax, CapCoordinates)
|
||||
self:F2({leglength, duration})
|
||||
|
||||
self.racetrack=true
|
||||
self.racetracklegmin=LegMin or 10000
|
||||
self.racetracklegmax=LegMax or 15000
|
||||
self.racetrackheadingmin=HeadingMin or 0
|
||||
self.racetrackheadingmax=HeadingMax or 180
|
||||
self.racetrackdurationmin=DurationMin
|
||||
self.racetrackdurationmax=DurationMax
|
||||
|
||||
if self.racetrackdurationmax and not self.racetrackdurationmin then
|
||||
self.racetrackdurationmin=self.racetrackdurationmax
|
||||
end
|
||||
|
||||
self.racetrackcapcoordinates=CapCoordinates
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings.
|
||||
-- @param #AI_A2A_PATROL self
|
||||
@ -426,13 +403,3 @@ function AI_A2A_PATROL:onafterRoute( AIPatrol, From, Event, To )
|
||||
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIPatrol
|
||||
function AI_A2A_PATROL.Resume( AIPatrol, Fsm )
|
||||
|
||||
AIPatrol:I( { "AI_A2A_PATROL.Resume:", AIPatrol:GetName() } )
|
||||
if AIPatrol:IsAlive() then
|
||||
Fsm:__Reset( 1 )
|
||||
Fsm:__Route( 5 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@ -1,69 +0,0 @@
|
||||
--- **AI** -- Models the process of air to ground operations for airplanes and helicopters.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- ### Author: **FlightControl**
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI.AI_A2G
|
||||
-- @image AI_Air_To_Ground_Dispatching.JPG
|
||||
|
||||
--- @type AI_A2G
|
||||
-- @extends AI.AI_Air#AI_AIR
|
||||
|
||||
--- The AI_A2G class implements the core functions to operate an AI @{Wrapper.Group} A2G tasking.
|
||||
--
|
||||
--
|
||||
-- # 1) AI_A2G constructor
|
||||
--
|
||||
-- * @{#AI_A2G.New}(): Creates a new AI_A2G object.
|
||||
--
|
||||
-- # 2) AI_A2G is a Finite State Machine.
|
||||
--
|
||||
-- This section must be read as follows. Each of the rows indicate a state transition, triggered through an event, and with an ending state of the event was executed.
|
||||
-- The first column is the **From** state, the second column the **Event**, and the third column the **To** state.
|
||||
--
|
||||
-- So, each of the rows have the following structure.
|
||||
--
|
||||
-- * **From** => **Event** => **To**
|
||||
--
|
||||
-- Important to know is that an event can only be executed if the **current state** is the **From** state.
|
||||
-- This, when an **Event** that is being triggered has a **From** state that is equal to the **Current** state of the state machine, the event will be executed,
|
||||
-- and the resulting state will be the **To** state.
|
||||
--
|
||||
-- These are the different possible state transitions of this state machine implementation:
|
||||
--
|
||||
-- * Idle => Start => Monitoring
|
||||
--
|
||||
-- ## 2.1) AI_A2G States.
|
||||
--
|
||||
-- * **Idle**: The process is idle.
|
||||
--
|
||||
-- ## 2.2) AI_A2G Events.
|
||||
--
|
||||
-- * **Start**: Start the transport process.
|
||||
-- * **Stop**: Stop the transport process.
|
||||
-- * **Monitor**: Monitor and take action.
|
||||
--
|
||||
-- @field #AI_A2G
|
||||
AI_A2G = {
|
||||
ClassName = "AI_A2G",
|
||||
}
|
||||
|
||||
--- Creates a new AI_A2G process.
|
||||
-- @param #AI_A2G self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The group object to receive the A2G Process.
|
||||
-- @return #AI_A2G
|
||||
function AI_A2G:New( AIGroup )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_AIR:New( AIGroup ) ) -- #AI_A2G
|
||||
|
||||
self:SetFuelThreshold( .2, 60 )
|
||||
self:SetDamageThreshold( 0.95 )
|
||||
self:SetDisengageRadius( 70000 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -35,6 +35,7 @@ AI_A2G_BAI = {
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
@ -42,10 +43,12 @@ AI_A2G_BAI = {
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2G_BAI
|
||||
function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
function AI_A2G_BAI:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_BAI
|
||||
local AI_Air = AI_AIR:New( AIGroup )
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||
|
||||
local RTBSpeedMax = AIGroup:GetSpeedMax() or 9999
|
||||
|
||||
@ -55,112 +58,46 @@ function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAlt
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2G_BAI self
|
||||
-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_BAI:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
--- Creates a new AI_A2G_BAI object
|
||||
-- @param #AI_A2G_BAI self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2G_BAI
|
||||
function AI_A2G_BAI:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
self:I( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
||||
|
||||
local DefenderGroupName = DefenderGroup:GetName()
|
||||
|
||||
local AttackCount = AttackSetUnit:Count()
|
||||
|
||||
self.AttackSetUnit = AttackSetUnit -- Kept in memory in case of resume from refuel in air!
|
||||
|
||||
if AttackCount > 0 then
|
||||
|
||||
if DefenderGroup:IsAlive() then
|
||||
|
||||
local EngageAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
|
||||
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||
|
||||
-- Determine the distance to the target.
|
||||
-- If it is less than 10km, then attack without a route.
|
||||
-- Otherwise perform a route attack.
|
||||
|
||||
local DefenderCoord = DefenderGroup:GetPointVec3()
|
||||
DefenderCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetCoord = AttackSetUnit:GetFirst():GetPointVec3()
|
||||
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
||||
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
||||
|
||||
local EngageRoute = {}
|
||||
local AttackTasks = {}
|
||||
|
||||
--- Calculate the target route point.
|
||||
|
||||
local FromWP = DefenderCoord:WaypointAir(
|
||||
self.PatrolAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
EngageRoute[#EngageRoute+1] = FromWP
|
||||
|
||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||
|
||||
local FromEngageAngle = TargetCoord:GetAngleDegrees( TargetCoord:GetDirectionVec3( DefenderCoord ) )
|
||||
local ToWP = TargetCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir(
|
||||
self.PatrolAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
local AttackSetUnitPerThreatLevel = AttackSetUnit:GetSetPerThreatLevel( 10, 0 )
|
||||
for AttackUnitIndex, AttackUnit in ipairs( AttackSetUnitPerThreatLevel or {} ) do
|
||||
if AttackUnit then
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsGround() then
|
||||
self:T( { "BAI Unit:", AttackUnit:GetName() } )
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit, true, false, nil, nil, EngageAltitude )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #AttackUnitTasks == 0 then
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
else
|
||||
DefenderGroup:OptionROEOpenFire()
|
||||
DefenderGroup:OptionROTEvadeFire()
|
||||
DefenderGroup:OptionKeepWeaponsOnThreat()
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskCombo( AttackUnitTasks )
|
||||
end
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.___Engage", self, AttackSetUnit )
|
||||
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
||||
|
||||
DefenderGroup:Route( EngageRoute, self.TaskDelay )
|
||||
end
|
||||
else
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
end
|
||||
return self:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType)
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIEngage
|
||||
function AI_A2G_BAI.Resume( AIEngage, Fsm )
|
||||
--- Evaluate the attack and create an AttackUnitTask list.
|
||||
-- @param #AI_A2G_BAI self
|
||||
-- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack.
|
||||
-- @param Wrappper.Group#GROUP DefenderGroup The group of defenders.
|
||||
-- @param #number EngageAltitude The altitude to engage the targets.
|
||||
-- @return #AI_A2G_BAI self
|
||||
function AI_A2G_BAI:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude )
|
||||
|
||||
AIEngage:F( { "AI_A2G_BAI.Resume:", AIEngage:GetName() } )
|
||||
if AIEngage:IsAlive() then
|
||||
Fsm:__Reset( Fsm.TaskDelay )
|
||||
Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit )
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
local AttackSetUnitPerThreatLevel = AttackSetUnit:GetSetPerThreatLevel( 10, 0 )
|
||||
for AttackUnitIndex, AttackUnit in ipairs( AttackSetUnitPerThreatLevel or {} ) do
|
||||
if AttackUnit then
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsGround() then
|
||||
self:T( { "BAI Unit:", AttackUnit:GetName() } )
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit, true, false, nil, nil, EngageAltitude )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return AttackUnitTasks
|
||||
end
|
||||
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
--- @type AI_A2G_CAS
|
||||
-- @extends AI.AI_A2G_Patrol#AI_A2G_PATROL
|
||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL
|
||||
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
@ -35,6 +35,7 @@ AI_A2G_CAS = {
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
@ -42,10 +43,12 @@ AI_A2G_CAS = {
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2G_CAS
|
||||
function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
function AI_A2G_CAS:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_CAS
|
||||
local AI_Air = AI_AIR:New( AIGroup )
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||
|
||||
local RTBSpeedMax = AIGroup:GetSpeedMax() or 9999
|
||||
|
||||
@ -55,108 +58,47 @@ function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAlt
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2G_CAS self
|
||||
-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_CAS:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
--- Creates a new AI_A2G_CAS object
|
||||
-- @param #AI_A2G_CAS self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2G_CAS
|
||||
function AI_A2G_CAS:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
||||
|
||||
local DefenderGroupName = DefenderGroup:GetName()
|
||||
|
||||
self.AttackSetUnit = AttackSetUnit -- Kept in memory in case of resume from refuel in air!
|
||||
|
||||
local AttackCount = AttackSetUnit:Count()
|
||||
|
||||
if AttackCount > 0 then
|
||||
|
||||
if DefenderGroup:IsAlive() then
|
||||
|
||||
local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 )
|
||||
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||
|
||||
local DefenderCoord = DefenderGroup:GetPointVec3()
|
||||
DefenderCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetCoord = AttackSetUnit:GetFirst():GetPointVec3()
|
||||
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
||||
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
||||
|
||||
local EngageRoute = {}
|
||||
local AttackTasks = {}
|
||||
|
||||
local FromWP = DefenderCoord:WaypointAir(
|
||||
self.PatrolAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
EngageRoute[#EngageRoute+1] = FromWP
|
||||
|
||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||
|
||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir(
|
||||
self.PatrolAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
if TargetDistance <= EngageDistance * 3 then
|
||||
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
local AttackSetUnitPerThreatLevel = AttackSetUnit:GetSetPerThreatLevel( 10, 0 )
|
||||
for AttackUnitIndex, AttackUnit in ipairs( AttackSetUnitPerThreatLevel or {} ) do
|
||||
if AttackUnit then
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsGround() then
|
||||
self:T( { "CAS Unit:", AttackUnit:GetName() } )
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit, true, false, nil, nil, EngageAltitude )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
if #AttackUnitTasks == 0 then
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
else
|
||||
DefenderGroup:OptionROEOpenFire()
|
||||
DefenderGroup:OptionROTEvadeFire()
|
||||
DefenderGroup:OptionKeepWeaponsOnThreat()
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskCombo( AttackUnitTasks )
|
||||
end
|
||||
end
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.___Engage", self, AttackSetUnit )
|
||||
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
||||
|
||||
DefenderGroup:Route( EngageRoute, self.TaskDelay )
|
||||
end
|
||||
else
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
end
|
||||
return self:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType)
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIEngage
|
||||
function AI_A2G_CAS.Resume( AIEngage, Fsm )
|
||||
--- Evaluate the attack and create an AttackUnitTask list.
|
||||
-- @param #AI_A2G_CAS self
|
||||
-- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack.
|
||||
-- @param Wrappper.Group#GROUP DefenderGroup The group of defenders.
|
||||
-- @param #number EngageAltitude The altitude to engage the targets.
|
||||
-- @return #AI_A2G_CAS self
|
||||
function AI_A2G_CAS:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude )
|
||||
|
||||
AIEngage:F( { "AI_A2G_CAS.Resume:", AIEngage:GetName() } )
|
||||
if AIEngage:IsAlive() then
|
||||
Fsm:__Reset( Fsm.TaskDelay )
|
||||
Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit )
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
local AttackSetUnitPerThreatLevel = AttackSetUnit:GetSetPerThreatLevel( 10, 0 )
|
||||
for AttackUnitIndex, AttackUnit in ipairs( AttackSetUnitPerThreatLevel or {} ) do
|
||||
if AttackUnit then
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsGround() then
|
||||
self:T( { "CAS Unit:", AttackUnit:GetName() } )
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit, true, false, nil, nil, EngageAltitude )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return AttackUnitTasks
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@ -2088,22 +2088,23 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
|
||||
|
||||
---
|
||||
--- Set a squadron to engage for suppression of air defenses, when a defense point is under attack.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the SEAD task can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the SEAD task can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @param #number EngageAltType The altitude type when engaging, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @usage
|
||||
--
|
||||
-- -- SEAD Squadron execution.
|
||||
-- A2GDispatcher:SetSquadronSead( "Mozdok", 900, 1200 )
|
||||
-- A2GDispatcher:SetSquadronSead( "Novo", 900, 2100 )
|
||||
-- A2GDispatcher:SetSquadronSead( "Maykop", 900, 1200 )
|
||||
-- A2GDispatcher:SetSquadronSead( "Mozdok", 900, 1200, 4000, 5000, "BARO" )
|
||||
-- A2GDispatcher:SetSquadronSead( "Novo", 900, 2100, 6000, 9000, "BARO" )
|
||||
-- A2GDispatcher:SetSquadronSead( "Maykop", 900, 1200, 30, 100, "RADIO" )
|
||||
--
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
function AI_A2G_DISPATCHER:SetSquadronSead( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
function AI_A2G_DISPATCHER:SetSquadronSead2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
@ -2115,9 +2116,32 @@ do -- AI_A2G_DISPATCHER
|
||||
Sead.EngageMaxSpeed = EngageMaxSpeed
|
||||
Sead.EngageFloorAltitude = EngageFloorAltitude or 500
|
||||
Sead.EngageCeilingAltitude = EngageCeilingAltitude or 1000
|
||||
Sead.EngageAltType = EngageAltType
|
||||
Sead.Defend = true
|
||||
|
||||
self:F( { Sead = Sead } )
|
||||
self:I( { SEAD = { SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set a squadron to engage for suppression of air defenses, when a defense point is under attack.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the SEAD task can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the SEAD task can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @usage
|
||||
--
|
||||
-- -- SEAD Squadron execution.
|
||||
-- A2GDispatcher:SetSquadronSead( "Mozdok", 900, 1200, 4000, 5000 )
|
||||
-- A2GDispatcher:SetSquadronSead( "Novo", 900, 2100, 6000, 8000 )
|
||||
-- A2GDispatcher:SetSquadronSead( "Maykop", 900, 1200, 6000, 10000 )
|
||||
--
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
function AI_A2G_DISPATCHER:SetSquadronSead( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
|
||||
return self:SetSquadronSead2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, "RADIO" )
|
||||
end
|
||||
|
||||
--- Set the squadron SEAD engage limit.
|
||||
@ -2140,6 +2164,55 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
|
||||
|
||||
--- Set a Sead patrol for a Squadron.
|
||||
-- The Sead patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed.
|
||||
-- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed.
|
||||
-- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed.
|
||||
-- @param #number PatrolFloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolCeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolAltType The altitude type when patrolling, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the engage can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the engage can be executed.
|
||||
-- @param #number EngageFloorAltitude (optional, default = 1000m ) The minimum altitude at which the engage can be executed.
|
||||
-- @param #number EngageCeilingAltitude (optional, default = 1500m ) The maximum altitude at which the engage can be executed.
|
||||
-- @param #number EngageAltType The altitude type when engaging, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Sead Patrol Squadron execution.
|
||||
-- PatrolZoneEast = ZONE_POLYGON:New( "Patrol Zone East", GROUP:FindByName( "Patrol Zone East" ) )
|
||||
-- A2GDispatcher:SetSquadronSeadPatrol2( "Mineralnye", PatrolZoneEast, 500, 600, 4000, 10000, "BARO", 800, 900, 2000, 3000, "RADIO", )
|
||||
--
|
||||
function AI_A2G_DISPATCHER:SetSquadronSeadPatrol2( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.SEAD = DefenderSquadron.SEAD or {}
|
||||
|
||||
local SeadPatrol = DefenderSquadron.SEAD
|
||||
SeadPatrol.Name = SquadronName
|
||||
SeadPatrol.Zone = Zone
|
||||
SeadPatrol.PatrolFloorAltitude = PatrolFloorAltitude
|
||||
SeadPatrol.PatrolCeilingAltitude = PatrolCeilingAltitude
|
||||
SeadPatrol.EngageFloorAltitude = EngageFloorAltitude
|
||||
SeadPatrol.EngageCeilingAltitude = EngageCeilingAltitude
|
||||
SeadPatrol.PatrolMinSpeed = PatrolMinSpeed
|
||||
SeadPatrol.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
SeadPatrol.EngageMinSpeed = EngageMinSpeed
|
||||
SeadPatrol.EngageMaxSpeed = EngageMaxSpeed
|
||||
SeadPatrol.PatrolAltType = PatrolAltType
|
||||
SeadPatrol.EngageAltType = EngageAltType
|
||||
SeadPatrol.Patrol = true
|
||||
|
||||
self:SetSquadronPatrolInterval( SquadronName, self.DefenderDefault.PatrolLimit, self.DefenderDefault.PatrolMinSeconds, self.DefenderDefault.PatrolMaxSeconds, 1, "SEAD" )
|
||||
|
||||
self:I( { SEAD = { Zone:GetName(), PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
end
|
||||
|
||||
|
||||
--- Set a Sead patrol for a Squadron.
|
||||
-- The Sead patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
@ -2160,47 +2233,29 @@ do -- AI_A2G_DISPATCHER
|
||||
-- A2GDispatcher:SetSquadronSeadPatrol( "Mineralnye", PatrolZoneEast, 4000, 10000, 500, 600, 800, 900 )
|
||||
--
|
||||
function AI_A2G_DISPATCHER:SetSquadronSeadPatrol( SquadronName, Zone, FloorAltitude, CeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, AltType )
|
||||
|
||||
self:SetSquadronSeadPatrol2( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, FloorAltitude, CeilingAltitude, AltType, EngageMinSpeed, EngageMaxSpeed, FloorAltitude, CeilingAltitude, AltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.SEAD = DefenderSquadron.SEAD or {}
|
||||
|
||||
local SeadPatrol = DefenderSquadron.SEAD
|
||||
SeadPatrol.Name = SquadronName
|
||||
SeadPatrol.Zone = Zone
|
||||
SeadPatrol.PatrolFloorAltitude = FloorAltitude
|
||||
SeadPatrol.PatrolCeilingAltitude = CeilingAltitude
|
||||
SeadPatrol.EngageFloorAltitude = FloorAltitude
|
||||
SeadPatrol.EngageCeilingAltitude = CeilingAltitude
|
||||
SeadPatrol.PatrolMinSpeed = PatrolMinSpeed
|
||||
SeadPatrol.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
SeadPatrol.EngageMinSpeed = EngageMinSpeed
|
||||
SeadPatrol.EngageMaxSpeed = EngageMaxSpeed
|
||||
SeadPatrol.AltType = AltType
|
||||
SeadPatrol.Patrol = true
|
||||
|
||||
self:SetSquadronPatrolInterval( SquadronName, self.DefenderDefault.PatrolLimit, self.DefenderDefault.PatrolMinSeconds, self.DefenderDefault.PatrolMaxSeconds, 1, "SEAD" )
|
||||
|
||||
self:F( { Sead = SeadPatrol } )
|
||||
end
|
||||
|
||||
|
||||
|
||||
---
|
||||
--- Set a squadron to engage for close air support, when a defense point is under attack.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the CAS task can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the CAS task can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @param #number EngageAltType The altitude type when engaging, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @usage
|
||||
--
|
||||
-- -- CAS Squadron execution.
|
||||
-- A2GDispatcher:SetSquadronCas( "Mozdok", 900, 1200 )
|
||||
-- A2GDispatcher:SetSquadronCas( "Novo", 900, 2100 )
|
||||
-- A2GDispatcher:SetSquadronCas( "Maykop", 900, 1200 )
|
||||
-- A2GDispatcher:SetSquadronCas( "Mozdok", 900, 1200, 4000, 5000, "BARO" )
|
||||
-- A2GDispatcher:SetSquadronCas( "Novo", 900, 2100, 6000, 9000, "BARO" )
|
||||
-- A2GDispatcher:SetSquadronCas( "Maykop", 900, 1200, 30, 100, "RADIO" )
|
||||
--
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
function AI_A2G_DISPATCHER:SetSquadronCas( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
function AI_A2G_DISPATCHER:SetSquadronCas2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
@ -2212,9 +2267,32 @@ do -- AI_A2G_DISPATCHER
|
||||
Cas.EngageMaxSpeed = EngageMaxSpeed
|
||||
Cas.EngageFloorAltitude = EngageFloorAltitude or 500
|
||||
Cas.EngageCeilingAltitude = EngageCeilingAltitude or 1000
|
||||
Cas.EngageAltType = EngageAltType
|
||||
Cas.Defend = true
|
||||
|
||||
self:F( { Cas = Cas } )
|
||||
self:I( { CAS = { SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set a squadron to engage for close air support, when a defense point is under attack.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the CAS task can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the CAS task can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @usage
|
||||
--
|
||||
-- -- CAS Squadron execution.
|
||||
-- A2GDispatcher:SetSquadronCas( "Mozdok", 900, 1200, 4000, 5000 )
|
||||
-- A2GDispatcher:SetSquadronCas( "Novo", 900, 2100, 6000, 8000 )
|
||||
-- A2GDispatcher:SetSquadronCas( "Maykop", 900, 1200, 6000, 10000 )
|
||||
--
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
function AI_A2G_DISPATCHER:SetSquadronCas( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
|
||||
return self:SetSquadronCas2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, "RADIO" )
|
||||
end
|
||||
|
||||
|
||||
@ -2236,6 +2314,53 @@ do -- AI_A2G_DISPATCHER
|
||||
end
|
||||
|
||||
|
||||
--- Set a Cas patrol for a Squadron.
|
||||
-- The Cas patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed.
|
||||
-- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed.
|
||||
-- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed.
|
||||
-- @param #number PatrolFloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolCeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolAltType The altitude type when patrolling, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the engage can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the engage can be executed.
|
||||
-- @param #number EngageFloorAltitude (optional, default = 1000m ) The minimum altitude at which the engage can be executed.
|
||||
-- @param #number EngageCeilingAltitude (optional, default = 1500m ) The maximum altitude at which the engage can be executed.
|
||||
-- @param #number EngageAltType The altitude type when engaging, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Cas Patrol Squadron execution.
|
||||
-- PatrolZoneEast = ZONE_POLYGON:New( "Patrol Zone East", GROUP:FindByName( "Patrol Zone East" ) )
|
||||
-- A2GDispatcher:SetSquadronCasPatrol2( "Mineralnye", PatrolZoneEast, 500, 600, 4000, 10000, "BARO", 800, 900, 2000, 3000, "RADIO", )
|
||||
--
|
||||
function AI_A2G_DISPATCHER:SetSquadronCasPatrol2( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.CAS = DefenderSquadron.CAS or {}
|
||||
|
||||
local CasPatrol = DefenderSquadron.CAS
|
||||
CasPatrol.Name = SquadronName
|
||||
CasPatrol.Zone = Zone
|
||||
CasPatrol.PatrolFloorAltitude = PatrolFloorAltitude
|
||||
CasPatrol.PatrolCeilingAltitude = PatrolCeilingAltitude
|
||||
CasPatrol.EngageFloorAltitude = EngageFloorAltitude
|
||||
CasPatrol.EngageCeilingAltitude = EngageCeilingAltitude
|
||||
CasPatrol.PatrolMinSpeed = PatrolMinSpeed
|
||||
CasPatrol.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
CasPatrol.EngageMinSpeed = EngageMinSpeed
|
||||
CasPatrol.EngageMaxSpeed = EngageMaxSpeed
|
||||
CasPatrol.PatrolAltType = PatrolAltType
|
||||
CasPatrol.EngageAltType = EngageAltType
|
||||
CasPatrol.Patrol = true
|
||||
|
||||
self:SetSquadronPatrolInterval( SquadronName, self.DefenderDefault.PatrolLimit, self.DefenderDefault.PatrolMinSeconds, self.DefenderDefault.PatrolMaxSeconds, 1, "CAS" )
|
||||
|
||||
self:I( { CAS = { Zone:GetName(), PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
end
|
||||
|
||||
|
||||
--- Set a Cas patrol for a Squadron.
|
||||
@ -2258,47 +2383,28 @@ do -- AI_A2G_DISPATCHER
|
||||
-- A2GDispatcher:SetSquadronCasPatrol( "Mineralnye", PatrolZoneEast, 4000, 10000, 500, 600, 800, 900 )
|
||||
--
|
||||
function AI_A2G_DISPATCHER:SetSquadronCasPatrol( SquadronName, Zone, FloorAltitude, CeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, AltType )
|
||||
|
||||
self:SetSquadronCasPatrol2( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, FloorAltitude, CeilingAltitude, AltType, EngageMinSpeed, EngageMaxSpeed, FloorAltitude, CeilingAltitude, AltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.CAS = DefenderSquadron.CAS or {}
|
||||
|
||||
local CasPatrol = DefenderSquadron.CAS
|
||||
CasPatrol.Name = SquadronName
|
||||
CasPatrol.Zone = Zone
|
||||
CasPatrol.PatrolFloorAltitude = FloorAltitude
|
||||
CasPatrol.PatrolCeilingAltitude = CeilingAltitude
|
||||
CasPatrol.EngageFloorAltitude = FloorAltitude
|
||||
CasPatrol.EngageCeilingAltitude = CeilingAltitude
|
||||
CasPatrol.PatrolMinSpeed = PatrolMinSpeed
|
||||
CasPatrol.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
CasPatrol.EngageMinSpeed = EngageMinSpeed
|
||||
CasPatrol.EngageMaxSpeed = EngageMaxSpeed
|
||||
CasPatrol.AltType = AltType
|
||||
CasPatrol.Patrol = true
|
||||
|
||||
self:SetSquadronPatrolInterval( SquadronName, self.DefenderDefault.PatrolLimit, self.DefenderDefault.PatrolMinSeconds, self.DefenderDefault.PatrolMaxSeconds, 1, "CAS" )
|
||||
|
||||
self:F( { Cas = CasPatrol } )
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
--- Set a squadron to engage for a battlefield area interdiction, when a defense point is under attack.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the BAI task can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the BAI task can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @param #number EngageAltType The altitude type when engaging, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @usage
|
||||
--
|
||||
-- -- BAI Squadron execution.
|
||||
-- A2GDispatcher:SetSquadronBai( "Mozdok", 900, 1200 )
|
||||
-- A2GDispatcher:SetSquadronBai( "Novo", 900, 2100 )
|
||||
-- A2GDispatcher:SetSquadronBai( "Maykop", 900, 1200 )
|
||||
-- A2GDispatcher:SetSquadronBai( "Mozdok", 900, 1200, 4000, 5000, "BARO" )
|
||||
-- A2GDispatcher:SetSquadronBai( "Novo", 900, 2100, 6000, 9000, "BARO" )
|
||||
-- A2GDispatcher:SetSquadronBai( "Maykop", 900, 1200, 30, 100, "RADIO" )
|
||||
--
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
function AI_A2G_DISPATCHER:SetSquadronBai( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
function AI_A2G_DISPATCHER:SetSquadronBai2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
@ -2310,9 +2416,32 @@ do -- AI_A2G_DISPATCHER
|
||||
Bai.EngageMaxSpeed = EngageMaxSpeed
|
||||
Bai.EngageFloorAltitude = EngageFloorAltitude or 500
|
||||
Bai.EngageCeilingAltitude = EngageCeilingAltitude or 1000
|
||||
Bai.EngageAltType = EngageAltType
|
||||
Bai.Defend = true
|
||||
|
||||
self:F( { Bai = Bai } )
|
||||
self:I( { BAI = { SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set a squadron to engage for a battlefield area interdiction, when a defense point is under attack.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the BAI task can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the BAI task can be executed.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @usage
|
||||
--
|
||||
-- -- BAI Squadron execution.
|
||||
-- A2GDispatcher:SetSquadronBai( "Mozdok", 900, 1200, 4000, 5000 )
|
||||
-- A2GDispatcher:SetSquadronBai( "Novo", 900, 2100, 6000, 8000 )
|
||||
-- A2GDispatcher:SetSquadronBai( "Maykop", 900, 1200, 6000, 10000 )
|
||||
--
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
function AI_A2G_DISPATCHER:SetSquadronBai( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
|
||||
return self:SetSquadronBai2( SquadronName, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, "RADIO" )
|
||||
end
|
||||
|
||||
|
||||
@ -2333,6 +2462,54 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
end
|
||||
|
||||
|
||||
--- Set a Bai patrol for a Squadron.
|
||||
-- The Bai patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded.
|
||||
-- @param #AI_A2G_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @param Core.Zone#ZONE_BASE Zone The @{Zone} object derived from @{Core.Zone#ZONE_BASE} that defines the zone wherein the Patrol will be executed.
|
||||
-- @param #number PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed at which the cap can be executed.
|
||||
-- @param #number PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the cap can be executed.
|
||||
-- @param #number PatrolFloorAltitude (optional, default = 1000m ) The minimum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolCeilingAltitude (optional, default = 1500m ) The maximum altitude at which the cap can be executed.
|
||||
-- @param #number PatrolAltType The altitude type when patrolling, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @param #number EngageMinSpeed (optional, default = 50% of max speed) The minimum speed at which the engage can be executed.
|
||||
-- @param #number EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed at which the engage can be executed.
|
||||
-- @param #number EngageFloorAltitude (optional, default = 1000m ) The minimum altitude at which the engage can be executed.
|
||||
-- @param #number EngageCeilingAltitude (optional, default = 1500m ) The maximum altitude at which the engage can be executed.
|
||||
-- @param #number EngageAltType The altitude type when engaging, which is a string "BARO" defining Barometric or "RADIO" defining radio controlled altitude.
|
||||
-- @return #AI_A2G_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Bai Patrol Squadron execution.
|
||||
-- PatrolZoneEast = ZONE_POLYGON:New( "Patrol Zone East", GROUP:FindByName( "Patrol Zone East" ) )
|
||||
-- A2GDispatcher:SetSquadronBaiPatrol2( "Mineralnye", PatrolZoneEast, 500, 600, 4000, 10000, "BARO", 800, 900, 2000, 3000, "RADIO", )
|
||||
--
|
||||
function AI_A2G_DISPATCHER:SetSquadronBaiPatrol2( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.BAI = DefenderSquadron.BAI or {}
|
||||
|
||||
local BaiPatrol = DefenderSquadron.BAI
|
||||
BaiPatrol.Name = SquadronName
|
||||
BaiPatrol.Zone = Zone
|
||||
BaiPatrol.PatrolFloorAltitude = PatrolFloorAltitude
|
||||
BaiPatrol.PatrolCeilingAltitude = PatrolCeilingAltitude
|
||||
BaiPatrol.EngageFloorAltitude = EngageFloorAltitude
|
||||
BaiPatrol.EngageCeilingAltitude = EngageCeilingAltitude
|
||||
BaiPatrol.PatrolMinSpeed = PatrolMinSpeed
|
||||
BaiPatrol.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
BaiPatrol.EngageMinSpeed = EngageMinSpeed
|
||||
BaiPatrol.EngageMaxSpeed = EngageMaxSpeed
|
||||
BaiPatrol.PatrolAltType = PatrolAltType
|
||||
BaiPatrol.EngageAltType = EngageAltType
|
||||
BaiPatrol.Patrol = true
|
||||
|
||||
self:SetSquadronPatrolInterval( SquadronName, self.DefenderDefault.PatrolLimit, self.DefenderDefault.PatrolMinSeconds, self.DefenderDefault.PatrolMaxSeconds, 1, "BAI" )
|
||||
|
||||
self:I( { BAI = { Zone:GetName(), PatrolMinSpeed, PatrolMaxSpeed, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolAltType, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType } } )
|
||||
end
|
||||
|
||||
--- Set a Bai patrol for a Squadron.
|
||||
-- The Bai patrol will start a patrol of the aircraft at a specified zone, and will engage when commanded.
|
||||
@ -2354,28 +2531,9 @@ do -- AI_A2G_DISPATCHER
|
||||
-- A2GDispatcher:SetSquadronBaiPatrol( "Mineralnye", PatrolZoneEast, 4000, 10000, 500, 600, 800, 900 )
|
||||
--
|
||||
function AI_A2G_DISPATCHER:SetSquadronBaiPatrol( SquadronName, Zone, FloorAltitude, CeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageMinSpeed, EngageMaxSpeed, AltType )
|
||||
|
||||
self:SetSquadronBaiPatrol2( SquadronName, Zone, PatrolMinSpeed, PatrolMaxSpeed, FloorAltitude, CeilingAltitude, AltType, EngageMinSpeed, EngageMaxSpeed, FloorAltitude, CeilingAltitude, AltType )
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.BAI = DefenderSquadron.BAI or {}
|
||||
|
||||
local BaiPatrol = DefenderSquadron.BAI
|
||||
BaiPatrol.Name = SquadronName
|
||||
BaiPatrol.Zone = Zone
|
||||
BaiPatrol.PatrolFloorAltitude = FloorAltitude
|
||||
BaiPatrol.PatrolCeilingAltitude = CeilingAltitude
|
||||
BaiPatrol.EngageFloorAltitude = FloorAltitude
|
||||
BaiPatrol.EngageCeilingAltitude = CeilingAltitude
|
||||
BaiPatrol.PatrolMinSpeed = PatrolMinSpeed
|
||||
BaiPatrol.PatrolMaxSpeed = PatrolMaxSpeed
|
||||
BaiPatrol.EngageMinSpeed = EngageMinSpeed
|
||||
BaiPatrol.EngageMaxSpeed = EngageMaxSpeed
|
||||
BaiPatrol.AltType = AltType
|
||||
BaiPatrol.Patrol = true
|
||||
|
||||
self:SetSquadronPatrolInterval( SquadronName, self.DefenderDefault.PatrolLimit, self.DefenderDefault.PatrolMinSeconds, self.DefenderDefault.PatrolMaxSeconds, 1, "BAI" )
|
||||
|
||||
self:F( { Bai = BaiPatrol } )
|
||||
end
|
||||
|
||||
|
||||
@ -3496,7 +3654,7 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
local AI_A2G_PATROL = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
||||
|
||||
local AI_A2G_Fsm = AI_A2G_PATROL[DefenseTaskType]:New( DefenderGroup, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.EngageFloorAltitude, Patrol.EngageCeilingAltitude, Patrol.Zone, Patrol.PatrolFloorAltitude, Patrol.PatrolCeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.AltType )
|
||||
local AI_A2G_Fsm = AI_A2G_PATROL[DefenseTaskType]:New2( DefenderGroup, Patrol.EngageMinSpeed, Patrol.EngageMaxSpeed, Patrol.EngageFloorAltitude, Patrol.EngageCeilingAltitude, Patrol.EngageAltType, Patrol.Zone, Patrol.PatrolFloorAltitude, Patrol.PatrolCeilingAltitude, Patrol.PatrolMinSpeed, Patrol.PatrolMaxSpeed, Patrol.PatrolAltType )
|
||||
AI_A2G_Fsm:SetDispatcher( self )
|
||||
AI_A2G_Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||
AI_A2G_Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||
@ -3508,7 +3666,7 @@ do -- AI_A2G_DISPATCHER
|
||||
self:SetDefenderTask( SquadronName, DefenderGroup, DefenseTaskType, AI_A2G_Fsm, nil, DefenderGrouping )
|
||||
|
||||
function AI_A2G_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
|
||||
self:F({"Defender Takeoff", DefenderGroup:GetName()})
|
||||
self:F({"Takeoff", DefenderGroup:GetName()})
|
||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign() -- #string
|
||||
@ -3522,7 +3680,7 @@ do -- AI_A2G_DISPATCHER
|
||||
end
|
||||
|
||||
function AI_A2G_Fsm:onafterPatrolRoute( DefenderGroup, From, Event, To )
|
||||
self:F({"Defender PatrolRoute", DefenderGroup:GetName()})
|
||||
self:F({"PatrolRoute", DefenderGroup:GetName()})
|
||||
self:GetParent(self).onafterPatrolRoute( self, DefenderGroup, From, Event, To )
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign()
|
||||
@ -3544,7 +3702,7 @@ do -- AI_A2G_DISPATCHER
|
||||
local Dispatcher = AI_A2G_Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER
|
||||
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
|
||||
|
||||
if Squadron then
|
||||
if Squadron and AttackSetUnit:Count() > 0 then
|
||||
local FirstUnit = AttackSetUnit:GetFirst()
|
||||
local Coordinate = FirstUnit:GetCoordinate() -- Core.Point#COORDINATE
|
||||
|
||||
@ -3568,7 +3726,7 @@ do -- AI_A2G_DISPATCHER
|
||||
end
|
||||
|
||||
function AI_A2G_Fsm:onafterRTB( DefenderGroup, From, Event, To )
|
||||
self:F({"Defender RTB", DefenderGroup:GetName()})
|
||||
self:F({"RTB", DefenderGroup:GetName()})
|
||||
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign()
|
||||
@ -3581,7 +3739,7 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
--- @param #AI_A2G_DISPATCHER self
|
||||
function AI_A2G_Fsm:onafterLostControl( DefenderGroup, From, Event, To )
|
||||
self:F({"Defender LostControl", DefenderGroup:GetName()})
|
||||
self:F({"LostControl", DefenderGroup:GetName()})
|
||||
self:GetParent(self).onafterHome( self, DefenderGroup, From, Event, To )
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign()
|
||||
@ -3596,7 +3754,7 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
--- @param #AI_A2G_DISPATCHER self
|
||||
function AI_A2G_Fsm:onafterHome( DefenderGroup, From, Event, To, Action )
|
||||
self:F({"Defender Home", DefenderGroup:GetName()})
|
||||
self:F({"Home", DefenderGroup:GetName()})
|
||||
self:GetParent(self).onafterHome( self, DefenderGroup, From, Event, To )
|
||||
|
||||
local DefenderName = DefenderGroup:GetCallsign()
|
||||
@ -3635,9 +3793,9 @@ do -- AI_A2G_DISPATCHER
|
||||
|
||||
if DefenderGroup then
|
||||
|
||||
local AI_A2G = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
||||
local AI_A2G_ENGAGE = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
||||
|
||||
local AI_A2G_Fsm = AI_A2G[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude ) -- AI.AI_A2G_ENGAGE
|
||||
local AI_A2G_Fsm = AI_A2G_ENGAGE[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude, Defense.EngageAltType ) -- AI.AI_AIR_ENGAGE
|
||||
AI_A2G_Fsm:SetDispatcher( self )
|
||||
AI_A2G_Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||
AI_A2G_Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||
|
||||
@ -14,7 +14,7 @@
|
||||
|
||||
|
||||
--- @type AI_A2G_SEAD
|
||||
-- @extends AI.AI_A2G_Patrol#AI_A2G_PATROL
|
||||
-- @extends AI.AI_A2G_Patrol#AI_AIR_PATROL
|
||||
|
||||
|
||||
--- Implements the core functions to SEAD intruders. Use the Engage trigger to intercept intruders.
|
||||
@ -85,6 +85,7 @@ AI_A2G_SEAD = {
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
@ -92,10 +93,12 @@ AI_A2G_SEAD = {
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2G_SEAD
|
||||
function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
function AI_A2G_SEAD:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_A2G_SEAD
|
||||
local AI_Air = AI_AIR:New( AIGroup )
|
||||
local AI_Air_Patrol = AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) -- #AI_AIR_PATROL
|
||||
local AI_Air_Engage = AI_AIR_ENGAGE:New( AI_Air_Patrol, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
local self = BASE:Inherit( self, AI_Air_Engage )
|
||||
|
||||
local RTBSpeedMax = AIGroup:GetSpeedMax() or 9999
|
||||
|
||||
@ -105,116 +108,49 @@ function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAl
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new AI_A2G_SEAD object
|
||||
-- @param #AI_A2G_SEAD self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
-- @param DCS#Speed EngageMinSpeed The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude The highest altitude in meters where to execute the engagement.
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO
|
||||
-- @return #AI_A2G_SEAD
|
||||
function AI_A2G_SEAD:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
--- @param #AI_A2G_SEAD self
|
||||
-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_SEAD:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
|
||||
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
||||
|
||||
local DefenderGroupName = DefenderGroup:GetName()
|
||||
|
||||
self.AttackSetUnit = AttackSetUnit -- Kept in memory in case of resume from refuel in air!
|
||||
|
||||
local AttackCount = AttackSetUnit:Count()
|
||||
|
||||
if AttackCount > 0 then
|
||||
|
||||
if DefenderGroup:IsAlive() then
|
||||
|
||||
-- Determine the distance to the target.
|
||||
-- If it is less than 50km, then attack without a route.
|
||||
-- Otherwise perform a route attack.
|
||||
|
||||
local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 )
|
||||
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||
|
||||
local DefenderCoord = DefenderGroup:GetPointVec3()
|
||||
DefenderCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetCoord = AttackSetUnit:GetFirst():GetPointVec3()
|
||||
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
||||
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 25000 )
|
||||
|
||||
local EngageRoute = {}
|
||||
local AttackTasks = {}
|
||||
|
||||
local FromWP = DefenderCoord:WaypointAir(
|
||||
self.PatrolAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
false
|
||||
)
|
||||
EngageRoute[#EngageRoute+1] = FromWP
|
||||
|
||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||
|
||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir(
|
||||
self.PatrolAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
if TargetDistance <= EngageDistance * 3 then
|
||||
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
local AttackSetUnitPerThreatLevel = AttackSetUnit:GetSetPerThreatLevel( 10, 0 )
|
||||
for AttackUnitID, AttackUnit in ipairs( AttackSetUnitPerThreatLevel ) do
|
||||
if AttackUnit then
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsGround() then
|
||||
local HasRadar = AttackUnit:HasSEAD()
|
||||
if HasRadar then
|
||||
self:F( { "SEAD Unit:", AttackUnit:GetName() } )
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit, true, false, nil, nil, EngageAltitude )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if #AttackUnitTasks == 0 then
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
else
|
||||
DefenderGroup:OptionROEOpenFire()
|
||||
DefenderGroup:OptionROTVertical()
|
||||
DefenderGroup:OptionKeepWeaponsOnThreat()
|
||||
--DefenderGroup:OptionRTBAmmo( Weapon.flag.AnyASM )
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskCombo( AttackUnitTasks )
|
||||
end
|
||||
end
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.___Engage", self, AttackSetUnit )
|
||||
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
||||
|
||||
DefenderGroup:Route( EngageRoute, self.TaskDelay )
|
||||
end
|
||||
else
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
end
|
||||
return self:New2( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolAltType, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIEngage
|
||||
function AI_A2G_SEAD.Resume( AIEngage, Fsm )
|
||||
|
||||
AIEngage:F( { "AI_A2G_SEAD.Resume:", AIEngage:GetName() } )
|
||||
if AIEngage:IsAlive() then
|
||||
Fsm:__Reset( Fsm.TaskDelay )
|
||||
Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit )
|
||||
--- Evaluate the attack and create an AttackUnitTask list.
|
||||
-- @param #AI_A2G_SEAD self
|
||||
-- @param Core.Set#SET_UNIT AttackSetUnit The set of units to attack.
|
||||
-- @param Wrappper.Group#GROUP DefenderGroup The group of defenders.
|
||||
-- @param #number EngageAltitude The altitude to engage the targets.
|
||||
-- @return #AI_A2G_SEAD self
|
||||
function AI_A2G_SEAD:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude )
|
||||
|
||||
local AttackUnitTasks = {}
|
||||
|
||||
local AttackSetUnitPerThreatLevel = AttackSetUnit:GetSetPerThreatLevel( 10, 0 )
|
||||
for AttackUnitID, AttackUnit in ipairs( AttackSetUnitPerThreatLevel ) do
|
||||
if AttackUnit then
|
||||
if AttackUnit:IsAlive() and AttackUnit:IsGround() then
|
||||
local HasRadar = AttackUnit:HasSEAD()
|
||||
if HasRadar then
|
||||
self:F( { "SEAD Unit:", AttackUnit:GetName() } )
|
||||
AttackUnitTasks[#AttackUnitTasks+1] = DefenderGroup:TaskAttackUnit( AttackUnit, true, false, nil, nil, EngageAltitude )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return AttackUnitTasks
|
||||
end
|
||||
|
||||
|
||||
@ -2577,7 +2577,7 @@ do -- AI_AIR_DISPATCHER
|
||||
|
||||
local AI_A2G = { SEAD = AI_A2G_SEAD, BAI = AI_A2G_BAI, CAS = AI_A2G_CAS }
|
||||
|
||||
local Fsm = AI_A2G[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude ) -- AI.AI_A2G_ENGAGE
|
||||
local Fsm = AI_A2G[DefenseTaskType]:New( DefenderGroup, Defense.EngageMinSpeed, Defense.EngageMaxSpeed, Defense.EngageFloorAltitude, Defense.EngageCeilingAltitude ) -- AI.AI_AIR_ENGAGE
|
||||
Fsm:SetDispatcher( self )
|
||||
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||
|
||||
@ -8,20 +8,20 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI.AI_A2G_Engage
|
||||
-- @module AI.AI_Air_Engage
|
||||
-- @image AI_Air_To_Ground_Engage.JPG
|
||||
|
||||
|
||||
|
||||
--- @type AI_A2G_ENGAGE
|
||||
-- @extends AI.AI_A2G#AI_A2G
|
||||
--- @type AI_AIR_ENGAGE
|
||||
-- @extends AI.AI_AIR#AI_AIR
|
||||
|
||||
|
||||
--- Implements the core functions to intercept intruders. Use the Engage trigger to intercept intruders.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2G_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_ENGAGE process can be started using the **Start** event.
|
||||
-- The AI_AIR_ENGAGE is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_ENGAGE process can be started using the **Start** event.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@ -47,9 +47,9 @@
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## 1. AI_A2G_ENGAGE constructor
|
||||
-- ## 1. AI_AIR_ENGAGE constructor
|
||||
--
|
||||
-- * @{#AI_A2G_ENGAGE.New}(): Creates a new AI_A2G_ENGAGE object.
|
||||
-- * @{#AI_AIR_ENGAGE.New}(): Creates a new AI_AIR_ENGAGE object.
|
||||
--
|
||||
-- ## 3. Set the Range of Engagement
|
||||
--
|
||||
@ -59,7 +59,7 @@
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- The range can be beyond or smaller than the range of the Patrol Zone.
|
||||
-- The range is applied at the position of the AI.
|
||||
-- Use the method @{AI.AI_GCI#AI_A2G_ENGAGE.SetEngageRange}() to define that range.
|
||||
-- Use the method @{AI.AI_GCI#AI_AIR_ENGAGE.SetEngageRange}() to define that range.
|
||||
--
|
||||
-- ## 4. Set the Zone of Engagement
|
||||
--
|
||||
@ -67,29 +67,30 @@
|
||||
--
|
||||
-- An optional @{Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI.AI_Cap#AI_A2G_ENGAGE.SetEngageZone}() to define that Zone.
|
||||
-- Use the method @{AI.AI_Cap#AI_AIR_ENGAGE.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2G_ENGAGE
|
||||
AI_A2G_ENGAGE = {
|
||||
ClassName = "AI_A2G_ENGAGE",
|
||||
-- @field #AI_AIR_ENGAGE
|
||||
AI_AIR_ENGAGE = {
|
||||
ClassName = "AI_AIR_ENGAGE",
|
||||
}
|
||||
|
||||
|
||||
|
||||
--- Creates a new AI_A2G_ENGAGE object
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
--- Creates a new AI_AIR_ENGAGE object
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
-- @param DCS#Speed EngageMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @return #AI_A2G_ENGAGE
|
||||
function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude )
|
||||
-- @param DCS#AltitudeType EngageAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to "RADIO".
|
||||
-- @return #AI_AIR_ENGAGE
|
||||
function AI_AIR_ENGAGE:New( AI_Air, AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, EngageAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2G:New( AIGroup ) ) -- #AI_A2G_ENGAGE
|
||||
local self = BASE:Inherit( self, AI_Air ) -- #AI_AIR_ENGAGE
|
||||
|
||||
self.Accomplished = false
|
||||
self.Engaging = false
|
||||
@ -100,12 +101,13 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
self.EngageMaxSpeed = EngageMaxSpeed or SpeedMax * 0.75
|
||||
self.EngageFloorAltitude = EngageFloorAltitude or 1000
|
||||
self.EngageCeilingAltitude = EngageCeilingAltitude or 1500
|
||||
self.EngageAltType = EngageAltType or "RADIO"
|
||||
|
||||
self:AddTransition( { "Started", "Engaging", "Returning", "Airborne", "Patrolling" }, "EngageRoute", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE.
|
||||
self:AddTransition( { "Started", "Engaging", "Returning", "Airborne", "Patrolling" }, "EngageRoute", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_ENGAGE.
|
||||
|
||||
--- OnBefore Transition Handler for Event EngageRoute.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnBeforeEngageRoute
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnBeforeEngageRoute
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -113,25 +115,25 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event EngageRoute.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnAfterEngageRoute
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnAfterEngageRoute
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event EngageRoute.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] EngageRoute
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] EngageRoute
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
|
||||
--- Asynchronous Event Trigger for Event EngageRoute.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] __EngageRoute
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] __EngageRoute
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
--- OnLeave Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnLeaveEngaging
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnLeaveEngaging
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -139,18 +141,18 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnEnterEngaging
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnEnterEngaging
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
self:AddTransition( { "Started", "Engaging", "Returning", "Airborne", "Patrolling" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE.
|
||||
self:AddTransition( { "Started", "Engaging", "Returning", "Airborne", "Patrolling" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_ENGAGE.
|
||||
|
||||
--- OnBefore Transition Handler for Event Engage.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnBeforeEngage
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnBeforeEngage
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -158,25 +160,25 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Engage.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnAfterEngage
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnAfterEngage
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] Engage
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] Engage
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Engage.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] __Engage
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] __Engage
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
--- OnLeave Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnLeaveEngaging
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnLeaveEngaging
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -184,18 +186,18 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Engaging.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnEnterEngaging
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnEnterEngaging
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE.
|
||||
self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_ENGAGE.
|
||||
|
||||
--- OnBefore Transition Handler for Event Fired.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnBeforeFired
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnBeforeFired
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -203,27 +205,27 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Fired.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnAfterFired
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnAfterFired
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Fired.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] Fired
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] Fired
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Fired.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] __Fired
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] __Fired
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE.
|
||||
self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_ENGAGE.
|
||||
|
||||
--- OnBefore Transition Handler for Event Destroy.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnBeforeDestroy
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnBeforeDestroy
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -231,28 +233,28 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Destroy.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnAfterDestroy
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnAfterDestroy
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Destroy.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] Destroy
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] Destroy
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Destroy.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] __Destroy
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] __Destroy
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
|
||||
self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE.
|
||||
self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_ENGAGE.
|
||||
|
||||
--- OnBefore Transition Handler for Event Abort.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnBeforeAbort
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnBeforeAbort
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -260,27 +262,27 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Abort.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnAfterAbort
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnAfterAbort
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Abort.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] Abort
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] Abort
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Abort.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] __Abort
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] __Abort
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_ENGAGE.
|
||||
self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_ENGAGE.
|
||||
|
||||
--- OnBefore Transition Handler for Event Accomplish.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnBeforeAccomplish
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnBeforeAccomplish
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -288,20 +290,20 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Accomplish.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] OnAfterAccomplish
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] OnAfterAccomplish
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Accomplish.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] Accomplish
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] Accomplish
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Accomplish.
|
||||
-- @function [parent=#AI_A2G_ENGAGE] __Accomplish
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @function [parent=#AI_AIR_ENGAGE] __Accomplish
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
self:AddTransition( { "Patrolling", "Engaging" }, "Refuel", "Refuelling" )
|
||||
@ -310,14 +312,14 @@ function AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
end
|
||||
|
||||
--- onafter event handler for Start event.
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The AI group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_ENGAGE:onafterStart( AIGroup, From, Event, To )
|
||||
function AI_AIR_ENGAGE:onafterStart( AIGroup, From, Event, To )
|
||||
|
||||
self:GetParent( self, AI_A2G_ENGAGE ).onafterStart( self, AIGroup, From, Event, To )
|
||||
self:GetParent( self, AI_AIR_ENGAGE ).onafterStart( self, AIGroup, From, Event, To )
|
||||
|
||||
AIGroup:HandleEvent( EVENTS.Takeoff, nil, self )
|
||||
|
||||
@ -326,12 +328,12 @@ end
|
||||
|
||||
|
||||
--- onafter event handler for Engage event.
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_ENGAGE:onafterEngage( AIGroup, From, Event, To )
|
||||
function AI_AIR_ENGAGE:onafterEngage( AIGroup, From, Event, To )
|
||||
|
||||
self:HandleEvent( EVENTS.Dead )
|
||||
|
||||
@ -339,39 +341,14 @@ end
|
||||
|
||||
-- todo: need to fix this global function
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIControllable
|
||||
function AI_A2G_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit )
|
||||
|
||||
AIGroup:I( { "AI_A2G_ENGAGE.___EngageRoute:", AIGroup:GetName() } )
|
||||
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__EngageRoute( Fsm.TaskDelay, AttackSetUnit )
|
||||
|
||||
--local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
|
||||
--AIGroup:SetTask( Task )
|
||||
end
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIControllable
|
||||
function AI_A2G_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit )
|
||||
|
||||
AIGroup:I( { "AI_A2G_ENGAGE.___Engage:", AIGroup:GetName() } )
|
||||
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__Engage( Fsm.TaskDelay, AttackSetUnit )
|
||||
|
||||
--local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
|
||||
--AIGroup:SetTask( Task )
|
||||
end
|
||||
end
|
||||
|
||||
--- onbefore event handler for Engage event.
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_ENGAGE:onbeforeEngage( AIGroup, From, Event, To )
|
||||
function AI_AIR_ENGAGE:onbeforeEngage( AIGroup, From, Event, To )
|
||||
|
||||
if self.Accomplished == true then
|
||||
return false
|
||||
@ -379,44 +356,44 @@ function AI_A2G_ENGAGE:onbeforeEngage( AIGroup, From, Event, To )
|
||||
end
|
||||
|
||||
--- onafter event handler for Abort event.
|
||||
-- @param #AI_A2G_ENGAGE self
|
||||
-- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The AI Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_ENGAGE:onafterAbort( AIGroup, From, Event, To )
|
||||
function AI_AIR_ENGAGE:onafterAbort( AIGroup, From, Event, To )
|
||||
AIGroup:ClearTasks()
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2G_ENGAGE self
|
||||
--- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_ENGAGE:onafterAccomplish( AIGroup, From, Event, To )
|
||||
function AI_AIR_ENGAGE:onafterAccomplish( AIGroup, From, Event, To )
|
||||
self.Accomplished = true
|
||||
self:SetDetectionOff()
|
||||
end
|
||||
|
||||
--- @param #AI_A2G_ENGAGE self
|
||||
--- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP AIGroup The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2G_ENGAGE:onafterDestroy( AIGroup, From, Event, To, EventData )
|
||||
function AI_AIR_ENGAGE:onafterDestroy( AIGroup, From, Event, To, EventData )
|
||||
|
||||
if EventData.IniUnit then
|
||||
self.AttackUnits[EventData.IniUnit] = nil
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2G_ENGAGE self
|
||||
--- @param #AI_AIR_ENGAGE self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2G_ENGAGE:OnEventDead( EventData )
|
||||
function AI_AIR_ENGAGE:OnEventDead( EventData )
|
||||
self:F( { "EventDead", EventData } )
|
||||
|
||||
if EventData.IniDCSUnit then
|
||||
@ -426,14 +403,29 @@ function AI_A2G_ENGAGE:OnEventDead( EventData )
|
||||
end
|
||||
end
|
||||
|
||||
--- @param #AI_A2G_ENGAGE self
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIControllable
|
||||
function AI_AIR_ENGAGE.___EngageRoute( AIGroup, Fsm, AttackSetUnit )
|
||||
|
||||
Fsm:I( { "AI_AIR_ENGAGE.___EngageRoute:", AIGroup:GetName() } )
|
||||
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__EngageRoute( Fsm.TaskDelay, AttackSetUnit )
|
||||
|
||||
--local Task = AIGroup:TaskOrbitCircle( 4000, 400 )
|
||||
--AIGroup:SetTask( Task )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
function AI_AIR_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
|
||||
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
||||
self:I( { DefenderGroup, From, Event, To, AttackSetUnit } )
|
||||
|
||||
local DefenderGroupName = DefenderGroup:GetName()
|
||||
|
||||
@ -495,7 +487,7 @@ function AI_A2G_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
||||
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_A2G_ENGAGE.___EngageRoute", self, AttackSetUnit )
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___EngageRoute", self, AttackSetUnit )
|
||||
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
||||
|
||||
DefenderGroup:OptionROEReturnFire()
|
||||
@ -512,3 +504,113 @@ function AI_A2G_ENGAGE:onafterEngageRoute( DefenderGroup, From, Event, To, Attac
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIControllable
|
||||
function AI_AIR_ENGAGE.___Engage( AIGroup, Fsm, AttackSetUnit )
|
||||
|
||||
Fsm:I( { "AI_AIR_ENGAGE.___Engage:", AIGroup:GetName() } )
|
||||
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__Engage( Fsm.TaskDelay, AttackSetUnit )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_AIR_ENGAGE self
|
||||
-- @param Wrapper.Group#GROUP DefenderGroup The GroupGroup managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_AIR_ENGAGE:onafterEngage( DefenderGroup, From, Event, To, AttackSetUnit )
|
||||
|
||||
self:F( { DefenderGroup, From, Event, To, AttackSetUnit} )
|
||||
|
||||
local DefenderGroupName = DefenderGroup:GetName()
|
||||
|
||||
self.AttackSetUnit = AttackSetUnit -- Kept in memory in case of resume from refuel in air!
|
||||
|
||||
local AttackCount = AttackSetUnit:Count()
|
||||
self:I({AttackCount = AttackCount})
|
||||
|
||||
if AttackCount > 0 then
|
||||
|
||||
if DefenderGroup:IsAlive() then
|
||||
|
||||
local EngageAltitude = math.random( self.EngageFloorAltitude or 500, self.EngageCeilingAltitude or 1000 )
|
||||
local EngageSpeed = math.random( self.EngageMinSpeed, self.EngageMaxSpeed )
|
||||
|
||||
local DefenderCoord = DefenderGroup:GetPointVec3()
|
||||
DefenderCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetCoord = AttackSetUnit:GetFirst():GetPointVec3()
|
||||
TargetCoord:SetY( EngageAltitude ) -- Ground targets don't have an altitude.
|
||||
|
||||
local TargetDistance = DefenderCoord:Get2DDistance( TargetCoord )
|
||||
local EngageDistance = ( DefenderGroup:IsHelicopter() and 5000 ) or ( DefenderGroup:IsAirPlane() and 10000 )
|
||||
|
||||
local EngageRoute = {}
|
||||
local AttackTasks = {}
|
||||
|
||||
local FromWP = DefenderCoord:WaypointAir(
|
||||
self.EngageAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
EngageRoute[#EngageRoute+1] = FromWP
|
||||
|
||||
self:SetTargetDistance( TargetCoord ) -- For RTB status check
|
||||
|
||||
local FromEngageAngle = DefenderCoord:GetAngleDegrees( DefenderCoord:GetDirectionVec3( TargetCoord ) )
|
||||
local ToWP = DefenderCoord:Translate( EngageDistance, FromEngageAngle, true ):WaypointAir(
|
||||
self.EngageAltType or "RADIO",
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
EngageSpeed,
|
||||
true
|
||||
)
|
||||
EngageRoute[#EngageRoute+1] = ToWP
|
||||
|
||||
if TargetDistance <= EngageDistance * 3 then
|
||||
|
||||
local AttackUnitTasks = self:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageAltitude )
|
||||
|
||||
if #AttackUnitTasks == 0 then
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
return
|
||||
else
|
||||
DefenderGroup:OptionROEOpenFire()
|
||||
DefenderGroup:OptionROTEvadeFire()
|
||||
DefenderGroup:OptionKeepWeaponsOnThreat()
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskCombo( AttackUnitTasks )
|
||||
end
|
||||
end
|
||||
|
||||
AttackTasks[#AttackTasks+1] = DefenderGroup:TaskFunction( "AI_AIR_ENGAGE.___Engage", self, AttackSetUnit )
|
||||
EngageRoute[#EngageRoute].task = DefenderGroup:TaskCombo( AttackTasks )
|
||||
|
||||
DefenderGroup:Route( EngageRoute, self.TaskDelay )
|
||||
|
||||
end
|
||||
else
|
||||
self:I( DefenderGroupName .. ": No targets found -> Going RTB")
|
||||
self:Return()
|
||||
self:__RTB( self.TaskDelay )
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIEngage
|
||||
function AI_AIR_ENGAGE.Resume( AIEngage, Fsm )
|
||||
|
||||
AIEngage:F( { "Resume:", AIEngage:GetName() } )
|
||||
if AIEngage:IsAlive() then
|
||||
Fsm:__Reset( Fsm.TaskDelay )
|
||||
Fsm:__EngageRoute( Fsm.TaskDelay, Fsm.AttackSetUnit )
|
||||
end
|
||||
|
||||
end
|
||||
@ -6,19 +6,19 @@
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module AI.AI_A2G_Patrol
|
||||
-- @module AI.AI_Air_Patrol
|
||||
-- @image AI_Air_To_Ground_Patrol.JPG
|
||||
|
||||
--- @type AI_A2G_PATROL
|
||||
-- @extends AI.AI_A2G_Engage#AI_A2G_ENGAGE
|
||||
--- @type AI_AIR_PATROL
|
||||
-- @extends AI.AI_Air#AI_AIR
|
||||
|
||||
|
||||
--- The AI_A2G_PATROL class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
||||
--- The AI_AIR_PATROL class implements the core functions to patrol a @{Zone} by an AI @{Wrapper.Group} or @{Wrapper.Group}
|
||||
-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- The AI_A2G_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_A2G_PATROL process can be started using the **Start** event.
|
||||
-- The AI_AIR_PATROL is assigned a @{Wrapper.Group} and this must be done before the AI_AIR_PATROL process can be started using the **Start** event.
|
||||
--
|
||||
-- 
|
||||
--
|
||||
@ -44,32 +44,32 @@
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ## 1. AI_A2G_PATROL constructor
|
||||
-- ## 1. AI_AIR_PATROL constructor
|
||||
--
|
||||
-- * @{#AI_A2G_PATROL.New}(): Creates a new AI_A2G_PATROL object.
|
||||
-- * @{#AI_AIR_PATROL.New}(): Creates a new AI_AIR_PATROL object.
|
||||
--
|
||||
-- ## 2. AI_A2G_PATROL is a FSM
|
||||
-- ## 2. AI_AIR_PATROL is a FSM
|
||||
--
|
||||
-- 
|
||||
--
|
||||
-- ### 2.1 AI_A2G_PATROL States
|
||||
-- ### 2.1 AI_AIR_PATROL States
|
||||
--
|
||||
-- * **None** ( Group ): The process is not started yet.
|
||||
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
|
||||
-- * **Engaging** ( Group ): The AI is engaging the bogeys.
|
||||
-- * **Returning** ( Group ): The AI is returning to Base..
|
||||
--
|
||||
-- ### 2.2 AI_A2G_PATROL Events
|
||||
-- ### 2.2 AI_AIR_PATROL Events
|
||||
--
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.PatrolRoute}**: Route the AI to a new random 3D point within the Patrol Zone.
|
||||
-- * **@{#AI_A2G_PATROL.Engage}**: Let the AI engage the bogeys.
|
||||
-- * **@{#AI_A2G_PATROL.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{#AI_AIR_PATROL.Engage}**: Let the AI engage the bogeys.
|
||||
-- * **@{#AI_AIR_PATROL.Abort}**: Aborts the engagement and return patrolling in the patrol zone.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets.
|
||||
-- * **@{AI.AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets.
|
||||
-- * **@{#AI_A2G_PATROL.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
|
||||
-- * **@{#AI_A2G_PATROL.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **@{#AI_AIR_PATROL.Destroy}**: The AI has destroyed a bogey @{Wrapper.Unit}.
|
||||
-- * **@{#AI_AIR_PATROL.Destroyed}**: The AI has destroyed all bogeys @{Wrapper.Unit}s assigned in the CAS task.
|
||||
-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
|
||||
--
|
||||
-- ## 3. Set the Range of Engagement
|
||||
@ -80,7 +80,7 @@
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- The range can be beyond or smaller than the range of the Patrol Zone.
|
||||
-- The range is applied at the position of the AI.
|
||||
-- Use the method @{AI.AI_CAP#AI_A2G_PATROL.SetEngageRange}() to define that range.
|
||||
-- Use the method @{AI.AI_CAP#AI_AIR_PATROL.SetEngageRange}() to define that range.
|
||||
--
|
||||
-- ## 4. Set the Zone of Engagement
|
||||
--
|
||||
@ -88,33 +88,29 @@
|
||||
--
|
||||
-- An optional @{Zone} can be set,
|
||||
-- that will define when the AI will engage with the detected airborne enemy targets.
|
||||
-- Use the method @{AI.AI_Cap#AI_A2G_PATROL.SetEngageZone}() to define that Zone.
|
||||
-- Use the method @{AI.AI_Cap#AI_AIR_PATROL.SetEngageZone}() to define that Zone.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @field #AI_A2G_PATROL
|
||||
AI_A2G_PATROL = {
|
||||
ClassName = "AI_A2G_PATROL",
|
||||
-- @field #AI_AIR_PATROL
|
||||
AI_AIR_PATROL = {
|
||||
ClassName = "AI_AIR_PATROL",
|
||||
}
|
||||
|
||||
--- Creates a new AI_A2G_PATROL object
|
||||
-- @param #AI_A2G_PATROL self
|
||||
--- Creates a new AI_AIR_PATROL object
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIGroup
|
||||
-- @param DCS#Speed EngageMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Speed EngageMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h when engaging a target.
|
||||
-- @param DCS#Altitude EngageFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the engagement.
|
||||
-- @param DCS#Altitude EngageCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the engagement.
|
||||
-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
|
||||
-- @param DCS#Altitude PatrolFloorAltitude (optional, default = 1000m ) The lowest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Altitude PatrolCeilingAltitude (optional, default = 1500m ) The highest altitude in meters where to execute the patrol.
|
||||
-- @param DCS#Speed PatrolMinSpeed (optional, default = 50% of max speed) The minimum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#Speed PatrolMaxSpeed (optional, default = 75% of max speed) The maximum speed of the @{Wrapper.Group} in km/h.
|
||||
-- @param DCS#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO.
|
||||
-- @return #AI_A2G_PATROL
|
||||
function AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
-- @return #AI_AIR_PATROL
|
||||
function AI_AIR_PATROL:New( AI_Air, AIGroup, PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, AI_A2G_ENGAGE:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloorAltitude, EngageCeilingAltitude ) ) -- #AI_A2G_PATROL
|
||||
local self = BASE:Inherit( self, AI_Air ) -- #AI_AIR_PATROL
|
||||
|
||||
local SpeedMax = AIGroup:GetSpeedMax()
|
||||
|
||||
@ -131,8 +127,8 @@ function AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
self:AddTransition( { "Started", "Airborne", "Refuelling" }, "Patrol", "Patrolling" )
|
||||
|
||||
--- OnBefore Transition Handler for Event Patrol.
|
||||
-- @function [parent=#AI_A2G_PATROL] OnBeforePatrol
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] OnBeforePatrol
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -140,25 +136,25 @@ function AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event Patrol.
|
||||
-- @function [parent=#AI_A2G_PATROL] OnAfterPatrol
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] OnAfterPatrol
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event Patrol.
|
||||
-- @function [parent=#AI_A2G_PATROL] Patrol
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] Patrol
|
||||
-- @param #AI_AIR_PATROL self
|
||||
|
||||
--- Asynchronous Event Trigger for Event Patrol.
|
||||
-- @function [parent=#AI_A2G_PATROL] __Patrol
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] __Patrol
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
--- OnLeave Transition Handler for State Patrolling.
|
||||
-- @function [parent=#AI_A2G_PATROL] OnLeavePatrolling
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] OnLeavePatrolling
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -166,18 +162,18 @@ function AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnEnter Transition Handler for State Patrolling.
|
||||
-- @function [parent=#AI_A2G_PATROL] OnEnterPatrolling
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] OnEnterPatrolling
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
self:AddTransition( "Patrolling", "PatrolRoute", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL.
|
||||
self:AddTransition( "Patrolling", "PatrolRoute", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_PATROL.
|
||||
|
||||
--- OnBefore Transition Handler for Event PatrolRoute.
|
||||
-- @function [parent=#AI_A2G_PATROL] OnBeforePatrolRoute
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] OnBeforePatrolRoute
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
@ -185,34 +181,34 @@ function AI_A2G_PATROL:New( AIGroup, EngageMinSpeed, EngageMaxSpeed, EngageFloor
|
||||
-- @return #boolean Return false to cancel Transition.
|
||||
|
||||
--- OnAfter Transition Handler for Event PatrolRoute.
|
||||
-- @function [parent=#AI_A2G_PATROL] OnAfterPatrolRoute
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] OnAfterPatrolRoute
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
|
||||
--- Synchronous Event Trigger for Event PatrolRoute.
|
||||
-- @function [parent=#AI_A2G_PATROL] PatrolRoute
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] PatrolRoute
|
||||
-- @param #AI_AIR_PATROL self
|
||||
|
||||
--- Asynchronous Event Trigger for Event PatrolRoute.
|
||||
-- @function [parent=#AI_A2G_PATROL] __PatrolRoute
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @function [parent=#AI_AIR_PATROL] __PatrolRoute
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param #number Delay The delay in seconds.
|
||||
|
||||
|
||||
self:AddTransition( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_A2G_PATROL.
|
||||
self:AddTransition( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_AIR_PATROL.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- Set the Engage Range when the AI will engage with airborne enemies.
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param #number EngageRange The Engage Range.
|
||||
-- @return #AI_A2G_PATROL self
|
||||
function AI_A2G_PATROL:SetEngageRange( EngageRange )
|
||||
-- @return #AI_AIR_PATROL self
|
||||
function AI_AIR_PATROL:SetEngageRange( EngageRange )
|
||||
self:F2()
|
||||
|
||||
if EngageRange then
|
||||
@ -222,14 +218,44 @@ function AI_A2G_PATROL:SetEngageRange( EngageRange )
|
||||
end
|
||||
end
|
||||
|
||||
--- Set race track parameters. CAP flights will perform race track patterns rather than randomly patrolling the zone.
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param #number LegMin Min Length of the race track leg in meters. Default 10,000 m.
|
||||
-- @param #number LegMax Max length of the race track leg in meters. Default 15,000 m.
|
||||
-- @param #number HeadingMin Min heading of the race track in degrees. Default 0 deg, i.e. from South to North.
|
||||
-- @param #number HeadingMax Max heading of the race track in degrees. Default 180 deg, i.e. from South to North.
|
||||
-- @param #number DurationMin (Optional) Min duration before switching the orbit position. Default is keep same orbit until RTB or engage.
|
||||
-- @param #number DurationMax (Optional) Max duration before switching the orbit position. Default is keep same orbit until RTB or engage.
|
||||
-- @param #table CapCoordinates Table of coordinates of first race track point. Second point is determined by leg length and heading.
|
||||
-- @return #AI_AIR_PATROL self
|
||||
function AI_AIR_PATROL:SetRaceTrackPattern(LegMin, LegMax, HeadingMin, HeadingMax, DurationMin, DurationMax, CapCoordinates)
|
||||
|
||||
self.racetrack=true
|
||||
self.racetracklegmin=LegMin or 10000
|
||||
self.racetracklegmax=LegMax or 15000
|
||||
self.racetrackheadingmin=HeadingMin or 0
|
||||
self.racetrackheadingmax=HeadingMax or 180
|
||||
self.racetrackdurationmin=DurationMin
|
||||
self.racetrackdurationmax=DurationMax
|
||||
|
||||
if self.racetrackdurationmax and not self.racetrackdurationmin then
|
||||
self.racetrackdurationmin=self.racetrackdurationmax
|
||||
end
|
||||
|
||||
self.racetrackcapcoordinates=CapCoordinates
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings.
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @return #AI_A2G_PATROL self
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @return #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group Object managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_PATROL:onafterPatrol( AIPatrol, From, Event, To )
|
||||
function AI_AIR_PATROL:onafterPatrol( AIPatrol, From, Event, To )
|
||||
self:F2()
|
||||
|
||||
self:ClearTargetDistance()
|
||||
@ -247,9 +273,9 @@ end
|
||||
--- @param Wrapper.Group#GROUP AIPatrol
|
||||
-- This statis method is called from the route path within the last task at the last waaypoint of the AIPatrol.
|
||||
-- Note that this method is required, as triggers the next route when patrolling for the AIPatrol.
|
||||
function AI_A2G_PATROL.___PatrolRoute( AIPatrol, Fsm )
|
||||
function AI_AIR_PATROL.___PatrolRoute( AIPatrol, Fsm )
|
||||
|
||||
AIPatrol:F( { "AI_A2G_PATROL.___PatrolRoute:", AIPatrol:GetName() } )
|
||||
AIPatrol:F( { "AI_AIR_PATROL.___PatrolRoute:", AIPatrol:GetName() } )
|
||||
|
||||
if AIPatrol:IsAlive() then
|
||||
Fsm:PatrolRoute()
|
||||
@ -258,12 +284,12 @@ function AI_A2G_PATROL.___PatrolRoute( AIPatrol, Fsm )
|
||||
end
|
||||
|
||||
--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings.
|
||||
-- @param #AI_A2G_PATROL self
|
||||
-- @param #AI_AIR_PATROL self
|
||||
-- @param Wrapper.Group#GROUP AIPatrol The Group managed by the FSM.
|
||||
-- @param #string From The From State string.
|
||||
-- @param #string Event The Event string.
|
||||
-- @param #string To The To State string.
|
||||
function AI_A2G_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
||||
function AI_AIR_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
||||
|
||||
self:F2()
|
||||
|
||||
@ -295,34 +321,82 @@ function AI_A2G_PATROL:onafterPatrolRoute( AIPatrol, From, Event, To )
|
||||
true
|
||||
)
|
||||
PatrolRoute[#PatrolRoute+1] = FromWP
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToWP = ToTargetCoord:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
PatrolRoute[#PatrolRoute+1] = ToWP
|
||||
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = AIPatrol:TaskFunction( "AI_A2G_PATROL.___PatrolRoute", self )
|
||||
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
||||
|
||||
AIPatrol:OptionROEReturnFire()
|
||||
AIPatrol:OptionROTEvadeFire()
|
||||
if self.racetrack then
|
||||
|
||||
-- Random heading.
|
||||
local heading = math.random(self.racetrackheadingmin, self.racetrackheadingmax)
|
||||
|
||||
-- Random leg length.
|
||||
local leg=math.random(self.racetracklegmin, self.racetracklegmax)
|
||||
|
||||
-- Random duration if any.
|
||||
local duration = self.racetrackdurationmin
|
||||
if self.racetrackdurationmax then
|
||||
duration=math.random(self.racetrackdurationmin, self.racetrackdurationmax)
|
||||
end
|
||||
|
||||
-- CAP coordinate.
|
||||
local c0=self.PatrolZone:GetRandomCoordinate()
|
||||
if self.racetrackcapcoordinates and #self.racetrackcapcoordinates>0 then
|
||||
c0=self.racetrackcapcoordinates[math.random(#self.racetrackcapcoordinates)]
|
||||
end
|
||||
|
||||
-- Race track points.
|
||||
local c1=c0:SetAltitude(altitude) --Core.Point#COORDINATE
|
||||
local c2=c1:Translate(leg, heading):SetAltitude(altitude)
|
||||
|
||||
self:SetTargetDistance(c0) -- For RTB status check
|
||||
|
||||
-- Debug:
|
||||
self:T(string.format("Patrol zone race track: v=%.1f knots, h=%.1f ft, heading=%03d, leg=%d m, t=%s sec", UTILS.KmphToKnots(speedkmh), UTILS.MetersToFeet(altitude), heading, leg, tostring(duration)))
|
||||
--c1:MarkToAll("Race track c1")
|
||||
--c2:MarkToAll("Race track c2")
|
||||
|
||||
AIPatrol:Route( PatrolRoute, self.TaskDelay )
|
||||
-- Task to orbit.
|
||||
local taskOrbit=AIPatrol:TaskOrbit(c1, altitude, UTILS.KmphToMps(speedkmh), c2)
|
||||
|
||||
-- Task function to redo the patrol at other random position.
|
||||
local taskPatrol=AIPatrol:TaskFunction("AI_A2A_PATROL.PatrolRoute", self)
|
||||
|
||||
-- Controlled task with task condition.
|
||||
local taskCond=AIPatrol:TaskCondition(nil, nil, nil, nil, duration, nil)
|
||||
local taskCont=AIPatrol:TaskControlled(taskOrbit, taskCond)
|
||||
|
||||
-- Second waypoint
|
||||
PatrolRoute[2]=c1:WaypointAirTurningPoint(self.PatrolAltType, speedkmh, {taskCont, taskPatrol}, "CAP Orbit")
|
||||
|
||||
else
|
||||
|
||||
--- Create a route point of type air.
|
||||
local ToWP = ToTargetCoord:WaypointAir(
|
||||
self.PatrolAltType,
|
||||
POINT_VEC3.RoutePointType.TurningPoint,
|
||||
POINT_VEC3.RoutePointAction.TurningPoint,
|
||||
ToTargetSpeed,
|
||||
true
|
||||
)
|
||||
|
||||
PatrolRoute[#PatrolRoute+1] = ToWP
|
||||
|
||||
local Tasks = {}
|
||||
Tasks[#Tasks+1] = AIPatrol:TaskFunction( "AI_AIR_PATROL.___PatrolRoute", self )
|
||||
PatrolRoute[#PatrolRoute].task = AIPatrol:TaskCombo( Tasks )
|
||||
|
||||
AIPatrol:OptionROEReturnFire()
|
||||
AIPatrol:OptionROTEvadeFire()
|
||||
|
||||
AIPatrol:Route( PatrolRoute, self.TaskDelay )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIPatrol
|
||||
function AI_A2G_PATROL.Resume( AIPatrol, Fsm )
|
||||
function AI_AIR_PATROL.Resume( AIPatrol, Fsm )
|
||||
|
||||
AIPatrol:F( { "AI_A2G_PATROL.Resume:", AIPatrol:GetName() } )
|
||||
AIPatrol:F( { "AI_AIR_PATROL.Resume:", AIPatrol:GetName() } )
|
||||
if AIPatrol:IsAlive() then
|
||||
Fsm:__Reset( Fsm.TaskDelay )
|
||||
Fsm:__PatrolRoute( Fsm.TaskDelay )
|
||||
@ -58,6 +58,14 @@ RADIOSPEECH.Vocabulary.EN = {
|
||||
["80"] = { "80", 0.26 },
|
||||
["90"] = { "90", 0.36 },
|
||||
["100"] = { "100", 0.55 },
|
||||
["200"] = { "200", 0.55 },
|
||||
["300"] = { "300", 0.61 },
|
||||
["400"] = { "400", 0.60 },
|
||||
["500"] = { "500", 0.61 },
|
||||
["600"] = { "600", 0.65 },
|
||||
["700"] = { "700", 0.70 },
|
||||
["800"] = { "800", 0.54 },
|
||||
["900"] = { "900", 0.60 },
|
||||
["1000"] = { "1000", 1 },
|
||||
|
||||
["chevy"] = { "chevy", 0.35 },
|
||||
@ -70,7 +78,6 @@ RADIOSPEECH.Vocabulary.EN = {
|
||||
["uzi"] = { "uzi", 0.28 },
|
||||
|
||||
["degrees"] = { "degrees", 0.5 },
|
||||
["<EFBFBD>"] = { "degrees", 0.5 },
|
||||
["kilometers"] = { "kilometers", 0.65 },
|
||||
["km"] = { "kilometers", 0.65 },
|
||||
["miles"] = { "miles", 0.45 },
|
||||
@ -81,7 +88,7 @@ RADIOSPEECH.Vocabulary.EN = {
|
||||
|
||||
|
||||
["returning to base"] = { "returning_to_base", 0.85 },
|
||||
["moving on to ground target"] = { "moving_on_to_ground_target", 1.20 },
|
||||
["on route to ground target"] = { "on_route_to_ground_target", 1.05 },
|
||||
["engaging ground target"] = { "engaging_ground_target", 1.20 },
|
||||
["wheels up"] = { "wheels_up", 0.42 },
|
||||
["landing at base"] = { "landing at base", 0.8 },
|
||||
|
||||
@ -71,17 +71,15 @@ __Moose.Include( 'Scripts/Moose/Ops/RescueHelo.lua' )
|
||||
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Balancer.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air_Patrol.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Air_Engage.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Patrol.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Cap.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Gci.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2A_Dispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Engage.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_BAI.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_CAS.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_SEAD.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Patrol.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_A2G_Dispatcher.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Patrol.lua' )
|
||||
__Moose.Include( 'Scripts/Moose/AI/AI_Cap.lua' )
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user