diff --git a/Moose Development/Maths/Distance.ggb b/Moose Development/Maths/Distance.ggb new file mode 100644 index 000000000..dc32fd5af Binary files /dev/null and b/Moose Development/Maths/Distance.ggb differ diff --git a/Moose Development/Moose/AI/AI_BAI.lua b/Moose Development/Moose/AI/AI_BAI.lua new file mode 100644 index 000000000..efa68c3b1 --- /dev/null +++ b/Moose Development/Moose/AI/AI_BAI.lua @@ -0,0 +1,674 @@ +--- **AI** -- **Provide Battlefield Air Interdiction (bombing).** +-- +-- ![Banner Image](..\Presentations\AI_BAI\Dia1.JPG) +-- +-- === +-- +-- AI_BAI classes makes AI Controllables execute bombing tasks. +-- +-- There are the following types of BAI classes defined: +-- +-- * @{#AI_BAI_ZONE}: Perform a BAI in a zone. +-- +-- ==== +-- +-- # Demo Missions +-- +-- ### [AI_BAI Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/BOMB%20-%20Close%20Air%20Support) +-- +-- ### [AI_BAI Demo Missions, only for beta testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/BOMB%20-%20Close%20Air%20Support) +-- +-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases) +-- +-- ==== +-- +-- # YouTube Channel +-- +-- ### [AI_BAI YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3JBO1WDqqpyYRRmIkR2ir2) +-- +-- === +-- +-- # **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: +-- +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Bai + + +--- AI_BAI_ZONE class +-- @type AI_BAI_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_BAI_ZONE class, extends @{AI_Patrol#AI_PATROL_ZONE} +-- +-- AI_BAI_ZONE derives from the @{AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour. +-- +-- The AI_BAI_ZONE class implements the core functions to provide BattleGround Air Interdiction in an Engage @{Zone} by an AIR @{Controllable} or @{Group}. +-- The AI_BAI_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. +-- +-- ![HoldAndEngage](..\Presentations\AI_BAI\Dia3.JPG) +-- +-- The AI_BAI_ZONE is assigned a @{Group} and this must be done before the AI_BAI_ZONE process can be started through the **Start** event. +-- +-- ![Start Event](..\Presentations\AI_BAI\Dia4.JPG) +-- +-- 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. +-- +-- ![Route Event](..\Presentations\AI_BAI\Dia5.JPG) +-- +-- When the AI is commanded to provide BattleGround Air Interdiction (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. +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia6.JPG) +-- +-- The AI will detect the targets and will only destroy the targets within the Engage Zone. +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia7.JPG) +-- +-- Every target that is destroyed, is reported< by the AI. +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia8.JPG) +-- +-- Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone. +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia9.JPG) +-- +-- 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 ... +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia10.JPG) +-- +-- When the AI has accomplished the Bombing, it will fly back to the Patrol Zone. +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia11.JPG) +-- +-- It will keep patrolling there, until it is notified to RTB or move to another BOMB 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. +-- +-- ![Engage Event](..\Presentations\AI_BAI\Dia12.JPG) +-- +-- # 1. AI_BAI_ZONE constructor +-- +-- * @{#AI_BAI_ZONE.New}(): Creates a new AI_BAI_ZONE object. +-- +-- ## 2. AI_BAI_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_BAI\Dia2.JPG) +-- +-- ### 2.1. AI_BAI_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 BOMB. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 2.2. AI_BAI_ZONE Events +-- +-- * **@{AI_Patrol#AI_PATROL_ZONE.Start}**: Start the process. +-- * **@{AI_Patrol#AI_PATROL_ZONE.Route}**: Route the AI to a new random 3D point within the Patrol Zone. +-- * **@{#AI_BAI_ZONE.Engage}**: Engage the AI to provide BOMB in the Engage Zone, destroying any target it finds. +-- * **@{#AI_BAI_ZONE.Abort}**: Aborts the engagement and return patrolling in the patrol zone. +-- * **@{AI_Patrol#AI_PATROL_ZONE.RTB}**: Route the AI to the home base. +-- * **@{AI_Patrol#AI_PATROL_ZONE.Detect}**: The AI is detecting targets. +-- * **@{AI_Patrol#AI_PATROL_ZONE.Detected}**: The AI has detected new targets. +-- * **@{#AI_BAI_ZONE.Destroy}**: The AI has destroyed a target @{Unit}. +-- * **@{#AI_BAI_ZONE.Destroyed}**: The AI has destroyed all target @{Unit}s assigned in the BOMB task. +-- * **Status**: The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ## 3. Modify the Engage Zone behaviour to pinpoint a **map object** or **scenery object** +-- +-- Use the method @{#AI_BAI_ZONE.SearchOff}() to specify that the EngageZone is not to be searched for potential targets (UNITs), but that the center of the zone +-- is the point where a map object is to be destroyed (like a bridge). +-- +-- Example: +-- +-- -- Tell the BAI not to search for potential targets in the BAIEngagementZone, but rather use the center of the BAIEngagementZone as the bombing location. +-- AIBAIZone:SearchOff() +-- +-- Searching can be switched back on with the method @{#AI_BAI_ZONE.SearchOn}(). Use the method @{#AI_BAI_ZONE.SearchOnOff}() to flexibily switch searching on or off. +-- +-- === +-- +-- @field #AI_BAI_ZONE +AI_BAI_ZONE = { + ClassName = "AI_BAI_ZONE", +} + + + +--- Creates a new AI_BAI_ZONE object +-- @param #AI_BAI_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_BASE EngageZone The zone where the engage will happen. +-- @param Dcs.DCSTypes#AltitudeType PatrolAltType The altitude type ("RADIO"=="AGL", "BARO"=="ASL"). Defaults to RADIO +-- @return #AI_BAI_ZONE self +function AI_BAI_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, PatrolAltType ) ) -- #AI_BAI_ZONE + + self.EngageZone = EngageZone + self.Accomplished = false + + self:SetDetectionZone( self.EngageZone ) + self:SearchOn() + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_BAI_ZONE] OnBeforeEngage + -- @param #AI_BAI_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_BAI_ZONE] OnAfterEngage + -- @param #AI_BAI_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_BAI_ZONE] Engage + -- @param #AI_BAI_ZONE self + -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. + -- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. + -- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. + -- If parameter is not defined the unit / controllable will choose expend on its own discretion. + -- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack. + -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. + -- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_BAI_ZONE] __Engage + -- @param #AI_BAI_ZONE self + -- @param #number Delay The delay in seconds. + -- @param #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. + -- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. + -- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. + -- If parameter is not defined the unit / controllable will choose expend on its own discretion. + -- Use the structure @{DCSTypes#AI.Task.WeaponExpend} to define the amount of weapons to be release at each attack. + -- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. + -- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_BAI_ZONE] OnLeaveEngaging +-- @param #AI_BAI_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_BAI_ZONE] OnEnterEngaging +-- @param #AI_BAI_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", "Target", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_BAI_ZONE] OnBeforeFired + -- @param #AI_BAI_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_BAI_ZONE] OnAfterFired + -- @param #AI_BAI_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_BAI_ZONE] Fired + -- @param #AI_BAI_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_BAI_ZONE] __Fired + -- @param #AI_BAI_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_BAI_ZONE] OnBeforeDestroy + -- @param #AI_BAI_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_BAI_ZONE] OnAfterDestroy + -- @param #AI_BAI_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_BAI_ZONE] Destroy + -- @param #AI_BAI_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_BAI_ZONE] __Destroy + -- @param #AI_BAI_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_BAI_ZONE] OnBeforeAbort + -- @param #AI_BAI_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_BAI_ZONE] OnAfterAbort + -- @param #AI_BAI_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_BAI_ZONE] Abort + -- @param #AI_BAI_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_BAI_ZONE] __Abort + -- @param #AI_BAI_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_BAI_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_BAI_ZONE] OnBeforeAccomplish + -- @param #AI_BAI_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_BAI_ZONE] OnAfterAccomplish + -- @param #AI_BAI_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_BAI_ZONE] Accomplish + -- @param #AI_BAI_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_BAI_ZONE] __Accomplish + -- @param #AI_BAI_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone where the AI is performing BOMB. Note that if the EngageZone is changed, the AI needs to re-detect targets. +-- @param #AI_BAI_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing BOMB. +-- @return #AI_BAI_ZONE self +function AI_BAI_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + + +--- Specifies whether to search for potential targets in the zone, or let the center of the zone be the bombing coordinate. +-- AI_BAI_ZONE will search for potential targets by default. +-- @param #AI_BAI_ZONE self +-- @return #AI_BAI_ZONE +function AI_BAI_ZONE:SearchOnOff( Search ) + + self.Search = Search + + return self +end + +--- If Search is Off, the current zone coordinate will be the center of the bombing. +-- @param #AI_BAI_ZONE self +-- @return #AI_BAI_ZONE +function AI_BAI_ZONE:SearchOff() + + self:SearchOnOff( false ) + + return self +end + + +--- If Search is On, BAI will search for potential targets in the zone. +-- @param #AI_BAI_ZONE self +-- @return #AI_BAI_ZONE +function AI_BAI_ZONE:SearchOn() + + self:SearchOnOff( true ) + + return self +end + + +--- onafter State Transition for Event Start. +-- @param #AI_BAI_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_BAI_ZONE:onafterStart( Controllable, From, Event, To ) + + -- Call the parent Start event handler + self:GetParent(self).onafterStart( self, Controllable, From, Event, To ) + self:HandleEvent( EVENTS.Dead ) + + self:SetDetectionDeactivated() -- When not engaging, set the detection off. +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_BAI#AI_BAI_ZONE + EngageZone:__Engage( 1, EngageZone.EngageSpeed, EngageZone.EngageAltitude, EngageZone.EngageWeaponExpend, EngageZone.EngageAttackQty, EngageZone.EngageDirection ) +end + + +--- @param #AI_BAI_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_BAI_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + +--- @param #AI_BAI_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_BAI_ZONE:onafterTarget( Controllable, From, Event, To ) + self:F({"onafterTarget",self.Search,Controllable:IsAlive()}) + + + + if Controllable:IsAlive() then + + local AttackTasks = {} + + if self.Search == true then + for DetectedUnit, Detected in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + if DetectedUnit:IsAlive() then + if DetectedUnit:IsInZone( self.EngageZone ) then + if Detected == true then + self:F( {"Target: ", DetectedUnit } ) + self.DetectedUnits[DetectedUnit] = false + local AttackTask = Controllable:TaskAttackUnit( DetectedUnit, false, self.EngageWeaponExpend, self.EngageAttackQty, self.EngageDirection, self.EngageAltitude, nil ) + self.Controllable:PushTask( AttackTask, 1 ) + end + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + else + self:F("Attack zone") + local AttackTask = Controllable:TaskAttackMapObject( + self.EngageZone:GetPointVec2():GetVec2(), + true, + self.EngageWeaponExpend, + self.EngageAttackQty, + self.EngageDirection, + self.EngageAltitude + ) + self.Controllable:PushTask( AttackTask, 1 ) + end + + self:__Target( -10 ) + + end +end + + +--- @param #AI_BAI_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_BAI_ZONE:onafterAbort( Controllable, From, Event, To ) + Controllable:ClearTasks() + self:__Route( 1 ) +end + +--- @param #AI_BAI_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 #number EngageSpeed (optional) The speed the Group will hold when engaging to the target zone. +-- @param Dcs.DCSTypes#Distance EngageAltitude (optional) Desired altitude to perform the unit engagement. +-- @param Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. +-- @param #number EngageAttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. +-- @param Dcs.DCSTypes#Azimuth EngageDirection (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. +function AI_BAI_ZONE:onafterEngage( Controllable, From, Event, To, + EngageSpeed, + EngageAltitude, + EngageWeaponExpend, + EngageAttackQty, + EngageDirection ) + + self:F("onafterEngage") + + self.EngageSpeed = EngageSpeed or 400 + self.EngageAltitude = EngageAltitude or 2000 + self.EngageWeaponExpend = EngageWeaponExpend + self.EngageAttackQty = EngageAttackQty + self.EngageDirection = EngageDirection + + if Controllable:IsAlive() then + + 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( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + self.EngageSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + local AttackTasks = {} + + if self.Search == true then + + for DetectedUnitID, DetectedUnitData in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:F( {"Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskBombing( + DetectedUnit:GetPointVec2():GetVec2(), + true, + EngageWeaponExpend, + EngageAttackQty, + EngageDirection, + EngageAltitude + ) + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + else + self:F("Attack zone") + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackMapObject( + self.EngageZone:GetPointVec2():GetVec2(), + true, + EngageWeaponExpend, + EngageAttackQty, + EngageDirection, + EngageAltitude + ) + end + + EngageRoute[#EngageRoute].task = Controllable:TaskCombo( AttackTasks ) + + --- 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 ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, self.EngageAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir( + self.PatrolAltType, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + self.EngageSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToTargetRoutePoint + + Controllable:OptionROEOpenFire() + Controllable:OptionROTVertical() + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + Controllable:WayPointInitialize( EngageRoute ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + Controllable:SetState( Controllable, "EngageZone", self ) + + Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" ) + + --- NOW ROUTE THE GROUP! + Controllable:WayPointExecute( 1 ) + + self:SetDetectionInterval( 2 ) + self:SetDetectionActivated() + self:__Target( -2 ) -- Start Targetting + end +end + + +--- @param #AI_BAI_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_BAI_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self:SetDetectionDeactivated() +end + + +--- @param #AI_BAI_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_BAI_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end +end + + +--- @param #AI_BAI_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_BAI_ZONE:OnEventDead( EventData ) + self:F( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + if self.DetectedUnits and self.DetectedUnits[EventData.IniUnit] then + self:__Destroy( 1, EventData ) + end + end +end + + diff --git a/Moose Development/Moose/AI/AI_CAS.lua b/Moose Development/Moose/AI/AI_CAS.lua index b9f866f0e..8e9eb20f6 100644 --- a/Moose Development/Moose/AI/AI_CAS.lua +++ b/Moose Development/Moose/AI/AI_CAS.lua @@ -28,19 +28,6 @@ -- -- === -- --- # **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: diff --git a/Moose Development/Moose/AI/AI_Formation.lua b/Moose Development/Moose/AI/AI_Formation.lua new file mode 100644 index 000000000..4f9ed5d20 --- /dev/null +++ b/Moose Development/Moose/AI/AI_Formation.lua @@ -0,0 +1,1075 @@ +--- **AI** -- (R2.1) Build large **formations** of AI @{Group}s flying together. +-- +-- ![Banner Image](..\Presentations\AI_FORMATION\Dia1.JPG) +-- +-- === +-- +-- AI_FORMATION makes AI @{GROUP}s fly in formation of various compositions. +-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!! +-- The purpose of the class is to: +-- +-- * Make formation building a process that can be managed while in flight, rather than a task. +-- * Human players can guide formations, consisting of larget planes. +-- * Build large formations (like a large bomber field). +-- * Form formations that DCS does not support off the shelve. +-- +-- A few remarks: +-- +-- * Depending on the type of plane, the change in direction by the leader may result in the formation getting disentangled while in flight and needs to be rebuild. +-- * Formations are vulnerable to collissions, but is depending on the type of plane, the distance between the planes and the speed and angle executed by the leader. +-- * Formations may take a while to build up. +-- +-- As a result, the AI_FORMATION is not perfect, but is very useful to: +-- +-- * Model large formations when flying straight line. +-- * Make humans guide a large formation, when the planes are wide from each other. +-- +-- There are the following types of classes defined: +-- +-- * @{#AI_FORMATION}: Create a formation from several @{GROUP}s. +-- +-- ==== +-- +-- # Demo Missions +-- +-- ### [AI_FORMATION Demo Missions source code]() +-- +-- ### [AI_FORMATION Demo Missions, only for beta testers]() +-- +-- ### [ALL Demo Missions pack of the last release]() +-- +-- ==== +-- +-- # YouTube Channel +-- +--- ### [AI_FORMATION YouTube Channel]() +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Formation + +--- AI_FORMATION class +-- @type AI_FORMATION +-- @extends Fsm#FSM_SET +-- @field Unit#UNIT FollowUnit +-- @field Set#SET_GROUP FollowGroupSet +-- @field #string FollowName +-- @field #AI_FORMATION.MODE FollowMode The mode the escort is in. +-- @field Scheduler#SCHEDULER FollowScheduler The instance of the SCHEDULER class. +-- @field #number FollowDistance The current follow distance. +-- @field #boolean ReportTargets If true, nearby targets are reported. +-- @Field DCSTypes#AI.Option.Air.val.ROE OptionROE Which ROE is set to the FollowGroup. +-- @field DCSTypes#AI.Option.Air.val.REACTION_ON_THREAT OptionReactionOnThreat Which REACTION_ON_THREAT is set to the FollowGroup. +-- @field Menu#MENU_CLIENT FollowMenuResumeMission + + +--- # AI_FORMATION class, extends @{Fsm#FSM_SET} +-- +-- The #AI_FORMATION class allows you to build large formations, make AI follow a @{Client#CLIENT} (player) leader or a @{Unit#UNIT} (AI) leader. +-- +-- AI_FORMATION makes AI @{GROUP}s fly in formation of various compositions. +-- The AI_FORMATION class models formations in a different manner than the internal DCS formation logic!!! +-- The purpose of the class is to: +-- +-- * Make formation building a process that can be managed while in flight, rather than a task. +-- * Human players can guide formations, consisting of larget planes. +-- * Build large formations (like a large bomber field). +-- * Form formations that DCS does not support off the shelve. +-- +-- A few remarks: +-- +-- * Depending on the type of plane, the change in direction by the leader may result in the formation getting disentangled while in flight and needs to be rebuild. +-- * Formations are vulnerable to collissions, but is depending on the type of plane, the distance between the planes and the speed and angle executed by the leader. +-- * Formations may take a while to build up. +-- +-- As a result, the AI_FORMATION is not perfect, but is very useful to: +-- +-- * Model large formations when flying straight line. You can build close formations when doing this. +-- * Make humans guide a large formation, when the planes are wide from each other. +-- +-- ## AI_FORMATION construction +-- +-- Create a new SPAWN object with the @{#AI_FORMATION.New} method: +-- +-- * @{Follow#AI_FORMATION.New}(): Creates a new AI_FORMATION object from a @{Group#GROUP} for a @{Client#CLIENT} or a @{Unit#UNIT}, with an optional briefing text. +-- +-- ## Formation methods +-- +-- The following methods can be used to set or change the formation: +-- +-- * @{AI_Formation#AI_FORMATION.FormationLine}(): Form a line formation (core formation function). +-- * @{AI_Formation#AI_FORMATION.FormationTrail}(): Form a trail formation. +-- * @{AI_Formation#AI_FORMATION.FormationLeftLine}(): Form a left line formation. +-- * @{AI_Formation#AI_FORMATION.FormationRightLine}(): Form a right line formation. +-- * @{AI_Formation#AI_FORMATION.FormationRightWing}(): Form a right wing formation. +-- * @{AI_Formation#AI_FORMATION.FormationLeftWing}(): Form a left wing formation. +-- * @{AI_Formation#AI_FORMATION.FormationCenterWing}(): Form a center wing formation. +-- * @{AI_Formation#AI_FORMATION.FormationCenterVic}(): Form a Vic formation (same as CenterWing. +-- * @{AI_Formation#AI_FORMATION.FormationCenterBoxed}(): Form a center boxed formation. +-- +-- ## Randomization +-- +-- Use the method @{AI_Formation#AI_FORMATION.SetFlightRandomization}() to simulate the formation flying errors that pilots make while in formation. Is a range set in meters. +-- +-- @usage +-- local FollowGroupSet = SET_GROUP:New():FilterCategories("plane"):FilterCoalitions("blue"):FilterPrefixes("Follow"):FilterStart() +-- FollowGroupSet:Flush() +-- local LeaderUnit = UNIT:FindByName( "Leader" ) +-- local LargeFormation = AI_FORMATION:New( LeaderUnit, FollowGroupSet, "Center Wing Formation", "Briefing" ) +-- LargeFormation:FormationCenterWing( 500, 50, 0, 250, 250 ) +-- LargeFormation:__Start( 1 ) +-- +-- @field #AI_FORMATION +AI_FORMATION = { + ClassName = "AI_FORMATION", + FollowName = nil, -- The Follow Name + FollowUnit = nil, + FollowGroupSet = nil, + FollowMode = 1, + MODE = { + FOLLOW = 1, + MISSION = 2, + }, + FollowScheduler = nil, + OptionROE = AI.Option.Air.val.ROE.OPEN_FIRE, + OptionReactionOnThreat = AI.Option.Air.val.REACTION_ON_THREAT.ALLOW_ABORT_MISSION, +} + +--- AI_FORMATION.Mode class +-- @type AI_FORMATION.MODE +-- @field #number FOLLOW +-- @field #number MISSION + +--- MENUPARAM type +-- @type MENUPARAM +-- @field #AI_FORMATION ParamSelf +-- @field #Distance ParamDistance +-- @field #function ParamFunction +-- @field #string ParamMessage + +--- AI_FORMATION class constructor for an AI group +-- @param #AI_FORMATION self +-- @param Unit#UNIT FollowUnit The UNIT leading the FolllowGroupSet. +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string FollowName Name of the escort. +-- @return #AI_FORMATION self +function AI_FORMATION:New( FollowUnit, FollowGroupSet, FollowName, FollowBriefing ) + local self = BASE:Inherit( self, FSM_SET:New( FollowGroupSet ) ) + self:F( { FollowUnit, FollowGroupSet, FollowName } ) + + self.FollowUnit = FollowUnit -- Unit#UNIT + self.FollowGroupSet = FollowGroupSet -- Set#SET_GROUP + + self:SetFlightRandomization( 2 ) + + self:SetStartState( "None" ) + + self:AddTransition( "*", "Stop", "Stopped" ) + + self:AddTransition( "None", "Start", "Following" ) + + self:AddTransition( "*", "FormationLine", "*" ) + --- FormationLine Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationLine + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationLine Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationLine + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationLine Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationLine + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationLine Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationLine + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationTrail", "*" ) + --- FormationTrail Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationTrail + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @return #boolean + + --- FormationTrail Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationTrail + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + + --- FormationTrail Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationTrail + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + + --- FormationTrail Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationTrail + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + + self:AddTransition( "*", "FormationStack", "*" ) + --- FormationStack Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationStack + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @return #boolean + + --- FormationStack Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationStack + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + + --- FormationStack Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationStack + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + + --- FormationStack Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationStack + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationLeftLine", "*" ) + --- FormationLeftLine Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationLeftLine + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationLeftLine Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationLeftLine + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationLeftLine Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationLeftLine + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationLeftLine Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationLeftLine + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationRightLine", "*" ) + --- FormationRightLine Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationRightLine + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationRightLine Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationRightLine + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationRightLine Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationRightLine + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationRightLine Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationRightLine + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationLeftWing", "*" ) + --- FormationLeftWing Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationLeftWing + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationLeftWing Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationLeftWing + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationLeftWing Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationLeftWing + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationLeftWing Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationLeftWing + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationRightWing", "*" ) + --- FormationRightWing Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationRightWing + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationRightWing Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationRightWing + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationRightWing Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationRightWing + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationRightWing Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationRightWing + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationCenterWing", "*" ) + --- FormationCenterWing Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationCenterWing + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationCenterWing Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationCenterWing + -- @param #AI_FORMATION self + -- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationCenterWing Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationCenterWing + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationCenterWing Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationCenterWing + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationVic", "*" ) + --- FormationVic Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationVic + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @return #boolean + + --- FormationVic Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationVic + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationVic Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationVic + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + --- FormationVic Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationVic + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + + self:AddTransition( "*", "FormationBox", "*" ) + --- FormationBox Handler OnBefore for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnBeforeFormationBox + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @param #number ZLevels The amount of levels on the Z-axis. + -- @return #boolean + + --- FormationBox Handler OnAfter for AI_FORMATION + -- @function [parent=#AI_FORMATION] OnAfterFormationBox + -- @param #AI_FORMATION self + -- @param #string From + -- @param #string Event + -- @param #string To + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @param #number ZLevels The amount of levels on the Z-axis. + + --- FormationBox Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] FormationBox + -- @param #AI_FORMATION self + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @param #number ZLevels The amount of levels on the Z-axis. + + --- FormationBox Asynchronous Trigger for AI_FORMATION + -- @function [parent=#AI_FORMATION] __FormationBox + -- @param #AI_FORMATION self + -- @param #number Delay + -- @param #number XStart The start position on the X-axis in meters for the first group. + -- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. + -- @param #nubmer YStart The start position on the Y-axis in meters for the first group. + -- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. + -- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. + -- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. + -- @param #number ZLevels The amount of levels on the Z-axis. + + + self:AddTransition( "*", "Follow", "Following" ) + + self:FormationLeftLine( 500, 0, 250, 250 ) + + self.FollowName = FollowName + self.FollowBriefing = FollowBriefing + + + self.CT1 = 0 + self.GT1 = 0 + + self.FollowMode = AI_FORMATION.MODE.MISSION + + return self +end + +--- This function is for test, it will put on the frequency of the FollowScheduler a red smoke at the direction vector calculated for the escort to fly to. +-- This allows to visualize where the escort is flying to. +-- @param #AI_FORMATION self +-- @param #boolean SmokeDirection If true, then the direction vector will be smoked. +-- @return #AI_FORMATION +function AI_FORMATION:TestSmokeDirectionVector( SmokeDirection ) + self.SmokeDirectionVector = ( SmokeDirection == true ) and true or false + return self +end + +--- FormationLine Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #nubmer YSpace The space between groups on the Y-axis in meters for each sequent group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationLine( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) + self:F( { FollowGroupSet, From , Event ,To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace } ) + + FollowGroupSet:Flush() + + local FollowSet = FollowGroupSet:GetSet() + + local i = 0 + + for FollowID, FollowGroup in pairs( FollowSet ) do + + local PointVec3 = POINT_VEC3:New() + PointVec3:SetX( XStart + i * XSpace ) + PointVec3:SetY( YStart + i * YSpace ) + PointVec3:SetZ( ZStart + i * ZSpace ) + + local Vec3 = PointVec3:GetVec3() + FollowGroup:SetState( self, "FormationVec3", Vec3 ) + i = i + 1 + end + + return self + +end + +--- FormationTrail Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationTrail( FollowGroupSet, From , Event , To, XStart, XSpace, YStart ) + + self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,0,0) + + return self +end + + +--- FormationStack Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationStack( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace ) + + self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,0,0) + + return self +end + + + + +--- FormationLeftLine Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationLeftLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) + + self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,0,YStart,0,ZStart,ZSpace) + + return self +end + + +--- FormationRightLine Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationRightLine( FollowGroupSet, From , Event , To, XStart, YStart, ZStart, ZSpace ) + + self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,0,YStart,0,-ZStart,-ZSpace) + + return self +end + + +--- FormationLeftWing Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +function AI_FORMATION:onafterFormationLeftWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) + + self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,ZStart,ZSpace) + + return self +end + + +--- FormationRightWing Handler OnAfter for AI_FORMATION +-- @function [parent=#AI_FORMATION] OnAfterFormationRightWing +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +function AI_FORMATION:onafterFormationRightWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, ZStart, ZSpace ) + + self:onafterFormationLine(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,0,-ZStart,-ZSpace) + + return self +end + + +--- FormationCenterWing Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param Core.Set#SET_GROUP FollowGroupSet The group AI escorting the FollowUnit. +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +function AI_FORMATION:onafterFormationCenterWing( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) + + local FollowSet = FollowGroupSet:GetSet() + + local i = 0 + + for FollowID, FollowGroup in pairs( FollowSet ) do + + local PointVec3 = POINT_VEC3:New() + + local Side = ( i % 2 == 0 ) and 1 or -1 + local Row = i / 2 + 1 + + PointVec3:SetX( XStart + Row * XSpace ) + PointVec3:SetY( YStart ) + PointVec3:SetZ( Side * ( ZStart + i * ZSpace ) ) + + local Vec3 = PointVec3:GetVec3() + FollowGroup:SetState( self, "FormationVec3", Vec3 ) + i = i + 1 + end + + return self +end + + +--- FormationVic Handle for AI_FORMATION +-- @param #AI_FORMATION self +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationVic( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace ) + + self:onafterFormationCenterWing(FollowGroupSet,From,Event,To,XStart,XSpace,YStart,YSpace,ZStart,ZSpace) + + return self +end + +--- FormationBox Handler OnAfter for AI_FORMATION +-- @param #AI_FORMATION self +-- @param #string From +-- @param #string Event +-- @param #string To +-- @param #number XStart The start position on the X-axis in meters for the first group. +-- @param #number XSpace The space between groups on the X-axis in meters for each sequent group. +-- @param #nubmer YStart The start position on the Y-axis in meters for the first group. +-- @param #number YSpace The space between groups on the Y-axis in meters for each sequent group. +-- @param #nubmer ZStart The start position on the Z-axis in meters for the first group. +-- @param #number ZSpace The space between groups on the Z-axis in meters for each sequent group. +-- @param #number ZLevels The amount of levels on the Z-axis. +-- @return #AI_FORMATION +function AI_FORMATION:onafterFormationBox( FollowGroupSet, From , Event , To, XStart, XSpace, YStart, YSpace, ZStart, ZSpace, ZLevels ) + + local FollowSet = FollowGroupSet:GetSet() + + local i = 0 + + for FollowID, FollowGroup in pairs( FollowSet ) do + + local PointVec3 = POINT_VEC3:New() + + local ZIndex = i % ZLevels + local XIndex = math.floor( i / ZLevels ) + local YIndex = math.floor( i / ZLevels ) + + PointVec3:SetX( XStart + XIndex * XSpace ) + PointVec3:SetY( YStart + YIndex * YSpace ) + PointVec3:SetZ( -ZStart - (ZSpace * ZLevels / 2 ) + ZSpace * ZIndex ) + + local Vec3 = PointVec3:GetVec3() + FollowGroup:SetState( self, "FormationVec3", Vec3 ) + i = i + 1 + end + + return self +end + + +--- Use the method @{AI_Formation#AI_FORMATION.SetFlightRandomization}() to make the air units in your formation randomize their flight a bit while in formation. +-- @param #AI_FORMATION self +-- @param #number FlightRandomization The formation flying errors that pilots can make while in formation. Is a range set in meters. +-- @return #AI_FORMATION +function AI_FORMATION:SetFlightRandomization( FlightRandomization ) + + self.FlightRandomization = FlightRandomization + + return self +end + + +--- @param Follow#AI_FORMATION self +function AI_FORMATION:onenterFollowing( FollowGroupSet ) + self:F( ) + + self:T( { self.FollowUnit.UnitName, self.FollowUnit:IsAlive() } ) + if self.FollowUnit:IsAlive() then + + local ClientUnit = self.FollowUnit + + self:T( {ClientUnit.UnitName } ) + + local CT1, CT2, CV1, CV2 + CT1 = ClientUnit:GetState( self, "CT1" ) + + if CT1 == nil or CT1 == 0 then + ClientUnit:SetState( self, "CV1", ClientUnit:GetPointVec3() ) + ClientUnit:SetState( self, "CT1", timer.getTime() ) + else + CT1 = ClientUnit:GetState( self, "CT1" ) + CT2 = timer.getTime() + CV1 = ClientUnit:GetState( self, "CV1" ) + CV2 = ClientUnit:GetPointVec3() + + ClientUnit:SetState( self, "CT1", CT2 ) + ClientUnit:SetState( self, "CV1", CV2 ) + end + + FollowGroupSet:ForEachGroup( + --- @param Wrapper.Group#GROUP FollowGroup + -- @param Wrapper.Unit#UNIT ClientUnit + function( FollowGroup, Formation, ClientUnit, CT1, CV1, CT2, CV2 ) + + FollowGroup:OptionROTPassiveDefense() + FollowGroup:OptionROEReturnFire() + + local GroupUnit = FollowGroup:GetUnit( 1 ) + local FollowFormation = FollowGroup:GetState( self, "FormationVec3" ) + if FollowFormation then + local FollowDistance = FollowFormation.x + + local GT1 = GroupUnit:GetState( self, "GT1" ) + + if CT1 == nil or CT1 == 0 or GT1 == nil or GT1 == 0 then + GroupUnit:SetState( self, "GV1", GroupUnit:GetPointVec3() ) + GroupUnit:SetState( self, "GT1", timer.getTime() ) + else + local CD = ( ( CV2.x - CV1.x )^2 + ( CV2.y - CV1.y )^2 + ( CV2.z - CV1.z )^2 ) ^ 0.5 + local CT = CT2 - CT1 + + local CS = ( 3600 / CT ) * ( CD / 1000 ) / 3.6 + + local CDv = { x = CV2.x - CV1.x, y = CV2.y - CV1.y, z = CV2.z - CV1.z } + local Ca = math.atan2( CDv.x, CDv.z ) + + local GT1 = GroupUnit:GetState( self, "GT1" ) + local GT2 = timer.getTime() + local GV1 = GroupUnit:GetState( self, "GV1" ) + local GV2 = GroupUnit:GetPointVec3() + GV2:AddX( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) ) + GV2:AddY( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) ) + GV2:AddZ( math.random( -Formation.FlightRandomization / 2, Formation.FlightRandomization / 2 ) ) + GroupUnit:SetState( self, "GT1", GT2 ) + GroupUnit:SetState( self, "GV1", GV2 ) + + + local GD = ( ( GV2.x - GV1.x )^2 + ( GV2.y - GV1.y )^2 + ( GV2.z - GV1.z )^2 ) ^ 0.5 + local GT = GT2 - GT1 + + + -- Calculate the distance + local GDv = { x = GV2.x - CV1.x, y = GV2.y - CV1.y, z = GV2.z - CV1.z } + local Alpha_T = math.atan2( GDv.x, GDv.z ) - math.atan2( CDv.x, CDv.z ) + local Alpha_R = ( Alpha_T < 0 ) and Alpha_T + 2 * math.pi or Alpha_T + local Position = math.cos( Alpha_R ) + local GD = ( ( GDv.x )^2 + ( GDv.z )^2 ) ^ 0.5 + local Distance = GD * Position + - CS * 0,5 + + -- Calculate the group direction vector + local GV = { x = GV2.x - CV2.x, y = GV2.y - CV2.y, z = GV2.z - CV2.z } + + -- Calculate GH2, GH2 with the same height as CV2. + local GH2 = { x = GV2.x, y = CV2.y + FollowFormation.y, z = GV2.z } + + -- Calculate the angle of GV to the orthonormal plane + local alpha = math.atan2( GV.x, GV.z ) + + local GVx = FollowFormation.z * math.cos( Ca ) + FollowFormation.x * math.sin( Ca ) + local GVz = FollowFormation.x * math.cos( Ca ) - FollowFormation.z * math.sin( Ca ) + + + -- Now we calculate the intersecting vector between the circle around CV2 with radius FollowDistance and GH2. + -- From the GeoGebra model: CVI = (x(CV2) + FollowDistance cos(alpha), y(GH2) + FollowDistance sin(alpha), z(CV2)) + local CVI = { x = CV2.x + CS * 10 * math.sin(Ca), + y = GH2.y - ( Distance + FollowFormation.x ) / 5, -- + FollowFormation.y, + z = CV2.z + CS * 10 * math.cos(Ca), + } + + -- Calculate the direction vector DV of the escort group. We use CVI as the base and CV2 as the direction. + local DV = { x = CV2.x - CVI.x, y = CV2.y - CVI.y, z = CV2.z - CVI.z } + + -- We now calculate the unary direction vector DVu, so that we can multiply DVu with the speed, which is expressed in meters / s. + -- We need to calculate this vector to predict the point the escort group needs to fly to according its speed. + -- The distance of the destination point should be far enough not to have the aircraft starting to swipe left to right... + local DVu = { x = DV.x / FollowDistance, y = DV.y, z = DV.z / FollowDistance } + + -- Now we can calculate the group destination vector GDV. + local GDV = { x = CVI.x, y = CVI.y, z = CVI.z } + + local ADDx = FollowFormation.x * math.cos(alpha) - FollowFormation.z * math.sin(alpha) + local ADDz = FollowFormation.z * math.cos(alpha) + FollowFormation.x * math.sin(alpha) + + local GDV_Formation = { + x = GDV.x - GVx, + y = GDV.y, + z = GDV.z - GVz + } + + if self.SmokeDirectionVector == true then + trigger.action.smoke( GDV, trigger.smokeColor.Green ) + trigger.action.smoke( GDV_Formation, trigger.smokeColor.White ) + end + + + + local Time = 60 + + local Speed = - ( Distance + FollowFormation.x ) / Time + local GS = Speed + CS + if Speed < 0 then + Speed = 0 + end + + -- Now route the escort to the desired point with the desired speed. + FollowGroup:RouteToVec3( GDV_Formation, GS ) -- DCS models speed in Mps (Miles per second) + end + end + end, + self, ClientUnit, CT1, CV1, CT2, CV2 + ) + + self:__Follow( -0.5 ) + end + +end + diff --git a/Moose Development/Moose/Actions/Act_Assign.lua b/Moose Development/Moose/Actions/Act_Assign.lua index 7d45ad21a..e04139698 100644 --- a/Moose Development/Moose/Actions/Act_Assign.lua +++ b/Moose Development/Moose/Actions/Act_Assign.lua @@ -173,8 +173,6 @@ do -- ACT_ASSIGN_ACCEPT local ProcessGroup = ProcessUnit:GetGroup() - self:Message( "You are assigned to the task " .. self.Task:GetName() ) - self.Task:Assign( ProcessUnit, ProcessUnit:GetPlayerName() ) end diff --git a/Moose Development/Moose/Core/Cargo.lua b/Moose Development/Moose/Core/Cargo.lua index 825bb5084..88635422f 100644 --- a/Moose Development/Moose/Core/Cargo.lua +++ b/Moose Development/Moose/Core/Cargo.lua @@ -239,12 +239,15 @@ function CARGO:New( Type, Name, Weight ) --R2.1 self:SetStartState( "UnLoaded" ) self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" ) self:AddTransition( "Boarding" , "Boarding", "Boarding" ) + self:AddTransition( "Boarding", "CancelBoarding", "UnLoaded" ) self:AddTransition( "Boarding", "Load", "Loaded" ) self:AddTransition( "UnLoaded", "Load", "Loaded" ) self:AddTransition( "Loaded", "UnBoard", "UnBoarding" ) self:AddTransition( "UnBoarding", "UnBoarding", "UnBoarding" ) self:AddTransition( "UnBoarding", "UnLoad", "UnLoaded" ) self:AddTransition( "Loaded", "UnLoad", "UnLoaded" ) + self:AddTransition( "*", "Destroyed", "Destroyed" ) + self:AddTransition( "*", "Respawn", "UnLoaded" ) self.Type = Type @@ -262,6 +265,7 @@ function CARGO:New( Type, Name, Weight ) --R2.1 CARGOS[self.Name] = self self:SetEventPriority( 5 ) + return self end @@ -273,6 +277,17 @@ function CARGO:GetName() --R2.1 return self.Name end +--- Get the object name of the Cargo. +-- @param #CARGO self +-- @return #string The object name of the Cargo. +function CARGO:GetObjectName() --R2.1 + if self:IsLoaded() then + return self.CargoCarrier:GetName() + else + return self.CargoObject:GetName() + end +end + --- Get the type of the Cargo. -- @param #CARGO self -- @return #string The type of the Cargo. @@ -280,6 +295,14 @@ function CARGO:GetType() return self.Type end +--- Get the current coordinates of the Cargo. +-- @param #CARGO self +-- @return Core.Point#COORDINATE The coordinates of the Cargo. +function CARGO:GetCoordinate() + return self.CargoObject:GetCoordinate() +end + + --- Check if cargo is loaded. -- @param #CARGO self -- @return #boolean true if loaded @@ -294,6 +317,20 @@ function CARGO:IsUnLoaded() return self:Is( "UnLoaded" ) end +--- Check if cargo is alive. +-- @param #CARGO self +-- @return #boolean true if unloaded +function CARGO:IsAlive() + + if self:IsLoaded() then + return self.CargoCarrier:IsAlive() + else + return self.CargoObject:IsAlive() + end +end + + + --- Template method to spawn a new representation of the CARGO in the simulator. -- @param #CARGO self @@ -329,7 +366,7 @@ end -- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). -- @return #boolean function CARGO:IsNear( PointVec2, NearRadius ) - self:F( { PointVec2 } ) + self:F( { PointVec2, NearRadius } ) local Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) self:T( Distance ) @@ -520,6 +557,16 @@ function CARGO_UNIT:New( CargoUnit, Type, Name, Weight, NearRadius ) self:T( self.ClassName ) + self:HandleEvent( EVENTS.Dead, + --- @param #CARGO Cargo + -- @param Core.Event#EVENTDATA EventData + function( Cargo, EventData ) + if Cargo:GetObjectName() == EventData.IniUnit:GetName() then + self:E( { "Cargo destroyed", Cargo } ) + Cargo:Destroyed() + end + end + ) return self end @@ -542,7 +589,7 @@ end -- @param #string To -- @param Core.Point#POINT_VEC2 ToPointVec2 function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) - self:F() + self:F( { From, Event, To, ToPointVec2, NearRadius } ) NearRadius = NearRadius or 25 @@ -575,7 +622,7 @@ function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius -- Respawn the group... if self.CargoObject then self.CargoObject:ReSpawn( CargoDeployPointVec2:GetVec3(), CargoDeployHeading ) - self:E( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } ) + self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } ) self.CargoCarrier = nil local Points = {} @@ -586,7 +633,8 @@ function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius local TaskRoute = self.CargoObject:TaskRoute( Points ) self.CargoObject:SetTask( TaskRoute, 1 ) - self:__UnBoarding( -1, ToPointVec2, NearRadius ) + + self:__UnBoarding( 1, ToPointVec2, NearRadius ) end end @@ -599,7 +647,7 @@ end -- @param #string To -- @param Core.Point#POINT_VEC2 ToPointVec2 function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius ) - self:F( { ToPointVec2, From, Event, To } ) + self:F( { From, Event, To, ToPointVec2, NearRadius } ) NearRadius = NearRadius or 25 @@ -611,6 +659,7 @@ function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius if self:IsNear( ToPointVec2, NearRadius ) then return true else + self:__UnBoarding( 1, ToPointVec2, NearRadius ) end return false @@ -625,7 +674,7 @@ end -- @param #string To -- @param Core.Point#POINT_VEC2 ToPointVec2 function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius ) - self:F( { ToPointVec2, From, Event, To } ) + self:F( { From, Event, To, ToPointVec2, NearRadius } ) NearRadius = NearRadius or 25 @@ -639,7 +688,7 @@ function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius end - self:__UnLoad( 1, ToPointVec2 ) + self:__UnLoad( 1, ToPointVec2, NearRadius ) end @@ -687,9 +736,9 @@ end -- @param #string From -- @param #string To function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... ) - self:F() + self:F( { From, Event, To, CargoCarrier, NearRadius } ) - NearRadius = NearRadius or 25 + local NearRadius = NearRadius or 25 self.CargoInAir = self.CargoObject:InAir() @@ -722,32 +771,13 @@ function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... local TaskRoute = self.CargoObject:TaskRoute( Points ) self.CargoObject:SetTask( TaskRoute, 2 ) self:__Boarding( -1, CargoCarrier, NearRadius ) + self.RunCount = 0 end end end ---- Leave Boarding State. --- @param #CARGO_UNIT self --- @param #string Event --- @param #string From --- @param #string To --- @param Wrapper.Unit#UNIT CargoCarrier -function CARGO_UNIT:onleaveBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } ) - - NearRadius = NearRadius or 25 - - if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then - self:__Load( 1, CargoCarrier, ... ) - return true - end - - return true -end - - --- Boarding Event. -- @param #CARGO_UNIT self -- @param #string Event @@ -759,8 +789,45 @@ function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } ) - self:__Boarding( -1, CargoCarrier, NearRadius, ... ) - self:__Board( -15, CargoCarrier, NearRadius, ... ) + if CargoCarrier and CargoCarrier:IsAlive() then + if CargoCarrier:InAir() == false then + if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then + self:__Load( 1, CargoCarrier, ... ) + else + self:__Boarding( -1, CargoCarrier, NearRadius, ... ) + self.RunCount = self.RunCount + 1 + if self.RunCount >= 20 then + self.RunCount = 0 + local Speed = 90 + local Angle = 180 + local Distance = 5 + + NearRadius = NearRadius or 25 + + local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() + local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees. + local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) + local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( Distance, CargoDeployHeading ) + + local Points = {} + + local PointStartVec2 = self.CargoObject:GetPointVec2() + + Points[#Points+1] = PointStartVec2:RoutePointGround( Speed ) + Points[#Points+1] = CargoDeployPointVec2:RoutePointGround( Speed ) + + local TaskRoute = self.CargoObject:TaskRoute( Points ) + self.CargoObject:SetTask( TaskRoute, 0.2 ) + end + end + else + self.CargoObject:MessageToGroup( "Cancelling Boarding... Get back on the ground!", 5, CargoCarrier:GetGroup(), self:GetName() ) + self:CancelBoarding( CargoCarrier, NearRadius, ... ) + self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) ) + end + else + self:E("Something is wrong") + end end @@ -778,7 +845,7 @@ function CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, local Angle = 180 local Distance = 5 - NearRadius = NearRadius or 25 + local NearRadius = NearRadius or 25 if From == "UnLoaded" or From == "Boarding" then @@ -793,7 +860,7 @@ end -- @param #string To -- @param Wrapper.Unit#UNIT CargoCarrier function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier ) - self:F() + self:F( { From, Event, To, CargoCarrier } ) self.CargoCarrier = CargoCarrier @@ -808,6 +875,263 @@ end end + +do -- CARGO_GROUP + + --- @type CARGO_GROUP + -- @extends #CARGO_REPORTABLE + + --- # CARGO\_GROUP class + -- + -- The CARGO\_GROUP class defines a cargo that is represented by a @{Group} object within the simulator, and can be transported by a carrier. + -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_GROUP to and from carrier. + -- + -- @field #CARGO_GROUP CARGO_GROUP + -- + CARGO_GROUP = { + ClassName = "CARGO_GROUP", + } + +--- CARGO_GROUP constructor. +-- @param #CARGO_GROUP self +-- @param Wrapper.Group#GROUP CargoGroup +-- @param #string Type +-- @param #string Name +-- @param #number ReportRadius (optional) +-- @param #number NearRadius (optional) +-- @return #CARGO_GROUP +function CARGO_GROUP:New( CargoGroup, Type, Name, ReportRadius ) + local self = BASE:Inherit( self, CARGO_REPORTABLE:New( CargoGroup, Type, Name, 0, ReportRadius ) ) -- #CARGO_GROUP + self:F( { Type, Name, ReportRadius } ) + + self.CargoSet = SET_CARGO:New() + + self.CargoObject = CargoGroup + + local WeightGroup = 0 + + for UnitID, UnitData in pairs( CargoGroup:GetUnits() ) do + local Unit = UnitData -- Wrapper.Unit#UNIT + local WeightUnit = Unit:GetDesc().massEmpty + WeightGroup = WeightGroup + WeightUnit + local CargoUnit = CARGO_UNIT:New( Unit, Type, Unit:GetName(), WeightUnit ) + self.CargoSet:Add( CargoUnit:GetName(), CargoUnit ) + end + + self:SetWeight( WeightGroup ) + + self:T( { "Weight Cargo", WeightGroup } ) + + -- Cargo objects are added to the _DATABASE and SET_CARGO objects. + _EVENTDISPATCHER:CreateEventNewCargo( self ) + + return self +end + +--- Enter Boarding State. +-- @param #CARGO_GROUP self +-- @param Wrapper.Unit#UNIT CargoCarrier +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) + self:F( { CargoCarrier.UnitName, From, Event, To } ) + + local NearRadius = NearRadius or 25 + + if From == "UnLoaded" then + + -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo, ... ) + Cargo:__Board( 1, CargoCarrier, NearRadius, ... ) + end, ... + ) + + self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + end + +end + +--- Enter Loaded State. +-- @param #CARGO_GROUP self +-- @param Wrapper.Unit#UNIT CargoCarrier +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... ) + self:F( { From, Event, To, CargoCarrier, ...} ) + + if From == "UnLoaded" then + -- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier. + for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do + Cargo:Load( CargoCarrier ) + end + end + + self.CargoObject:Destroy() + self.CargoCarrier = CargoCarrier + +end + +--- Leave Boarding State. +-- @param #CARGO_GROUP self +-- @param Wrapper.Unit#UNIT CargoCarrier +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) + self:F( { CargoCarrier.UnitName, From, Event, To } ) + + local NearRadius = NearRadius or 25 + + local Boarded = true + local Cancelled = false + local Dead = true + + self.CargoSet:Flush() + + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 + for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do + self:T( { Cargo:GetName(), Cargo.current } ) + if not Cargo:is( "Loaded" ) then + Boarded = false + end + + if Cargo:is( "UnLoaded" ) then + Cancelled = true + end + + if not Cargo:is( "Destroyed" ) then + Dead = false + end + + end + + if not Dead then + + if not Cancelled then + if not Boarded then + self:__Boarding( 1, CargoCarrier, NearRadius, ... ) + else + self:__Load( 1, CargoCarrier, ... ) + end + else + self:__CancelBoarding( 1, CargoCarrier, NearRadius, ... ) + end + else + self:__Destroyed( 1, CargoCarrier, NearRadius, ... ) + end + +end + +--- Enter UnBoarding State. +-- @param #CARGO_GROUP self +-- @param Core.Point#POINT_VEC2 ToPointVec2 +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) + self:F( {From, Event, To, ToPointVec2, NearRadius } ) + + NearRadius = NearRadius or 25 + + local Timer = 1 + + if From == "Loaded" then + + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo, NearRadius ) + + Cargo:__UnBoard( Timer, ToPointVec2, NearRadius ) + Timer = Timer + 10 + end, { NearRadius } + ) + + + self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) + end + +end + +--- Leave UnBoarding State. +-- @param #CARGO_GROUP self +-- @param Core.Point#POINT_VEC2 ToPointVec2 +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) + self:F( { From, Event, To, ToPointVec2, NearRadius } ) + + --local NearRadius = NearRadius or 25 + + local Angle = 180 + local Speed = 10 + local Distance = 5 + + if From == "UnBoarding" then + local UnBoarded = true + + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 + for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do + self:T( Cargo.current ) + if not Cargo:is( "UnLoaded" ) then + UnBoarded = false + end + end + + if UnBoarded then + return true + else + self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) + end + + return false + end + +end + +--- UnBoard Event. +-- @param #CARGO_GROUP self +-- @param Core.Point#POINT_VEC2 ToPointVec2 +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) + self:F( { From, Event, To, ToPointVec2, NearRadius } ) + + --local NearRadius = NearRadius or 25 + + self:__UnLoad( 1, ToPointVec2, ... ) +end + + + +--- Enter UnLoaded State. +-- @param #CARGO_GROUP self +-- @param Core.Point#POINT_VEC2 +-- @param #string Event +-- @param #string From +-- @param #string To +function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... ) + self:F( { From, Event, To, ToPointVec2 } ) + + if From == "Loaded" then + + -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 + self.CargoSet:ForEach( + function( Cargo ) + Cargo:UnLoad( ToPointVec2 ) + end + ) + + end + +end + +end -- CARGO_GROUP + do -- CARGO_PACKAGE --- @type CARGO_PACKAGE @@ -1022,238 +1346,3 @@ end end - -do -- CARGO_GROUP - - --- @type CARGO_GROUP - -- @extends #CARGO_REPORTABLE - - --- # CARGO\_GROUP class - -- - -- The CARGO\_GROUP class defines a cargo that is represented by a @{Group} object within the simulator, and can be transported by a carrier. - -- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_GROUP to and from carrier. - -- - -- @field #CARGO_GROUP CARGO_GROUP - -- - CARGO_GROUP = { - ClassName = "CARGO_GROUP", - } - ---- CARGO_GROUP constructor. --- @param #CARGO_GROUP self --- @param Wrapper.Group#GROUP CargoGroup --- @param #string Type --- @param #string Name --- @param #number ReportRadius (optional) --- @param #number NearRadius (optional) --- @return #CARGO_GROUP -function CARGO_GROUP:New( CargoGroup, Type, Name, ReportRadius ) - local self = BASE:Inherit( self, CARGO_REPORTABLE:New( CargoGroup, Type, Name, 0, ReportRadius ) ) -- #CARGO_GROUP - self:F( { Type, Name, ReportRadius } ) - - self.CargoSet = SET_CARGO:New() - - self.CargoObject = CargoGroup - - local WeightGroup = 0 - - for UnitID, UnitData in pairs( CargoGroup:GetUnits() ) do - local Unit = UnitData -- Wrapper.Unit#UNIT - local WeightUnit = Unit:GetDesc().massEmpty - WeightGroup = WeightGroup + WeightUnit - local CargoUnit = CARGO_UNIT:New( Unit, Type, Unit:GetName(), WeightUnit ) - self.CargoSet:Add( CargoUnit:GetName(), CargoUnit ) - end - - self:SetWeight( WeightGroup ) - - self:T( { "Weight Cargo", WeightGroup } ) - - -- Cargo objects are added to the _DATABASE and SET_CARGO objects. - _EVENTDISPATCHER:CreateEventNewCargo( self ) - - return self -end - ---- Enter Boarding State. --- @param #CARGO_GROUP self --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - self:F( { CargoCarrier.UnitName, From, Event, To } ) - - NearRadius = NearRadius or 25 - - if From == "UnLoaded" then - - -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo ) - Cargo:__Board( 1, CargoCarrier, NearRadius ) - end - ) - - self:__Boarding( 1, CargoCarrier, NearRadius, ... ) - end - -end - ---- Enter Loaded State. --- @param #CARGO_GROUP self --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... ) - self:F( { CargoCarrier.UnitName, From, Event, To } ) - - if From == "UnLoaded" then - -- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier. - for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - Cargo:Load( CargoCarrier ) - end - end - - self.CargoObject:Destroy() - self.CargoCarrier = CargoCarrier - -end - ---- Leave Boarding State. --- @param #CARGO_GROUP self --- @param Wrapper.Unit#UNIT CargoCarrier --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onleaveBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) - self:F( { CargoCarrier.UnitName, From, Event, To } ) - - NearRadius = NearRadius or 25 - - local Boarded = true - - self.CargoSet:Flush() - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - self:T( { Cargo:GetName(), Cargo.current } ) - if not Cargo:is( "Loaded" ) then - Boarded = false - end - end - - if not Boarded then - self:__Boarding( 1, CargoCarrier, NearRadius, ... ) - else - self:__Load( 1, CargoCarrier, ... ) - end - return Boarded -end - ---- Enter UnBoarding State. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 ToPointVec2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - self:F({From, Event, To, ToPointVec2, NearRadius}) - - NearRadius = NearRadius or 25 - - local Timer = 1 - - if From == "Loaded" then - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo ) - Cargo:__UnBoard( Timer, ToPointVec2, NearRadius ) - Timer = Timer + 10 - end - ) - - self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) - end - -end - ---- Leave UnBoarding State. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 ToPointVec2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - self:F( { From, Event, To, ToPointVec2, NearRadius } ) - - NearRadius = NearRadius or 25 - - local Angle = 180 - local Speed = 10 - local Distance = 5 - - if From == "UnBoarding" then - local UnBoarded = true - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do - self:T( Cargo.current ) - if not Cargo:is( "UnLoaded" ) then - UnBoarded = false - end - end - - if UnBoarded then - return true - else - self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) - end - - return false - end - -end - ---- UnBoard Event. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 ToPointVec2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) - self:F( { From, Event, To, ToPointVec2, NearRadius } ) - - NearRadius = NearRadius or 25 - - self:__UnLoad( 1, ToPointVec2, ... ) -end - - - ---- Enter UnLoaded State. --- @param #CARGO_GROUP self --- @param Core.Point#POINT_VEC2 --- @param #string Event --- @param #string From --- @param #string To -function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... ) - self:F( { From, Event, To, ToPointVec2 } ) - - if From == "Loaded" then - - -- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2 - self.CargoSet:ForEach( - function( Cargo ) - Cargo:UnLoad( ToPointVec2 ) - end - ) - - end - -end - -end -- CARGO_GROUP - diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index f37e590df..f9da8ec67 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -890,7 +890,7 @@ function EVENT:onEvent( Event ) for EventClass, EventData in pairs( self.Events[Event.id][EventPriority] ) do if Event.IniObjectCategory ~= Object.Category.STATIC then - self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } ) + --self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } ) end Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName ) diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index aaa06e3a8..6ca7f6d5d 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -1336,6 +1336,11 @@ SET_UNIT = { } +--- Get the first unit from the set. +-- @function [parent=#SET_UNIT] GetFirst +-- @param #SET_UNIT self +-- @return Wrapper.Unit#UNIT The UNIT object. + --- Creates a new SET_UNIT object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names. -- @param #SET_UNIT self -- @return #SET_UNIT diff --git a/Moose Development/Moose/Functional/MissileTrainer.lua b/Moose Development/Moose/Functional/MissileTrainer.lua index 511cbca44..38b2008ae 100644 --- a/Moose Development/Moose/Functional/MissileTrainer.lua +++ b/Moose Development/Moose/Functional/MissileTrainer.lua @@ -442,7 +442,7 @@ function MISSILETRAINER._MenuMessages( MenuParameters ) if MenuParameters.Distance ~= nil then self.Distance = MenuParameters.Distance - MESSAGE:New( "Hit detection distance set to " .. self.Distance .. " meters", 15, "Menu" ):ToAll() + MESSAGE:New( "Hit detection distance set to " .. self.Distance * 1000 .. " meters", 15, "Menu" ):ToAll() end end diff --git a/Moose Development/Moose/Functional/Spawn.lua b/Moose Development/Moose/Functional/Spawn.lua index c6faf2ee8..6e9386a7d 100644 --- a/Moose Development/Moose/Functional/Spawn.lua +++ b/Moose Development/Moose/Functional/Spawn.lua @@ -1595,11 +1595,13 @@ function SPAWN:_OnBirth( EventData ) if SpawnGroup then local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup ) - self:T( { "Birth Event:", EventPrefix, self.SpawnTemplatePrefix } ) - if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then - self.AliveUnits = self.AliveUnits + 1 - self:T( "Alive Units: " .. self.AliveUnits ) - end + if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group! + self:T( { "Birth Event:", EventPrefix, self.SpawnTemplatePrefix } ) + if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then + self.AliveUnits = self.AliveUnits + 1 + self:T( "Alive Units: " .. self.AliveUnits ) + end + end end end @@ -1616,11 +1618,13 @@ function SPAWN:_OnDeadOrCrash( EventData ) if SpawnGroup then local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup ) - self:T( { "Dead event: " .. EventPrefix } ) - if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then - self.AliveUnits = self.AliveUnits - 1 - self:T( "Alive Units: " .. self.AliveUnits ) - end + if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group! + self:T( { "Dead event: " .. EventPrefix } ) + if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then + self.AliveUnits = self.AliveUnits - 1 + self:T( "Alive Units: " .. self.AliveUnits ) + end + end end end @@ -1634,10 +1638,12 @@ function SPAWN:_OnTakeOff( EventData ) local SpawnGroup = EventData.IniGroup if SpawnGroup then local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup ) - self:T( { "TakeOff event: " .. EventPrefix } ) - if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then - self:T( "self.Landed = false" ) - SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", false ) + if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group! + self:T( { "TakeOff event: " .. EventPrefix } ) + if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then + self:T( "self.Landed = false" ) + SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", false ) + end end end end @@ -1652,16 +1658,18 @@ function SPAWN:_OnLand( EventData ) local SpawnGroup = EventData.IniGroup if SpawnGroup then local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup ) - self:T( { "Land event: " .. EventPrefix } ) - if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then - -- TODO: Check if this is the last unit of the group that lands. - SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", true ) - if self.RepeatOnLanding then - local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup ) - self:T( { "Landed:", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } ) - self:ReSpawn( SpawnGroupIndex ) - end - end + if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group! + self:T( { "Land event: " .. EventPrefix } ) + if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then + -- TODO: Check if this is the last unit of the group that lands. + SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", true ) + if self.RepeatOnLanding then + local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup ) + self:T( { "Landed:", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } ) + self:ReSpawn( SpawnGroupIndex ) + end + end + end end end @@ -1676,16 +1684,18 @@ function SPAWN:_OnEngineShutDown( EventData ) local SpawnGroup = EventData.IniGroup if SpawnGroup then local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup ) - self:T( { "EngineShutdown event: " .. EventPrefix } ) - if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then - -- todo: test if on the runway - local Landed = SpawnGroup:GetState( SpawnGroup, "Spawn_Landed" ) - if Landed and self.RepeatOnEngineShutDown then - local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup ) - self:T( { "EngineShutDown: ", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } ) - self:ReSpawn( SpawnGroupIndex ) - end - end + if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group! + self:T( { "EngineShutdown event: " .. EventPrefix } ) + if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then + -- todo: test if on the runway + local Landed = SpawnGroup:GetState( SpawnGroup, "Spawn_Landed" ) + if Landed and self.RepeatOnEngineShutDown then + local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup ) + self:T( { "EngineShutDown: ", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } ) + self:ReSpawn( SpawnGroupIndex ) + end + end + end end end diff --git a/Moose Development/Moose/Tasking/CommandCenter.lua b/Moose Development/Moose/Tasking/CommandCenter.lua index 2a696ead2..93fd01162 100644 --- a/Moose Development/Moose/Tasking/CommandCenter.lua +++ b/Moose Development/Moose/Tasking/CommandCenter.lua @@ -112,9 +112,9 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName ) if EventData.IniObjectCategory == 1 then local EventGroup = GROUP:Find( EventData.IniDCSGroup ) if EventGroup and self:HasGroup( EventGroup ) then - local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu ) - local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Summary Report", MenuReporting, self.ReportSummary, self, EventGroup ) - local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Details Report", MenuReporting, self.ReportDetails, self, EventGroup ) + local MenuReporting = MENU_GROUP:New( EventGroup, "Missions Reports", self.CommandCenterMenu ) + local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Status Report", MenuReporting, self.ReportMissionsStatus, self, EventGroup ) + local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Players Report", MenuReporting, self.ReportMissionsPlayers, self, EventGroup ) self:ReportSummary( EventGroup ) end local PlayerUnit = EventData.IniUnit @@ -189,7 +189,10 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName ) function( self, EventData ) local PlayerUnit = EventData.IniUnit for MissionID, Mission in pairs( self:GetMissions() ) do - Mission:CrashUnit( PlayerUnit ) + local Mission = Mission -- Tasking.Mission#MISSION + if Mission:IsENGAGED() then + Mission:CrashUnit( PlayerUnit ) + end end end ) @@ -304,11 +307,9 @@ end -- @param #string Message -- @param Wrapper.Group#GROUP TaskGroup -- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown. -function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name ) +function COMMANDCENTER:MessageToGroup( Message, TaskGroup ) - local Prefix = Name and "@ " .. Name .. ": " or "@ " .. TaskGroup:GetCallsign() .. ": " - Message = Prefix .. Message - self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() ) + self:GetPositionable():MessageToGroup( Message , 15, TaskGroup, self:GetName() ) end @@ -318,7 +319,8 @@ function COMMANDCENTER:MessageToCoalition( Message ) local CCCoalition = self:GetPositionable():GetCoalition() --TODO: Fix coalition bug! - self:GetPositionable():MessageToCoalition( Message, 20, CCCoalition, self:GetName() ) + + self:GetPositionable():MessageToCoalition( Message, 15, CCCoalition ) end @@ -326,18 +328,37 @@ end --- Report the status of all MISSIONs to a GROUP. -- Each Mission is listed, with an indication how many Tasks are still to be completed. -- @param #COMMANDCENTER self -function COMMANDCENTER:ReportSummary( ReportGroup ) +function COMMANDCENTER:ReportMissionsStatus( ReportGroup ) + self:E( ReportGroup ) + + local Report = REPORT:New() + + Report:Add( "Status report of all missions." ) + + for MissionID, Mission in pairs( self.Missions ) do + local Mission = Mission -- Tasking.Mission#MISSION + Report:Add( " - " .. Mission:ReportStatus() ) + end + + self:MessageToGroup( Report:Text(), ReportGroup ) +end + +--- Report the players of all MISSIONs to a GROUP. +-- Each Mission is listed, with an indication how many Tasks are still to be completed. +-- @param #COMMANDCENTER self +function COMMANDCENTER:ReportMissionsPlayers( ReportGroup ) self:E( ReportGroup ) local Report = REPORT:New() + Report:Add( "Players active in all missions." ) + for MissionID, Mission in pairs( self.Missions ) do local Mission = Mission -- Tasking.Mission#MISSION - Report:Add( " - " .. Mission:ReportOverview() ) + Report:Add( " - " .. Mission:ReportPlayers() ) end - self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup ) - + self:MessageToGroup( Report:Text(), ReportGroup ) end --- Report the status of a Task to a Group. @@ -353,6 +374,6 @@ function COMMANDCENTER:ReportDetails( ReportGroup, Task ) Report:Add( " - " .. Mission:ReportDetails() ) end - self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup ) + self:MessageToGroup( Report:Text(), ReportGroup ) end diff --git a/Moose Development/Moose/Tasking/Mission.lua b/Moose Development/Moose/Tasking/Mission.lua index c19af3f75..3be1a3910 100644 --- a/Moose Development/Moose/Tasking/Mission.lua +++ b/Moose Development/Moose/Tasking/Mission.lua @@ -27,6 +27,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM + self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } ) + + self.CommandCenter = CommandCenter + CommandCenter:AddMission( self ) + + self.Name = MissionName + self.MissionPriority = MissionPriority + self.MissionBriefing = MissionBriefing + self.MissionCoalition = MissionCoalition + + self.Tasks = {} + self:SetStartState( "IDLE" ) self:AddTransition( "IDLE", "Start", "ENGAGED" ) @@ -208,21 +220,10 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi -- @param #MISSION self -- @param #number Delay The delay in seconds. - self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } ) - - self.CommandCenter = CommandCenter - CommandCenter:AddMission( self ) - - self.Name = MissionName - self.MissionPriority = MissionPriority - self.MissionBriefing = MissionBriefing - self.MissionCoalition = MissionCoalition - - self.Tasks = {} -- Private implementations - + CommandCenter:SetMenu() return self end @@ -257,7 +258,7 @@ end -- @param #MISSION self -- @return #MISSION self function MISSION:GetName() - return self.Name + return string.format( 'Mission "%s (%s)"', self.Name, self.MissionPriority ) end --- Add a Unit to join the Mission. @@ -308,19 +309,17 @@ end -- If the Unit is part of a Task in the Mission, true is returned. -- @param #MISSION self -- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player crashing. --- @return #boolean true if Unit is part of a Task in the Mission. +-- @return #MISSION function MISSION:CrashUnit( PlayerUnit ) self:F( { PlayerUnit = PlayerUnit } ) - local PlayerUnitRemoved = false - for TaskID, Task in pairs( self:GetTasks() ) do - if Task:CrashUnit( PlayerUnit ) then - PlayerUnitRemoved = true - end + local Task = Task -- Tasking.Task#TASK + local PlayerGroup = PlayerUnit:GetGroup() + Task:CrashGroup( PlayerGroup ) end - return PlayerUnitRemoved + return self end --- Add a scoring to the mission. @@ -607,6 +606,117 @@ function MISSION:GetTasksRemaining() return TasksRemaining end +--- @param #MISSION self +-- @return #number +function MISSION:GetTaskTypes() + -- Determine how many tasks are remaining. + local TaskTypeList = {} + local TasksRemaining = 0 + for TaskID, Task in pairs( self:GetTasks() ) do + local Task = Task -- Tasking.Task#TASK + local TaskType = Task:GetType() + TaskTypeList[TaskType] = TaskType + end + return TaskTypeList +end + + +--- Create a status report of the Mission. +-- This reports provides a one liner of the mission status. It indicates how many players and how many Tasks. +-- +-- Mission "" - Status "" +-- - Task Types: , +-- - Planned Tasks (xp) +-- - Assigned Tasks(xp) +-- - Success Tasks (xp) +-- - Hold Tasks (xp) +-- - Cancelled Tasks (xp) +-- - Aborted Tasks (xp) +-- - Failed Tasks (xp) +-- +-- @param #MISSION self +-- @return #string +function MISSION:ReportStatus() + + local Report = REPORT:New() + + -- List the name of the mission. + local Name = self:GetName() + + -- Determine the status of the mission. + local Status = self:GetState() + local TasksRemaining = self:GetTasksRemaining() + + Report:Add( string.format( '%s - Status "%s"', Name, Status ) ) + + local TaskTypes = self:GetTaskTypes() + + Report:Add( string.format( " - Task Types: %s", table.concat(TaskTypes, ", " ) ) ) + + local TaskStatusList = { "Planned", "Assigned", "Success", "Hold", "Cancelled", "Aborted", "Failed" } + + for TaskStatusID, TaskStatus in pairs( TaskStatusList ) do + local TaskCount = 0 + local TaskPlayerCount = 0 + -- Determine how many tasks are remaining. + for TaskID, Task in pairs( self:GetTasks() ) do + local Task = Task -- Tasking.Task#TASK + if Task:Is( TaskStatus ) then + TaskCount = TaskCount + 1 + TaskPlayerCount = TaskPlayerCount + Task:GetPlayerCount() + end + end + if TaskCount > 0 then + Report:Add( string.format( " - %02d %s Tasks (%dp)", TaskCount, TaskStatus, TaskPlayerCount ) ) + end + end + + return Report:Text() +end + +--- Create a player report of the Mission. +-- This reports provides a one liner of the mission status. It indicates how many players and how many Tasks. +-- +-- Mission "" - Status "" +-- - Player ": Task , Task +-- - Player : Task , Task +-- - .. +-- +-- @param #MISSION self +-- @return #string +function MISSION:ReportPlayers() + + local Report = REPORT:New() + + -- List the name of the mission. + local Name = self:GetName() + + -- Determine the status of the mission. + local Status = self:GetState() + local TasksRemaining = self:GetTasksRemaining() + + Report:Add( string.format( '%s - Status "%s"', Name, Status ) ) + + local PlayerList = {} + + -- Determine how many tasks are remaining. + for TaskID, Task in pairs( self:GetTasks() ) do + local Task = Task -- Tasking.Task#TASK + local PlayerNames = Task:GetPlayerNames() + for PlayerID, PlayerName in pairs( PlayerNames ) do + PlayerList[PlayerName] = Task:GetName() + end + + end + + for PlayerName, TaskName in pairs( PlayerList ) do + Report:Add( string.format( ' - Player (%s): Task "%s"', PlayerName, TaskName ) ) + end + + return Report:Text() +end + + --- Create a summary report of the Mission (one line). -- @param #MISSION self -- @return #string @@ -646,7 +756,7 @@ function MISSION:ReportOverview( TaskStatus ) local Status = self:GetState() local TasksRemaining = self:GetTasksRemaining() - Report:Add( "Mission " .. Name .. " - " .. Status .. " Task Report ") + Report:Add( string.format( '%s - Status "%s"', Name, Status ) ) -- Determine how many tasks are remaining. local TasksRemaining = 0 @@ -673,7 +783,7 @@ function MISSION:ReportDetails() -- Determine the status of the mission. local Status = self:GetState() - Report:Add( "Mission " .. Name .. " - " .. Status ) + Report:Add( string.format( '%s - Status "%s"', Name, Status ) ) -- Determine how many tasks are remaining. local TasksRemaining = 0 diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index 15c88a013..618721d0b 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -157,9 +157,9 @@ TASK = { -- @param #string TaskName The name of the Task -- @param #string TaskType The type of the Task -- @return #TASK self -function TASK:New( Mission, SetGroupAssign, TaskName, TaskType ) +function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing ) - local self = BASE:Inherit( self, FSM_TASK:New() ) -- Core.Fsm#FSM_TASK + local self = BASE:Inherit( self, FSM_TASK:New() ) -- Tasking.Task#TASK self:SetStartState( "Planned" ) self:AddTransition( "Planned", "Assign", "Assigned" ) @@ -189,7 +189,7 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType ) self:SetName( TaskName ) self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences .. - self.TaskBriefing = "You are invited for the task: " .. self.TaskName .. "." + self:SetBriefing( TaskBriefing ) self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New() @@ -260,7 +260,7 @@ end -- If the Unit is part of the Task, true is returned. -- @param #TASK self -- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task. --- @return #boolean true if Unit is part of the Task. +-- @return #TASK function TASK:AbortGroup( PlayerGroup ) self:F( { PlayerGroup = PlayerGroup } ) @@ -312,14 +312,11 @@ end -- If the Unit is part of the Task, true is returned. -- @param #TASK self -- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task. --- @return #boolean true if Unit is part of the Task. -function TASK:CrashUnit( PlayerUnit ) - self:F( { PlayerUnit = PlayerUnit } ) - - local PlayerUnitCrashed = false +-- @return #TASK +function TASK:CrashGroup( PlayerGroup ) + self:F( { PlayerGroup = PlayerGroup } ) local PlayerGroups = self:GetGroups() - local PlayerGroup = PlayerUnit:GetGroup() -- Is the PlayerGroup part of the PlayerGroups? if PlayerGroups:IsIncludeObject( PlayerGroup ) then @@ -330,18 +327,35 @@ function TASK:CrashUnit( PlayerUnit ) local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup ) self:E( { IsGroupAssigned = IsGroupAssigned } ) if IsGroupAssigned then - self:UnAssignFromUnit( PlayerUnit ) - self:MessageToGroups( PlayerUnit:GetPlayerName() .. " crashed in Task " .. self:GetName() ) - self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } ) - if #PlayerGroup:GetUnits() == 1 then - self:ClearGroupAssignment( PlayerGroup ) + local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName() + self:MessageToGroups( PlayerName .. " crashed! " ) + self:UnAssignFromGroup( PlayerGroup ) + + -- Now check if the task needs to go to hold... + -- It will go to hold, if there are no players in the mission... + + PlayerGroups:Flush() + local IsRemaining = false + for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do + if self:IsGroupAssigned( AssignedGroup ) == true then + IsRemaining = true + self:F( { Task = self:GetName(), IsRemaining = IsRemaining } ) + break + end end - self:PlayerCrashed( PlayerUnit ) + + self:F( { Task = self:GetName(), IsRemaining = IsRemaining } ) + if IsRemaining == false then + self:Abort() + end + + self:PlayerCrashed( PlayerGroup:GetUnit(1) ) end + end end - return PlayerUnitCrashed + return self end @@ -399,15 +413,15 @@ do -- Group Assignment local SetAssignedGroups = self:GetGroups() - SetAssignedGroups:ForEachGroup( - function( AssignedGroup ) - if self:IsGroupAssigned(AssignedGroup) then - self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to group %s.", TaskName, TaskGroupName ), AssignedGroup ) - else - self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to your group.", TaskName ), AssignedGroup ) - end - end - ) +-- SetAssignedGroups:ForEachGroup( +-- function( AssignedGroup ) +-- if self:IsGroupAssigned(AssignedGroup) then +-- self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to group %s.", TaskName, TaskGroupName ), AssignedGroup ) +-- else +-- self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to your group.", TaskName ), AssignedGroup ) +-- end +-- end +-- ) return self end @@ -454,6 +468,8 @@ do -- Group Assignment self:F( TaskGroup:GetName() ) local TaskGroupName = TaskGroup:GetName() + local Mission = self:GetMission() + local CommandCenter = Mission:GetCommandCenter() self:SetGroupAssigned( TaskGroup ) @@ -464,11 +480,16 @@ do -- Group Assignment self:E(PlayerName) if PlayerName ~= nil or PlayerName ~= "" then self:AssignToUnit( TaskUnit ) + CommandCenter:MessageToGroup( + string.format( 'Task "%s": Briefing for player (%s):\n%s', + self:GetName(), + PlayerName, + self:GetBriefing() + ), TaskGroup + ) end end - local Mission = self:GetMission() - local CommandCenter = Mission:GetCommandCenter() CommandCenter:SetMenu() return self @@ -503,7 +524,8 @@ end -- @return #boolean function TASK:HasGroup( FindGroup ) - return self:GetGroups():IsIncludeObject( FindGroup ) + local SetAttackGroup = self:GetGroups() + return SetAttackGroup:FindGroup(FindGroup) end @@ -585,7 +607,9 @@ function TASK:UnAssignFromGroups() self:F2() for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do - self:UnAssignFromGroup( TaskGroup ) + if self:IsGroupAssigned(TaskGroup) then + self:UnAssignFromGroup( TaskGroup ) + end end end @@ -677,7 +701,12 @@ function TASK:SetPlannedMenuForGroup( TaskGroup, MenuTime ) local CommandCenterMenu = CommandCenter:GetMenu() local TaskType = self:GetType() - local TaskText = self:GetName() +-- local TaskThreatLevel = self.TaskInfo["ThreatLevel"] +-- local TaskThreatLevelString = TaskThreatLevel and " [" .. string.rep( "â– ", TaskThreatLevel ) .. "]" or " []" + local TaskPlayerCount = self:GetPlayerCount() + local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount ) + local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString ) + local TaskName = string.format( "%s", self:GetName() ) local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime ) @@ -686,10 +715,10 @@ function TASK:SetPlannedMenuForGroup( TaskGroup, MenuTime ) local TaskPlannedMenu = MENU_GROUP:New( TaskGroup, "Planned Tasks", MissionMenu ):SetTime( MenuTime ) local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, TaskPlannedMenu ):SetTime( MenuTime ):SetRemoveParent( true ) local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskText, TaskTypeMenu ):SetTime( MenuTime ):SetRemoveParent( true ) - local ReportTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task %s Status", TaskText ), TaskTypeMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true ) + local ReportTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Status" ), TaskTypeMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true ) if not Mission:IsGroupAssigned( TaskGroup ) then - local JoinTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Join Task %s", TaskText ), TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true ) + local JoinTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Join Task" ), TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true ) end return self @@ -709,15 +738,19 @@ function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime ) local CommandCenterMenu = CommandCenter:GetMenu() local TaskType = self:GetType() - local TaskText = self:GetName() +-- local TaskThreatLevel = self.TaskInfo["ThreatLevel"] +-- local TaskThreatLevelString = TaskThreatLevel and " [" .. string.rep( "â– ", TaskThreatLevel ) .. "]" or " []" + local TaskPlayerCount = self:GetPlayerCount() + local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount ) + local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString ) + local TaskName = string.format( "%s", self:GetName() ) local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime ) local MissionMenu = Mission:GetMenu( TaskGroup ) - - local TaskAssignedMenu = MENU_GROUP:New( TaskGroup, string.format( "Assigned Task %s", TaskText ), MissionMenu ):SetTime( MenuTime ) - local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task %s Status", TaskText ), TaskAssignedMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true ) - local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Abort Group from Task %s", TaskText ), TaskAssignedMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true ) + local TaskAssignedMenu = MENU_GROUP:New( TaskGroup, string.format( "Assigned Task %s", TaskName ), MissionMenu ):SetTime( MenuTime ) + local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Status" ), TaskAssignedMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true ) + local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Abort Group from Task" ), TaskAssignedMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true ) return self end @@ -753,9 +786,9 @@ function TASK:RefreshMenus( TaskGroup, MenuTime ) local MissionMenu = Mission:GetMenu( TaskGroup ) - local TaskText = self:GetName() + local TaskName = self:GetName() local PlannedMenu = MissionMenu:GetMenu( "Planned Tasks" ) - local AssignedMenu = MissionMenu:GetMenu( string.format( "Assigned Task %s", TaskText ) ) + local AssignedMenu = MissionMenu:GetMenu( string.format( "Assigned Task %s", TaskName ) ) if PlannedMenu then PlannedMenu:Remove( MenuTime ) @@ -823,6 +856,13 @@ function TASK:GetTaskName() return self.TaskName end +--- Returns the @{Task} briefing. +-- @param #TASK self +-- @return #string Task briefing. +function TASK:GetTaskBriefing() + return self.TaskBriefing +end + @@ -1092,10 +1132,18 @@ end -- @param #string TaskBriefing -- @return #TASK self function TASK:SetBriefing( TaskBriefing ) + self:E(TaskBriefing) self.TaskBriefing = TaskBriefing return self end +--- Gets the @{Task} briefing. +-- @param #TASK self +-- @return #string The briefing text. +function TASK:GetBriefing() + return self.TaskBriefing +end + @@ -1284,6 +1332,47 @@ function TASK:ReportOverview() --R2.1 fixed report. Now nicely formatted and con return Report:Text() end +--- Create a count of the players in the Task. +-- @param #TASK self +-- @return #number The total number of players in the task. +function TASK:GetPlayerCount() --R2.1 Get a count of the players. + + local PlayerCount = 0 + + -- Loop each Unit active in the Task, and find Player Names. + for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do + local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP + if self:IsGroupAssigned( PlayerGroup ) then + local PlayerNames = PlayerGroup:GetPlayerNames() + PlayerCount = PlayerCount + #PlayerNames + end + end + + return PlayerCount +end + + +--- Create a list of the players in the Task. +-- @param #TASK self +-- @return #map<#string,Wrapper.Group#GROUP> A map of the players +function TASK:GetPlayerNames() --R2.1 Get a map of the players. + + local PlayerNameMap = {} + + -- Loop each Unit active in the Task, and find Player Names. + for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do + local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP + if self:IsGroupAssigned( PlayerGroup ) then + local PlayerNames = PlayerGroup:GetPlayerNames() + for PlayerNameID, PlayerName in pairs( PlayerNames ) do + PlayerNameMap[PlayerName] = PlayerGroup + end + end + end + + return PlayerNameMap +end + --- Create a detailed report of the Task. -- List the Task Status, and the Players assigned to the Task. @@ -1298,18 +1387,13 @@ function TASK:ReportDetails() --R2.1 fixed report. Now nicely formatted and cont -- Determine the status of the Task. local State = self:GetState() - + -- Loop each Unit active in the Task, and find Player Names. - local PlayerNames = {} + local PlayerNames = self:GetPlayerNames() + local PlayerReport = REPORT:New() - for PlayerGroupID, PlayerGroupData in pairs( self:GetGroups():GetSet() ) do - - local PlayerGroup = PlayerGroupData -- Wrapper.Group#GROUP - - PlayerNames = PlayerGroup:GetPlayerNames() - if PlayerNames then - PlayerReport:Add( "Group " .. PlayerGroup:GetCallsign() .. ": " .. table.concat( PlayerNames, ", " ) ) - end + for PlayerName, PlayerGroup in pairs( PlayerNames ) do + PlayerReport:Add( "Group " .. PlayerGroup:GetCallsign() .. ": " .. PlayerName ) end local Players = PlayerReport:Text() diff --git a/Moose Development/Moose/Tasking/Task_A2G.lua b/Moose Development/Moose/Tasking/Task_A2G.lua index 17162ca7f..35387c045 100644 --- a/Moose Development/Moose/Tasking/Task_A2G.lua +++ b/Moose Development/Moose/Tasking/Task_A2G.lua @@ -86,8 +86,8 @@ do -- TASK_A2G -- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known. -- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be. -- @return #TASK_A2G self - function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType ) - local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- Tasking.Task#TASK_A2G + function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType, TaskBriefing ) + local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2G self:F() self.TargetSetUnit = TargetSetUnit @@ -364,16 +364,28 @@ do -- TASK_SEAD --- Instantiates a new TASK_SEAD. -- @param #TASK_SEAD self -- @param Tasking.Mission#MISSION Mission - -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. + -- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param #string TaskName The name of the Task. - -- @param Set#SET_UNIT TargetSetUnit + -- @param Core.Set#SET_UNIT TargetSetUnit + -- @param #string TaskBriefing The briefing of the task. -- @return #TASK_SEAD self - function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit ) - local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD" ) ) -- #TASK_SEAD + function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing ) + local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD", TaskBriefing ) ) -- #TASK_SEAD self:F() Mission:AddTask( self ) + local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate() + local TargetPositionText = TargetCoord:ToString() + local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G() + + self:SetBriefing( + TaskBriefing or + "Execute a Suppression of Enemy Air Defenses.\n" .. + "Initial Coordinates: " .. TargetPositionText .. "\n" .. + "Threat Level: [" .. string.rep( "â– ", TargetThreatLevel ) .. "]" + ) + return self end @@ -392,19 +404,28 @@ do -- TASK_BAI --- Instantiates a new TASK_BAI. -- @param #TASK_BAI self -- @param Tasking.Mission#MISSION Mission - -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. + -- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param #string TaskName The name of the Task. - -- @param Set#SET_UNIT UnitSetTargets - -- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range. - -- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known. - -- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be. + -- @param Core.Set#SET_UNIT TargetSetUnit + -- @param #string TaskBriefing The briefing of the task. -- @return #TASK_BAI self - function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit ) - local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI" ) ) -- #TASK_BAI + function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing ) + local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI", TaskBriefing ) ) -- #TASK_BAI self:F() Mission:AddTask( self ) + local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate() + local TargetPositionText = TargetCoord:ToString() + local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G() + + self:SetBriefing( + TaskBriefing or + "Execute a Battlefield Air Interdiction of a group of enemy targets.\n" .. + "Initial Coordinates: " .. TargetPositionText .. "\n" .. + "Threat Level: [" .. string.rep( "â– ", TargetThreatLevel ) .. "]" + ) + return self end @@ -423,19 +444,29 @@ do -- TASK_CAS --- Instantiates a new TASK_CAS. -- @param #TASK_CAS self -- @param Tasking.Mission#MISSION Mission - -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. + -- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param #string TaskName The name of the Task. - -- @param Set#SET_UNIT UnitSetTargets - -- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range. - -- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known. - -- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be. + -- @param Core.Set#SET_UNIT TargetSetUnit + -- @param #string TaskBriefing The briefing of the task. -- @return #TASK_CAS self - function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit ) - local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS" ) ) -- #TASK_CAS + function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing ) + local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS", TaskBriefing ) ) -- #TASK_CAS self:F() Mission:AddTask( self ) + local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate() + local TargetPositionText = TargetCoord:ToString() + local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G() + + self:SetBriefing( + TaskBriefing or + "Execute a Close Air Support for a group of enemy targets.\n" .. + "Beware of friendlies at the vicinity!\n" .. + "Initial Coordinates: " .. TargetPositionText .. "\n" .. + "Threat Level: [" .. string.rep( "â– ", TargetThreatLevel ) .. "]" + ) + return self end diff --git a/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua index b1a6e4348..f7101eea4 100644 --- a/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_A2G_Dispatcher.lua @@ -220,7 +220,7 @@ do -- TASK_A2G_DISPATCHER for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem - local DetectedSet = DetectedItem.Set -- Functional.Detection#DETECTION_BASE.DetectedSet + local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT local DetectedZone = DetectedItem.Zone self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } ) DetectedSet:Flush() @@ -258,6 +258,7 @@ do -- TASK_A2G_DISPATCHER self.Tasks[DetectedItemID] = Task Task:SetTargetZone( DetectedZone ) Task:SetDispatcher( self ) + Task:SetInfo( "ThreatLevel", DetectedSet:CalculateThreatLevelA2G() ) Task:SetInfo( "Detection", Detection:DetectedItemReportSummary( DetectedItemID ) ) Task:SetInfo( "Changes", Detection:GetChangeText( DetectedItem ) ) Mission:AddTask( Task ) @@ -277,7 +278,9 @@ do -- TASK_A2G_DISPATCHER Mission:GetCommandCenter():SetMenu() for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do - Mission:GetCommandCenter():MessageToGroup( string.format( "Mission *%s* has tasks %s. Subscribe to a task using the Mission *Overlord* radio menu.", Mission:GetName(), TaskReport:Text(", ") ), TaskGroup ) + if not Mission:IsGroupAssigned(TaskGroup) then + Mission:GetCommandCenter():MessageToGroup( string.format( "Mission *%s* has tasks %s. Subscribe to a task using the Mission *Overlord* radio menu.", Mission:GetName(), TaskReport:Text(", ") ), TaskGroup ) + end end end diff --git a/Moose Development/Moose/Tasking/Task_CARGO.lua b/Moose Development/Moose/Tasking/Task_CARGO.lua index 7ad7013e9..5af0f0b30 100644 --- a/Moose Development/Moose/Tasking/Task_CARGO.lua +++ b/Moose Development/Moose/Tasking/Task_CARGO.lua @@ -153,7 +153,7 @@ do -- TASK_CARGO -- -- === -- - -- @field #TASK_CARGO TASK_CARGO + -- @field #TASK_CARGO -- TASK_CARGO = { ClassName = "TASK_CARGO", @@ -166,9 +166,10 @@ do -- TASK_CARGO -- @param #string TaskName The name of the Task. -- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported. -- @param #string TaskType The type of Cargo task. + -- @param #string TaskBriefing The Cargo Task briefing. -- @return #TASK_CARGO self - function TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, TaskType ) - local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- #TASK_CARGO + function TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, TaskType, TaskBriefing ) + local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- #TASK_CARGO self:F( {Mission, SetGroup, TaskName, SetCargo, TaskType}) self.SetCargo = SetCargo @@ -181,24 +182,24 @@ do -- TASK_CARGO Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "SelectAction", Rejected = "Reject" } ) - Fsm:AddTransition( { "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Landed" }, "SelectAction", "WaitingForCommand" ) + Fsm:AddTransition( { "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Landed", "Boarding" }, "SelectAction", "*" ) - Fsm:AddTransition( "WaitingForCommand", "RouteToPickup", "RoutingToPickup" ) + Fsm:AddTransition( "*", "RouteToPickup", "RoutingToPickup" ) Fsm:AddProcess ( "RoutingToPickup", "RouteToPickupPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtPickup" } ) Fsm:AddTransition( "Arrived", "ArriveAtPickup", "ArrivedAtPickup" ) - Fsm:AddTransition( "WaitingForCommand", "RouteToDeploy", "RoutingToDeploy" ) + Fsm:AddTransition( "*", "RouteToDeploy", "RoutingToDeploy" ) Fsm:AddProcess ( "RoutingToDeploy", "RouteToDeployZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtDeploy" } ) Fsm:AddTransition( "Arrived", "ArriveAtDeploy", "ArrivedAtDeploy" ) Fsm:AddTransition( { "ArrivedAtPickup", "ArrivedAtDeploy", "Landing" }, "Land", "Landing" ) Fsm:AddTransition( "Landing", "Landed", "Landed" ) - Fsm:AddTransition( "WaitingForCommand", "PrepareBoarding", "AwaitBoarding" ) + Fsm:AddTransition( "*", "PrepareBoarding", "AwaitBoarding" ) Fsm:AddTransition( "AwaitBoarding", "Board", "Boarding" ) Fsm:AddTransition( "Boarding", "Boarded", "Boarded" ) - Fsm:AddTransition( "WaitingForCommand", "PrepareUnBoarding", "AwaitUnBoarding" ) + Fsm:AddTransition( "*", "PrepareUnBoarding", "AwaitUnBoarding" ) Fsm:AddTransition( "AwaitUnBoarding", "UnBoard", "UnBoarding" ) Fsm:AddTransition( "UnBoarding", "UnBoarded", "UnBoarded" ) @@ -211,71 +212,79 @@ do -- TASK_CARGO --- -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit - -- @param Tasking.Task_Cargo#TASK_CARGO Task - function Fsm:onenterWaitingForCommand( TaskUnit, Task ) + -- @param Tasking.Task_CARGO#TASK_CARGO Task + function Fsm:onafterSelectAction( TaskUnit, Task ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) - if TaskUnit.Menu then - TaskUnit.Menu:Remove() - end + local MenuTime = timer.getTime() - TaskUnit.Menu = MENU_GROUP:New( TaskUnit:GetGroup(), Task:GetName() .. " @ " .. TaskUnit:GetName() ) + TaskUnit.Menu = MENU_GROUP:New( TaskUnit:GetGroup(), Task:GetName() .. " @ " .. TaskUnit:GetName() ):SetTime( MenuTime ) Task.SetCargo:ForEachCargo( --- @param Core.Cargo#CARGO Cargo function( Cargo ) - if Cargo:IsUnLoaded() then - if Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then - MENU_GROUP_COMMAND:New( - TaskUnit:GetGroup(), - "Board cargo " .. Cargo.Name, - TaskUnit.Menu, - self.MenuBoardCargo, - self, - Cargo - ) - else - MENU_GROUP_COMMAND:New( - TaskUnit:GetGroup(), - "Route to Pickup cargo " .. Cargo.Name, - TaskUnit.Menu, - self.MenuRouteToPickup, - self, - Cargo - ) - end - end - - if Cargo:IsLoaded() then - for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do - if Cargo:IsInZone( DeployZone ) then + + if Cargo:IsAlive() then + + if Cargo:IsUnLoaded() then + if Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), - "Unboard cargo " .. Cargo.Name, + "Board cargo " .. Cargo.Name, TaskUnit.Menu, - self.MenuUnBoardCargo, + self.MenuBoardCargo, self, - Cargo, - DeployZone - ) + Cargo + ):SetTime(MenuTime) else MENU_GROUP_COMMAND:New( TaskUnit:GetGroup(), - "Route to Deploy cargo at " .. DeployZoneName, + "Route to Pickup cargo " .. Cargo.Name, TaskUnit.Menu, - self.MenuRouteToDeploy, + self.MenuRouteToPickup, self, - DeployZone - ) + Cargo + ):SetTime(MenuTime) + end + end + + if Cargo:IsLoaded() then + + MENU_GROUP_COMMAND:New( + TaskUnit:GetGroup(), + "Unboard cargo " .. Cargo.Name, + TaskUnit.Menu, + self.MenuUnBoardCargo, + self, + Cargo + ):SetTime(MenuTime) + + -- Deployzones are optional zones that can be selected to request routing information. + for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do + if not Cargo:IsInZone( DeployZone ) then + MENU_GROUP_COMMAND:New( + TaskUnit:GetGroup(), + "Route to Deploy cargo at " .. DeployZoneName, + TaskUnit.Menu, + self.MenuRouteToDeploy, + self, + DeployZone + ):SetTime(MenuTime) + end end end end end ) + + TaskUnit.Menu:Remove( MenuTime ) + self:__SelectAction( -15 ) + + --Task:GetMission():GetCommandCenter():MessageToGroup("Cargo menu is ready ...", TaskUnit:GetGroup() ) end --- @@ -308,13 +317,19 @@ do -- TASK_CARGO -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit -- @param Tasking.Task_Cargo#TASK_CARGO Task + -- @param From + -- @param Event + -- @param To + -- @param Core.Cargo#CARGO Cargo function Fsm:onafterRouteToPickup( TaskUnit, Task, From, Event, To, Cargo ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + if Cargo:IsAlive() then + self.Cargo = Cargo -- Core.Cargo#CARGO + Task:SetCargoPickup( self.Cargo, TaskUnit ) + self:__RouteToPickupPoint( -0.1 ) + end - self.Cargo = Cargo - Task:SetCargoPickup( self.Cargo, TaskUnit ) - self:__RouteToPickupPoint( -0.1 ) end @@ -325,10 +340,13 @@ do -- TASK_CARGO function Fsm:onafterArriveAtPickup( TaskUnit, Task ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) - if TaskUnit:IsAir() then - self:__Land( -0.1, "Pickup" ) - else - self:__SelectAction( -0.1 ) + if self.Cargo:IsAlive() then + if TaskUnit:IsAir() then + self.Cargo.CargoObject:GetUnit(1):SmokeRed() + self:__Land( -0.1, "Pickup" ) + else + self:__SelectAction( -0.1 ) + end end end @@ -369,19 +387,21 @@ do -- TASK_CARGO function Fsm:onafterLand( TaskUnit, Task, From, Event, To, Action ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) - if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then - if TaskUnit:InAir() then - Task:GetMission():GetCommandCenter():MessageToGroup( "Land", TaskUnit:GetGroup() ) - self:__Land( -10, Action ) + if self.Cargo:IsAlive() then + if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then + if TaskUnit:InAir() then + Task:GetMission():GetCommandCenter():MessageToGroup( "Land", TaskUnit:GetGroup() ) + self:__Land( -10, Action ) + else + Task:GetMission():GetCommandCenter():MessageToGroup( "Landed ...", TaskUnit:GetGroup() ) + self:__Landed( -0.1, Action ) + end else - Task:GetMission():GetCommandCenter():MessageToGroup( "Landed ...", TaskUnit:GetGroup() ) - self:__Landed( -0.1, Action ) - end - else - if Action == "Pickup" then - self:__RouteToPickupZone( -0.1 ) - else - self:__RouteToDeployZone( -0.1 ) + if Action == "Pickup" then + self:__RouteToPickupZone( -0.1 ) + else + self:__RouteToDeployZone( -0.1 ) + end end end end @@ -393,17 +413,19 @@ do -- TASK_CARGO function Fsm:onafterLanded( TaskUnit, Task, From, Event, To, Action ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) - if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then - if TaskUnit:InAir() then - self:__Land( -0.1, Action ) + if self.Cargo:IsAlive() then + if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then + if TaskUnit:InAir() then + self:__Land( -0.1, Action ) + else + self:__SelectAction( -0.1 ) + end else - self:__SelectAction( -0.1 ) - end - else - if Action == "Pickup" then - self:__RouteToPickupZone( -0.1 ) - else - self:__RouteToDeployZone( -0.1 ) + if Action == "Pickup" then + self:__RouteToPickupZone( -0.1 ) + else + self:__RouteToDeployZone( -0.1 ) + end end end end @@ -415,8 +437,10 @@ do -- TASK_CARGO function Fsm:onafterPrepareBoarding( TaskUnit, Task, From, Event, To, Cargo ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) - self.Cargo = Cargo -- Core.Cargo#CARGO_GROUP - self:__Board( -0.1 ) + if Cargo and Cargo:IsAlive() then + self.Cargo = Cargo -- Core.Cargo#CARGO_GROUP + self:__Board( -0.1 ) + end end --- @@ -427,23 +451,21 @@ do -- TASK_CARGO self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) function self.Cargo:OnEnterLoaded( From, Event, To, TaskUnit, TaskProcess ) - self:E({From, Event, To, TaskUnit, TaskProcess }) - TaskProcess:__Boarded( 0.1 ) - end - - if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then - if TaskUnit:InAir() then - --- ABORT the boarding. Split group if any and go back to select action. + if self.Cargo:IsAlive() then + if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then + if TaskUnit:InAir() then + --- ABORT the boarding. Split group if any and go back to select action. + else + self.Cargo:MessageToGroup( "Boarding ...", TaskUnit:GetGroup() ) + self.Cargo:Board( TaskUnit, 20, self ) + end else - self.Cargo:MessageToGroup( "Boarding ...", TaskUnit:GetGroup() ) - self.Cargo:Board( TaskUnit, 20, self ) + --self:__ArriveAtCargo( -0.1 ) end - else - --self:__ArriveAtCargo( -0.1 ) end end @@ -460,8 +482,10 @@ do -- TASK_CARGO -- TODO:I need to find a more decent solution for this. Task:E( { CargoPickedUp = Task.CargoPickedUp } ) - if Task.CargoPickedUp then - Task:CargoPickedUp( TaskUnit, self.Cargo ) + if self.Cargo:IsAlive() then + if Task.CargoPickedUp then + Task:CargoPickedUp( TaskUnit, self.Cargo ) + end end end @@ -471,31 +495,50 @@ do -- TASK_CARGO -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit -- @param Tasking.Task_Cargo#TASK_CARGO Task - function Fsm:onafterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo, DeployZone ) - self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + -- @param From + -- @param Event + -- @param To + -- @param Cargo + -- @param Core.Zone#ZONE_BASE DeployZone + function Fsm:onafterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo } ) self.Cargo = Cargo - self.DeployZone = DeployZone - self:__UnBoard( -0.1 ) + self.DeployZone = nil + + -- Check if the Cargo is at a deployzone... If it is, provide it as a parameter! + if Cargo:IsAlive() then + for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do + if Cargo:IsInZone( DeployZone ) then + self.DeployZone = DeployZone -- Core.Zone#ZONE_BASE + break + end + end + self:__UnBoard( -0.1, Cargo, self.DeployZone ) + end end --- -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit -- @param Tasking.Task_Cargo#TASK_CARGO Task - function Fsm:onafterUnBoard( TaskUnit, Task ) - self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + -- @param From + -- @param Event + -- @param To + -- @param Cargo + -- @param Core.Zone#ZONE_BASE DeployZone + function Fsm:onafterUnBoard( TaskUnit, Task, From, Event, To, Cargo, DeployZone ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo, DeployZone } ) function self.Cargo:OnEnterUnLoaded( From, Event, To, DeployZone, TaskProcess ) - - self:E({From, Event, To, TaskUnit, TaskProcess }) - + self:E({From, Event, To, DeployZone, TaskProcess }) TaskProcess:__UnBoarded( -0.1 ) - end - self.Cargo:MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup() ) - self.Cargo:UnBoard( self.DeployZone:GetPointVec2(), 20, self ) + if self.Cargo:IsAlive() then + self.Cargo:MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup() ) + self.Cargo:UnBoard( DeployZone:GetPointVec2(), 400, self ) + end end @@ -510,8 +553,10 @@ do -- TASK_CARGO -- TODO:I need to find a more decent solution for this. Task:E( { CargoDeployed = Task.CargoDeployed } ) - if Task.CargoDeployed then - Task:CargoDeployed( TaskUnit, self.Cargo, self.DeployZone ) + if self.Cargo:IsAlive() then + if Task.CargoDeployed then + Task:CargoDeployed( TaskUnit, self.Cargo, self.DeployZone ) + end end self:__SelectAction( 1 ) @@ -685,9 +730,10 @@ do -- TASK_CARGO_TRANSPORT -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param #string TaskName The name of the Task. -- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported. + -- @param #string TaskBriefing The Cargo Task briefing. -- @return #TASK_CARGO_TRANSPORT self - function TASK_CARGO_TRANSPORT:New( Mission, SetGroup, TaskName, SetCargo ) - local self = BASE:Inherit( self, TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, "Transport" ) ) -- #TASK_CARGO_TRANSPORT + function TASK_CARGO_TRANSPORT:New( Mission, SetGroup, TaskName, SetCargo, TaskBriefing ) + local self = BASE:Inherit( self, TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, "Transport", TaskBriefing ) ) -- #TASK_CARGO_TRANSPORT self:F() Mission:AddTask( self ) @@ -698,8 +744,6 @@ do -- TASK_CARGO_TRANSPORT self:AddTransition( "*", "CargoPickedUp", "*" ) self:AddTransition( "*", "CargoDeployed", "*" ) - do - --- OnBefore Transition Handler for Event CargoPickedUp. -- @function [parent=#TASK_CARGO_TRANSPORT] OnBeforeCargoPickedUp -- @param #TASK_CARGO_TRANSPORT self @@ -731,9 +775,7 @@ do -- TASK_CARGO_TRANSPORT -- @param #number Delay The delay in seconds. -- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc. -- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status. - end - do --- OnBefore Transition Handler for Event CargoDeployed. -- @function [parent=#TASK_CARGO_TRANSPORT] OnBeforeCargoDeployed -- @param #TASK_CARGO_TRANSPORT self @@ -769,10 +811,26 @@ do -- TASK_CARGO_TRANSPORT -- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc. -- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status. -- @param Core.Zone#ZONE DeployZone The zone where the Cargo got Deployed or UnBoarded. - end local Fsm = self:GetUnitProcess() + local CargoReport = REPORT:New( "Transport Cargo. The following cargo needs to be transported including initial positions:") + + SetCargo:ForEachCargo( + --- @param Core.Cargo#CARGO Cargo + function( Cargo ) + local CargoType = Cargo:GetType() + local CargoName = Cargo:GetName() + local CargoCoordinate = Cargo:GetCoordinate() + CargoReport:Add( string.format( '- "%s" (%s) at %s', CargoName, CargoType, CargoCoordinate:ToString() ) ) + end + ) + + self:SetBriefing( + TaskBriefing or + CargoReport:Text() + ) + return self end @@ -804,7 +862,7 @@ do -- TASK_CARGO_TRANSPORT end end end - + return CargoDeployed end diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index ec62872f1..5b84dd5c9 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -585,36 +585,64 @@ end --- (AIR) Delivering weapon at the point on the ground. -- @param #CONTROLLABLE self -- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at. --- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found. -- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. --- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. -- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. --- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft. +-- @param #number Altitude (optional) The altitude from where to attack. +-- @param #number WeaponType (optional) The WeaponType. -- @return Dcs.DCSTasking.Task#Task The DCS task structure. -function CONTROLLABLE:TaskBombing( Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack ) - self:F2( { self.ControllableName, Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } ) - --- Bombing = { --- id = 'Bombing', --- params = { --- point = Vec2, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend, --- attackQty = number, --- direction = Azimuth, --- controllableAttack = boolean, --- } --- } +function CONTROLLABLE:TaskBombing( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType ) + self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType } ) local DCSTask - DCSTask = { id = 'Bombing', + DCSTask = { + id = 'Bombing', params = { - point = Vec2, - weaponType = WeaponType, - expend = WeaponExpend, - attackQty = AttackQty, - direction = Direction, - controllableAttack = ControllableAttack, + point = Vec2, + groupAttack = GroupAttack or false, + expend = WeaponExpend or "Auto", + attackQtyLimit = AttackQty and true or false, + attackQty = AttackQty, + directionEnabled = Direction and true or false, + direction = Direction, + altitudeEnabled = Altitude and true or false, + altitude = Altitude or 30, + weaponType = WeaponType, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (AIR) Attacking the map object (building, structure, e.t.c). +-- @param #CONTROLLABLE self +-- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point to deliver weapon at. +-- @param #boolean GroupAttack (optional) If true, all units in the group will attack the Unit when found. +-- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. +-- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. +-- @param #number Altitude (optional) The altitude from where to attack. +-- @param #number WeaponType (optional) The WeaponType. +-- @return Dcs.DCSTasking.Task#Task The DCS task structure. +function CONTROLLABLE:TaskAttackMapObject( Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType ) + self:F2( { self.ControllableName, Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType } ) + + local DCSTask + DCSTask = { + id = 'AttackMapObject', + params = { + point = Vec2, + groupAttack = GroupAttack or false, + expend = WeaponExpend or "Auto", + attackQtyLimit = AttackQty and true or false, + attackQty = AttackQty, + directionEnabled = Direction and true or false, + direction = Direction, + altitudeEnabled = Altitude and true or false, + altitude = Altitude or 30, + weaponType = WeaponType, }, }, @@ -622,6 +650,7 @@ function CONTROLLABLE:TaskBombing( Vec2, WeaponType, WeaponExpend, AttackQty, Di return DCSTask end + --- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #CONTROLLABLE self -- @param Dcs.DCSTypes#Vec2 Point The point to hold the position. @@ -700,45 +729,6 @@ end ---- (AIR) Attacking the map object (building, structure, e.t.c). --- @param #CONTROLLABLE self --- @param Dcs.DCSTypes#Vec2 Vec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators. --- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. --- @param Dcs.DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion. --- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo. --- @param Dcs.DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction. --- @param #boolean ControllableAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft. --- @return Dcs.DCSTasking.Task#Task The DCS task structure. -function CONTROLLABLE:TaskAttackMapObject( Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack ) - self:F2( { self.ControllableName, Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack } ) - --- AttackMapObject = { --- id = 'AttackMapObject', --- params = { --- point = Vec2, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend, --- attackQty = number, --- direction = Azimuth, --- controllableAttack = boolean, --- } --- } - - local DCSTask - DCSTask = { id = 'AttackMapObject', - params = { - point = Vec2, - weaponType = WeaponType, - expend = WeaponExpend, - attackQty = AttackQty, - direction = Direction, - controllableAttack = ControllableAttack, - }, - }, - - self:T3( { DCSTask } ) - return DCSTask -end --- (AIR) Delivering weapon on the runway. diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 7a192ba64..fa554dad9 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -1,25 +1,4 @@ ---- This module contains the POSITIONABLE class. --- --- 1) @{Positionable#POSITIONABLE} class, extends @{Identifiable#IDENTIFIABLE} --- =========================================================== --- The @{Positionable#POSITIONABLE} class is a wrapper class to handle the POSITIONABLE objects: --- --- * Support all DCS APIs. --- * Enhance with POSITIONABLE specific APIs not in the DCS API set. --- * Manage the "state" of the POSITIONABLE. --- --- 1.1) POSITIONABLE constructor: --- ------------------------------ --- The POSITIONABLE class provides the following functions to construct a POSITIONABLE instance: --- --- * @{Positionable#POSITIONABLE.New}(): Create a POSITIONABLE instance. --- --- 1.2) POSITIONABLE methods: --- -------------------------- --- The following methods can be used to identify an measurable object: --- --- * @{Positionable#POSITIONABLE.GetID}(): Returns the ID of the measurable object. --- * @{Positionable#POSITIONABLE.GetName}(): Returns the name of the measurable object. +--- **Wrapper** -- This module contains the POSITIONABLE class. -- -- === -- @@ -31,11 +10,34 @@ -- @field #string PositionableName The name of the measurable. -- @field Core.Spot#SPOT Spot The laser Spot. -- @field #number LaserCode The last assigned laser code. + +--- # POSITIONABLE class, extends @{Identifiable#IDENTIFIABLE} +-- +-- The POSITIONABLE class is a wrapper class to handle the POSITIONABLE objects: +-- +-- * Support all DCS APIs. +-- * Enhance with POSITIONABLE specific APIs not in the DCS API set. +-- * Manage the "state" of the POSITIONABLE. +-- +-- ## POSITIONABLE constructor +-- +-- The POSITIONABLE class provides the following functions to construct a POSITIONABLE instance: +-- +-- * @{Positionable#POSITIONABLE.New}(): Create a POSITIONABLE instance. +-- +-- ## POSITIONABLE methods +-- +-- The following methods can be used to identify an measurable object: +-- +-- * @{Positionable#POSITIONABLE.GetID}(): Returns the ID of the measurable object. +-- * @{Positionable#POSITIONABLE.GetName}(): Returns the name of the measurable object. +-- +-- +-- @field #POSITIONABLE POSITIONABLE = { ClassName = "POSITIONABLE", PositionableName = "", } - --- A DCSPositionable -- @type DCSPositionable -- @field id_ The ID of the controllable in DCS @@ -207,6 +209,28 @@ function POSITIONABLE:GetVec3() return nil end + +--- Get the bounding box of the underlying POSITIONABLE DCS Object. +-- @param #POSITIONABLE self +-- @return Dcs.DCSTypes#Distance The bounding box of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function POSITIONABLE:GetBoundingBox() --R2.1 + self:F2() + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionableDesc = DCSPositionable:getDesc() --Dcs.DCSTypes#Desc + if PositionableDesc then + local PositionableBox = PositionableDesc.box + return PositionableBox + end + end + + return nil +end + + --- Returns the altitude of the POSITIONABLE. -- @param Wrapper.Positionable#POSITIONABLE self -- @return Dcs.DCSTypes#Distance The altitude of the POSITIONABLE. @@ -303,6 +327,29 @@ function POSITIONABLE:GetVelocity() return nil end + +--- Returns the POSITIONABLE height in meters. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Dcs.DCSTypes#Vec3 The height of the positionable. +-- @return #nil The POSITIONABLE is not existing or alive. +function POSITIONABLE:GetHeight() --R2.1 + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionablePosition = DCSPositionable:getPosition() + if PositionablePosition then + local PositionableHeight = PositionablePosition.p.y + self:T2( PositionableHeight ) + return PositionableHeight + end + end + + return nil +end + + --- Returns the POSITIONABLE velocity in km/h. -- @param Wrapper.Positionable#POSITIONABLE self -- @return #number The velocity in km/h @@ -334,7 +381,7 @@ function POSITIONABLE:GetMessageText( Message, Name ) --R2.1 added local DCSObject = self:GetDCSObject() if DCSObject then Name = Name and ( " (" .. Name .. ")" ) or "" - local Callsign = self:GetCallsign() ~= "" and self:GetCallsign() or self:GetName() + local Callsign = string.format( "[%s]", self:GetCallsign() ~= "" and self:GetCallsign() or self:GetName() ) local MessageText = Callsign .. Name .. ": " .. Message return MessageText end @@ -383,12 +430,19 @@ end -- @param #string Message The message text -- @param Dcs.DCSTYpes#Duration Duration The duration of the message. -- @param Dcs.DCScoalition#coalition MessageCoalition The Coalition receiving the message. --- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable. -function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition, Name ) +function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition ) self:F2( { Message, Duration } ) + local Name = "" + local DCSObject = self:GetDCSObject() if DCSObject then + if MessageCoalition == coalition.side.BLUE then + Name = "Blue coalition" + end + if MessageCoalition == coalition.side.RED then + Name = "Red coalition" + end self:GetMessage( Message, Duration, Name ):ToCoalition( MessageCoalition ) end @@ -593,3 +647,6 @@ function POSITIONABLE:GetLaserCode() --R2.1 return self.LaserCode end + + + diff --git a/Moose Mission Setup/Moose.files b/Moose Mission Setup/Moose.files index 2de1eb7b3..5d8c15212 100644 --- a/Moose Mission Setup/Moose.files +++ b/Moose Mission Setup/Moose.files @@ -43,6 +43,8 @@ AI/AI_Balancer.lua AI/AI_Patrol.lua AI/AI_Cap.lua AI/AI_Cas.lua +AI/AI_Bai.lua +AI/AI_Formation.lua Actions/Act_Assign.lua Actions/Act_Route.lua diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index c384faa86..ef7a6b0b3 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20170426_1017' ) +env.info( 'Moose Generation Timestamp: 20170510_1031' ) local base = _G @@ -62,6 +62,8 @@ __Moose.Include( 'AI/AI_Balancer.lua' ) __Moose.Include( 'AI/AI_Patrol.lua' ) __Moose.Include( 'AI/AI_Cap.lua' ) __Moose.Include( 'AI/AI_Cas.lua' ) +__Moose.Include( 'AI/AI_Bai.lua' ) +__Moose.Include( 'AI/AI_Formation.lua' ) __Moose.Include( 'Actions/Act_Assign.lua' ) __Moose.Include( 'Actions/Act_Route.lua' ) __Moose.Include( 'Actions/Act_Account.lua' ) diff --git a/Utils/Slate Documentation Generator/bin/TreeHierarchy.csv b/Utils/Slate Documentation Generator/bin/TreeHierarchy.csv index 41eb85a6a..94fc57631 100644 --- a/Utils/Slate Documentation Generator/bin/TreeHierarchy.csv +++ b/Utils/Slate Documentation Generator/bin/TreeHierarchy.csv @@ -1,22 +1,22 @@ -@K=function, @M=Task_A2G, @N=onafterRouteToRendezVous, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=5129, -@K=function, @M=Task_A2G, @N=OnAfterArriveAtRendezVous, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=5789, -@K=function, @M=Task_A2G, @N=onafterEngage, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=6186, -@K=function, @M=Task_A2G, @N=onafterRouteToTarget, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=6508, -@K=function, @M=Task_A2G, @N=onafterRouteToTargets, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=7380, -@K=function, @M=Task_Cargo, @N=onenterWaitingForCommand, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=10431, -@K=function, @M=Task_Cargo, @N=OnLeaveWaitingForCommand, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=12652, -@K=function, @M=Task_Cargo, @N=onafterRouteToPickup, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=13428, -@K=function, @M=Task_Cargo, @N=onafterArriveAtPickup, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=13882, -@K=function, @M=Task_Cargo, @N=onafterRouteToDeploy, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=14310, -@K=function, @M=Task_Cargo, @N=onafterArriveAtDeploy, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=14757, -@K=function, @M=Task_Cargo, @N=onafterLand, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=15187, -@K=function, @M=Task_Cargo, @N=onafterLanded, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=16069, -@K=function, @M=Task_Cargo, @N=onafterPrepareBoarding, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=16762, -@K=function, @M=Task_Cargo, @N=onafterBoard, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=17166, -@K=function, @M=Task_Cargo, @N=onafterBoarded, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=18074, -@K=function, @M=Task_Cargo, @N=onafterPrepareUnBoarding, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=18704, -@K=function, @M=Task_Cargo, @N=onafterUnBoard, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=19134, -@K=function, @M=Task_Cargo, @N=onafterUnBoarded, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=19788, +@K=function, @M=Task_A2G, @N=onafterRouteToRendezVous, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=5157, +@K=function, @M=Task_A2G, @N=OnAfterArriveAtRendezVous, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=5817, +@K=function, @M=Task_A2G, @N=onafterEngage, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=6214, +@K=function, @M=Task_A2G, @N=onafterRouteToTarget, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=6536, +@K=function, @M=Task_A2G, @N=onafterRouteToTargets, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_A2G.lua, @C=7408, +@K=function, @M=Task_Cargo, @N=onafterSelectAction, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=10439, +@K=function, @M=Task_Cargo, @N=OnLeaveWaitingForCommand, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=13084, +@K=function, @M=Task_Cargo, @N=onafterRouteToPickup, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=13860, +@K=function, @M=Task_Cargo, @N=onafterArriveAtPickup, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=14479, +@K=function, @M=Task_Cargo, @N=onafterRouteToDeploy, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=15020, +@K=function, @M=Task_Cargo, @N=onafterArriveAtDeploy, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=15467, +@K=function, @M=Task_Cargo, @N=onafterLand, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=15897, +@K=function, @M=Task_Cargo, @N=onafterLanded, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=16856, +@K=function, @M=Task_Cargo, @N=onafterPrepareBoarding, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=17622, +@K=function, @M=Task_Cargo, @N=onafterBoard, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=18082, +@K=function, @M=Task_Cargo, @N=onafterBoarded, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=19023, +@K=function, @M=Task_Cargo, @N=onafterPrepareUnBoarding, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=19706, +@K=function, @M=Task_Cargo, @N=onafterUnBoard, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=20666, +@K=function, @M=Task_Cargo, @N=onafterUnBoarded, @P=Fsm, @F=../../../MOOSE/Moose Development/Moose\Tasking\Task_CARGO.lua, @C=21541, @K=function, @M=Designate, @N=OnBeforeLaseOn, @P=DESIGNATE , @F=../../../MOOSE/Moose Development/Moose\Functional\Designate.lua, @C=12232, @K=function, @M=Designate, @N=OnAfterLaseOn, @P=DESIGNATE , @F=../../../MOOSE/Moose Development/Moose\Functional\Designate.lua, @C=12480, @K=function, @M=Designate, @N=LaseOn, @P=DESIGNATE , @F=../../../MOOSE/Moose Development/Moose\Functional\Designate.lua, @C=12701, diff --git a/docs/Documentation/AI_BAI.html b/docs/Documentation/AI_BAI.html new file mode 100644 index 000000000..a778055c0 --- /dev/null +++ b/docs/Documentation/AI_BAI.html @@ -0,0 +1,1992 @@ + + + + + + +
+
+ +
+
+
+
+ +
+

Module AI_Bai

+ +

AI -- Provide Battlefield Air Interdiction (bombing).

+ +

Banner Image

+ +
+ +

AI_BAI classes makes AI Controllables execute bombing tasks.

+ + + +

There are the following types of BAI classes defined:

+ + + +
+ +

Demo Missions

+ +

AI_BAI Demo Missions source code

+ +

AI_BAI Demo Missions, only for beta testers

+ +

ALL Demo Missions pack of the last release

+ +
+ +

YouTube Channel

+ +

AI_BAI YouTube Channel

+ +
+ +

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:

+ + + +

Authors:

+ +
    +
  • FlightControl: Concept, Design & Programming.
  • +
+ + +

Global(s)

+ + + + + + + + + +
AI_BAI_ZONE +

AIBAIZONE class, extends AIPatrol#AIPATROL_ZONE

+ +

AIBAIZONE derives from the AIPatrol#AIPATROL_ZONE, inheriting its methods and behaviour.

+
_NewEngageRoute(AIControllable) + +
+

Type AI_BAI_ZONE

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AI_BAI_ZONE.AIControllable +

The Controllable patrolling.

+
AI_BAI_ZONE:Abort() +

Synchronous Event Trigger for Event Abort.

+
AI_BAI_ZONE:Accomplish() +

Synchronous Event Trigger for Event Accomplish.

+
AI_BAI_ZONE.Accomplished + +
AI_BAI_ZONE:Destroy() +

Synchronous Event Trigger for Event Destroy.

+
AI_BAI_ZONE:Engage(EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection) +

Synchronous Event Trigger for Event Engage.

+
AI_BAI_ZONE.EngageAltitude + +
AI_BAI_ZONE.EngageAttackQty + +
AI_BAI_ZONE.EngageDirection + +
AI_BAI_ZONE.EngageSpeed + +
AI_BAI_ZONE.EngageWeaponExpend + +
AI_BAI_ZONE.EngageZone + +
AI_BAI_ZONE:Fired() +

Synchronous Event Trigger for Event Fired.

+
AI_BAI_ZONE:New(PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType) +

Creates a new AIBAIZONE object

+
AI_BAI_ZONE:OnAfterAbort(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Abort.

+
AI_BAI_ZONE:OnAfterAccomplish(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Accomplish.

+
AI_BAI_ZONE:OnAfterDestroy(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Destroy.

+
AI_BAI_ZONE:OnAfterEngage(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Engage.

+
AI_BAI_ZONE:OnAfterFired(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Fired.

+
AI_BAI_ZONE:OnBeforeAbort(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Abort.

+
AI_BAI_ZONE:OnBeforeAccomplish(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Accomplish.

+
AI_BAI_ZONE:OnBeforeDestroy(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Destroy.

+
AI_BAI_ZONE:OnBeforeEngage(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Engage.

+
AI_BAI_ZONE:OnBeforeFired(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Fired.

+
AI_BAI_ZONE:OnEnterEngaging(Controllable, From, Event, To) +

OnEnter Transition Handler for State Engaging.

+
AI_BAI_ZONE:OnEventDead(EventData) + +
AI_BAI_ZONE:OnLeaveEngaging(Controllable, From, Event, To) +

OnLeave Transition Handler for State Engaging.

+
AI_BAI_ZONE.Search + +
AI_BAI_ZONE:SearchOff() +

If Search is Off, the current zone coordinate will be the center of the bombing.

+
AI_BAI_ZONE:SearchOn() +

If Search is On, BAI will search for potential targets in the zone.

+
AI_BAI_ZONE:SearchOnOff(Search) +

Specifies whether to search for potential targets in the zone, or let the center of the zone be the bombing coordinate.

+
AI_BAI_ZONE:SetEngageZone(EngageZone) +

Set the Engage Zone where the AI is performing BOMB.

+
AI_BAI_ZONE.TargetZone +

The Zone where the patrol needs to be executed.

+
AI_BAI_ZONE:__Abort(Delay) +

Asynchronous Event Trigger for Event Abort.

+
AI_BAI_ZONE:__Accomplish(Delay) +

Asynchronous Event Trigger for Event Accomplish.

+
AI_BAI_ZONE:__Destroy(Delay) +

Asynchronous Event Trigger for Event Destroy.

+
AI_BAI_ZONE:__Engage(Delay, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection) +

Asynchronous Event Trigger for Event Engage.

+
AI_BAI_ZONE:__Fired(Delay) +

Asynchronous Event Trigger for Event Fired.

+
AI_BAI_ZONE:onafterAbort(Controllable, From, Event, To) + +
AI_BAI_ZONE:onafterAccomplish(Controllable, From, Event, To) + +
AI_BAI_ZONE:onafterDestroy(Controllable, From, Event, To, EventData) + +
AI_BAI_ZONE:onafterEngage(Controllable, From, Event, To, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection) + +
AI_BAI_ZONE:onafterStart(Controllable, From, Event, To) +

onafter State Transition for Event Start.

+
AI_BAI_ZONE:onafterTarget(Controllable, From, Event, To) + +
AI_BAI_ZONE:onbeforeEngage(Controllable, From, Event, To) + +
+ +

Global(s)

+
+
+ + #AI_BAI_ZONE + +AI_BAI_ZONE + +
+
+ +

AIBAIZONE class, extends AIPatrol#AIPATROL_ZONE

+ +

AIBAIZONE derives from the AIPatrol#AIPATROL_ZONE, inheriting its methods and behaviour.

+ + +

+The AIBAIZONE class implements the core functions to provide BattleGround Air Interdiction in an Engage Zone by an AIR Controllable or Group. +The AIBAIZONE 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.

+ +

HoldAndEngage

+ +

The AIBAIZONE is assigned a Group and this must be done before the AIBAIZONE process can be started through the Start event.

+ +

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.

+ +

Route Event

+ +

When the AI is commanded to provide BattleGround Air Interdiction (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.

+ +

Engage Event

+ +

The AI will detect the targets and will only destroy the targets within the Engage Zone.

+ +

Engage Event

+ +

Every target that is destroyed, is reported< by the AI.

+ +

Engage Event

+ +

Note that the AI does not know when the Engage Zone is cleared, and therefore will keep circling in the zone.

+ +

Engage Event

+ +

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 ...
  • +
+ +

Engage Event

+ +

When the AI has accomplished the Bombing, it will fly back to the Patrol Zone.

+ +

Engage Event

+ +

It will keep patrolling there, until it is notified to RTB or move to another BOMB 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.

+ +

Engage Event

+ +

1. AIBAIZONE constructor

+ + + +

2. AIBAIZONE is a FSM

+ +

Process

+ +

2.1. AIBAIZONE 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 BOMB.
  • +
  • Returning ( Group ): The AI is returning to Base..
  • +
+ +

2.2. AIBAIZONE Events

+ + + +

3. Modify the Engage Zone behaviour to pinpoint a map object or scenery object

+ +

Use the method AIBAIZONE.SearchOff() to specify that the EngageZone is not to be searched for potential targets (UNITs), but that the center of the zone +is the point where a map object is to be destroyed (like a bridge).

+ +

Example:

+ +
 -- Tell the BAI not to search for potential targets in the BAIEngagementZone, but rather use the center of the BAIEngagementZone as the bombing location.
+ AIBAIZone:SearchOff()
+
+ +

Searching can be switched back on with the method AIBAIZONE.SearchOn(). Use the method AIBAIZONE.SearchOnOff() to flexibily switch searching on or off.

+ +
+ + +
+
+
+
+ + +_NewEngageRoute(AIControllable) + +
+
+ + + +

Parameter

+ +
+
+

Type AI_Bai

+ +

Type AI_BAI_ZONE

+ +

AIBAIZONE class

+ +

Field(s)

+
+
+ + Wrapper.Controllable#CONTROLLABLE + +AI_BAI_ZONE.AIControllable + +
+
+ +

The Controllable patrolling.

+ +
+
+
+
+ + +AI_BAI_ZONE:Abort() + +
+
+ +

Synchronous Event Trigger for Event Abort.

+ +
+
+
+
+ + +AI_BAI_ZONE:Accomplish() + +
+
+ +

Synchronous Event Trigger for Event Accomplish.

+ +
+
+
+
+ + #boolean + +AI_BAI_ZONE.Accomplished + +
+
+ + + +
+
+
+
+ + +AI_BAI_ZONE:Destroy() + +
+
+ +

Synchronous Event Trigger for Event Destroy.

+ +
+
+
+
+ + +AI_BAI_ZONE:Engage(EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection) + +
+
+ +

Synchronous Event Trigger for Event Engage.

+ +

Parameters

+
    +
  • + +

    #number EngageSpeed : +(optional) The speed the Group will hold when engaging to the target zone.

    + +
  • +
  • + +

    Dcs.DCSTypes#Distance EngageAltitude : +(optional) Desired altitude to perform the unit engagement.

    + +
  • +
  • + +

    Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend : +(optional) Determines how much weapon will be released at each attack. +If parameter is not defined the unit / controllable will choose expend on its own discretion. +Use the structure DCSTypes#AI.Task.WeaponExpend to define the amount of weapons to be release at each attack.

    + +
  • +
  • + +

    #number EngageAttackQty : +(optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.

    + +
  • +
  • + +

    Dcs.DCSTypes#Azimuth EngageDirection : +(optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE.EngageAltitude + +
+
+ + + +
+
+
+
+ + + +AI_BAI_ZONE.EngageAttackQty + +
+
+ + + +
+
+
+
+ + + +AI_BAI_ZONE.EngageDirection + +
+
+ + + +
+
+
+
+ + +AI_BAI_ZONE.EngageSpeed + +
+
+ + + +
+
+
+
+ + + +AI_BAI_ZONE.EngageWeaponExpend + +
+
+ + + +
+
+
+
+ + + +AI_BAI_ZONE.EngageZone + +
+
+ + + +
+
+
+
+ + +AI_BAI_ZONE:Fired() + +
+
+ +

Synchronous Event Trigger for Event Fired.

+ +
+
+
+
+ + +AI_BAI_ZONE:New(PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone, PatrolAltType) + +
+
+ +

Creates a new AIBAIZONE object

+ +

Parameters

+ +

Return value

+ +

#AIBAIZONE: +self

+ +
+
+
+
+ + +AI_BAI_ZONE:OnAfterAbort(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Abort.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnAfterAccomplish(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Accomplish.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnAfterDestroy(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Destroy.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnAfterEngage(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Engage.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnAfterFired(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Fired.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnBeforeAbort(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Abort.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_BAI_ZONE:OnBeforeAccomplish(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Accomplish.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_BAI_ZONE:OnBeforeDestroy(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Destroy.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_BAI_ZONE:OnBeforeEngage(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Engage.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnBeforeFired(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Fired.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_BAI_ZONE:OnEnterEngaging(Controllable, From, Event, To) + +
+
+ +

OnEnter Transition Handler for State Engaging.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:OnEventDead(EventData) + +
+
+ + + +

Parameter

+ +
+
+
+
+ + +AI_BAI_ZONE:OnLeaveEngaging(Controllable, From, Event, To) + +
+
+ +

OnLeave Transition Handler for State Engaging.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + + +AI_BAI_ZONE.Search + +
+
+ + + +
+
+
+
+ + +AI_BAI_ZONE:SearchOff() + +
+
+ +

If Search is Off, the current zone coordinate will be the center of the bombing.

+ +

Return value

+ +

#AIBAIZONE:

+ + +
+
+
+
+ + +AI_BAI_ZONE:SearchOn() + +
+
+ +

If Search is On, BAI will search for potential targets in the zone.

+ +

Return value

+ +

#AIBAIZONE:

+ + +
+
+
+
+ + +AI_BAI_ZONE:SearchOnOff(Search) + +
+
+ +

Specifies whether to search for potential targets in the zone, or let the center of the zone be the bombing coordinate.

+ + +

AIBAIZONE will search for potential targets by default.

+ +

Parameter

+
    +
  • + +

    Search :

    + +
  • +
+

Return value

+ +

#AIBAIZONE:

+ + +
+
+
+
+ + +AI_BAI_ZONE:SetEngageZone(EngageZone) + +
+
+ +

Set the Engage Zone where the AI is performing BOMB.

+ + +

Note that if the EngageZone is changed, the AI needs to re-detect targets.

+ +

Parameter

+
    +
  • + +

    Core.Zone#ZONE EngageZone : +The zone where the AI is performing BOMB.

    + +
  • +
+

Return value

+ +

#AIBAIZONE: +self

+ +
+
+
+
+ + Core.Zone#ZONE_BASE + +AI_BAI_ZONE.TargetZone + +
+
+ +

The Zone where the patrol needs to be executed.

+ +
+
+
+
+ + +AI_BAI_ZONE:__Abort(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Abort.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:__Accomplish(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Accomplish.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:__Destroy(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Destroy.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:__Engage(Delay, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection) + +
+
+ +

Asynchronous Event Trigger for Event Engage.

+ +

Parameters

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
  • + +

    #number EngageSpeed : +(optional) The speed the Group will hold when engaging to the target zone.

    + +
  • +
  • + +

    Dcs.DCSTypes#Distance EngageAltitude : +(optional) Desired altitude to perform the unit engagement.

    + +
  • +
  • + +

    Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend : +(optional) Determines how much weapon will be released at each attack. +If parameter is not defined the unit / controllable will choose expend on its own discretion. +Use the structure DCSTypes#AI.Task.WeaponExpend to define the amount of weapons to be release at each attack.

    + +
  • +
  • + +

    #number EngageAttackQty : +(optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.

    + +
  • +
  • + +

    Dcs.DCSTypes#Azimuth EngageDirection : +(optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:__Fired(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Fired.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onafterAbort(Controllable, From, Event, To) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onafterAccomplish(Controllable, From, Event, To) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onafterDestroy(Controllable, From, Event, To, EventData) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
  • + +

    Core.Event#EVENTDATA EventData :

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onafterEngage(Controllable, From, Event, To, EngageSpeed, EngageAltitude, EngageWeaponExpend, EngageAttackQty, EngageDirection) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
  • + +

    #number EngageSpeed : +(optional) The speed the Group will hold when engaging to the target zone.

    + +
  • +
  • + +

    Dcs.DCSTypes#Distance EngageAltitude : +(optional) Desired altitude to perform the unit engagement.

    + +
  • +
  • + +

    Dcs.DCSTypes#AI.Task.WeaponExpend EngageWeaponExpend : +(optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / controllable will choose expend on its own discretion.

    + +
  • +
  • + +

    #number EngageAttackQty : +(optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.

    + +
  • +
  • + +

    Dcs.DCSTypes#Azimuth EngageDirection : +(optional) Desired ingress direction from the target to the attacking aircraft. Controllable/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain controllable/aircraft will choose another direction.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onafterStart(Controllable, From, Event, To) + +
+
+ +

onafter State Transition for Event Start.

+ +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onafterTarget(Controllable, From, Event, To) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+
+
+ + +AI_BAI_ZONE:onbeforeEngage(Controllable, From, Event, To) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE Controllable : +The Controllable Object managed by the FSM.

    + +
  • +
  • + +

    #string From : +The From State string.

    + +
  • +
  • + +

    #string Event : +The Event string.

    + +
  • +
  • + +

    #string To : +The To State string.

    + +
  • +
+
+
+ +
+ +
+ + diff --git a/docs/Documentation/AI_Balancer.html b/docs/Documentation/AI_Balancer.html index 230ca6776..c33e7f6ec 100644 --- a/docs/Documentation/AI_Balancer.html +++ b/docs/Documentation/AI_Balancer.html @@ -17,9 +17,11 @@ index
    +
  • AI_Bai
  • AI_Balancer
  • AI_Cap
  • AI_Cas
  • +
  • AI_Formation
  • AI_Patrol
  • Account
  • Airbase
  • diff --git a/docs/Documentation/AirbasePolice.html b/docs/Documentation/AirbasePolice.html index 54530566c..9e5241f98 100644 --- a/docs/Documentation/AirbasePolice.html +++ b/docs/Documentation/AirbasePolice.html @@ -17,9 +17,11 @@ index
@@ -2220,7 +2228,7 @@ The DCS task structure.

-CONTROLLABLE:TaskBombing(Vec2, WeaponType, WeaponExpend, AttackQty, Direction, ControllableAttack) +CONTROLLABLE:TaskBombing(Vec2, GroupAttack, WeaponExpend, AttackQty, Direction, Altitude, WeaponType)
@@ -2237,8 +2245,8 @@ The DCS task structure.

  • -

    #number WeaponType : -(optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage.

    +

    #boolean GroupAttack : +(optional) If true, all units in the group will attack the Unit when found.

  • @@ -2250,7 +2258,7 @@ The DCS task structure.

  • #number AttackQty : -(optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks.

    +(optional) This parameter limits maximal quantity of attack. The aicraft/controllable will not make more attack than allowed even if the target controllable not destroyed and the aicraft/controllable still have ammo. If not defined the aircraft/controllable will attack target until it will be destroyed or until the aircraft/controllable will run out of ammo.

  • @@ -2261,8 +2269,14 @@ The DCS task structure.

  • -

    #boolean ControllableAttack : -(optional) Flag indicates that the target must be engaged by all aircrafts of the controllable. Has effect only if the task is assigned to a controllable, not to a single aircraft.

    +

    #number Altitude : +(optional) The altitude from where to attack.

    + +
  • +
  • + +

    #number WeaponType : +(optional) The WeaponType.

  • diff --git a/docs/Documentation/DCSAirbase.html b/docs/Documentation/DCSAirbase.html index 01bc9464a..2af4af8a7 100644 --- a/docs/Documentation/DCSAirbase.html +++ b/docs/Documentation/DCSAirbase.html @@ -17,9 +17,11 @@ index
    + +
    +
    + + + +DATABASE.UNITS_Index + +
    +
    + + + +
    +
    +
    +
    + + +DATABASE.UNITS_Position + +
    +
    + + +
    diff --git a/docs/Documentation/Designate.html b/docs/Documentation/Designate.html index 0b38068a2..d8950ff85 100644 --- a/docs/Documentation/Designate.html +++ b/docs/Documentation/Designate.html @@ -17,9 +17,11 @@ index +
    +
    +
    + + +EVENT:CreateEventPlayerEnterUnit(PlayerUnit) + +
    +
    + +

    Creation of a SEVENTPLAYERENTERUNIT Event.

    + +

    Parameter

    + +
    diff --git a/docs/Documentation/Fsm.html b/docs/Documentation/Fsm.html index 425da196e..9f6365bca 100644 --- a/docs/Documentation/Fsm.html +++ b/docs/Documentation/Fsm.html @@ -17,9 +17,11 @@ index

    Return value

    -

    #boolean: -true if Unit is part of a Task in the Mission.

    +

    #MISSION:

    +
    @@ -601,6 +645,20 @@ is the Task object.

    Tasking.Task#TASK: The task added.

    + + +
    +
    + + + +MISSION.AssignedGroups + +
    +
    + + +
    @@ -615,6 +673,32 @@ The task added.

    + +
    +
    +
    + + +MISSION:ClearGroupAssignment(MissionGroup) + +
    +
    + +

    Clear the Group assignment from the Mission.

    + +

    Parameter

    + +

    Return value

    + +

    #MISSION:

    + +
    @@ -657,8 +741,8 @@ The CLIENT or UNIT of the Player crashing.

    Return value

    -

    #boolean: -true if Unit is part of a Task in the Mission.

    +

    #MISSION:

    +
    @@ -840,6 +924,24 @@ Returns nil if no task was found.

    + +MISSION:GetTaskTypes() + +
    +
    + + + +

    Return value

    + +

    #number:

    + + +
    +
    +
    +
    + MISSION:GetTasks() @@ -970,6 +1072,32 @@ true if the Mission has a Group.

    #boolean:

    + +
    +
    +
    + + +MISSION:IsGroupAssigned(MissionGroup) + +
    +
    + +

    Returns if the Mission is assigned to the Group.

    + +

    Parameter

    + +

    Return value

    + +

    #boolean:

    + +
    @@ -1907,6 +2035,67 @@ self

    #string:

    + +
    +
    +
    + + +MISSION:ReportPlayers() + +
    +
    + +

    Create a player report of the Mission.

    + + +

    This reports provides a one liner of the mission status. It indicates how many players and how many Tasks.

    + +
    Mission "<MissionName>" - Status "<MissionStatus>"
    + - Player "<PlayerName>: Task <TaskName> <TaskStatus>, Task <TaskName> <TaskStatus>
    + - Player <PlayerName>: Task <TaskName> <TaskStatus>, Task <TaskName> <TaskStatus>
    + - ..
    +
    + + +

    Return value

    + +

    #string:

    + + +
    +
    +
    +
    + + +MISSION:ReportStatus() + +
    +
    + +

    Create a status report of the Mission.

    + + +

    This reports provides a one liner of the mission status. It indicates how many players and how many Tasks.

    + +
    Mission "<MissionName>" - Status "<MissionStatus>"
    + - Task Types: <TaskType>, <TaskType>
    + - <xx> Planned Tasks (xp)
    + - <xx> Assigned Tasks(xp)
    + - <xx> Success Tasks (xp)
    + - <xx> Hold Tasks (xp)
    + - <xx> Cancelled Tasks (xp)
    + - <xx> Aborted Tasks (xp)
    + - <xx> Failed Tasks (xp)
    +
    + + +

    Return value

    + +

    #string:

    + +
    @@ -1939,6 +2128,32 @@ self

    + +
    +
    +
    + + +MISSION:SetGroupAssigned(MissionGroup) + +
    +
    + +

    Set Group assigned to the Mission.

    + +

    Parameter

    + +

    Return value

    + +

    #MISSION:

    + +
    diff --git a/docs/Documentation/Movement.html b/docs/Documentation/Movement.html index a7de96e12..ab459b6d5 100644 --- a/docs/Documentation/Movement.html +++ b/docs/Documentation/Movement.html @@ -17,9 +17,11 @@ index

    Return value

    @@ -936,6 +991,68 @@ The score in points.

    + +TASK_CARGO_TRANSPORT:CargoDeployed(TaskUnit, Cargo, DeployZone) + +
    +
    + +

    Synchronous Event Trigger for Event CargoDeployed.

    + +

    Parameters

    +
      +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    • + +

      Core.Zone#ZONE DeployZone : +The zone where the Cargo got Deployed or UnBoarded.

      + +
    • +
    +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:CargoPickedUp(TaskUnit, Cargo) + +
    +
    + +

    Synchronous Event Trigger for Event CargoPickedUp.

    + +

    Parameters

    +
      +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    +
    +
    +
    +
    + #string TASK_CARGO_TRANSPORT.ClassName @@ -969,7 +1086,7 @@ The score in points.

    -TASK_CARGO_TRANSPORT:New(Mission, SetGroup, TaskName, SetCargo) +TASK_CARGO_TRANSPORT:New(Mission, SetGroup, TaskName, SetCargo, TaskBriefing)
    @@ -1000,6 +1117,12 @@ The name of the Task.

    Core.Set#SET_CARGO SetCargo : The scope of the cargo to be transported.

    + +
  • + +

    #string TaskBriefing : +The Cargo Task briefing.

    +
  • Return value

    @@ -1007,6 +1130,286 @@ The scope of the cargo to be transported.

    #TASKCARGOTRANSPORT: self

    +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:OnAfterCargoDeployed(From, Event, To, TaskUnit, Cargo, DeployZone) + +
    +
    + +

    OnAfter Transition Handler for Event CargoDeployed.

    + +

    Parameters

    +
      +
    • + +

      #string From : +The From State string.

      + +
    • +
    • + +

      #string Event : +The Event string.

      + +
    • +
    • + +

      #string To : +The To State string.

      + +
    • +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    • + +

      Core.Zone#ZONE DeployZone : +The zone where the Cargo got Deployed or UnBoarded.

      + +
    • +
    +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:OnAfterCargoPickedUp(From, Event, To, TaskUnit, Cargo) + +
    +
    + +

    OnAfter Transition Handler for Event CargoPickedUp.

    + +

    Parameters

    +
      +
    • + +

      #string From : +The From State string.

      + +
    • +
    • + +

      #string Event : +The Event string.

      + +
    • +
    • + +

      #string To : +The To State string.

      + +
    • +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:OnBeforeCargoDeployed(From, Event, To, TaskUnit, Cargo, DeployZone) + +
    +
    + +

    OnBefore Transition Handler for Event CargoDeployed.

    + +

    Parameters

    +
      +
    • + +

      #string From : +The From State string.

      + +
    • +
    • + +

      #string Event : +The Event string.

      + +
    • +
    • + +

      #string To : +The To State string.

      + +
    • +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    • + +

      Core.Zone#ZONE DeployZone : +The zone where the Cargo got Deployed or UnBoarded.

      + +
    • +
    +

    Return value

    + +

    #boolean: +Return false to cancel Transition.

    + +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:OnBeforeCargoPickedUp(From, Event, To, TaskUnit, Cargo) + +
    +
    + +

    OnBefore Transition Handler for Event CargoPickedUp.

    + +

    Parameters

    +
      +
    • + +

      #string From : +The From State string.

      + +
    • +
    • + +

      #string Event : +The Event string.

      + +
    • +
    • + +

      #string To : +The To State string.

      + +
    • +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    +

    Return value

    + +

    #boolean: +Return false to cancel Transition.

    + +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:__CargoDeployed(Delay, TaskUnit, Cargo, DeployZone) + +
    +
    + +

    Asynchronous Event Trigger for Event CargoDeployed.

    + +

    Parameters

    +
      +
    • + +

      #number Delay : +The delay in seconds.

      + +
    • +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    • + +

      Core.Zone#ZONE DeployZone : +The zone where the Cargo got Deployed or UnBoarded.

      + +
    • +
    +
    +
    +
    +
    + + +TASK_CARGO_TRANSPORT:__CargoPickedUp(Delay, TaskUnit, Cargo) + +
    +
    + +

    Asynchronous Event Trigger for Event CargoPickedUp.

    + +

    Parameters

    +
      +
    • + +

      #number Delay : +The delay in seconds.

      + +
    • +
    • + +

      Wrapper.Unit#UNIT TaskUnit : +The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.

      + +
    • +
    • + +

      Core.Cargo#CARGO Cargo : +The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.

      + +
    • +
    diff --git a/docs/Documentation/Task_PICKUP.html b/docs/Documentation/Task_PICKUP.html index 3a8412d01..e33dca1db 100644 --- a/docs/Documentation/Task_PICKUP.html +++ b/docs/Documentation/Task_PICKUP.html @@ -17,9 +17,11 @@ index
      +
    • AI_Bai
    • AI_Balancer
    • AI_Cap
    • AI_Cas
    • +
    • AI_Formation
    • AI_Patrol
    • Account
    • Airbase
    • @@ -95,6 +97,18 @@

      Module

      + + + + + + + + @@ -413,7 +433,7 @@ are design patterns allowing efficient (long-lasting) processes and workflows. diff --git a/docs/Documentation/land.html b/docs/Documentation/land.html index 2eb402711..e3b4d5dc9 100644 --- a/docs/Documentation/land.html +++ b/docs/Documentation/land.html @@ -17,9 +17,11 @@ index
        +
      • AI_Bai
      • AI_Balancer
      • AI_Cap
      • AI_Cas
      • +
      • AI_Formation
      • AI_Patrol
      • Account
      • Airbase
      • diff --git a/docs/Presentations/AI_BAI/Dia1.JPG b/docs/Presentations/AI_BAI/Dia1.JPG new file mode 100644 index 000000000..7b9400259 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia1.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia10.JPG b/docs/Presentations/AI_BAI/Dia10.JPG new file mode 100644 index 000000000..f05ed47f0 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia10.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia11.JPG b/docs/Presentations/AI_BAI/Dia11.JPG new file mode 100644 index 000000000..93a3022fc Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia11.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia12.JPG b/docs/Presentations/AI_BAI/Dia12.JPG new file mode 100644 index 000000000..06e16117f Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia12.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia13.JPG b/docs/Presentations/AI_BAI/Dia13.JPG new file mode 100644 index 000000000..6cf4597db Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia13.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia2.JPG b/docs/Presentations/AI_BAI/Dia2.JPG new file mode 100644 index 000000000..4f357b026 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia2.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia3.JPG b/docs/Presentations/AI_BAI/Dia3.JPG new file mode 100644 index 000000000..c4021004c Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia3.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia4.JPG b/docs/Presentations/AI_BAI/Dia4.JPG new file mode 100644 index 000000000..e5f8119bf Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia4.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia5.JPG b/docs/Presentations/AI_BAI/Dia5.JPG new file mode 100644 index 000000000..22f923f5c Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia5.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia6.JPG b/docs/Presentations/AI_BAI/Dia6.JPG new file mode 100644 index 000000000..668413e95 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia6.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia7.JPG b/docs/Presentations/AI_BAI/Dia7.JPG new file mode 100644 index 000000000..9dbd086c3 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia7.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia8.JPG b/docs/Presentations/AI_BAI/Dia8.JPG new file mode 100644 index 000000000..b4c0aec03 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia8.JPG differ diff --git a/docs/Presentations/AI_BAI/Dia9.JPG b/docs/Presentations/AI_BAI/Dia9.JPG new file mode 100644 index 000000000..a2038d909 Binary files /dev/null and b/docs/Presentations/AI_BAI/Dia9.JPG differ diff --git a/docs/Presentations/AI_FORMATION/Dia1.JPG b/docs/Presentations/AI_FORMATION/Dia1.JPG new file mode 100644 index 000000000..a4edad01b Binary files /dev/null and b/docs/Presentations/AI_FORMATION/Dia1.JPG differ diff --git a/docs/README.md b/docs/README.md index 6339e9b0f..fa0266ad6 100644 --- a/docs/README.md +++ b/docs/README.md @@ -132,6 +132,13 @@ The POINT_VEC3 class manages the 3D simulation space, while the POINT_VEC2 class * [ZONES](Documentation/Zone.html): A set of zone classes that provide the functionality to validate the presence of GROUPS, UNITS, CLIENTS, STATICS within a certain ZONE. The zones can take various forms and can be movable. +* [CARGO](Documentation/Cargo.html): Manage Cargo in the simulation. + +* [SPAWNSTATIC](Documentation/SpawnStatic.html): Spawn dynamically static objects. + +* [BEACON](Documentation/Radio.html): Create beacons. + +* [RADIO](Documentation/Radio.html): Create radio communication. ## 4.3) MOOSE Wrapper Classes @@ -149,21 +156,13 @@ Wrapper classes provide another easier mechanism to control Groups, Units, Stati * **[AIRBASE](Documentation/Airbase.html)**: This class wraps a DCS Airbase object within the simulator. -* **[GROUP](Documentation/Group.html)**: This class wraps a DCS Group objects within the simulator, which are currently alive. -It provides a more extensive API set. -It takes an abstraction of the complexity to give tasks, commands and set various options to DCS Groups. -Additionally, the GROUP class provides a much richer API to identify various properties of the DCS Group. -For each DCS Group created object within a running mission, a GROUP object will be created automatically, beging managed within the DATABASE. +* **[GROUP](Documentation/Group.html)**: This class wraps a DCS Group objects within the simulator. -* **[UNIT](Documentation/Unit.html)**: This class wraps a DCS Unit object within the simulator, which are currently alive. It provides a more extensive API set, as well takes an abstraction of the complexity to give commands and set various options to DCS Units. Additionally, the UNIT class provides a much richer API to identify various properties of the DCS Unit. For each DCS Unit object created within a running mission, a UNIT object will be created automatically, that is stored within the DATABASE, under the _DATABASE object. -the UNIT class provides a more extensive API set, taking an abstraction of the complexity to give tasks, commands and set various options to DCS Units. -For each DCS Unit created object within a running mission, a UNIT object will be created automatically, beging managed within the DATABASE. +* **[UNIT](Documentation/Unit.html)**: This class wraps a DCS Unit object within the simulator. * **[CLIENT](Documentation/Client.html)**: This class wraps a DCS Unit object within the simulator, which has a skill Client or Player. -The CLIENT class derives from the UNIT class, thus contains the complete UNIT API set, and additionally, the CLIENT class provides an API set to manage players joining or leaving clients, sending messages to players, and manage the state of units joined by players. For each DCS Unit object created within a running mission that can be joined by a player, a CLIENT object will be created automatically, that is stored within the DATABASE, under the _DATABASE object. * **[STATIC](Documentation/Static.html)**: This class wraps a DCS StaticObject object within the simulator. -The STATIC class derives from the POSITIONABLE class, thus contains also the position API set. @@ -181,7 +180,13 @@ MOOSE Functional Classes provide various functions that are useful in mission de * [SCORING](Documentation/Scoring.html): Administer the scoring of player achievements, and create a CSV file logging the scoring events for use at team or squadron websites. +* [SEAD](Documentation/Sead.html): Make SAM sites avoid SEAD missiles being fired at. +* [DESIGNATE](Documentation/Designate.html): Make AI automatically designate detected targets, and provide menu options for players to give instructions to the AI how to designate (by laser, smoke or illumination). + +* [AIRBASEPOLICE](Documentation/AirbasePolice.html): Control the speed of players at the airbases. Speeding players are eliminated (does not work due to a bug in the DCS). + +* [CLEANUP](Documentation/Cleanup.html): Keeps the airbases clean from clutter. (Only partly functional due to a bug in DCS, destroyed objects cannot be removed). ## 4.5) MOOSE AI Controlling Classes @@ -192,11 +197,11 @@ These AI Controlling Classes are based on FSM (Finite State Machine) Classes, an * [AI_PATROL_ZONE](Documentation/AI_Patrol_Zone.html): Make an alive AI Group patrol a zone derived from the ZONE_BASE class. Manage out-of-fuel events and set altitude and speed ranges for the patrol. -* [AI_CAP](Documentation/AI_Cap.html): Make an alive AI Group perform Combat Air Patrol in a dynamic process. +* [AI_CAP](Documentation/AI_Cap.html): Make an alive AI Group perform Combat Air Patrol as a dynamic process. -* [AI_CAS](Documentation/AI_Cas.html): Make an alive AI Group perform Close Air Support in a dynamic process. +* [AI_CAS](Documentation/AI_Cas.html): Make an alive AI Group perform Close Air Support as a dynamic process. -* [AI_CARGO](Documentation/AI_Cargo.html): Make AI behave as cargo. Various CARGO types exist. +* [AI_BAI](Documentation/AI_Bai.html): Make an alive AI Group perform Battlefield Air Interdiction as a dynamic process.
      AI_Bai +

      AI -- Provide Battlefield Air Interdiction (bombing).

      + +

      Banner Image

      + +
      + +

      AI_BAI classes makes AI Controllables execute bombing tasks.

      +
      AI_Balancer @@ -149,6 +163,12 @@ even when there are hardly any players in the mission.


      AI CAS classes makes AI Controllables execute a Close Air Support.

      +
      AI_Formation +

      AI -- (R2.1) Build large formations of AI Groups flying together.

      Positionable -

      This module contains the POSITIONABLE class.

      +

      Wrapper -- This module contains the POSITIONABLE class.