diff --git a/Moose Development/Moose/AI/AI_Balancer.lua b/Moose Development/Moose/AI/AI_Balancer.lua
index e8d91a3bc..a5b58a4d1 100644
--- a/Moose Development/Moose/AI/AI_Balancer.lua
+++ b/Moose Development/Moose/AI/AI_Balancer.lua
@@ -1,4 +1,4 @@
---- SP:N MP:Y AI:Y HU:N TYP:A -- This module contains the AI_BALANCER class. AI Balancing will replace in multi player missions
+--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions
-- non-occupied human slots with AI groups, in order to provide an engaging simulation environment,
-- even when there are hardly any players in the mission.
--
diff --git a/Moose Development/Moose/AI/AI_CAP.lua b/Moose Development/Moose/AI/AI_CAP.lua
new file mode 100644
index 000000000..f1bac8c91
--- /dev/null
+++ b/Moose Development/Moose/AI/AI_CAP.lua
@@ -0,0 +1,542 @@
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Execute Combat Air Patrol (CAP).**
+--
+-- 
+--
+-- Examples can be found in the test missions.
+--
+-- ===
+--
+-- # 1) @{#AI_CAP_ZONE} class, extends @{AI.AI_Cap#AI_PATROL_ZONE}
+--
+-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
+-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
+--
+-- 
+--
+-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
+--
+-- 
+--
+-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
+-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+--
+-- 
+--
+-- This cycle will continue.
+--
+-- 
+--
+-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
+--
+-- 
+--
+-- When enemies are detected, the AI will automatically engage the enemy.
+--
+-- 
+--
+-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
+--
+-- 
+--
+-- ## 1.1) AI_CAP_ZONE constructor
+--
+-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object.
+--
+-- ## 1.2) AI_CAP_ZONE is a FSM
+--
+-- 
+--
+-- ### 1.2.1) AI_CAP_ZONE 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..
+--
+-- ### 1.2.2) AI_CAP_ZONE Events
+--
+-- * **Start** ( Group ): Start the process.
+-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
+-- * **Engage** ( Group ): Let the AI engage the bogeys.
+-- * **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.
+--
+-- ## 1.3) Set the Range of Engagement
+--
+-- 
+--
+-- An optional range can be set in meters,
+-- 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_CAP_ZONE.SetEngageRange}() to define that range.
+--
+-- ## 1.4) Set the Zone of Engagement
+--
+-- 
+--
+-- 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_CAP_ZONE.SetEngageZone}() to define that Zone.
+--
+-- ====
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- 2017-01-15: Initial class and API.
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
+-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
+-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Concept, Design & Programming.
+--
+-- @module AI_Cap
+
+
+--- AI_CAP_ZONE class
+-- @type AI_CAP_ZONE
+-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
+-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
+-- @extends AI.AI_Patrol#AI_PATROL_ZONE
+AI_CAP_ZONE = {
+ ClassName = "AI_CAP_ZONE",
+}
+
+
+
+--- Creates a new AI_CAP_ZONE object
+-- @param #AI_CAP_ZONE self
+-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
+-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
+-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed )
+
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAP_ZONE
+
+ self.Accomplished = false
+ self.Engaging = false
+
+ self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Engage.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeEngage
+ -- @param #AI_CAP_ZONE 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 Engage.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterEngage
+ -- @param #AI_CAP_ZONE 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 Engage.
+ -- @function [parent=#AI_CAP_ZONE] Engage
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Engage.
+ -- @function [parent=#AI_CAP_ZONE] __Engage
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+--- OnLeave Transition Handler for State Engaging.
+-- @function [parent=#AI_CAP_ZONE] OnLeaveEngaging
+-- @param #AI_CAP_ZONE 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 Engaging.
+-- @function [parent=#AI_CAP_ZONE] OnEnterEngaging
+-- @param #AI_CAP_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Fired.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeFired
+ -- @param #AI_CAP_ZONE 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 Fired.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterFired
+ -- @param #AI_CAP_ZONE 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 Fired.
+ -- @function [parent=#AI_CAP_ZONE] Fired
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Fired.
+ -- @function [parent=#AI_CAP_ZONE] __Fired
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Destroy.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeDestroy
+ -- @param #AI_CAP_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy
+ -- @param #AI_CAP_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAP_ZONE] Destroy
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Destroy.
+ -- @function [parent=#AI_CAP_ZONE] __Destroy
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+
+ self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Abort.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeAbort
+ -- @param #AI_CAP_ZONE 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 Abort.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterAbort
+ -- @param #AI_CAP_ZONE 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 Abort.
+ -- @function [parent=#AI_CAP_ZONE] Abort
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Abort.
+ -- @function [parent=#AI_CAP_ZONE] __Abort
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeAccomplish
+ -- @param #AI_CAP_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish
+ -- @param #AI_CAP_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] Accomplish
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] __Accomplish
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ return self
+end
+
+
+--- Set the Engage Zone which defines where the AI will engage bogies.
+-- @param #AI_CAP_ZONE self
+-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:SetEngageZone( EngageZone )
+ self:F2()
+
+ if EngageZone then
+ self.EngageZone = EngageZone
+ else
+ self.EngageZone = nil
+ end
+end
+
+--- Set the Engage Range when the AI will engage with airborne enemies.
+-- @param #AI_CAP_ZONE self
+-- @param #number EngageRange The Engage Range.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:SetEngageRange( EngageRange )
+ self:F2()
+
+ if EngageRange then
+ self.EngageRange = EngageRange
+ else
+ self.EngageRange = nil
+ end
+end
+
+--- onafter State Transition for Event Start.
+-- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterStart( Controllable, From, Event, To )
+
+
+ self:Route()
+ self:__Status( 30 ) -- Check status status every 30 seconds.
+ self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
+
+ self:EventOnDead( self.OnDead )
+
+ Controllable:OptionROEOpenFire()
+end
+
+--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
+function _NewEngageCapRoute( AIControllable )
+
+ AIControllable:T( "NewEngageRoute" )
+ local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_CAP_ZONE
+ EngageZone:__Engage( 1 )
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To )
+
+ if self.Accomplished == true then
+ return false
+ end
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
+
+ if From ~= "Engaging" then
+
+ local Engage = false
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
+ Engage = true
+ break
+ end
+ end
+
+ if Engage == true then
+ self:E( 'Detected -> Engaging' )
+ self:__Engage( 1 )
+ end
+ end
+end
+
+
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
+
+ if Controllable:IsAlive() then
+
+ self:Detect( self.EngageZone )
+
+ local EngageRoute = {}
+
+ --- Calculate the current route point.
+ local CurrentVec2 = self.Controllable:GetVec2()
+
+ --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
+ local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
+ local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = CurrentRoutePoint
+
+
+ --- Find a random 2D point in PatrolZone.
+ local ToTargetVec2 = self.PatrolZone:GetRandomVec2()
+ self:T2( ToTargetVec2 )
+
+ --- Define Speed and Altitude.
+ local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
+ self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
+
+ --- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
+
+ --- Create a route point of type air.
+ local ToPatrolRoutePoint = ToTargetPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToTargetSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
+
+ Controllable:OptionROEOpenFire()
+ Controllable:OptionROTPassiveDefense()
+
+ local AttackTasks = {}
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
+ if self.EngageZone then
+ if DetectedUnit:IsInZone( self.EngageZone ) then
+ self:E( {"Within Zone and Engaging ", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ if self.EngageRange then
+ if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then
+ self:E( {"Within Range and Engaging", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ end
+ else
+ self.DetectedUnits[DetectedUnit] = nil
+ end
+ end
+
+ --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
+ self.Controllable:WayPointInitialize( EngageRoute )
+
+
+ if #AttackTasks == 0 then
+ self:E("No targets found -> Going back to Patrolling")
+ self:Accomplish()
+ self:Route()
+ else
+ EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
+
+ --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
+ self.Controllable:SetState( self.Controllable, "EngageZone", self )
+
+ self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" )
+
+ end
+
+ --- NOW ROUTE THE GROUP!
+ self.Controllable:WayPointExecute( 1, 2 )
+
+ end
+end
+
+--- @param #AI_CAP_ZONE 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.
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
+
+ if EventData.IniUnit then
+ self.DetectedUnits[EventData.IniUnit] = nil
+ end
+
+ Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
+ self.Accomplished = true
+ self.DetectUnits = false
+end
+
+--- @param #AI_CAP_ZONE self
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAP_ZONE:OnDead( EventData )
+ self:T( { "EventDead", EventData } )
+
+ if EventData.IniDCSUnit then
+ self:__Destroy( 1, EventData )
+ end
+end
+
+
diff --git a/Moose Development/Moose/AI/AI_CAS.lua b/Moose Development/Moose/AI/AI_CAS.lua
index 12317910a..53dba83bf 100644
--- a/Moose Development/Moose/AI/AI_CAS.lua
+++ b/Moose Development/Moose/AI/AI_CAS.lua
@@ -1,4 +1,4 @@
---- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- This module contains the AI_CAS_ZONE class.
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.**
--
-- 
--
@@ -79,7 +79,7 @@
-- * **Engaging** ( Group ): The AI is engaging the targets in the Engage Zone, executing CAS.
-- * **Returning** ( Group ): The AI is returning to Base..
--
--- ### 1.2.2) AI_CAS_ZONE Events:
+-- ### 1.2.2) AI_CAS_ZONE Events
--
-- * **Start** ( Group ): Start the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
@@ -312,9 +312,9 @@ end
--- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets.
--- @param #AI_PATROL_ZONE self
+-- @param #AI_CAS_ZONE self
-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS.
--- @return #AI_PATROL_ZONE self
+-- @return #AI_CAS_ZONE self
function AI_CAS_ZONE:SetEngageZone( EngageZone )
self:F2()
@@ -338,7 +338,7 @@ function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To )
self:Route()
self:__Status( 30 ) -- Check status status every 30 seconds.
- self:__Detect( 30, self.EngageZone ) -- Detect for new targets every 30 seconds in the EngageZone.
+ self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
self:EventOnDead( self.OnDead )
diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua
index e8963c927..903181661 100644
--- a/Moose Development/Moose/AI/AI_Cargo.lua
+++ b/Moose Development/Moose/AI/AI_Cargo.lua
@@ -1,4 +1,4 @@
---- Management of logical cargo objects, that can be transported from and to transportation carriers.
+--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers.
--
-- ===
--
diff --git a/Moose Development/Moose/AI/AI_Patrol.lua b/Moose Development/Moose/AI/AI_Patrol.lua
index c8d08d230..e008e3d86 100644
--- a/Moose Development/Moose/AI/AI_Patrol.lua
+++ b/Moose Development/Moose/AI/AI_Patrol.lua
@@ -1,4 +1,4 @@
---- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Make AI patrol zones and report detected targets.
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Air Patrolling or Staging.**
--
-- 
--
@@ -9,12 +9,36 @@
-- # 1) @{#AI_PATROL_ZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE}
--
-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
--- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started.
+--
+-- 
+--
+-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
+--
+-- 
+--
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
--- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+--
+-- 
+--
+-- This cycle will continue.
+--
+-- 
+--
+-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
+--
+-- 
+--
+---- Note that the enemy is not engaged! To model enemy engagement, either tailor the **Detected** event, or
+-- use derived AI_ classes to model AI offensive or defensive behaviour.
+--
+-- 
+--
+-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
--
+-- 
+--
-- ## 1.1) AI_PATROL_ZONE constructor
--
-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object.
@@ -29,7 +53,7 @@
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Returning** ( Group ): The AI is returning to Base..
--
--- ### 1.2.2) AI_PATROL_ZONE Events:
+-- ### 1.2.2) AI_PATROL_ZONE Events
--
-- * **Start** ( Group ): Start the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
@@ -155,6 +179,8 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit
self:ManageFuel( .2, 60 )
self:ManageDamage( 10 )
+
+ self:SetDetectionInterval( 30 )
self.DetectedUnits = {} -- This table contains the targets detected during patrol.
@@ -525,6 +551,8 @@ end
--- @param Wrapper.Controllable#CONTROLLABLE Controllable
function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
+ local Detected = false
+
local DetectedTargets = Controllable:GetDetectedTargets()
for TargetID, Target in pairs( DetectedTargets ) do
local TargetObject = Target.object
@@ -537,14 +565,20 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
if self.DetectionZone then
if TargetUnit:IsInZone( self.DetectionZone ) then
self:T( {"Detected ", TargetUnit } )
- self.DetectedUnits[TargetUnit] = TargetUnit
+ self.DetectedUnits[TargetUnit] = TargetUnit
+ Detected = true
end
- else
+ else
self.DetectedUnits[TargetUnit] = TargetUnit
+ Detected = true
end
end
end
+ if Detected == true then
+ self:__Detected( 1 )
+ end
+
self:__Detect( self.DetectInterval )
end
diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua
index 710bc0da7..ed13ffe2e 100644
--- a/Moose Development/Moose/Moose.lua
+++ b/Moose Development/Moose/Moose.lua
@@ -42,8 +42,9 @@ Include.File( "Functional/Detection" )
--- AI Classes
Include.File( "AI/AI_Balancer" )
Include.File( "AI/AI_Patrol" )
-Include.File( "AI/AI_Cargo" )
+Include.File( "AI/AI_Cap" )
Include.File( "AI/AI_Cas" )
+Include.File( "AI/AI_Cargo" )
--- Actions
Include.File( "Actions/Act_Assign" )
diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua
index 220bc6fb5..d1d998934 100644
--- a/Moose Development/Moose/Wrapper/Group.lua
+++ b/Moose Development/Moose/Wrapper/Group.lua
@@ -205,6 +205,23 @@ function GROUP:GetDCSObject()
return nil
end
+--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
+-- @param Wrapper.Positionable#POSITIONABLE self
+-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
+-- @return #nil The POSITIONABLE is not existing or alive.
+function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
+ self:F2( self.PositionableName )
+
+ local DCSPositionable = self:GetDCSObject()
+
+ if DCSPositionable then
+ local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p
+ self:T3( PositionablePosition )
+ return PositionablePosition
+ end
+
+ return nil
+end
--- Returns if the DCS Group is alive.
-- When the group exists at run-time, this method will return true, otherwise false.
diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua
index 696f64c10..343e8bf90 100644
--- a/Moose Development/Moose/Wrapper/Positionable.lua
+++ b/Moose Development/Moose/Wrapper/Positionable.lua
@@ -45,6 +45,7 @@ POSITIONABLE = {
function POSITIONABLE:New( PositionableName )
local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) )
+ self.PositionableName = PositionableName
return self
end
@@ -53,12 +54,12 @@ end
-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPositionVec3()
- self:F2( self.PositionableName )
+ self:E( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
- local PositionablePosition = DCSPositionable:getPosition()
+ local PositionablePosition = DCSPositionable:getPosition().p
self:T3( PositionablePosition )
return PositionablePosition
end
@@ -110,6 +111,27 @@ function POSITIONABLE:GetPointVec2()
return nil
end
+--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission.
+-- @param Wrapper.Positionable#POSITIONABLE self
+-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
+-- @return #nil The POSITIONABLE is not existing or alive.
+function POSITIONABLE:GetPointVec3()
+ self:F2( self.PositionableName )
+
+ local DCSPositionable = self:GetDCSObject()
+
+ if DCSPositionable then
+ local PositionableVec3 = self:GetPositionVec3()
+
+ local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 )
+
+ self:T2( PositionablePointVec3 )
+ return PositionablePointVec3
+ end
+
+ return nil
+end
+
--- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
index e3eb62072..35e9efd8c 100644
--- a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
+++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua
@@ -1,5 +1,5 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
-env.info( 'Moose Generation Timestamp: 20170115_2219' )
+env.info( 'Moose Generation Timestamp: 20170116_1223' )
local base = _G
Include = {}
@@ -12110,6 +12110,7 @@ POSITIONABLE = {
function POSITIONABLE:New( PositionableName )
local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) )
+ self.PositionableName = PositionableName
return self
end
@@ -12118,12 +12119,12 @@ end
-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPositionVec3()
- self:F2( self.PositionableName )
+ self:E( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
- local PositionablePosition = DCSPositionable:getPosition()
+ local PositionablePosition = DCSPositionable:getPosition().p
self:T3( PositionablePosition )
return PositionablePosition
end
@@ -12175,6 +12176,27 @@ function POSITIONABLE:GetPointVec2()
return nil
end
+--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission.
+-- @param Wrapper.Positionable#POSITIONABLE self
+-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
+-- @return #nil The POSITIONABLE is not existing or alive.
+function POSITIONABLE:GetPointVec3()
+ self:F2( self.PositionableName )
+
+ local DCSPositionable = self:GetDCSObject()
+
+ if DCSPositionable then
+ local PositionableVec3 = self:GetPositionVec3()
+
+ local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 )
+
+ self:T2( PositionablePointVec3 )
+ return PositionablePointVec3
+ end
+
+ return nil
+end
+
--- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
@@ -14972,6 +14994,23 @@ function GROUP:GetDCSObject()
return nil
end
+--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
+-- @param Wrapper.Positionable#POSITIONABLE self
+-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
+-- @return #nil The POSITIONABLE is not existing or alive.
+function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
+ self:F2( self.PositionableName )
+
+ local DCSPositionable = self:GetDCSObject()
+
+ if DCSPositionable then
+ local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p
+ self:T3( PositionablePosition )
+ return PositionablePosition
+ end
+
+ return nil
+end
--- Returns if the DCS Group is alive.
-- When the group exists at run-time, this method will return true, otherwise false.
@@ -24268,7 +24307,7 @@ function DETECTION_AREAS:CreateDetectionSets()
end
---- SP:N MP:Y AI:Y HU:N TYP:A -- This module contains the AI_BALANCER class. AI Balancing will replace in multi player missions
+--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions
-- non-occupied human slots with AI groups, in order to provide an engaging simulation environment,
-- even when there are hardly any players in the mission.
--
@@ -24573,7 +24612,7 @@ end
---- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Make AI patrol zones and report detected targets.
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Air Patrolling or Staging.**
--
-- 
--
@@ -24584,12 +24623,36 @@ end
-- # 1) @{#AI_PATROL_ZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE}
--
-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
--- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started.
+--
+-- 
+--
+-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
+--
+-- 
+--
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
--- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+--
+-- 
+--
+-- This cycle will continue.
+--
+-- 
+--
+-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
+--
+-- 
+--
+---- Note that the enemy is not engaged! To model enemy engagement, either tailor the **Detected** event, or
+-- use derived AI_ classes to model AI offensive or defensive behaviour.
+--
+-- 
+--
+-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
--
+-- 
+--
-- ## 1.1) AI_PATROL_ZONE constructor
--
-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object.
@@ -24604,7 +24667,7 @@ end
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Returning** ( Group ): The AI is returning to Base..
--
--- ### 1.2.2) AI_PATROL_ZONE Events:
+-- ### 1.2.2) AI_PATROL_ZONE Events
--
-- * **Start** ( Group ): Start the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
@@ -24730,6 +24793,8 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit
self:ManageFuel( .2, 60 )
self:ManageDamage( 10 )
+
+ self:SetDetectionInterval( 30 )
self.DetectedUnits = {} -- This table contains the targets detected during patrol.
@@ -25100,6 +25165,8 @@ end
--- @param Wrapper.Controllable#CONTROLLABLE Controllable
function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
+ local Detected = false
+
local DetectedTargets = Controllable:GetDetectedTargets()
for TargetID, Target in pairs( DetectedTargets ) do
local TargetObject = Target.object
@@ -25112,14 +25179,20 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
if self.DetectionZone then
if TargetUnit:IsInZone( self.DetectionZone ) then
self:T( {"Detected ", TargetUnit } )
- self.DetectedUnits[TargetUnit] = TargetUnit
+ self.DetectedUnits[TargetUnit] = TargetUnit
+ Detected = true
end
- else
+ else
self.DetectedUnits[TargetUnit] = TargetUnit
+ Detected = true
end
end
end
+ if Detected == true then
+ self:__Detected( 1 )
+ end
+
self:__Detect( self.DetectInterval )
end
@@ -25318,7 +25391,1073 @@ function AI_PATROL_ZONE:onafterRTB()
end
-end--- Management of logical cargo objects, that can be transported from and to transportation carriers.
+end--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.**
+--
+-- 
+--
+-- Examples can be found in the test missions.
+--
+-- ===
+--
+-- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE}
+--
+-- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
+--
+-- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
+-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
+--
+-- 
+--
+-- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
+--
+-- 
+--
+-- Upon started, The AI will **Route** itself towards the random 3D point within a patrol zone,
+-- using a random speed within the given altitude and speed limits.
+-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+-- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+--
+-- 
+--
+-- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone.
+-- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI.
+--
+-- 
+--
+-- The AI will detect the targets and will only destroy the targets within the Engage Zone.
+--
+-- 
+--
+-- Every target that is destroyed, is reported< by the AI.
+--
+-- 
+--
+-- Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone.
+--
+-- 
+--
+-- Until it is notified through the event **Accomplish**, which is to be triggered by an observing party:
+--
+-- * a FAC
+-- * a timed event
+-- * a menu option selected by a human
+-- * a condition
+-- * others ...
+--
+-- 
+--
+-- When the AI has accomplished the CAS, it will fly back to the Patrol Zone.
+--
+-- 
+--
+-- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone.
+-- It can be notified to go RTB through the **RTB** event.
+--
+-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
+--
+-- 
+--
+-- # 1.1) AI_CAS_ZONE constructor
+--
+-- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object.
+--
+-- ## 1.2) AI_CAS_ZONE is a FSM
+--
+-- 
+--
+-- ### 1.2.1) AI_CAS_ZONE 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 targets in the Engage Zone, executing CAS.
+-- * **Returning** ( Group ): The AI is returning to Base..
+--
+-- ### 1.2.2) AI_CAS_ZONE Events
+--
+-- * **Start** ( Group ): Start the process.
+-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
+-- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
+-- * **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.
+--
+-- ====
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- 2017-01-15: Initial class and API.
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
+-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
+-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Concept, Design & Programming.
+--
+-- @module AI_Cas
+
+
+--- AI_CAS_ZONE class
+-- @type AI_CAS_ZONE
+-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
+-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
+-- @extends AI.AI_Patrol#AI_CAS_ZONE
+AI_CAS_ZONE = {
+ ClassName = "AI_CAS_ZONE",
+}
+
+
+
+--- Creates a new AI_CAS_ZONE object
+-- @param #AI_CAS_ZONE self
+-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
+-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
+-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
+-- @param Core.Zone#ZONE EngageZone
+-- @return #AI_CAS_ZONE self
+function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone )
+
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE
+
+ self.EngageZone = EngageZone
+ self.Accomplished = false
+
+ self:SetDetectionZone( self.EngageZone )
+
+ self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Engage.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage
+ -- @param #AI_CAS_ZONE 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 Engage.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterEngage
+ -- @param #AI_CAS_ZONE 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 Engage.
+ -- @function [parent=#AI_CAS_ZONE] Engage
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Engage.
+ -- @function [parent=#AI_CAS_ZONE] __Engage
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+--- OnLeave Transition Handler for State Engaging.
+-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
+-- @param #AI_CAS_ZONE 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 Engaging.
+-- @function [parent=#AI_CAS_ZONE] OnEnterEngaging
+-- @param #AI_CAS_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Fired.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeFired
+ -- @param #AI_CAS_ZONE 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 Fired.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterFired
+ -- @param #AI_CAS_ZONE 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 Fired.
+ -- @function [parent=#AI_CAS_ZONE] Fired
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Fired.
+ -- @function [parent=#AI_CAS_ZONE] __Fired
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Destroy.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy
+ -- @param #AI_CAS_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy
+ -- @param #AI_CAS_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAS_ZONE] Destroy
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Destroy.
+ -- @function [parent=#AI_CAS_ZONE] __Destroy
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+
+ self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Abort.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort
+ -- @param #AI_CAS_ZONE 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 Abort.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterAbort
+ -- @param #AI_CAS_ZONE 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 Abort.
+ -- @function [parent=#AI_CAS_ZONE] Abort
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Abort.
+ -- @function [parent=#AI_CAS_ZONE] __Abort
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish
+ -- @param #AI_CAS_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish
+ -- @param #AI_CAS_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] Accomplish
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] __Accomplish
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ return self
+end
+
+
+--- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets.
+-- @param #AI_CAS_ZONE self
+-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS.
+-- @return #AI_CAS_ZONE self
+function AI_CAS_ZONE:SetEngageZone( EngageZone )
+ self:F2()
+
+ if EngageZone then
+ self.EngageZone = EngageZone
+ else
+ self.EngageZone = nil
+ end
+end
+
+
+
+--- onafter State Transition for Event Start.
+-- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterStart( Controllable, From, Event, To )
+
+
+ self:Route()
+ self:__Status( 30 ) -- Check status status every 30 seconds.
+ self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
+
+ self:EventOnDead( self.OnDead )
+
+ Controllable:OptionROEHoldFire()
+ Controllable:OptionROTVertical()
+end
+
+--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
+function _NewEngageRoute( AIControllable )
+
+ AIControllable:T( "NewEngageRoute" )
+ local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE
+ EngageZone:__Engage( 1 )
+end
+
+--- @param #AI_CAS_ZONE 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_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
+
+ if self.Accomplished == true then
+ return false
+ end
+end
+
+
+--- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterEngage( Controllable, From, Event, To )
+
+ if Controllable:IsAlive() then
+
+ self:Detect( self.EngageZone )
+
+ local EngageRoute = {}
+
+ --- Calculate the current route point.
+ local CurrentVec2 = self.Controllable:GetVec2()
+
+ --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
+ local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
+ local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = CurrentRoutePoint
+
+
+ if self.Controllable:IsNotInZone( self.EngageZone ) then
+
+ -- Find a random 2D point in EngageZone.
+ local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
+ self:T2( ToEngageZoneVec2 )
+
+ -- Define Speed and Altitude.
+ local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ self:T2( ToEngageZoneSpeed )
+
+ -- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y )
+
+ -- Create a route point of type air.
+ local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
+
+ end
+
+ --- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
+
+ --- Find a random 2D point in EngageZone.
+ local ToTargetVec2 = self.EngageZone:GetRandomVec2()
+ self:T2( ToTargetVec2 )
+
+ --- Define Speed and Altitude.
+ local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
+ self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
+
+ --- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
+
+ --- Create a route point of type air.
+ local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToTargetSpeed,
+ true
+ )
+
+ ToTargetPointVec3:SmokeBlue()
+
+ EngageRoute[#EngageRoute+1] = ToTargetRoutePoint
+
+
+ Controllable:OptionROEOpenFire()
+ Controllable:OptionROTPassiveDefense()
+
+ local AttackTasks = {}
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() then
+ if DetectedUnit:IsInZone( self.EngageZone ) then
+ self:E( {"Engaging ", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ self.DetectedUnits[DetectedUnit] = nil
+ end
+ end
+
+ EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
+
+ --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
+ self.Controllable:WayPointInitialize( EngageRoute )
+
+ --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
+ self.Controllable:SetState( self.Controllable, "EngageZone", self )
+
+ self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" )
+
+ --- NOW ROUTE THE GROUP!
+ self.Controllable:WayPointExecute( 1, 2 )
+ end
+end
+
+--- @param #AI_CAS_ZONE 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.
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
+
+ if EventData.IniUnit then
+ self.DetectedUnits[EventData.IniUnit] = nil
+ end
+
+ Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
+end
+
+--- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
+ self.Accomplished = true
+ self.DetectUnits = false
+end
+
+--- @param #AI_CAS_ZONE self
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAS_ZONE:OnDead( EventData )
+ self:T( { "EventDead", EventData } )
+
+ if EventData.IniDCSUnit then
+ self:__Destroy( 1, EventData )
+ end
+end
+
+
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Execute Combat Air Patrol (CAP).**
+--
+-- 
+--
+-- Examples can be found in the test missions.
+--
+-- ===
+--
+-- # 1) @{#AI_CAP_ZONE} class, extends @{AI.AI_Cap#AI_PATROL_ZONE}
+--
+-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
+-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
+--
+-- 
+--
+-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
+--
+-- 
+--
+-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
+-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+--
+-- 
+--
+-- This cycle will continue.
+--
+-- 
+--
+-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
+--
+-- 
+--
+-- When enemies are detected, the AI will automatically engage the enemy.
+--
+-- 
+--
+-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
+--
+-- 
+--
+-- ## 1.1) AI_CAP_ZONE constructor
+--
+-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object.
+--
+-- ## 1.2) AI_CAP_ZONE is a FSM
+--
+-- 
+--
+-- ### 1.2.1) AI_CAP_ZONE 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..
+--
+-- ### 1.2.2) AI_CAP_ZONE Events
+--
+-- * **Start** ( Group ): Start the process.
+-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
+-- * **Engage** ( Group ): Let the AI engage the bogeys.
+-- * **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.
+--
+-- ## 1.3) Set the Range of Engagement
+--
+-- 
+--
+-- An optional range can be set in meters,
+-- 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_CAP_ZONE.SetEngageRange}() to define that range.
+--
+-- ## 1.4) Set the Zone of Engagement
+--
+-- 
+--
+-- 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_CAP_ZONE.SetEngageZone}() to define that Zone.
+--
+-- ====
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- 2017-01-15: Initial class and API.
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
+-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
+-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Concept, Design & Programming.
+--
+-- @module AI_Cap
+
+
+--- AI_CAP_ZONE class
+-- @type AI_CAP_ZONE
+-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
+-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
+-- @extends AI.AI_Patrol#AI_PATROL_ZONE
+AI_CAP_ZONE = {
+ ClassName = "AI_CAP_ZONE",
+}
+
+
+
+--- Creates a new AI_CAP_ZONE object
+-- @param #AI_CAP_ZONE self
+-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
+-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
+-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed )
+
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAP_ZONE
+
+ self.Accomplished = false
+ self.Engaging = false
+
+ self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Engage.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeEngage
+ -- @param #AI_CAP_ZONE 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 Engage.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterEngage
+ -- @param #AI_CAP_ZONE 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 Engage.
+ -- @function [parent=#AI_CAP_ZONE] Engage
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Engage.
+ -- @function [parent=#AI_CAP_ZONE] __Engage
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+--- OnLeave Transition Handler for State Engaging.
+-- @function [parent=#AI_CAP_ZONE] OnLeaveEngaging
+-- @param #AI_CAP_ZONE 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 Engaging.
+-- @function [parent=#AI_CAP_ZONE] OnEnterEngaging
+-- @param #AI_CAP_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Fired.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeFired
+ -- @param #AI_CAP_ZONE 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 Fired.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterFired
+ -- @param #AI_CAP_ZONE 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 Fired.
+ -- @function [parent=#AI_CAP_ZONE] Fired
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Fired.
+ -- @function [parent=#AI_CAP_ZONE] __Fired
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Destroy.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeDestroy
+ -- @param #AI_CAP_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy
+ -- @param #AI_CAP_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAP_ZONE] Destroy
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Destroy.
+ -- @function [parent=#AI_CAP_ZONE] __Destroy
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+
+ self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Abort.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeAbort
+ -- @param #AI_CAP_ZONE 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 Abort.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterAbort
+ -- @param #AI_CAP_ZONE 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 Abort.
+ -- @function [parent=#AI_CAP_ZONE] Abort
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Abort.
+ -- @function [parent=#AI_CAP_ZONE] __Abort
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeAccomplish
+ -- @param #AI_CAP_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish
+ -- @param #AI_CAP_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] Accomplish
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] __Accomplish
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ return self
+end
+
+
+--- Set the Engage Zone which defines where the AI will engage bogies.
+-- @param #AI_CAP_ZONE self
+-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:SetEngageZone( EngageZone )
+ self:F2()
+
+ if EngageZone then
+ self.EngageZone = EngageZone
+ else
+ self.EngageZone = nil
+ end
+end
+
+--- Set the Engage Range when the AI will engage with airborne enemies.
+-- @param #AI_CAP_ZONE self
+-- @param #number EngageRange The Engage Range.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:SetEngageRange( EngageRange )
+ self:F2()
+
+ if EngageRange then
+ self.EngageRange = EngageRange
+ else
+ self.EngageRange = nil
+ end
+end
+
+--- onafter State Transition for Event Start.
+-- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterStart( Controllable, From, Event, To )
+
+
+ self:Route()
+ self:__Status( 30 ) -- Check status status every 30 seconds.
+ self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
+
+ self:EventOnDead( self.OnDead )
+
+ Controllable:OptionROEOpenFire()
+end
+
+--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
+function _NewEngageCapRoute( AIControllable )
+
+ AIControllable:T( "NewEngageRoute" )
+ local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_CAP_ZONE
+ EngageZone:__Engage( 1 )
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To )
+
+ if self.Accomplished == true then
+ return false
+ end
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
+
+ if From ~= "Engaging" then
+
+ local Engage = false
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
+ Engage = true
+ break
+ end
+ end
+
+ if Engage == true then
+ self:E( 'Detected -> Engaging' )
+ self:__Engage( 1 )
+ end
+ end
+end
+
+
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
+
+ if Controllable:IsAlive() then
+
+ self:Detect( self.EngageZone )
+
+ local EngageRoute = {}
+
+ --- Calculate the current route point.
+ local CurrentVec2 = self.Controllable:GetVec2()
+
+ --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
+ local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
+ local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = CurrentRoutePoint
+
+
+ --- Find a random 2D point in PatrolZone.
+ local ToTargetVec2 = self.PatrolZone:GetRandomVec2()
+ self:T2( ToTargetVec2 )
+
+ --- Define Speed and Altitude.
+ local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
+ self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
+
+ --- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
+
+ --- Create a route point of type air.
+ local ToPatrolRoutePoint = ToTargetPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToTargetSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
+
+ Controllable:OptionROEOpenFire()
+ Controllable:OptionROTPassiveDefense()
+
+ local AttackTasks = {}
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
+ if self.EngageZone then
+ if DetectedUnit:IsInZone( self.EngageZone ) then
+ self:E( {"Within Zone and Engaging ", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ if self.EngageRange then
+ if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then
+ self:E( {"Within Range and Engaging", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ end
+ else
+ self.DetectedUnits[DetectedUnit] = nil
+ end
+ end
+
+ --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
+ self.Controllable:WayPointInitialize( EngageRoute )
+
+
+ if #AttackTasks == 0 then
+ self:E("No targets found -> Going back to Patrolling")
+ self:Accomplish()
+ self:Route()
+ else
+ EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
+
+ --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
+ self.Controllable:SetState( self.Controllable, "EngageZone", self )
+
+ self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" )
+
+ end
+
+ --- NOW ROUTE THE GROUP!
+ self.Controllable:WayPointExecute( 1, 2 )
+
+ end
+end
+
+--- @param #AI_CAP_ZONE 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.
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
+
+ if EventData.IniUnit then
+ self.DetectedUnits[EventData.IniUnit] = nil
+ end
+
+ Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
+ self.Accomplished = true
+ self.DetectUnits = false
+end
+
+--- @param #AI_CAP_ZONE self
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAP_ZONE:OnDead( EventData )
+ self:T( { "EventDead", EventData } )
+
+ if EventData.IniDCSUnit then
+ self:__Destroy( 1, EventData )
+ end
+end
+
+
+--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers.
--
-- ===
--
@@ -26343,530 +27482,6 @@ end -- AI_CARGO_GROUPED
---- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- This module contains the AI_CAS_ZONE class.
---
--- 
---
--- Examples can be found in the test missions.
---
--- ===
---
--- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE}
---
--- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
---
--- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
--- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
---
--- 
---
--- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
---
--- 
---
--- Upon started, The AI will **Route** itself towards the random 3D point within a patrol zone,
--- using a random speed within the given altitude and speed limits.
--- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
--- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
---
--- 
---
--- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone.
--- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI.
---
--- 
---
--- The AI will detect the targets and will only destroy the targets within the Engage Zone.
---
--- 
---
--- Every target that is destroyed, is reported< by the AI.
---
--- 
---
--- Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone.
---
--- 
---
--- Until it is notified through the event **Accomplish**, which is to be triggered by an observing party:
---
--- * a FAC
--- * a timed event
--- * a menu option selected by a human
--- * a condition
--- * others ...
---
--- 
---
--- When the AI has accomplished the CAS, it will fly back to the Patrol Zone.
---
--- 
---
--- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone.
--- It can be notified to go RTB through the **RTB** event.
---
--- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
---
--- 
---
--- # 1.1) AI_CAS_ZONE constructor
---
--- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object.
---
--- ## 1.2) AI_CAS_ZONE is a FSM
---
--- 
---
--- ### 1.2.1) AI_CAS_ZONE 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 targets in the Engage Zone, executing CAS.
--- * **Returning** ( Group ): The AI is returning to Base..
---
--- ### 1.2.2) AI_CAS_ZONE Events:
---
--- * **Start** ( Group ): Start the process.
--- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
--- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
--- * **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.
---
--- ====
---
--- # **API CHANGE HISTORY**
---
--- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
---
--- * **Added** parts are expressed in bold type face.
--- * _Removed_ parts are expressed in italic type face.
---
--- Hereby the change log:
---
--- 2017-01-15: Initial class and API.
---
--- ===
---
--- # **AUTHORS and CONTRIBUTIONS**
---
--- ### Contributions:
---
--- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
--- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
--- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
---
--- ### Authors:
---
--- * **FlightControl**: Concept, Design & Programming.
---
--- @module AI_Cas
-
-
---- AI_CAS_ZONE class
--- @type AI_CAS_ZONE
--- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
--- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
--- @extends AI.AI_Patrol#AI_CAS_ZONE
-AI_CAS_ZONE = {
- ClassName = "AI_CAS_ZONE",
-}
-
-
-
---- Creates a new AI_CAS_ZONE object
--- @param #AI_CAS_ZONE self
--- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
--- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
--- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
--- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
--- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
--- @param Core.Zone#ZONE EngageZone
--- @return #AI_CAS_ZONE self
-function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone )
-
- -- Inherits from BASE
- local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE
-
- self.EngageZone = EngageZone
- self.Accomplished = false
-
- self:SetDetectionZone( self.EngageZone )
-
- self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Engage.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage
- -- @param #AI_CAS_ZONE 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 Engage.
- -- @function [parent=#AI_CAS_ZONE] OnAfterEngage
- -- @param #AI_CAS_ZONE 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 Engage.
- -- @function [parent=#AI_CAS_ZONE] Engage
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Engage.
- -- @function [parent=#AI_CAS_ZONE] __Engage
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
---- OnLeave Transition Handler for State Engaging.
--- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
--- @param #AI_CAS_ZONE 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 Engaging.
--- @function [parent=#AI_CAS_ZONE] OnEnterEngaging
--- @param #AI_CAS_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Fired.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeFired
- -- @param #AI_CAS_ZONE 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 Fired.
- -- @function [parent=#AI_CAS_ZONE] OnAfterFired
- -- @param #AI_CAS_ZONE 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 Fired.
- -- @function [parent=#AI_CAS_ZONE] Fired
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Fired.
- -- @function [parent=#AI_CAS_ZONE] __Fired
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
- self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Destroy.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy
- -- @param #AI_CAS_ZONE 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 Destroy.
- -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy
- -- @param #AI_CAS_ZONE 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 Destroy.
- -- @function [parent=#AI_CAS_ZONE] Destroy
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Destroy.
- -- @function [parent=#AI_CAS_ZONE] __Destroy
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
-
- self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Abort.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort
- -- @param #AI_CAS_ZONE 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 Abort.
- -- @function [parent=#AI_CAS_ZONE] OnAfterAbort
- -- @param #AI_CAS_ZONE 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 Abort.
- -- @function [parent=#AI_CAS_ZONE] Abort
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Abort.
- -- @function [parent=#AI_CAS_ZONE] __Abort
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
- self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Accomplish.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish
- -- @param #AI_CAS_ZONE 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 Accomplish.
- -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish
- -- @param #AI_CAS_ZONE 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 Accomplish.
- -- @function [parent=#AI_CAS_ZONE] Accomplish
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Accomplish.
- -- @function [parent=#AI_CAS_ZONE] __Accomplish
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
- return self
-end
-
-
---- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets.
--- @param #AI_PATROL_ZONE self
--- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS.
--- @return #AI_PATROL_ZONE self
-function AI_CAS_ZONE:SetEngageZone( EngageZone )
- self:F2()
-
- if EngageZone then
- self.EngageZone = EngageZone
- else
- self.EngageZone = nil
- end
-end
-
-
-
---- onafter State Transition for Event Start.
--- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterStart( Controllable, From, Event, To )
-
-
- self:Route()
- self:__Status( 30 ) -- Check status status every 30 seconds.
- self:__Detect( 30, self.EngageZone ) -- Detect for new targets every 30 seconds in the EngageZone.
-
- self:EventOnDead( self.OnDead )
-
- Controllable:OptionROEHoldFire()
- Controllable:OptionROTVertical()
-end
-
---- @param Wrapper.Controllable#CONTROLLABLE AIControllable
-function _NewEngageRoute( AIControllable )
-
- AIControllable:T( "NewEngageRoute" )
- local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE
- EngageZone:__Engage( 1 )
-end
-
---- @param #AI_CAS_ZONE 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_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
-
- if self.Accomplished == true then
- return false
- end
-end
-
-
---- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterEngage( Controllable, From, Event, To )
-
- if Controllable:IsAlive() then
-
- self:Detect( self.EngageZone )
-
- local EngageRoute = {}
-
- --- Calculate the current route point.
- local CurrentVec2 = self.Controllable:GetVec2()
-
- --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
- local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
- local ToEngageZoneSpeed = self.PatrolMaxSpeed
- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
- POINT_VEC3.RoutePointAltType.BARO,
- POINT_VEC3.RoutePointType.TurningPoint,
- POINT_VEC3.RoutePointAction.TurningPoint,
- ToEngageZoneSpeed,
- true
- )
-
- EngageRoute[#EngageRoute+1] = CurrentRoutePoint
-
-
- if self.Controllable:IsNotInZone( self.EngageZone ) then
-
- -- Find a random 2D point in EngageZone.
- local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
- self:T2( ToEngageZoneVec2 )
-
- -- Define Speed and Altitude.
- local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
- local ToEngageZoneSpeed = self.PatrolMaxSpeed
- self:T2( ToEngageZoneSpeed )
-
- -- Obtain a 3D @{Point} from the 2D point + altitude.
- local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y )
-
- -- Create a route point of type air.
- local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
- POINT_VEC3.RoutePointAltType.BARO,
- POINT_VEC3.RoutePointType.TurningPoint,
- POINT_VEC3.RoutePointAction.TurningPoint,
- ToEngageZoneSpeed,
- true
- )
-
- EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
-
- end
-
- --- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
-
- --- Find a random 2D point in EngageZone.
- local ToTargetVec2 = self.EngageZone:GetRandomVec2()
- self:T2( ToTargetVec2 )
-
- --- Define Speed and Altitude.
- local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
- local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
- self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
-
- --- Obtain a 3D @{Point} from the 2D point + altitude.
- local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
-
- --- Create a route point of type air.
- local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
- POINT_VEC3.RoutePointAltType.BARO,
- POINT_VEC3.RoutePointType.TurningPoint,
- POINT_VEC3.RoutePointAction.TurningPoint,
- ToTargetSpeed,
- true
- )
-
- ToTargetPointVec3:SmokeBlue()
-
- EngageRoute[#EngageRoute+1] = ToTargetRoutePoint
-
-
- Controllable:OptionROEOpenFire()
- Controllable:OptionROTPassiveDefense()
-
- local AttackTasks = {}
-
- for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
- local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
- self:T( DetectedUnit )
- if DetectedUnit:IsAlive() then
- if DetectedUnit:IsInZone( self.EngageZone ) then
- self:E( {"Engaging ", DetectedUnit } )
- AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
- end
- else
- self.DetectedUnits[DetectedUnit] = nil
- end
- end
-
- EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
-
- --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
- self.Controllable:WayPointInitialize( EngageRoute )
-
- --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
- self.Controllable:SetState( self.Controllable, "EngageZone", self )
-
- self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" )
-
- --- NOW ROUTE THE GROUP!
- self.Controllable:WayPointExecute( 1, 2 )
- end
-end
-
---- @param #AI_CAS_ZONE 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.
--- @param Core.Event#EVENTDATA EventData
-function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
-
- if EventData.IniUnit then
- self.DetectedUnits[EventData.IniUnit] = nil
- end
-
- Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
-end
-
---- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
- self.Accomplished = true
- self.DetectUnits = false
-end
-
---- @param #AI_CAS_ZONE self
--- @param Core.Event#EVENTDATA EventData
-function AI_CAS_ZONE:OnDead( EventData )
- self:T( { "EventDead", EventData } )
-
- if EventData.IniDCSUnit then
- self:__Destroy( 1, EventData )
- end
-end
-
-
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
--
-- ===
@@ -30833,8 +31448,9 @@ Include.File( "Functional/Detection" )
--- AI Classes
Include.File( "AI/AI_Balancer" )
Include.File( "AI/AI_Patrol" )
-Include.File( "AI/AI_Cargo" )
+Include.File( "AI/AI_Cap" )
Include.File( "AI/AI_Cas" )
+Include.File( "AI/AI_Cargo" )
--- Actions
Include.File( "Actions/Act_Assign" )
diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua
index e3eb62072..35e9efd8c 100644
--- a/Moose Mission Setup/Moose.lua
+++ b/Moose Mission Setup/Moose.lua
@@ -1,5 +1,5 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
-env.info( 'Moose Generation Timestamp: 20170115_2219' )
+env.info( 'Moose Generation Timestamp: 20170116_1223' )
local base = _G
Include = {}
@@ -12110,6 +12110,7 @@ POSITIONABLE = {
function POSITIONABLE:New( PositionableName )
local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) )
+ self.PositionableName = PositionableName
return self
end
@@ -12118,12 +12119,12 @@ end
-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetPositionVec3()
- self:F2( self.PositionableName )
+ self:E( self.PositionableName )
local DCSPositionable = self:GetDCSObject()
if DCSPositionable then
- local PositionablePosition = DCSPositionable:getPosition()
+ local PositionablePosition = DCSPositionable:getPosition().p
self:T3( PositionablePosition )
return PositionablePosition
end
@@ -12175,6 +12176,27 @@ function POSITIONABLE:GetPointVec2()
return nil
end
+--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission.
+-- @param Wrapper.Positionable#POSITIONABLE self
+-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE.
+-- @return #nil The POSITIONABLE is not existing or alive.
+function POSITIONABLE:GetPointVec3()
+ self:F2( self.PositionableName )
+
+ local DCSPositionable = self:GetDCSObject()
+
+ if DCSPositionable then
+ local PositionableVec3 = self:GetPositionVec3()
+
+ local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 )
+
+ self:T2( PositionablePointVec3 )
+ return PositionablePointVec3
+ end
+
+ return nil
+end
+
--- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission.
-- @param Wrapper.Positionable#POSITIONABLE self
@@ -14972,6 +14994,23 @@ function GROUP:GetDCSObject()
return nil
end
+--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission.
+-- @param Wrapper.Positionable#POSITIONABLE self
+-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE.
+-- @return #nil The POSITIONABLE is not existing or alive.
+function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3()
+ self:F2( self.PositionableName )
+
+ local DCSPositionable = self:GetDCSObject()
+
+ if DCSPositionable then
+ local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p
+ self:T3( PositionablePosition )
+ return PositionablePosition
+ end
+
+ return nil
+end
--- Returns if the DCS Group is alive.
-- When the group exists at run-time, this method will return true, otherwise false.
@@ -24268,7 +24307,7 @@ function DETECTION_AREAS:CreateDetectionSets()
end
---- SP:N MP:Y AI:Y HU:N TYP:A -- This module contains the AI_BALANCER class. AI Balancing will replace in multi player missions
+--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions
-- non-occupied human slots with AI groups, in order to provide an engaging simulation environment,
-- even when there are hardly any players in the mission.
--
@@ -24573,7 +24612,7 @@ end
---- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Make AI patrol zones and report detected targets.
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Air Patrolling or Staging.**
--
-- 
--
@@ -24584,12 +24623,36 @@ end
-- # 1) @{#AI_PATROL_ZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE}
--
-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}.
--- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started.
+--
+-- 
+--
+-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
+--
+-- 
+--
-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
--- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+--
+-- 
+--
+-- This cycle will continue.
+--
+-- 
+--
+-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
+--
+-- 
+--
+---- Note that the enemy is not engaged! To model enemy engagement, either tailor the **Detected** event, or
+-- use derived AI_ classes to model AI offensive or defensive behaviour.
+--
+-- 
+--
+-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
--
+-- 
+--
-- ## 1.1) AI_PATROL_ZONE constructor
--
-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object.
@@ -24604,7 +24667,7 @@ end
-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone.
-- * **Returning** ( Group ): The AI is returning to Base..
--
--- ### 1.2.2) AI_PATROL_ZONE Events:
+-- ### 1.2.2) AI_PATROL_ZONE Events
--
-- * **Start** ( Group ): Start the process.
-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
@@ -24730,6 +24793,8 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit
self:ManageFuel( .2, 60 )
self:ManageDamage( 10 )
+
+ self:SetDetectionInterval( 30 )
self.DetectedUnits = {} -- This table contains the targets detected during patrol.
@@ -25100,6 +25165,8 @@ end
--- @param Wrapper.Controllable#CONTROLLABLE Controllable
function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
+ local Detected = false
+
local DetectedTargets = Controllable:GetDetectedTargets()
for TargetID, Target in pairs( DetectedTargets ) do
local TargetObject = Target.object
@@ -25112,14 +25179,20 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
if self.DetectionZone then
if TargetUnit:IsInZone( self.DetectionZone ) then
self:T( {"Detected ", TargetUnit } )
- self.DetectedUnits[TargetUnit] = TargetUnit
+ self.DetectedUnits[TargetUnit] = TargetUnit
+ Detected = true
end
- else
+ else
self.DetectedUnits[TargetUnit] = TargetUnit
+ Detected = true
end
end
end
+ if Detected == true then
+ self:__Detected( 1 )
+ end
+
self:__Detect( self.DetectInterval )
end
@@ -25318,7 +25391,1073 @@ function AI_PATROL_ZONE:onafterRTB()
end
-end--- Management of logical cargo objects, that can be transported from and to transportation carriers.
+end--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.**
+--
+-- 
+--
+-- Examples can be found in the test missions.
+--
+-- ===
+--
+-- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE}
+--
+-- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
+--
+-- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
+-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
+--
+-- 
+--
+-- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
+--
+-- 
+--
+-- Upon started, The AI will **Route** itself towards the random 3D point within a patrol zone,
+-- using a random speed within the given altitude and speed limits.
+-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+-- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+--
+-- 
+--
+-- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone.
+-- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI.
+--
+-- 
+--
+-- The AI will detect the targets and will only destroy the targets within the Engage Zone.
+--
+-- 
+--
+-- Every target that is destroyed, is reported< by the AI.
+--
+-- 
+--
+-- Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone.
+--
+-- 
+--
+-- Until it is notified through the event **Accomplish**, which is to be triggered by an observing party:
+--
+-- * a FAC
+-- * a timed event
+-- * a menu option selected by a human
+-- * a condition
+-- * others ...
+--
+-- 
+--
+-- When the AI has accomplished the CAS, it will fly back to the Patrol Zone.
+--
+-- 
+--
+-- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone.
+-- It can be notified to go RTB through the **RTB** event.
+--
+-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
+--
+-- 
+--
+-- # 1.1) AI_CAS_ZONE constructor
+--
+-- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object.
+--
+-- ## 1.2) AI_CAS_ZONE is a FSM
+--
+-- 
+--
+-- ### 1.2.1) AI_CAS_ZONE 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 targets in the Engage Zone, executing CAS.
+-- * **Returning** ( Group ): The AI is returning to Base..
+--
+-- ### 1.2.2) AI_CAS_ZONE Events
+--
+-- * **Start** ( Group ): Start the process.
+-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
+-- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
+-- * **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.
+--
+-- ====
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- 2017-01-15: Initial class and API.
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
+-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
+-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Concept, Design & Programming.
+--
+-- @module AI_Cas
+
+
+--- AI_CAS_ZONE class
+-- @type AI_CAS_ZONE
+-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
+-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
+-- @extends AI.AI_Patrol#AI_CAS_ZONE
+AI_CAS_ZONE = {
+ ClassName = "AI_CAS_ZONE",
+}
+
+
+
+--- Creates a new AI_CAS_ZONE object
+-- @param #AI_CAS_ZONE self
+-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
+-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
+-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
+-- @param Core.Zone#ZONE EngageZone
+-- @return #AI_CAS_ZONE self
+function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone )
+
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE
+
+ self.EngageZone = EngageZone
+ self.Accomplished = false
+
+ self:SetDetectionZone( self.EngageZone )
+
+ self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Engage.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage
+ -- @param #AI_CAS_ZONE 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 Engage.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterEngage
+ -- @param #AI_CAS_ZONE 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 Engage.
+ -- @function [parent=#AI_CAS_ZONE] Engage
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Engage.
+ -- @function [parent=#AI_CAS_ZONE] __Engage
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+--- OnLeave Transition Handler for State Engaging.
+-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
+-- @param #AI_CAS_ZONE 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 Engaging.
+-- @function [parent=#AI_CAS_ZONE] OnEnterEngaging
+-- @param #AI_CAS_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Fired.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeFired
+ -- @param #AI_CAS_ZONE 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 Fired.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterFired
+ -- @param #AI_CAS_ZONE 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 Fired.
+ -- @function [parent=#AI_CAS_ZONE] Fired
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Fired.
+ -- @function [parent=#AI_CAS_ZONE] __Fired
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Destroy.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy
+ -- @param #AI_CAS_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy
+ -- @param #AI_CAS_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAS_ZONE] Destroy
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Destroy.
+ -- @function [parent=#AI_CAS_ZONE] __Destroy
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+
+ self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Abort.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort
+ -- @param #AI_CAS_ZONE 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 Abort.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterAbort
+ -- @param #AI_CAS_ZONE 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 Abort.
+ -- @function [parent=#AI_CAS_ZONE] Abort
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Abort.
+ -- @function [parent=#AI_CAS_ZONE] __Abort
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
+
+ --- OnBefore Transition Handler for Event Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish
+ -- @param #AI_CAS_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish
+ -- @param #AI_CAS_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] Accomplish
+ -- @param #AI_CAS_ZONE self
+
+ --- Asynchronous Event Trigger for Event Accomplish.
+ -- @function [parent=#AI_CAS_ZONE] __Accomplish
+ -- @param #AI_CAS_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ return self
+end
+
+
+--- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets.
+-- @param #AI_CAS_ZONE self
+-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS.
+-- @return #AI_CAS_ZONE self
+function AI_CAS_ZONE:SetEngageZone( EngageZone )
+ self:F2()
+
+ if EngageZone then
+ self.EngageZone = EngageZone
+ else
+ self.EngageZone = nil
+ end
+end
+
+
+
+--- onafter State Transition for Event Start.
+-- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterStart( Controllable, From, Event, To )
+
+
+ self:Route()
+ self:__Status( 30 ) -- Check status status every 30 seconds.
+ self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
+
+ self:EventOnDead( self.OnDead )
+
+ Controllable:OptionROEHoldFire()
+ Controllable:OptionROTVertical()
+end
+
+--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
+function _NewEngageRoute( AIControllable )
+
+ AIControllable:T( "NewEngageRoute" )
+ local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE
+ EngageZone:__Engage( 1 )
+end
+
+--- @param #AI_CAS_ZONE 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_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
+
+ if self.Accomplished == true then
+ return false
+ end
+end
+
+
+--- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterEngage( Controllable, From, Event, To )
+
+ if Controllable:IsAlive() then
+
+ self:Detect( self.EngageZone )
+
+ local EngageRoute = {}
+
+ --- Calculate the current route point.
+ local CurrentVec2 = self.Controllable:GetVec2()
+
+ --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
+ local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
+ local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = CurrentRoutePoint
+
+
+ if self.Controllable:IsNotInZone( self.EngageZone ) then
+
+ -- Find a random 2D point in EngageZone.
+ local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
+ self:T2( ToEngageZoneVec2 )
+
+ -- Define Speed and Altitude.
+ local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ self:T2( ToEngageZoneSpeed )
+
+ -- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y )
+
+ -- Create a route point of type air.
+ local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
+
+ end
+
+ --- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
+
+ --- Find a random 2D point in EngageZone.
+ local ToTargetVec2 = self.EngageZone:GetRandomVec2()
+ self:T2( ToTargetVec2 )
+
+ --- Define Speed and Altitude.
+ local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
+ self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
+
+ --- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
+
+ --- Create a route point of type air.
+ local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToTargetSpeed,
+ true
+ )
+
+ ToTargetPointVec3:SmokeBlue()
+
+ EngageRoute[#EngageRoute+1] = ToTargetRoutePoint
+
+
+ Controllable:OptionROEOpenFire()
+ Controllable:OptionROTPassiveDefense()
+
+ local AttackTasks = {}
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() then
+ if DetectedUnit:IsInZone( self.EngageZone ) then
+ self:E( {"Engaging ", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ self.DetectedUnits[DetectedUnit] = nil
+ end
+ end
+
+ EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
+
+ --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
+ self.Controllable:WayPointInitialize( EngageRoute )
+
+ --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
+ self.Controllable:SetState( self.Controllable, "EngageZone", self )
+
+ self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" )
+
+ --- NOW ROUTE THE GROUP!
+ self.Controllable:WayPointExecute( 1, 2 )
+ end
+end
+
+--- @param #AI_CAS_ZONE 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.
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
+
+ if EventData.IniUnit then
+ self.DetectedUnits[EventData.IniUnit] = nil
+ end
+
+ Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
+end
+
+--- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
+ self.Accomplished = true
+ self.DetectUnits = false
+end
+
+--- @param #AI_CAS_ZONE self
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAS_ZONE:OnDead( EventData )
+ self:T( { "EventDead", EventData } )
+
+ if EventData.IniDCSUnit then
+ self:__Destroy( 1, EventData )
+ end
+end
+
+
+--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Execute Combat Air Patrol (CAP).**
+--
+-- 
+--
+-- Examples can be found in the test missions.
+--
+-- ===
+--
+-- # 1) @{#AI_CAP_ZONE} class, extends @{AI.AI_Cap#AI_PATROL_ZONE}
+--
+-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}
+-- and automatically engage any airborne enemies that are within a certain range or within a certain zone.
+--
+-- 
+--
+-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
+--
+-- 
+--
+-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
+-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+--
+-- 
+--
+-- This cycle will continue.
+--
+-- 
+--
+-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event.
+--
+-- 
+--
+-- When enemies are detected, the AI will automatically engage the enemy.
+--
+-- 
+--
+-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
+--
+-- 
+--
+-- ## 1.1) AI_CAP_ZONE constructor
+--
+-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object.
+--
+-- ## 1.2) AI_CAP_ZONE is a FSM
+--
+-- 
+--
+-- ### 1.2.1) AI_CAP_ZONE 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..
+--
+-- ### 1.2.2) AI_CAP_ZONE Events
+--
+-- * **Start** ( Group ): Start the process.
+-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
+-- * **Engage** ( Group ): Let the AI engage the bogeys.
+-- * **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.
+--
+-- ## 1.3) Set the Range of Engagement
+--
+-- 
+--
+-- An optional range can be set in meters,
+-- 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_CAP_ZONE.SetEngageRange}() to define that range.
+--
+-- ## 1.4) Set the Zone of Engagement
+--
+-- 
+--
+-- 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_CAP_ZONE.SetEngageZone}() to define that Zone.
+--
+-- ====
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- 2017-01-15: Initial class and API.
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
+-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
+-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Concept, Design & Programming.
+--
+-- @module AI_Cap
+
+
+--- AI_CAP_ZONE class
+-- @type AI_CAP_ZONE
+-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
+-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
+-- @extends AI.AI_Patrol#AI_PATROL_ZONE
+AI_CAP_ZONE = {
+ ClassName = "AI_CAP_ZONE",
+}
+
+
+
+--- Creates a new AI_CAP_ZONE object
+-- @param #AI_CAP_ZONE self
+-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
+-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
+-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
+-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed )
+
+ -- Inherits from BASE
+ local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAP_ZONE
+
+ self.Accomplished = false
+ self.Engaging = false
+
+ self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Engage.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeEngage
+ -- @param #AI_CAP_ZONE 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 Engage.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterEngage
+ -- @param #AI_CAP_ZONE 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 Engage.
+ -- @function [parent=#AI_CAP_ZONE] Engage
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Engage.
+ -- @function [parent=#AI_CAP_ZONE] __Engage
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+--- OnLeave Transition Handler for State Engaging.
+-- @function [parent=#AI_CAP_ZONE] OnLeaveEngaging
+-- @param #AI_CAP_ZONE 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 Engaging.
+-- @function [parent=#AI_CAP_ZONE] OnEnterEngaging
+-- @param #AI_CAP_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Fired.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeFired
+ -- @param #AI_CAP_ZONE 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 Fired.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterFired
+ -- @param #AI_CAP_ZONE 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 Fired.
+ -- @function [parent=#AI_CAP_ZONE] Fired
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Fired.
+ -- @function [parent=#AI_CAP_ZONE] __Fired
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Destroy.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeDestroy
+ -- @param #AI_CAP_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy
+ -- @param #AI_CAP_ZONE 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 Destroy.
+ -- @function [parent=#AI_CAP_ZONE] Destroy
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Destroy.
+ -- @function [parent=#AI_CAP_ZONE] __Destroy
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+
+ self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Abort.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeAbort
+ -- @param #AI_CAP_ZONE 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 Abort.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterAbort
+ -- @param #AI_CAP_ZONE 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 Abort.
+ -- @function [parent=#AI_CAP_ZONE] Abort
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Abort.
+ -- @function [parent=#AI_CAP_ZONE] __Abort
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE.
+
+ --- OnBefore Transition Handler for Event Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] OnBeforeAccomplish
+ -- @param #AI_CAP_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish
+ -- @param #AI_CAP_ZONE 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 Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] Accomplish
+ -- @param #AI_CAP_ZONE self
+
+ --- Asynchronous Event Trigger for Event Accomplish.
+ -- @function [parent=#AI_CAP_ZONE] __Accomplish
+ -- @param #AI_CAP_ZONE self
+ -- @param #number Delay The delay in seconds.
+
+ return self
+end
+
+
+--- Set the Engage Zone which defines where the AI will engage bogies.
+-- @param #AI_CAP_ZONE self
+-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:SetEngageZone( EngageZone )
+ self:F2()
+
+ if EngageZone then
+ self.EngageZone = EngageZone
+ else
+ self.EngageZone = nil
+ end
+end
+
+--- Set the Engage Range when the AI will engage with airborne enemies.
+-- @param #AI_CAP_ZONE self
+-- @param #number EngageRange The Engage Range.
+-- @return #AI_CAP_ZONE self
+function AI_CAP_ZONE:SetEngageRange( EngageRange )
+ self:F2()
+
+ if EngageRange then
+ self.EngageRange = EngageRange
+ else
+ self.EngageRange = nil
+ end
+end
+
+--- onafter State Transition for Event Start.
+-- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterStart( Controllable, From, Event, To )
+
+
+ self:Route()
+ self:__Status( 30 ) -- Check status status every 30 seconds.
+ self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
+
+ self:EventOnDead( self.OnDead )
+
+ Controllable:OptionROEOpenFire()
+end
+
+--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
+function _NewEngageCapRoute( AIControllable )
+
+ AIControllable:T( "NewEngageRoute" )
+ local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_CAP_ZONE
+ EngageZone:__Engage( 1 )
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To )
+
+ if self.Accomplished == true then
+ return false
+ end
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterDetected( Controllable, From, Event, To )
+
+ if From ~= "Engaging" then
+
+ local Engage = false
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
+ Engage = true
+ break
+ end
+ end
+
+ if Engage == true then
+ self:E( 'Detected -> Engaging' )
+ self:__Engage( 1 )
+ end
+ end
+end
+
+
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
+
+ if Controllable:IsAlive() then
+
+ self:Detect( self.EngageZone )
+
+ local EngageRoute = {}
+
+ --- Calculate the current route point.
+ local CurrentVec2 = self.Controllable:GetVec2()
+
+ --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
+ local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
+ local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
+ local ToEngageZoneSpeed = self.PatrolMaxSpeed
+ local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToEngageZoneSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = CurrentRoutePoint
+
+
+ --- Find a random 2D point in PatrolZone.
+ local ToTargetVec2 = self.PatrolZone:GetRandomVec2()
+ self:T2( ToTargetVec2 )
+
+ --- Define Speed and Altitude.
+ local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
+ local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
+ self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
+
+ --- Obtain a 3D @{Point} from the 2D point + altitude.
+ local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
+
+ --- Create a route point of type air.
+ local ToPatrolRoutePoint = ToTargetPointVec3:RoutePointAir(
+ POINT_VEC3.RoutePointAltType.BARO,
+ POINT_VEC3.RoutePointType.TurningPoint,
+ POINT_VEC3.RoutePointAction.TurningPoint,
+ ToTargetSpeed,
+ true
+ )
+
+ EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint
+
+ Controllable:OptionROEOpenFire()
+ Controllable:OptionROTPassiveDefense()
+
+ local AttackTasks = {}
+
+ for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
+ local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
+ self:T( DetectedUnit )
+ if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
+ if self.EngageZone then
+ if DetectedUnit:IsInZone( self.EngageZone ) then
+ self:E( {"Within Zone and Engaging ", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ if self.EngageRange then
+ if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then
+ self:E( {"Within Range and Engaging", DetectedUnit } )
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ else
+ AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
+ end
+ end
+ else
+ self.DetectedUnits[DetectedUnit] = nil
+ end
+ end
+
+ --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
+ self.Controllable:WayPointInitialize( EngageRoute )
+
+
+ if #AttackTasks == 0 then
+ self:E("No targets found -> Going back to Patrolling")
+ self:Accomplish()
+ self:Route()
+ else
+ EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
+
+ --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
+ self.Controllable:SetState( self.Controllable, "EngageZone", self )
+
+ self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" )
+
+ end
+
+ --- NOW ROUTE THE GROUP!
+ self.Controllable:WayPointExecute( 1, 2 )
+
+ end
+end
+
+--- @param #AI_CAP_ZONE 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.
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
+
+ if EventData.IniUnit then
+ self.DetectedUnits[EventData.IniUnit] = nil
+ end
+
+ Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
+end
+
+--- @param #AI_CAP_ZONE 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_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
+ self.Accomplished = true
+ self.DetectUnits = false
+end
+
+--- @param #AI_CAP_ZONE self
+-- @param Core.Event#EVENTDATA EventData
+function AI_CAP_ZONE:OnDead( EventData )
+ self:T( { "EventDead", EventData } )
+
+ if EventData.IniDCSUnit then
+ self:__Destroy( 1, EventData )
+ end
+end
+
+
+--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers.
--
-- ===
--
@@ -26343,530 +27482,6 @@ end -- AI_CARGO_GROUPED
---- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- This module contains the AI_CAS_ZONE class.
---
--- 
---
--- Examples can be found in the test missions.
---
--- ===
---
--- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE}
---
--- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour.
---
--- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}.
--- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone.
---
--- 
---
--- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
---
--- 
---
--- Upon started, The AI will **Route** itself towards the random 3D point within a patrol zone,
--- using a random speed within the given altitude and speed limits.
--- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
--- This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
---
--- 
---
--- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone.
--- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI.
---
--- 
---
--- The AI will detect the targets and will only destroy the targets within the Engage Zone.
---
--- 
---
--- Every target that is destroyed, is reported< by the AI.
---
--- 
---
--- Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone.
---
--- 
---
--- Until it is notified through the event **Accomplish**, which is to be triggered by an observing party:
---
--- * a FAC
--- * a timed event
--- * a menu option selected by a human
--- * a condition
--- * others ...
---
--- 
---
--- When the AI has accomplished the CAS, it will fly back to the Patrol Zone.
---
--- 
---
--- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone.
--- It can be notified to go RTB through the **RTB** event.
---
--- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
---
--- 
---
--- # 1.1) AI_CAS_ZONE constructor
---
--- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object.
---
--- ## 1.2) AI_CAS_ZONE is a FSM
---
--- 
---
--- ### 1.2.1) AI_CAS_ZONE 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 targets in the Engage Zone, executing CAS.
--- * **Returning** ( Group ): The AI is returning to Base..
---
--- ### 1.2.2) AI_CAS_ZONE Events:
---
--- * **Start** ( Group ): Start the process.
--- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
--- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
--- * **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.
---
--- ====
---
--- # **API CHANGE HISTORY**
---
--- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
---
--- * **Added** parts are expressed in bold type face.
--- * _Removed_ parts are expressed in italic type face.
---
--- Hereby the change log:
---
--- 2017-01-15: Initial class and API.
---
--- ===
---
--- # **AUTHORS and CONTRIBUTIONS**
---
--- ### Contributions:
---
--- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
--- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
--- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
---
--- ### Authors:
---
--- * **FlightControl**: Concept, Design & Programming.
---
--- @module AI_Cas
-
-
---- AI_CAS_ZONE class
--- @type AI_CAS_ZONE
--- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
--- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
--- @extends AI.AI_Patrol#AI_CAS_ZONE
-AI_CAS_ZONE = {
- ClassName = "AI_CAS_ZONE",
-}
-
-
-
---- Creates a new AI_CAS_ZONE object
--- @param #AI_CAS_ZONE self
--- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed.
--- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol.
--- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol.
--- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h.
--- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h.
--- @param Core.Zone#ZONE EngageZone
--- @return #AI_CAS_ZONE self
-function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone )
-
- -- Inherits from BASE
- local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE
-
- self.EngageZone = EngageZone
- self.Accomplished = false
-
- self:SetDetectionZone( self.EngageZone )
-
- self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Engage.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage
- -- @param #AI_CAS_ZONE 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 Engage.
- -- @function [parent=#AI_CAS_ZONE] OnAfterEngage
- -- @param #AI_CAS_ZONE 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 Engage.
- -- @function [parent=#AI_CAS_ZONE] Engage
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Engage.
- -- @function [parent=#AI_CAS_ZONE] __Engage
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
---- OnLeave Transition Handler for State Engaging.
--- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging
--- @param #AI_CAS_ZONE 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 Engaging.
--- @function [parent=#AI_CAS_ZONE] OnEnterEngaging
--- @param #AI_CAS_ZONE 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( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Fired.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeFired
- -- @param #AI_CAS_ZONE 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 Fired.
- -- @function [parent=#AI_CAS_ZONE] OnAfterFired
- -- @param #AI_CAS_ZONE 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 Fired.
- -- @function [parent=#AI_CAS_ZONE] Fired
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Fired.
- -- @function [parent=#AI_CAS_ZONE] __Fired
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
- self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Destroy.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy
- -- @param #AI_CAS_ZONE 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 Destroy.
- -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy
- -- @param #AI_CAS_ZONE 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 Destroy.
- -- @function [parent=#AI_CAS_ZONE] Destroy
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Destroy.
- -- @function [parent=#AI_CAS_ZONE] __Destroy
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
-
- self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Abort.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort
- -- @param #AI_CAS_ZONE 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 Abort.
- -- @function [parent=#AI_CAS_ZONE] OnAfterAbort
- -- @param #AI_CAS_ZONE 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 Abort.
- -- @function [parent=#AI_CAS_ZONE] Abort
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Abort.
- -- @function [parent=#AI_CAS_ZONE] __Abort
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
- self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE.
-
- --- OnBefore Transition Handler for Event Accomplish.
- -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish
- -- @param #AI_CAS_ZONE 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 Accomplish.
- -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish
- -- @param #AI_CAS_ZONE 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 Accomplish.
- -- @function [parent=#AI_CAS_ZONE] Accomplish
- -- @param #AI_CAS_ZONE self
-
- --- Asynchronous Event Trigger for Event Accomplish.
- -- @function [parent=#AI_CAS_ZONE] __Accomplish
- -- @param #AI_CAS_ZONE self
- -- @param #number Delay The delay in seconds.
-
- return self
-end
-
-
---- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets.
--- @param #AI_PATROL_ZONE self
--- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS.
--- @return #AI_PATROL_ZONE self
-function AI_CAS_ZONE:SetEngageZone( EngageZone )
- self:F2()
-
- if EngageZone then
- self.EngageZone = EngageZone
- else
- self.EngageZone = nil
- end
-end
-
-
-
---- onafter State Transition for Event Start.
--- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterStart( Controllable, From, Event, To )
-
-
- self:Route()
- self:__Status( 30 ) -- Check status status every 30 seconds.
- self:__Detect( 30, self.EngageZone ) -- Detect for new targets every 30 seconds in the EngageZone.
-
- self:EventOnDead( self.OnDead )
-
- Controllable:OptionROEHoldFire()
- Controllable:OptionROTVertical()
-end
-
---- @param Wrapper.Controllable#CONTROLLABLE AIControllable
-function _NewEngageRoute( AIControllable )
-
- AIControllable:T( "NewEngageRoute" )
- local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE
- EngageZone:__Engage( 1 )
-end
-
---- @param #AI_CAS_ZONE 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_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To )
-
- if self.Accomplished == true then
- return false
- end
-end
-
-
---- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterEngage( Controllable, From, Event, To )
-
- if Controllable:IsAlive() then
-
- self:Detect( self.EngageZone )
-
- local EngageRoute = {}
-
- --- Calculate the current route point.
- local CurrentVec2 = self.Controllable:GetVec2()
-
- --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1).
- local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude()
- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y )
- local ToEngageZoneSpeed = self.PatrolMaxSpeed
- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir(
- POINT_VEC3.RoutePointAltType.BARO,
- POINT_VEC3.RoutePointType.TurningPoint,
- POINT_VEC3.RoutePointAction.TurningPoint,
- ToEngageZoneSpeed,
- true
- )
-
- EngageRoute[#EngageRoute+1] = CurrentRoutePoint
-
-
- if self.Controllable:IsNotInZone( self.EngageZone ) then
-
- -- Find a random 2D point in EngageZone.
- local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2()
- self:T2( ToEngageZoneVec2 )
-
- -- Define Speed and Altitude.
- local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
- local ToEngageZoneSpeed = self.PatrolMaxSpeed
- self:T2( ToEngageZoneSpeed )
-
- -- Obtain a 3D @{Point} from the 2D point + altitude.
- local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y )
-
- -- Create a route point of type air.
- local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir(
- POINT_VEC3.RoutePointAltType.BARO,
- POINT_VEC3.RoutePointType.TurningPoint,
- POINT_VEC3.RoutePointAction.TurningPoint,
- ToEngageZoneSpeed,
- true
- )
-
- EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint
-
- end
-
- --- Define a random point in the @{Zone}. The AI will fly to that point within the zone.
-
- --- Find a random 2D point in EngageZone.
- local ToTargetVec2 = self.EngageZone:GetRandomVec2()
- self:T2( ToTargetVec2 )
-
- --- Define Speed and Altitude.
- local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude )
- local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed )
- self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } )
-
- --- Obtain a 3D @{Point} from the 2D point + altitude.
- local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y )
-
- --- Create a route point of type air.
- local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir(
- POINT_VEC3.RoutePointAltType.BARO,
- POINT_VEC3.RoutePointType.TurningPoint,
- POINT_VEC3.RoutePointAction.TurningPoint,
- ToTargetSpeed,
- true
- )
-
- ToTargetPointVec3:SmokeBlue()
-
- EngageRoute[#EngageRoute+1] = ToTargetRoutePoint
-
-
- Controllable:OptionROEOpenFire()
- Controllable:OptionROTPassiveDefense()
-
- local AttackTasks = {}
-
- for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
- local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
- self:T( DetectedUnit )
- if DetectedUnit:IsAlive() then
- if DetectedUnit:IsInZone( self.EngageZone ) then
- self:E( {"Engaging ", DetectedUnit } )
- AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit )
- end
- else
- self.DetectedUnits[DetectedUnit] = nil
- end
- end
-
- EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
-
- --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable...
- self.Controllable:WayPointInitialize( EngageRoute )
-
- --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ...
- self.Controllable:SetState( self.Controllable, "EngageZone", self )
-
- self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" )
-
- --- NOW ROUTE THE GROUP!
- self.Controllable:WayPointExecute( 1, 2 )
- end
-end
-
---- @param #AI_CAS_ZONE 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.
--- @param Core.Event#EVENTDATA EventData
-function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData )
-
- if EventData.IniUnit then
- self.DetectedUnits[EventData.IniUnit] = nil
- end
-
- Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" )
-end
-
---- @param #AI_CAS_ZONE 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_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
- self.Accomplished = true
- self.DetectUnits = false
-end
-
---- @param #AI_CAS_ZONE self
--- @param Core.Event#EVENTDATA EventData
-function AI_CAS_ZONE:OnDead( EventData )
- self:T( { "EventDead", EventData } )
-
- if EventData.IniDCSUnit then
- self:__Destroy( 1, EventData )
- end
-end
-
-
--- (SP) (MP) (FSM) Accept or reject process for player (task) assignments.
--
-- ===
@@ -30833,8 +31448,9 @@ Include.File( "Functional/Detection" )
--- AI Classes
Include.File( "AI/AI_Balancer" )
Include.File( "AI/AI_Patrol" )
-Include.File( "AI/AI_Cargo" )
+Include.File( "AI/AI_Cap" )
Include.File( "AI/AI_Cas" )
+Include.File( "AI/AI_Cargo" )
--- Actions
Include.File( "Actions/Act_Assign" )
diff --git a/Moose Mission Setup/Moose_Create.bat b/Moose Mission Setup/Moose_Create.bat
index 9ef11dac0..ea27cb4f9 100644
--- a/Moose Mission Setup/Moose_Create.bat
+++ b/Moose Mission Setup/Moose_Create.bat
@@ -80,8 +80,9 @@ COPY /b Moose.lua + %1\Functional\Detection.lua Moose.lua
rem AI Classes
COPY /b Moose.lua + %1\AI\AI_Balancer.lua Moose.lua
COPY /b Moose.lua + %1\AI\AI_Patrol.lua Moose.lua
+COPY /b Moose.lua + %1\AI\AI_Cas.lua Moose.lua
+COPY /b Moose.lua + %1\AI\AI_Cap.lua Moose.lua
COPY /b Moose.lua + %1\AI\AI_Cargo.lua Moose.lua
-COPY /b Moose.lua + %1\AI\AI_CAS.lua Moose.lua
rem Actions
diff --git a/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz b/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz
index c5a0a4265..426c88b41 100644
Binary files a/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz and b/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz differ
diff --git a/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz b/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz
index 6c4e10997..dc29d51b6 100644
Binary files a/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz and b/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz differ
diff --git a/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz b/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz
index c544b34e8..4151a474b 100644
Binary files a/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz and b/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz differ
diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz
index 8a3d9a2d2..2647360d0 100644
Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz differ
diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz b/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz
index 751c31342..f88c29eb0 100644
Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz differ
diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz b/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz
index a2beeac0a..b5b1f2f31 100644
Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz differ
diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz b/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz
index 3db154d00..30d1fd8a0 100644
Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz differ
diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz
index 19c6ccff5..8ad6dd268 100644
Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz differ
diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz b/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz
index 2f9fc6a4f..e5050cda3 100644
Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz differ
diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.lua b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.lua
new file mode 100644
index 000000000..92d27b1b2
--- /dev/null
+++ b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.lua
@@ -0,0 +1,18 @@
+-- Name: CAP-001 - Combat Air Patrol
+-- Author: FlightControl
+-- Date Created: 16 January 2017
+--
+-- # Situation:
+--
+-- # Test cases:
+--
+
+local CapPlane = GROUP:FindByName( "Plane" )
+
+local PatrolZone = ZONE:New( "Patrol Zone" )
+
+local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 )
+
+AICapZone:SetControllable( CapPlane )
+
+AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone.
diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.miz b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.miz
new file mode 100644
index 000000000..8d113c72a
Binary files /dev/null and b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.miz differ
diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.lua b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.lua
new file mode 100644
index 000000000..283396d73
--- /dev/null
+++ b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.lua
@@ -0,0 +1,19 @@
+-- Name: CAP-001 - Combat Air Patrol
+-- Author: FlightControl
+-- Date Created: 16 January 2017
+--
+-- # Situation:
+--
+-- # Test cases:
+--
+
+local CapPlane = GROUP:FindByName( "Plane" )
+
+local PatrolZone = ZONE:New( "Patrol Zone" )
+
+local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 )
+
+AICapZone:SetControllable( CapPlane )
+AICapZone:SetEngageRange( 20000 ) -- Set the Engage Range to 20.000 meters. The AI won't engage when the enemy is beyond 20.000 meters.
+
+AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone.
diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.miz b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.miz
new file mode 100644
index 000000000..b3b660040
Binary files /dev/null and b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.miz differ
diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua
new file mode 100644
index 000000000..5e911a096
--- /dev/null
+++ b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua
@@ -0,0 +1,23 @@
+-- Name: CAP-001 - Combat Air Patrol
+-- Author: FlightControl
+-- Date Created: 16 January 2017
+--
+-- # Situation:
+--
+-- # Test cases:
+--
+
+local CapPlane = GROUP:FindByName( "Plane" )
+
+local PatrolZone = ZONE:New( "Patrol Zone" )
+
+local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 )
+
+local EngageZoneGroup = GROUP:FindByName( "Engage Zone" )
+
+local CapEngageZone = ZONE_POLYGON:New( "Engage Zone", EngageZoneGroup )
+
+AICapZone:SetControllable( CapPlane )
+AICapZone:SetEngageZone( CapEngageZone ) -- Set the Engage Zone. The AI will only engage when the bogeys are within the CapEngageZone.
+
+AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone.
diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.miz b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.miz
new file mode 100644
index 000000000..26f205c91
Binary files /dev/null and b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.miz differ
diff --git a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz
index bbb524ad9..daf610748 100644
Binary files a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz and b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz differ
diff --git a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz
index 450958f64..af7b961fa 100644
Binary files a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz and b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz b/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz
index 8e59506af..28521ce27 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz b/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz
index 1f41f47d5..923838c4d 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz b/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz
index 9e5b8c5a4..ad2537d83 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz and b/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz b/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz
index 049ab5405..6644d11be 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz b/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz
index 57abed429..6dfba76a4 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz b/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz
index 98cf72e54..70f690b00 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz and b/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz b/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz
index 5ced1ce26..ae67a1656 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz differ
diff --git a/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz b/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz
index 503879839..4445eacc8 100644
Binary files a/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz differ
diff --git a/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz b/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz
index 8c20fe7eb..22a183b5a 100644
Binary files a/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz and b/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz differ
diff --git a/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz b/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz
index b0da3e3de..3a52024cf 100644
Binary files a/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz and b/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz differ
diff --git a/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz b/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz
index 3ca93eb69..4b360230e 100644
Binary files a/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz and b/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz differ
diff --git a/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz b/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz
index 51b5f24cc..0feadde85 100644
Binary files a/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz and b/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz differ
diff --git a/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz b/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz
index 0b2e7ea0a..78470505d 100644
Binary files a/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz and b/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz differ
diff --git a/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz b/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz
index dd683384e..bacda2920 100644
Binary files a/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz and b/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz differ
diff --git a/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz b/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz
index 916b1efa9..d1a2fa859 100644
Binary files a/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz and b/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz differ
diff --git a/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz b/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz
index a45bcdd3f..2c48910d4 100644
Binary files a/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz and b/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz differ
diff --git a/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz b/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz
index adac6c44f..3ad808ee7 100644
Binary files a/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz and b/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz differ
diff --git a/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz b/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz
index 2f099cb30..2538b0f82 100644
Binary files a/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz and b/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz differ
diff --git a/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz b/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz
index 802c8c978..92d3cc5fb 100644
Binary files a/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz and b/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz differ
diff --git a/Moose Test Missions/MOOSE_Test_Template.miz b/Moose Test Missions/MOOSE_Test_Template.miz
index 24b47ab60..b898248f8 100644
Binary files a/Moose Test Missions/MOOSE_Test_Template.miz and b/Moose Test Missions/MOOSE_Test_Template.miz differ
diff --git a/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz b/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz
index 863109bdc..175e57495 100644
Binary files a/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz and b/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz
index 1de140f2a..466138adf 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz
index 540ed95f9..0e9679dbd 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz
index b61fe6ede..0246a8a95 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz
index 2d8896842..6899a6ee7 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz b/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz
index d0f6499f7..69469490d 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz and b/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz
index 124684130..fe8b74377 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz differ
diff --git a/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz
index 9202b6364..742f44006 100644
Binary files a/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz differ
diff --git a/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz b/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz
index 042c01361..608a9772f 100644
Binary files a/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz and b/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz differ
diff --git a/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz b/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz
index df187062a..1d63770f7 100644
Binary files a/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz and b/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz differ
diff --git a/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz b/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz
index 573af7752..48e731338 100644
Binary files a/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz and b/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz differ
diff --git a/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz b/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz
index 242a3b103..2ca30e7b7 100644
Binary files a/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz and b/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz b/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz
index 93a1cc81c..0f328fdd1 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz and b/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz b/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz
index aa9087e1d..a321ea25f 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz and b/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz b/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz
index 3b5f9ebb7..a0ff246be 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz and b/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz b/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz
index a3aabb2c7..a3c8735eb 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz and b/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz b/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz
index b15243692..46b861d6d 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz and b/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz b/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz
index 8c999aaba..887ba2dff 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz and b/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz b/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz
index 5c02773b0..e26c4550a 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz and b/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz b/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz
index 2b322d287..108f60af1 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz and b/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz b/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz
index 3cad92191..1470282a0 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz and b/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz b/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz
index 5904f54dc..45cfd45ac 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz and b/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz b/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz
index 6e558cab1..636ac6ee6 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz and b/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz b/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz
index 602631895..6ab25e6b4 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz and b/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz b/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz
index 91e371b08..786c1ec92 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz and b/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz b/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz
index c199d551a..253b3839f 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz and b/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz b/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz
index ac6a7f384..dc7127af8 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz and b/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz differ
diff --git a/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz b/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz
index 19503e2b0..04e46a819 100644
Binary files a/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz and b/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz differ
diff --git a/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz b/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz
index d4c27f002..27a02f851 100644
Binary files a/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz and b/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz differ
diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz
index 749b66e70..a9e7dd877 100644
Binary files a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz and b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz differ
diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz b/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz
index aa19a4be1..8532c0727 100644
Binary files a/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz and b/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz differ
diff --git a/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz b/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz
index dcddd5de1..165214259 100644
Binary files a/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz differ
diff --git a/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz b/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz
index 5da561f33..5127657bf 100644
Binary files a/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz differ
diff --git a/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz b/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz
index 65282dbbd..e0e99c87c 100644
Binary files a/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz differ
diff --git a/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz b/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz
index 80fa70cb7..466d2c93c 100644
Binary files a/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz differ
diff --git a/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz b/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz
index 6ec926530..89b2345fd 100644
Binary files a/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz differ
diff --git a/docs/Documentation/AI_Balancer.html b/docs/Documentation/AI_Balancer.html
index 46de2c5c1..9e08c2a78 100644
--- a/docs/Documentation/AI_Balancer.html
+++ b/docs/Documentation/AI_Balancer.html
@@ -18,6 +18,7 @@
SP:N MP:Y AI:Y HU:N TYP:A -- This module contains the AI_BALANCER class.
-
-
-
AI Balancing will replace in multi player missions
+
Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions
non-occupied human slots with AI groups, in order to provide an engaging simulation environment,
even when there are hardly any players in the mission.
The #AICAPZONE class implements the core functions to patrol a Zone by an AI Controllable or Group
+and automatically engage any airborne enemies that are within a certain range or within a certain zone.
+
+
+
+
The AICAPZONE is assigned a @(Group) and this must be done before the AICAPZONE process can be started using the Start event.
+
+
+
+
The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
+Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+
+
+
+
This cycle will continue.
+
+
+
+
During the patrol, the AI will detect enemy targets, which are reported through the Detected event.
+
+
+
+
When enemies are detected, the AI will automatically engage the enemy.
+
+
+
+
Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
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..
+
+
+
1.2.2) AICAPZONE Events
+
+
+
Start ( Group ): Start the process.
+
Route ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
+
Engage ( Group ): Let the AI engage the bogeys.
+
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.
+
+
+
1.3) Set the Range of Engagement
+
+
+
+
An optional range can be set in meters,
+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.AICap#AICAP_ZONE.SetEngageRange() to define that range.
+
+
1.4) Set the Zone of Engagement
+
+
+
+
An optional Zone can be set,
+that will define when the AI will engage with the detected airborne enemy targets.
+Use the method AI.AICap#AICAP_ZONE.SetEngageZone() to define that Zone.
+
+
+
+
API CHANGE HISTORY
+
+
The underlying change log documents the API changes. Please read this carefully. The following notation is used:
The #AIPATROLZONE class implements the core functions to patrol a Zone by an AI Controllable or Group.
-The AIPATROLZONE is assigned a @(Group) and this must be done before the AIPATROLZONE process can be started.
-The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
-Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
-This cycle will continue until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
+
The AIPATROLZONE is assigned a @(Group) and this must be done before the AIPATROLZONE process can be started using the Start event.
+
+
+
+
The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits.
+Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.
+
+
+
+
This cycle will continue.
+
+
+
+
During the patrol, the AI will detect enemy targets, which are reported through the Detected event.
+
+
+
+
-- Note that the enemy is not engaged! To model enemy engagement, either tailor the Detected event, or
+use derived AI_ classes to model AI offensive or defensive behaviour.
+
+
+
+
Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB.
When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.
+
+
1.1) AIPATROLZONE constructor
@@ -106,7 +131,7 @@ When the fuel treshold has been reached, the airplane will fly towards the neare
Returning ( Group ): The AI is returning to Base..
Management of logical cargo objects, that can be transported from and to transportation carriers.
+
Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers.
SP:N MP:Y AI:Y HU:N TYP:A -- This module contains the AI_BALANCER class.
+
Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions
+non-occupied human slots with AI groups, in order to provide an engaging simulation environment,
+even when there are hardly any players in the mission.
Management of logical cargo objects, that can be transported from and to transportation carriers.
+
Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers.