diff --git a/Moose Development/Moose/AI/AI_Balancer.lua b/Moose Development/Moose/AI/AI_Balancer.lua index dd8fa50c9..52adb5978 100644 --- a/Moose Development/Moose/AI/AI_Balancer.lua +++ b/Moose Development/Moose/AI/AI_Balancer.lua @@ -1,40 +1,69 @@ ---- This module contains the AI_BALANCER class. +--- Single-Player:**No** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**All** -- **AI Balancing will replace in multi player missions +-- non-occupied human slots with AI groups, in order to provide an engaging simulation environment, +-- even when there are hardly any players in the mission.** +-- +-- ![Banner Image](..\Presentations\AI_Balancer\Dia1.JPG) +-- -- -- === -- --- 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET} --- =================================================================================== --- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many AI GROUPS as there are --- CLIENTS in a SET_CLIENT collection not occupied by players. --- The AI_BALANCER class manages internally a collection of AI management objects, which govern the behaviour --- of the underlying AI GROUPS. +-- # 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET} -- --- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM) --- and calls for each event the state transition methods providing the internal @{Core.Fsm#FSM_SET.Set} object containing the --- SET_GROUP and additional event parameters provided during the event. +-- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many replacement AI groups as there are +-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players. +-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions. -- --- 1.1) AI_BALANCER construction method --- --------------------------------------- --- Create a new AI_BALANCER object with the @{#AI_BALANCER.New} method: +-- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM). +-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods. +-- An explanation about state and event transition methods can be found in the @{FSM} module documentation. -- --- * @{#AI_BALANCER.New}: Creates a new AI_BALANCER object. +-- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following: +-- +-- * **@{#AI_BALANCER.OnAfterSpawned}**( AISet, From, Event, To, AIGroup ): Define to add extra logic when an AI is spawned. +-- +-- ## 1.1) AI_BALANCER construction +-- +-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New}() method: +-- +-- ## 1.2) AI_BALANCER is a FSM +-- +-- ![Process](..\Presentations\AI_Balancer\Dia13.JPG) +-- +-- ### 1.2.1) AI_BALANCER States +-- +-- * **Monitoring** ( Set ): Monitoring the Set if all AI is spawned for the Clients. +-- * **Spawning** ( Set, ClientName ): There is a new AI group spawned with ClientName as the name of reference. +-- * **Spawned** ( Set, AIGroup ): A new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes. +-- * **Destroying** ( Set, AIGroup ): The AI is being destroyed. +-- * **Returning** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. Handle this state to customize the return behaviour of the AI, if any. +-- +-- ### 1.2.2) AI_BALANCER Events +-- +-- * **Monitor** ( Set ): Every 10 seconds, the Monitor event is triggered to monitor the Set. +-- * **Spawn** ( Set, ClientName ): Triggers when there is a new AI group to be spawned with ClientName as the name of reference. +-- * **Spawned** ( Set, AIGroup ): Triggers when a new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes. +-- * **Destroy** ( Set, AIGroup ): The AI is being destroyed. +-- * **Return** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. -- --- 1.2) --- ---- --- * Add --- * Remove +-- ## 1.3) AI_BALANCER spawn interval for replacement AI -- --- 1.2) AI_BALANCER returns AI to Airbases --- ------------------------------------------ --- You can configure to have the AI to return to: +-- Use the method @{#AI_BALANCER.InitSpawnInterval}() to set the earliest and latest interval in seconds that is waited until a new replacement AI is spawned. -- --- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the home @{Wrapper.Airbase#AIRBASE}. --- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}. --- -- +-- ## 1.4) AI_BALANCER returns AI to Airbases +-- +-- By default, When a human player joins a slot that is AI_BALANCED, the AI group will be destroyed by default. +-- However, there are 2 additional options that you can use to customize the destroy behaviour. +-- When a human player joins a slot, you can configure to let the AI return to: +-- +-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Wrapper.Airbase#AIRBASE}. +-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Wrapper.Airbase#AIRBASE}. +-- +-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return, +-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed. +-- -- === -- --- **API CHANGE HISTORY** --- ====================== +-- # **API CHANGE HISTORY** -- -- The underlying change log documents the API changes. Please read this carefully. The following notation is used: -- @@ -43,78 +72,86 @@ -- -- Hereby the change log: -- --- 2016-08-17: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval ) +-- 2017-01-17: There is still a problem with AI being destroyed, but not respawned. Need to check further upon that. -- --- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called! --- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods. +-- 2017-01-08: AI_BALANCER:**InitSpawnInterval( Earliest, Latest )** added. -- -- === -- --- AUTHORS and CONTRIBUTIONS --- ========================= +-- # **AUTHORS and CONTRIBUTIONS** -- -- ### Contributions: -- --- * **Dutch_Baron (James)**: Who you can search on the Eagle Dynamics Forums. --- Working together with James has resulted in the creation of the AI_BALANCER class. --- James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) --- --- * **SNAFU**: --- Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. --- None of the script code has been used however within the new AI_BALANCER moose class. +-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) +-- * **SNAFU**: Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. None of the script code has been used however within the new AI_BALANCER moose class. -- -- ### Authors: -- --- * FlightControl: Framework Design & Programming +-- * FlightControl: Framework Design & Programming and Documentation. -- -- @module AI_Balancer - - --- AI_BALANCER class -- @type AI_BALANCER -- @field Core.Set#SET_CLIENT SetClient +-- @field Functional.Spawn#SPAWN SpawnAI +-- @field Wrapper.Group#GROUP Test -- @extends Core.Fsm#FSM_SET AI_BALANCER = { ClassName = "AI_BALANCER", PatrolZones = {}, AIGroups = {}, + Earliest = 5, -- Earliest a new AI can be spawned is in 5 seconds. + Latest = 60, -- Latest a new AI can be spawned is in 60 seconds. } + + --- Creates a new AI_BALANCER object -- @param #AI_BALANCER self -- @param Core.Set#SET_CLIENT SetClient A SET\_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player). -- @param Functional.Spawn#SPAWN SpawnAI The default Spawn object to spawn new AI Groups when needed. -- @return #AI_BALANCER --- @usage --- -- Define a new AI_BALANCER Object. function AI_BALANCER:New( SetClient, SpawnAI ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- Core.Fsm#FSM_SET + local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- AI.AI_Balancer#AI_BALANCER self:SetStartState( "None" ) - self:AddTransition( "*", "Start", "Monitoring" ) self:AddTransition( "*", "Monitor", "Monitoring" ) self:AddTransition( "*", "Spawn", "Spawning" ) self:AddTransition( "Spawning", "Spawned", "Spawned" ) self:AddTransition( "*", "Destroy", "Destroying" ) self:AddTransition( "*", "Return", "Returning" ) - self:AddTransition( "*", "End", "End" ) - self:AddTransition( "*", "Dead", "End" ) - - self.SetClient = SetClient + self.SetClient:FilterOnce() self.SpawnAI = SpawnAI + + self.SpawnQueue = {} + self.ToNearestAirbase = false self.ToHomeAirbase = false - self:__Start( 1 ) + self:__Monitor( 1 ) return self end +--- Sets the earliest to the latest interval in seconds how long AI_BALANCER will wait to spawn a new AI. +-- Provide 2 identical seconds if the interval should be a fixed amount of seconds. +-- @param #AI_BALANCER self +-- @param #number Earliest The earliest a new AI can be spawned in seconds. +-- @param #number Latest The latest a new AI can be spawned in seconds. +-- @return self +function AI_BALANCER:InitSpawnInterval( Earliest, Latest ) + + self.Earliest = Earliest + self.Latest = Latest + + return self +end + --- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}. -- @param #AI_BALANCER self -- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}. @@ -142,23 +179,27 @@ end function AI_BALANCER:onenterSpawning( SetGroup, From, Event, To, ClientName ) -- OK, Spawn a new group from the default SpawnAI object provided. - local AIGroup = self.SpawnAI:Spawn() + local AIGroup = self.SpawnAI:Spawn() -- Wrapper.Group#GROUP AIGroup:E( "Spawning new AIGroup" ) --TODO: need to rework UnitName thing ... SetGroup:Add( ClientName, AIGroup ) + self.SpawnQueue[ClientName] = nil -- Fire the Spawned event. The first parameter is the AIGroup just Spawned. -- Mission designers can catch this event to bind further actions to the AIGroup. - self:Spawned( AIGroup ) + self:Spawned( AIGroup ) end --- @param #AI_BALANCER self -- @param Core.Set#SET_GROUP SetGroup -- @param Wrapper.Group#GROUP AIGroup -function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, AIGroup ) +function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup ) AIGroup:Destroy() + SetGroup:Flush() + SetGroup:Remove( ClientName ) + SetGroup:Flush() end --- @param #AI_BALANCER self @@ -190,10 +231,13 @@ end --- @param #AI_BALANCER self function AI_BALANCER:onenterMonitoring( SetGroup ) + self:T2( { self.SetClient:Count() } ) + --self.SetClient:Flush() + self.SetClient:ForEachClient( --- @param Wrapper.Client#CLIENT Client function( Client ) - self:E(Client.ClientName) + self:T3(Client.ClientName) local AIGroup = self.Set:Get( Client.UnitName ) -- Wrapper.Group#GROUP if Client:IsAlive() then @@ -201,7 +245,7 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) if AIGroup and AIGroup:IsAlive() == true then if self.ToNearestAirbase == false and self.ToHomeAirbase == false then - self:Destroy( AIGroup ) + self:Destroy( Client.UnitName, AIGroup ) else -- We test if there is no other CLIENT within the self.ReturnTresholdRange of the first unit of the AI group. -- If there is a CLIENT, the AI stays engaged and will not return. @@ -210,16 +254,16 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) local PlayerInRange = { Value = false } local RangeZone = ZONE_RADIUS:New( 'RangeZone', AIGroup:GetVec2(), self.ReturnTresholdRange ) - self:E( RangeZone ) + self:T2( RangeZone ) _DATABASE:ForEachPlayer( --- @param Wrapper.Unit#UNIT RangeTestUnit function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange ) - self:E( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } ) + self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } ) if RangeTestUnit:IsInZone( RangeZone ) == true then - self:E( "in zone" ) + self:T2( "in zone" ) if RangeTestUnit:GetCoalition() ~= AIGroup:GetCoalition() then - self:E( "in range" ) + self:T2( "in range" ) PlayerInRange.Value = true end end @@ -240,9 +284,13 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) end else if not AIGroup or not AIGroup:IsAlive() == true then - self:E("client not alive") - self:Spawn( Client.UnitName ) - self:E("text after spawn") + self:T( "Client " .. Client.UnitName .. " not alive." ) + if not self.SpawnQueue[Client.UnitName] then + -- Spawn a new AI taking into account the spawn interval Earliest, Latest + self:__Spawn( math.random( self.Earliest, self.Latest ), Client.UnitName ) + self.SpawnQueue[Client.UnitName] = true + self:E( "New AI Spawned for Client " .. Client.UnitName ) + end end end return true diff --git a/Moose Development/Moose/AI/AI_CAP.lua b/Moose Development/Moose/AI/AI_CAP.lua new file mode 100644 index 000000000..c8f7186f9 --- /dev/null +++ b/Moose Development/Moose/AI/AI_CAP.lua @@ -0,0 +1,550 @@ +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Execute Combat Air Patrol (CAP).** +-- +-- ![Banner Image](..\Presentations\AI_Cap\Dia1.JPG) +-- +-- +-- === +-- +-- # 1) @{#AI_CAP_ZONE} class, extends @{AI.AI_Cap#AI_PATROL_ZONE} +-- +-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group} +-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. +-- +-- ![Process](..\Presentations\AI_Cap\Dia3.JPG) +-- +-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_Cap\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_Cap\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_Cap\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_Cap\Dia9.JPG) +-- +-- When enemies are detected, the AI will automatically engage the enemy. +-- +-- ![Process](..\Presentations\AI_Cap\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Process](..\Presentations\AI_Cap\Dia13.JPG) +-- +-- ## 1.1) AI_CAP_ZONE constructor +-- +-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object. +-- +-- ## 1.2) AI_CAP_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_Cap\Dia2.JPG) +-- +-- ### 1.2.1) AI_CAP_ZONE States +-- +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Engaging** ( Group ): The AI is engaging the bogeys. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 1.2.2) AI_CAP_ZONE Events +-- +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **Engage** ( Group ): Let the AI engage the bogeys. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ## 1.3) Set the Range of Engagement +-- +-- ![Range](..\Presentations\AI_Cap\Dia11.JPG) +-- +-- An optional range can be set in meters, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- The range can be beyond or smaller than the range of the Patrol Zone. +-- The range is applied at the position of the AI. +-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageRange}() to define that range. +-- +-- ## 1.4) Set the Zone of Engagement +-- +-- ![Zone](..\Presentations\AI_Cap\Dia12.JPG) +-- +-- An optional @{Zone} can be set, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** +-- +-- The underlying change log documents the API changes. Please read this carefully. The following notation is used: +-- +-- * **Added** parts are expressed in bold type face. +-- * _Removed_ parts are expressed in italic type face. +-- +-- Hereby the change log: +-- +-- 2017-01-15: Initial class and API. +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Cap + + +--- AI_CAP_ZONE class +-- @type AI_CAP_ZONE +-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @extends AI.AI_Patrol#AI_PATROL_ZONE +AI_CAP_ZONE = { + ClassName = "AI_CAP_ZONE", +} + + + +--- Creates a new AI_CAP_ZONE object +-- @param #AI_CAP_ZONE self +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. +-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAP_ZONE + + self.Accomplished = false + self.Engaging = false + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_CAP_ZONE] OnBeforeEngage + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Engage. + -- @function [parent=#AI_CAP_ZONE] OnAfterEngage + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAP_ZONE] Engage + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAP_ZONE] __Engage + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_CAP_ZONE] OnLeaveEngaging +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @return #boolean Return false to cancel Transition. + +--- OnEnter Transition Handler for State Engaging. +-- @function [parent=#AI_CAP_ZONE] OnEnterEngaging +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_CAP_ZONE] OnBeforeFired + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Fired. + -- @function [parent=#AI_CAP_ZONE] OnAfterFired + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAP_ZONE] Fired + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAP_ZONE] __Fired + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] OnBeforeDestroy + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] Destroy + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] __Destroy + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_CAP_ZONE] OnBeforeAbort + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Abort. + -- @function [parent=#AI_CAP_ZONE] OnAfterAbort + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAP_ZONE] Abort + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAP_ZONE] __Abort + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] OnBeforeAccomplish + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] Accomplish + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] __Accomplish + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone which defines where the AI will engage bogies. +-- @param #AI_CAP_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + +--- Set the Engage Range when the AI will engage with airborne enemies. +-- @param #AI_CAP_ZONE self +-- @param #number EngageRange The Engage Range. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:SetEngageRange( EngageRange ) + self:F2() + + if EngageRange then + self.EngageRange = EngageRange + else + self.EngageRange = nil + end +end + +--- onafter State Transition for Event Start. +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To ) + + + self:Route() + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone. + + self:EventOnDead( self.OnDead ) + + Controllable:OptionROEOpenFire() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageCapRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_CAP_ZONE + EngageZone:__Engage( 1 ) +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To ) + + if From ~= "Engaging" then + + local Engage = false + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then + Engage = true + break + end + end + + if Engage == true then + self:E( 'Detected -> Engaging' ) + self:__Engage( 1 ) + end + end +end + + + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) + + if Controllable:IsAlive() then + + self:Detect( self.EngageZone ) + + local EngageRoute = {} + + --- Calculate the current route point. + local CurrentVec2 = self.Controllable:GetVec2() + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() + local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + + --- Find a random 2D point in PatrolZone. + local ToTargetVec2 = self.PatrolZone:GetRandomVec2() + self:T2( ToTargetVec2 ) + + --- Define Speed and Altitude. + local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToPatrolRoutePoint = ToTargetPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint + + Controllable:OptionROEOpenFire() + Controllable:OptionROTPassiveDefense() + + local AttackTasks = {} + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then + if self.EngageZone then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:E( {"Within Zone and Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + if self.EngageRange then + if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then + self:E( {"Within Range and Engaging", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( EngageRoute ) + + + if #AttackTasks == 0 then + self:E("No targets found -> Going back to Patrolling") + self:Accomplish() + self:Route() + else + EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + self.Controllable:SetState( self.Controllable, "EngageZone", self ) + + self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" ) + + end + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) + + end +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @param Core.Event#EVENTDATA EventData +function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end + + Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" ) +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self.DetectUnits = false +end + +--- @param #AI_CAP_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_CAP_ZONE:OnDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Destroy( 1, EventData ) + end +end + + diff --git a/Moose Development/Moose/AI/AI_CAS.lua b/Moose Development/Moose/AI/AI_CAS.lua new file mode 100644 index 000000000..ac60b1ea5 --- /dev/null +++ b/Moose Development/Moose/AI/AI_CAS.lua @@ -0,0 +1,532 @@ +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.** +-- +-- ![Banner Image](..\Presentations\AI_Cas\Dia1.JPG) +-- +-- +-- === +-- +-- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE} +-- +-- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour. +-- +-- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}. +-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. +-- +-- ![HoldAndEngage](..\Presentations\AI_Cas\Dia3.JPG) +-- +-- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event. +-- +-- ![Start Event](..\Presentations\AI_Cas\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_Cas\Dia5.JPG) +-- +-- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone. +-- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia6.JPG) +-- +-- The AI will detect the targets and will only destroy the targets within the Engage Zone. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia7.JPG) +-- +-- Every target that is destroyed, is reported< by the AI. +-- +-- ![Engage Event](..\Presentations\AI_Cas\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_Cas\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_Cas\Dia10.JPG) +-- +-- When the AI has accomplished the CAS, it will fly back to the Patrol Zone. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia11.JPG) +-- +-- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone. +-- It can be notified to go RTB through the **RTB** event. +-- +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia12.JPG) +-- +-- # 1.1) AI_CAS_ZONE constructor +-- +-- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object. +-- +-- ## 1.2) AI_CAS_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_Cas\Dia2.JPG) +-- +-- ### 1.2.1) AI_CAS_ZONE States +-- +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Engaging** ( Group ): The AI is engaging the targets in the Engage Zone, executing CAS. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 1.2.2) AI_CAS_ZONE Events +-- +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** +-- +-- The underlying change log documents the API changes. Please read this carefully. The following notation is used: +-- +-- * **Added** parts are expressed in bold type face. +-- * _Removed_ parts are expressed in italic type face. +-- +-- Hereby the change log: +-- +-- 2017-01-15: Initial class and API. +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Cas + + +--- AI_CAS_ZONE class +-- @type AI_CAS_ZONE +-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @extends AI.AI_Patrol#AI_CAS_ZONE +AI_CAS_ZONE = { + ClassName = "AI_CAS_ZONE", +} + + + +--- Creates a new AI_CAS_ZONE object +-- @param #AI_CAS_ZONE self +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. +-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @param Core.Zone#ZONE EngageZone +-- @return #AI_CAS_ZONE self +function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE + + self.EngageZone = EngageZone + self.Accomplished = false + + self:SetDetectionZone( self.EngageZone ) + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Engage. + -- @function [parent=#AI_CAS_ZONE] OnAfterEngage + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAS_ZONE] Engage + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAS_ZONE] __Engage + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @return #boolean Return false to cancel Transition. + +--- OnEnter Transition Handler for State Engaging. +-- @function [parent=#AI_CAS_ZONE] OnEnterEngaging +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_CAS_ZONE] OnBeforeFired + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Fired. + -- @function [parent=#AI_CAS_ZONE] OnAfterFired + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAS_ZONE] Fired + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAS_ZONE] __Fired + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] Destroy + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] __Destroy + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Abort. + -- @function [parent=#AI_CAS_ZONE] OnAfterAbort + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAS_ZONE] Abort + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAS_ZONE] __Abort + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] Accomplish + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] __Accomplish + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets. +-- @param #AI_CAS_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS. +-- @return #AI_CAS_ZONE self +function AI_CAS_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + + + +--- onafter State Transition for Event Start. +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To ) + + + self:Route() + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone. + + self:EventOnDead( self.OnDead ) + + Controllable:OptionROEHoldFire() + Controllable:OptionROTVertical() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE + EngageZone:__Engage( 1 ) +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To ) + + if Controllable:IsAlive() then + + self:Detect( self.EngageZone ) + + local EngageRoute = {} + + --- Calculate the current route point. + local CurrentVec2 = self.Controllable:GetVec2() + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() + local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + + if self.Controllable:IsNotInZone( self.EngageZone ) then + + -- Find a random 2D point in EngageZone. + local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2() + self:T2( ToEngageZoneVec2 ) + + -- Define Speed and Altitude. + local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + self:T2( ToEngageZoneSpeed ) + + -- Obtain a 3D @{Point} from the 2D point + altitude. + local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y ) + + -- Create a route point of type air. + local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint + + end + + --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. + + --- Find a random 2D point in EngageZone. + local ToTargetVec2 = self.EngageZone:GetRandomVec2() + self:T2( ToTargetVec2 ) + + --- Define Speed and Altitude. + local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + ToTargetPointVec3:SmokeBlue() + + EngageRoute[#EngageRoute+1] = ToTargetRoutePoint + + + Controllable:OptionROEOpenFire() + Controllable:OptionROTPassiveDefense() + + local AttackTasks = {} + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:E( {"Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + + EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( EngageRoute ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + self.Controllable:SetState( self.Controllable, "EngageZone", self ) + + self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" ) + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) + end +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @param Core.Event#EVENTDATA EventData +function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end + + Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" ) +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self.DetectUnits = false +end + +--- @param #AI_CAS_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_CAS_ZONE:OnDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Destroy( 1, EventData ) + end +end + + diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index eeecd3226..903181661 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -1,4 +1,4 @@ ---- Management of logical cargo objects, that can be transported from and to transportation carriers. +--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers. -- -- === -- @@ -42,14 +42,14 @@ -- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state. -- There are 2 moments when state transition methods will be called by the state machine: -- --- * **Before** the state transition. --- The state transition method needs to start with the name **OnBefore + the name of the state**. +-- * **Leaving** the state. +-- The state transition method needs to start with the name **OnLeave + the name of the state**. -- If the state transition method returns false, then the processing of the state transition will not be done! -- If you want to change the behaviour of the AIControllable at this event, return false, -- but then you'll need to specify your own logic using the AIControllable! -- --- * **After** the state transition. --- The state transition method needs to start with the name **OnAfter + the name of the state**. +-- * **Entering** the state. +-- The state transition method needs to start with the name **OnEnter + the name of the state**. -- These state transition methods need to provide a return value, which is specified at the function description. -- -- 2) #AI_CARGO_UNIT class @@ -135,45 +135,45 @@ -- UnLoaded ---- @function [parent=#AI_CARGO] OnBeforeUnLoaded +--- @function [parent=#AI_CARGO] OnLeaveUnLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterUnLoaded +--- @function [parent=#AI_CARGO] OnEnterUnLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- Loaded ---- @function [parent=#AI_CARGO] OnBeforeLoaded +--- @function [parent=#AI_CARGO] OnLeaveLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterLoaded +--- @function [parent=#AI_CARGO] OnEnterLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- Boarding ---- @function [parent=#AI_CARGO] OnBeforeBoarding +--- @function [parent=#AI_CARGO] OnLeaveBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterBoarding +--- @function [parent=#AI_CARGO] OnEnterBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- UnBoarding ---- @function [parent=#AI_CARGO] OnBeforeUnBoarding +--- @function [parent=#AI_CARGO] OnLeaveUnBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterUnBoarding +--- @function [parent=#AI_CARGO] OnEnterUnBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable diff --git a/Moose Development/Moose/AI/AI_Patrol.lua b/Moose Development/Moose/AI/AI_Patrol.lua index 6781fe964..9edc140a8 100644 --- a/Moose Development/Moose/AI/AI_Patrol.lua +++ b/Moose Development/Moose/AI/AI_Patrol.lua @@ -1,110 +1,122 @@ ---- (AI) (FSM) Make AI patrol routes or zones. +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Air Patrolling or Staging.** +-- +-- ![Banner Image](..\Presentations\AI_Patrol\Dia1.JPG) +-- -- -- === -- --- 1) @{#AI_PATROLZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE} --- ================================================================ --- The @{#AI_PATROLZONE} class implements the core functions to patrol a @{Zone} by an AIR @{Controllable} @{Group}. --- The patrol algorithm works that for each airplane patrolling, upon arrival at the patrol zone, --- a random point is selected as the route point within the 3D space, within the given boundary limits. --- The airplane will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. --- Upon arrival at the random 3D point, a new 3D random point will be selected within the patrol zone using the given limits. --- This cycle will continue until a fuel treshold has been reached by the airplane. +-- # 1) @{#AI_PATROL_ZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE} +-- +-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia3.JPG) +-- +-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia9.JPG) +-- +---- Note that the enemy is not engaged! To model enemy engagement, either tailor the **Detected** event, or +-- use derived AI_ classes to model AI offensive or defensive behaviour. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. -- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. -- --- 1.1) AI_PATROLZONE constructor: --- ---------------------------- +-- ![Process](..\Presentations\AI_Patrol\Dia11.JPG) +-- +-- ## 1.1) AI_PATROL_ZONE constructor -- --- * @{#AI_PATROLZONE.New}(): Creates a new AI_PATROLZONE object. +-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object. -- --- 1.2) AI_PATROLZONE state machine: --- ---------------------------------- --- The AI_PATROLZONE is a state machine: it manages the different events and states of the AIControllable it is controlling. +-- ## 1.2) AI_PATROL_ZONE is a FSM -- --- ### 1.2.1) AI_PATROLZONE Events: +-- ![Process](..\Presentations\AI_Patrol\Dia2.JPG) -- --- * @{#AI_PATROLZONE.Route}( AIControllable ): A new 3D route point is selected and the AIControllable will fly towards that point with the given speed. --- * @{#AI_PATROLZONE.Patrol}( AIControllable ): The AIControllable reports it is patrolling. This event is called every 30 seconds. --- * @{#AI_PATROLZONE.RTB}( AIControllable ): The AIControllable will report return to base. --- * @{#AI_PATROLZONE.End}( AIControllable ): The end of the AI_PATROLZONE process. --- * @{#AI_PATROLZONE.Dead}( AIControllable ): The AIControllable is dead. The AI_PATROLZONE process will be ended. +-- ### 1.2.1) AI_PATROL_ZONE States -- --- ### 1.2.2) AI_PATROLZONE States: +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Returning** ( Group ): The AI is returning to Base.. -- --- * **Route**: A new 3D route point is selected and the AIControllable will fly towards that point with the given speed. --- * **Patrol**: The AIControllable is patrolling. This state is set every 30 seconds, so every 30 seconds, a state transition method can be used. --- * **RTB**: The AIControllable reports it wants to return to the base. --- * **Dead**: The AIControllable is dead ... --- * **End**: The process has come to an end. --- --- ### 1.2.3) AI_PATROLZONE state transition methods: +-- ### 1.2.2) AI_PATROL_ZONE Events -- --- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state. --- There are 2 moments when state transition methods will be called by the state machine: --- --- * **Before** the state transition. --- The state transition method needs to start with the name **OnBefore + the name of the state**. --- If the state transition method returns false, then the processing of the state transition will not be done! --- If you want to change the behaviour of the AIControllable at this event, return false, --- but then you'll need to specify your own logic using the AIControllable! --- --- * **After** the state transition. --- The state transition method needs to start with the name **OnAfter + the name of the state**. --- These state transition methods need to provide a return value, which is specified at the function description. --- --- An example how to manage a state transition for an AI_PATROLZONE object **Patrol** for the state **RTB**: --- --- local PatrolZoneGroup = GROUP:FindByName( "Patrol Zone" ) --- local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) --- --- local PatrolSpawn = SPAWN:New( "Patrol Group" ) --- local PatrolGroup = PatrolSpawn:Spawn() --- --- local Patrol = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 300, 600 ) --- Patrol:SetControllable( PatrolGroup ) --- Patrol:ManageFuel( 0.2, 60 ) --- --- **OnBefore**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **before** the RTB default action is processed by the AI_PATROLZONE object. --- --- --- State transition function for the AI_PATROLZONE **Patrol** object --- -- @param #AI_PATROLZONE self --- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup --- -- @return #boolean If false is returned, then the OnAfter state transition method will not be called. --- function Patrol:OnBeforeRTB( AIGroup ) --- AIGroup:MessageToRed( "Returning to base", 20 ) --- end --- --- **OnAfter**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **after** the RTB default action was processed by the AI_PATROLZONE object. --- --- --- State transition function for the AI_PATROLZONE **Patrol** object --- -- @param #AI_PATROLZONE self --- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup --- -- @return #Wrapper.Controllable#CONTROLLABLE The new AIGroup object that is set to be patrolling the zone. --- function Patrol:OnAfterRTB( AIGroup ) --- return PatrolSpawn:Spawn() --- end +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- --- 1.3) Manage the AI_PATROLZONE parameters: --- ------------------------------------------ --- The following methods are available to modify the parameters of a AI_PATROLZONE object: +-- ## 1.3) Set or Get the AI controllable -- --- * @{#AI_PATROLZONE.SetControllable}(): Set the AIControllable. --- * @{#AI_PATROLZONE.GetControllable}(): Get the AIControllable. --- * @{#AI_PATROLZONE.SetSpeed}(): Set the patrol speed of the AI, for the next patrol. --- * @{#AI_PATROLZONE.SetAltitude}(): Set altitude of the AI, for the next patrol. +-- * @{#AI_PATROL_ZONE.SetControllable}(): Set the AIControllable. +-- * @{#AI_PATROL_ZONE.GetControllable}(): Get the AIControllable. +-- +-- ## 1.4) Set the Speed and Altitude boundaries of the AI controllable +-- +-- * @{#AI_PATROL_ZONE.SetSpeed}(): Set the patrol speed boundaries of the AI, for the next patrol. +-- * @{#AI_PATROL_ZONE.SetAltitude}(): Set altitude boundaries of the AI, for the next patrol. -- --- 1.3) Manage the out of fuel in the AI_PATROLZONE: --- ---------------------------------------------- --- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base. +-- ## 1.5) Manage the detection process of the AI controllable +-- +-- The detection process of the AI controllable can be manipulated. +-- Detection requires an amount of CPU power, which has an impact on your mission performance. +-- Only put detection on when absolutely necessary, and the frequency of the detection can also be set. +-- +-- * @{#AI_PATROL_ZONE.SetDetectionOn}(): Set the detection on. The AI will detect for targets. +-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. +-- +-- The detection frequency can be set with @{#AI_PATROL_ZONE.SetDetectionInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection. +-- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI. +-- +-- The detection can be filtered to potential targets in a specific zone. +-- Use the method @{#AI_PATROL_ZONE.SetDetectionZone}() to set the zone where targets need to be detected. +-- Note that when the zone is too far away, or the AI is not heading towards the zone, or the AI is too high, no targets may be detected +-- according the weather conditions. +-- +-- ## 1.6) Manage the "out of fuel" in the AI_PATROL_ZONE +-- +-- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. --- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE. --- Once the time is finished, the old AIControllable will return to the base. --- Use the method @{#AI_PATROLZONE.ManageFuel}() to have this proces in place. +-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, +-- while a new AI is targetted to the AI_PATROL_ZONE. +-- Once the time is finished, the old AI will return to the base. +-- Use the method @{#AI_PATROL_ZONE.ManageFuel}() to have this proces in place. +-- +-- ## 1.7) Manage "damage" behaviour of the AI in the AI_PATROL_ZONE +-- +-- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on. +-- Therefore, when the damage treshold is reached, the AI will return immediately to the home base (RTB). +-- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this proces in place. -- -- ==== -- --- **API CHANGE HISTORY** --- ====================== +-- # **OPEN ISSUES** +-- +-- 2017-01-17: When Spawned AI is located at an airbase, it will be routed first back to the airbase after take-off. +-- +-- 2016-01-17: +-- -- Fixed problem with AI returning to base too early and unexpected. +-- -- ReSpawning of AI will reset the AI_PATROL and derived classes. +-- -- Checked the correct workings of SCHEDULER, and it DOES work correctly. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** -- -- The underlying change log documents the API changes. Please read this carefully. The following notation is used: -- @@ -113,87 +125,283 @@ -- -- Hereby the change log: -- +-- 2017-01-17: Rename of class: **AI\_PATROL\_ZONE** is the new name for the old _AI\_PATROLZONE_. +-- +-- 2017-01-15: Complete revision. AI_PATROL_ZONE is the base class for other AI_PATROL like classes. +-- -- 2016-09-01: Initial class and API. -- -- === -- --- AUTHORS and CONTRIBUTIONS --- ========================= +-- # **AUTHORS and CONTRIBUTIONS** -- -- ### Contributions: -- --- * **DutchBaron**: Testing. --- * **Pikey**: Testing and API concept review. +-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. -- -- ### Authors: -- -- * **FlightControl**: Design & Programming. -- --- --- @module Patrol +-- @module AI_Patrol --- State Transition Functions - ---- OnBefore State Transition Function --- @function [parent=#AI_PATROLZONE] OnBeforeRoute --- @param #AI_PATROLZONE self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- OnAfter State Transition Function --- @function [parent=#AI_PATROLZONE] OnAfterRoute --- @param #AI_PATROLZONE self --- @param Wrapper.Controllable#CONTROLLABLE Controllable - - - ---- AI_PATROLZONE class --- @type AI_PATROLZONE +--- AI_PATROL_ZONE class +-- @type AI_PATROL_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @field Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @field Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @field Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @field Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @field Functional.Spawn#SPAWN CoordTest -- @extends Core.Fsm#FSM_CONTROLLABLE -AI_PATROLZONE = { - ClassName = "AI_PATROLZONE", +AI_PATROL_ZONE = { + ClassName = "AI_PATROL_ZONE", } - - ---- Creates a new AI_PATROLZONE object --- @param #AI_PATROLZONE self +--- Creates a new AI_PATROL_ZONE object +-- @param #AI_PATROL_ZONE self -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. --- @return #AI_PATROLZONE self +-- @return #AI_PATROL_ZONE self -- @usage --- -- Define a new AI_PATROLZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. +-- -- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. -- PatrolZone = ZONE:New( 'PatrolZone' ) -- PatrolSpawn = SPAWN:New( 'Patrol Group' ) --- PatrolArea = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 600, 900 ) -function AI_PATROLZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) +-- PatrolArea = AI_PATROL_ZONE:New( PatrolZone, 3000, 6000, 600, 900 ) +function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_CONTROLLABLE + local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_PATROL_ZONE - self:SetStartState( "None" ) - self:AddTransition( "*", "Start", "Route" ) - self:AddTransition( "*", "Route", "Route" ) - self:AddTransition( { "Patrol", "Route" }, "Patrol", "Patrol" ) - self:AddTransition( "Patrol", "RTB", "RTB" ) - self:AddTransition( "*", "End", "End" ) - self:AddTransition( "*", "Dead", "End" ) self.PatrolZone = PatrolZone self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude self.PatrolMinSpeed = PatrolMinSpeed self.PatrolMaxSpeed = PatrolMaxSpeed + + self:SetDetectionOn() + self.CheckStatus = true + + self:ManageFuel( .2, 60 ) + self:ManageDamage( 1 ) + + self:SetDetectionInterval( 30 ) + + self.DetectedUnits = {} -- This table contains the targets detected during patrol. + + self:SetStartState( "None" ) + + self:AddTransition( "None", "Start", "Patrolling" ) + +--- OnBefore Transition Handler for Event Start. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeStart +-- @param #AI_PATROL_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 Start. +-- @function [parent=#AI_PATROL_ZONE] OnAfterStart +-- @param #AI_PATROL_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 Start. +-- @function [parent=#AI_PATROL_ZONE] Start +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Start. +-- @function [parent=#AI_PATROL_ZONE] __Start +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Patrolling. +-- @function [parent=#AI_PATROL_ZONE] OnLeavePatrolling +-- @param #AI_PATROL_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 Patrolling. +-- @function [parent=#AI_PATROL_ZONE] OnEnterPatrolling +-- @param #AI_PATROL_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( "Patrolling", "Route", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Route. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeRoute +-- @param #AI_PATROL_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 Route. +-- @function [parent=#AI_PATROL_ZONE] OnAfterRoute +-- @param #AI_PATROL_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 Route. +-- @function [parent=#AI_PATROL_ZONE] Route +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Route. +-- @function [parent=#AI_PATROL_ZONE] __Route +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Status", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Status. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeStatus +-- @param #AI_PATROL_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 Status. +-- @function [parent=#AI_PATROL_ZONE] OnAfterStatus +-- @param #AI_PATROL_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 Status. +-- @function [parent=#AI_PATROL_ZONE] Status +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Status. +-- @function [parent=#AI_PATROL_ZONE] __Status +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Detect", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Detect. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeDetect +-- @param #AI_PATROL_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 Detect. +-- @function [parent=#AI_PATROL_ZONE] OnAfterDetect +-- @param #AI_PATROL_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 Detect. +-- @function [parent=#AI_PATROL_ZONE] Detect +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Detect. +-- @function [parent=#AI_PATROL_ZONE] __Detect +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Detected", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Detected. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeDetected +-- @param #AI_PATROL_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 Detected. +-- @function [parent=#AI_PATROL_ZONE] OnAfterDetected +-- @param #AI_PATROL_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 Detected. +-- @function [parent=#AI_PATROL_ZONE] Detected +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Detected. +-- @function [parent=#AI_PATROL_ZONE] __Detected +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "RTB", "Returning" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event RTB. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeRTB +-- @param #AI_PATROL_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 RTB. +-- @function [parent=#AI_PATROL_ZONE] OnAfterRTB +-- @param #AI_PATROL_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 RTB. +-- @function [parent=#AI_PATROL_ZONE] RTB +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event RTB. +-- @function [parent=#AI_PATROL_ZONE] __RTB +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Returning. +-- @function [parent=#AI_PATROL_ZONE] OnLeaveReturning +-- @param #AI_PATROL_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 Returning. +-- @function [parent=#AI_PATROL_ZONE] OnEnterReturning +-- @param #AI_PATROL_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( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + return self end @@ -201,11 +409,11 @@ end --- Sets (modifies) the minimum and maximum speed of the patrol. --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) self.PatrolMinSpeed = PatrolMinSpeed @@ -215,39 +423,92 @@ end --- Sets the floor and ceiling altitude of the patrol. --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @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. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude end +-- * @{#AI_PATROL_ZONE.SetDetectionOn}(): Set the detection on. The AI will detect for targets. +-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. +--- Set the detection on. The AI will detect for targets. +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionOn() + self:F2() + + self.DetectUnits = true +end ---- @param Wrapper.Controllable#CONTROLLABLE AIControllable -function _NewPatrolRoute( AIControllable ) +--- Set the detection off. The AI will NOT detect for targets. +-- However, the list of already detected targets will be kept and can be enquired! +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionOff() + self:F2() + + self.DetectUnits = false +end - AIControllable:T( "NewPatrolRoute" ) - local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROLZONE - PatrolZone:__Route( 1 ) +--- Set the interval in seconds between each detection executed by the AI. +-- The list of already detected targets will be kept and updated. +-- Newly detected targets will be added, but already detected targets that were +-- not detected in this cycle, will NOT be removed! +-- The default interval is 30 seconds. +-- @param #AI_PATROL_ZONE self +-- @param #number Seconds The interval in seconds. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionInterval( Seconds ) + self:F2() + + if Seconds then + self.DetectInterval = Seconds + else + self.DetectInterval = 30 + end +end + +--- Set the detection zone where the AI is detecting targets. +-- @param #AI_PATROL_ZONE self +-- @param Core.Zone#ZONE DetectionZone The zone where to detect targets. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionZone( DetectionZone ) + self:F2() + + if DetectionZone then + self.DetectZone = DetectionZone + else + self.DetectZone = nil + end +end + +--- Gets a list of @{Wrapper.Unit#UNIT}s that were detected by the AI. +-- No filtering is applied, so, ANY detected UNIT can be in this list. +-- It is up to the mission designer to use the @{Unit} class and methods to filter the targets. +-- @param #AI_PATROL_ZONE self +-- @return #table The list of @{Wrapper.Unit#UNIT}s +function AI_PATROL_ZONE:GetDetectedUnits() + self:F2() + + return self.DetectedUnits end - - ---- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base. +--- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. --- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE. --- Once the time is finished, the old AIControllable will return to the base. --- @param #AI_PATROLZONE self +-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROL_ZONE. +-- Once the time is finished, the old AI will return to the base. +-- @param #AI_PATROL_ZONE self -- @param #number PatrolFuelTresholdPercentage The treshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel. -- @param #number PatrolOutOfFuelOrbitTime The amount of seconds the out of fuel AIControllable will orbit before returning to the base. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime ) self.PatrolManageFuel = true self.PatrolFuelTresholdPercentage = PatrolFuelTresholdPercentage @@ -256,60 +517,165 @@ function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuel return self end +--- When the AI is damaged beyond a certain treshold, it is required that the AI returns to the home base. +-- However, damage cannot be foreseen early on. +-- Therefore, when the damage treshold is reached, +-- the AI will return immediately to the home base (RTB). +-- Note that for groups, the average damage of the complete group will be calculated. +-- So, in a group of 4 airplanes, 2 lost and 2 with damage 0.2, the damage treshold will be 0.25. +-- @param #AI_PATROL_ZONE self +-- @param #number PatrolDamageTreshold The treshold in percentage (between 0 and 1) when the AI is considered to be damaged. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:ManageDamage( PatrolDamageTreshold ) + + self.PatrolManageDamage = true + self.PatrolDamageTreshold = PatrolDamageTreshold + + return self +end + --- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. --- @param #AI_PATROLZONE self --- @return #AI_PATROLZONE self -function AI_PATROLZONE:onenterRoute() +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_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_PATROL_ZONE:onafterStart( Controllable, From, Event, To ) + self:F2() + + self:__Route( 5 ) -- Route to the patrol point. The asynchronous trigger is important, because a spawned group and units takes at least one second to come live. + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every 30 seconds. + + Controllable:OptionROEHoldFire() + Controllable:OptionROTVertical() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + + +--- @param #AI_PATROL_ZONE self +--- @param Wrapper.Controllable#CONTROLLABLE Controllable +function AI_PATROL_ZONE:onbeforeDetect( Controllable, From, Event, To ) + + return self.DetectUnits +end + +--- @param #AI_PATROL_ZONE self +--- @param Wrapper.Controllable#CONTROLLABLE Controllable +function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To ) + + local Detected = false + + local DetectedTargets = Controllable:GetDetectedTargets() + for TargetID, Target in pairs( DetectedTargets or {} ) do + local TargetObject = Target.object + self:T( TargetObject ) + if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then + + local TargetUnit = UNIT:Find( TargetObject ) + local TargetUnitName = TargetUnit:GetName() + + if self.DetectionZone then + if TargetUnit:IsInZone( self.DetectionZone ) then + self:T( {"Detected ", TargetUnit } ) + self.DetectedUnits[TargetUnit] = TargetUnit + Detected = true + end + else + self.DetectedUnits[TargetUnit] = TargetUnit + Detected = true + end + end + end + + if Detected == true then + self:__Detected( 1 ) + end + + self:__Detect( self.DetectInterval ) +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +-- This statis method is called from the route path within the last task at the last waaypoint of the Controllable. +-- Note that this method is required, as triggers the next route when patrolling for the Controllable. +function AI_PATROL_ZONE:_NewPatrolRoute( AIControllable ) + + local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROL_ZONE + PatrolZone:__Route( 1 ) +end + + +--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +-- @param #AI_PATROL_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_PATROL_ZONE:onafterRoute( Controllable, From, Event, To ) self:F2() - local PatrolRoute = {} + -- When RTB, don't allow anymore the routing. + if From == "RTB" then + return + end + if self.Controllable:IsAlive() then - --- Determine if the AIControllable is within the PatrolZone. + -- Determine if the AIControllable is within the PatrolZone. -- If not, make a waypoint within the to that the AIControllable will fly at maximum speed to that point. --- --- Calculate the current route point. --- local CurrentVec2 = self.Controllable:GetVec2() --- local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() --- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) --- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( --- POINT_VEC3.RoutePointAltType.BARO, --- POINT_VEC3.RoutePointType.TurningPoint, --- POINT_VEC3.RoutePointAction.TurningPoint, --- ToPatrolZoneSpeed, --- true --- ) --- --- PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + local PatrolRoute = {} + + -- Calculate the current route point of the controllable as the start point of the route. + -- However, when the controllable is not in the air, + -- the controllable current waypoint is probably the airbase... + -- Thus, if we would take the current waypoint as the startpoint, upon take-off, the controllable flies + -- immediately back to the airbase, and this is not correct. + -- Therefore, when on a runway, get as the current route point a random point within the PatrolZone. + -- This will make the plane fly immediately to the patrol zone. - self:T2( PatrolRoute ) - - if self.Controllable:IsNotInZone( self.PatrolZone ) then - --- Find a random 2D point in PatrolZone. - local ToPatrolZoneVec2 = self.PatrolZone:GetRandomVec2() - self:T2( ToPatrolZoneVec2 ) - - --- Define Speed and Altitude. - local ToPatrolZoneAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ) + if self.Controllable:InAir() == false then + self:E( "Not in the air, finding route path within PatrolZone" ) + 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed - self:T2( ToPatrolZoneSpeed ) - - --- Obtain a 3D @{Point} from the 2D point + altitude. - local ToPatrolZonePointVec3 = POINT_VEC3:New( ToPatrolZoneVec2.x, ToPatrolZoneAltitude, ToPatrolZoneVec2.y ) - - --- Create a route point of type air. - local ToPatrolZoneRoutePoint = ToPatrolZonePointVec3:RoutePointAir( - POINT_VEC3.RoutePointAltType.BARO, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToPatrolZoneSpeed, - true - ) - - PatrolRoute[#PatrolRoute+1] = ToPatrolZoneRoutePoint - - end + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TakeOffParking, + POINT_VEC3.RoutePointAction.FromParkingArea, + ToPatrolZoneSpeed, + true + ) + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + else + self:E( "In the air, finding route path within PatrolZone" ) + 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToPatrolZoneSpeed, + true + ) + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + end + --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. @@ -334,6 +700,8 @@ function AI_PATROLZONE:onenterRoute() true ) + --self.CoordTest:SpawnFromVec3( ToTargetPointVec3:GetVec3() ) + --ToTargetPointVec3:SmokeRed() PatrolRoute[#PatrolRoute+1] = ToTargetRoutePoint @@ -343,25 +711,31 @@ function AI_PATROLZONE:onenterRoute() --- Do a trick, link the NewPatrolRoute function of the PATROLGROUP object to the AIControllable in a temporary variable ... self.Controllable:SetState( self.Controllable, "PatrolZone", self ) - self.Controllable:WayPointFunction( #PatrolRoute, 1, "_NewPatrolRoute" ) + self.Controllable:WayPointFunction( #PatrolRoute, 1, "AI_PATROL_ZONE:_NewPatrolRoute" ) - --- NOW ACT_ROUTE THE GROUP! - self.Controllable:WayPointExecute( 1 ) - - self:__Patrol( 30 ) + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) end - + end +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onbeforeStatus() ---- @param #AI_PATROLZONE self -function AI_PATROLZONE:onenterPatrol() + return self.CheckStatus +end + +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onafterStatus() self:F2() if self.Controllable and self.Controllable:IsAlive() then + local RTB = false + local Fuel = self.Controllable:GetUnit(1):GetFuel() if Fuel < self.PatrolFuelTresholdPercentage then + self:E( self.Controllable:GetName() .. " is out of fuel:" .. Fuel .. ", RTB!" ) local OldAIControllable = self.Controllable local AIControllableTemplate = self.Controllable:GetTemplate() @@ -369,10 +743,59 @@ function AI_PATROLZONE:onenterPatrol() local TimedOrbitTask = OldAIControllable:TaskControlled( OrbitTask, OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil ) ) OldAIControllable:SetTask( TimedOrbitTask, 10 ) + RTB = true + else + end + + -- TODO: Check GROUP damage function. + local Damage = self.Controllable:GetLife() + if Damage <= self.PatrolDamageTreshold then + self:E( self.Controllable:GetName() .. " is damaged:" .. Damage .. ", RTB!" ) + RTB = true + end + + if RTB == true then self:RTB() else - self:__Patrol( 30 ) -- Execute the Patrol event after 30 seconds. + self:__Status( 30 ) -- Execute the Patrol event after 30 seconds. end end - +end + +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onafterRTB() + self:F2() + + if self.Controllable and self.Controllable:IsAlive() then + + self:SetDetectionOff() + self.CheckStatus = false + + local PatrolRoute = {} + + --- 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToPatrolZoneSpeed, + true + ) + + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( PatrolRoute ) + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 1 ) + + end + end diff --git a/Moose Development/Moose/Core/Fsm.lua b/Moose Development/Moose/Core/Fsm.lua index 0f060855a..382ca1cad 100644 --- a/Moose Development/Moose/Core/Fsm.lua +++ b/Moose Development/Moose/Core/Fsm.lua @@ -310,7 +310,7 @@ do -- FSM function FSM:New( FsmT ) -- Inherits from BASE - local self = BASE:Inherit( self, BASE:New() ) + self = BASE:Inherit( self, BASE:New() ) self.options = options or {} self.options.subs = self.options.subs or {} @@ -535,19 +535,26 @@ do -- FSM function FSM._handler( self, EventName, ... ) - self:E( { EventName, ... } ) + local Can, to = self:can( EventName ) - local can, to = self:can( EventName ) - self:E( { EventName, self.current, can, to } ) + if to == "*" then + to = self.current + end - local ReturnValues = nil - - if can then + if Can then local from = self.current local params = { from, EventName, to, ... } + + if self.Controllable then + self:E( "FSM Transition for " .. self.Controllable.ControllableName .. " :" .. self.current .. " --> " .. EventName .. " --> " .. to ) + else + self:E( "FSM Transition:" .. self.current .. " --> " .. EventName .. " --> " .. to ) + end if self:_call_handler("onbefore" .. EventName, params) == false - or self:_call_handler("onleave" .. from, params) == false then + or self:_call_handler("OnBefore" .. EventName, params) == false + or self:_call_handler("onleave" .. from, params) == false + or self:_call_handler("OnLeave" .. from, params) == false then return false end @@ -565,14 +572,16 @@ do -- FSM sub.fsm.fsmparent = self sub.fsm.ReturnEvents = sub.ReturnEvents sub.fsm[sub.StartEvent]( sub.fsm ) - execute = true + execute = false end local fsmparent, Event = self:_isendstate( to ) if fsmparent and Event then self:F2( { "end state: ", fsmparent, Event } ) self:_call_handler("onenter" .. to, params) + self:_call_handler("OnEnter" .. to, params) self:_call_handler("onafter" .. EventName, params) + self:_call_handler("OnAfter" .. EventName, params) self:_call_handler("onstatechange", params) fsmparent[Event]( fsmparent ) execute = false @@ -580,25 +589,19 @@ do -- FSM if execute then -- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute! - if from ~= to then - self:T3( { onenter = "onenter" .. to, callback = self["onenter" .. to] } ) + --if from ~= to then self:_call_handler("onenter" .. to, params) - end + self:_call_handler("OnEnter" .. to, params) + --end - self:T3( { On = "OnBefore" .. to, callback = self["OnBefore" .. to] } ) - if ( self:_call_handler("OnBefore" .. to, params ) ~= false ) then - - self:T3( { onafter = "onafter" .. EventName, callback = self["onafter" .. EventName] } ) - self:_call_handler("onafter" .. EventName, params) - - self:T3( { On = "OnAfter" .. EventName, callback = self["OnAfter" .. EventName] } ) - ReturnValues = self:_call_handler("OnAfter" .. EventName, params ) - end + self:_call_handler("onafter" .. EventName, params) + self:_call_handler("OnAfter" .. EventName, params) self:_call_handler("onstatechange", params) end - - return ReturnValues + else + self:E( "Cannot execute transition." ) + self:E( { From = self.current, Event = EventName, To = to, Can = Can } ) end return nil @@ -674,7 +677,6 @@ do -- FSM end function FSM:can(e) - self:E( { e, self.Events, self.Events[e] } ) local Event = self.Events[e] self:F3( { self.current, Event } ) local To = Event and Event.map[self.current] or Event.map['*'] @@ -743,7 +745,7 @@ do -- FSM_CONTROLLABLE end if self[handler] then - self:E( "Calling " .. handler ) + self:F3( "Calling " .. handler ) return xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler ) --return self[handler]( self, self.Controllable, unpack( params ) ) end @@ -1007,7 +1009,7 @@ do -- FSM_SET function FSM_SET:New( FSMSet ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET + self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET if FSMSet then self:Set( FSMSet ) @@ -1034,7 +1036,7 @@ do -- FSM_SET function FSM_SET:_call_handler( handler, params ) if self[handler] then - self:E( "Calling " .. handler ) + self:T( "Calling " .. handler ) return self[handler]( self, self.Set, unpack( params ) ) end end diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index 4269fb4cc..39801e785 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -74,9 +74,11 @@ POINT_VEC3 = { BARO = "BARO", }, RoutePointType = { + TakeOffParking = "TakeOffParking", TurningPoint = "Turning Point", }, RoutePointAction = { + FromParkingArea = "From Parking Area", TurningPoint = "Turning Point", }, } @@ -99,10 +101,12 @@ do -- POINT_VEC3 --- RoutePoint Types -- @type POINT_VEC3.RoutePointType +-- @field TakeOffParking "TakeOffParking" -- @field TurningPoint "Turning Point" --- RoutePoint Actions -- @type POINT_VEC3.RoutePointAction +-- @field FromParkingArea "From Parking Area" -- @field TurningPoint "Turning Point" -- Constructor. diff --git a/Moose Development/Moose/Core/ScheduleDispatcher.lua b/Moose Development/Moose/Core/ScheduleDispatcher.lua index b34ffd782..277fb7b8e 100644 --- a/Moose Development/Moose/Core/ScheduleDispatcher.lua +++ b/Moose Development/Moose/Core/ScheduleDispatcher.lua @@ -66,21 +66,21 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr -- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array. self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } ) - if Scheduler.SchedulerObject then + if Scheduler.MasterObject then self.ObjectSchedulers[self.CallID] = Scheduler - self:T3( { self.CallID, self.ObjectSchedulers[self.CallID] } ) + self:F3( { CallID = self.CallID, ObjectScheduler = tostring(self.ObjectSchedulers[self.CallID]), MasterObject = tostring(Scheduler.MasterObject) } ) else self.PersistentSchedulers[self.CallID] = Scheduler - self:T3( { self.CallID, self.PersistentSchedulers[self.CallID] } ) + self:F3( { CallID = self.CallID, PersistentScheduler = self.PersistentSchedulers[self.CallID] } ) end self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } ) - self.Schedule[Scheduler] = {} + self.Schedule[Scheduler] = self.Schedule[Scheduler] or {} self.Schedule[Scheduler][self.CallID] = {} self.Schedule[Scheduler][self.CallID].Function = ScheduleFunction self.Schedule[Scheduler][self.CallID].Arguments = ScheduleArguments self.Schedule[Scheduler][self.CallID].StartTime = timer.getTime() + ( Start or 0 ) - self.Schedule[Scheduler][self.CallID].Start = Start + .001 + self.Schedule[Scheduler][self.CallID].Start = Start + .1 self.Schedule[Scheduler][self.CallID].Repeat = Repeat self.Schedule[Scheduler][self.CallID].Randomize = Randomize self.Schedule[Scheduler][self.CallID].Stop = Stop @@ -156,7 +156,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr self:Stop( Scheduler, CallID ) end else - --self:E( "Scheduled obscolete call for CallID: " .. CallID ) + self:E( "Scheduled obscolete call for CallID: " .. CallID ) end return nil diff --git a/Moose Development/Moose/Core/Scheduler.lua b/Moose Development/Moose/Core/Scheduler.lua index 6047240aa..2b68e54bd 100644 --- a/Moose Development/Moose/Core/Scheduler.lua +++ b/Moose Development/Moose/Core/Scheduler.lua @@ -69,6 +69,8 @@ function SCHEDULER:New( SchedulerObject, SchedulerFunction, SchedulerArguments, local ScheduleID = nil + self.MasterObject = SchedulerObject + if SchedulerFunction then ScheduleID = self:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop ) end @@ -96,7 +98,11 @@ function SCHEDULER:Schedule( SchedulerObject, SchedulerFunction, SchedulerArgume self:F2( { Start, Repeat, RandomizeFactor, Stop } ) self:T3( { SchedulerArguments } ) - + local ObjectName = "-" + if SchedulerObject and SchedulerObject.ClassName and SchedulerObject.ClassID then + ObjectName = SchedulerObject.ClassName .. SchedulerObject.ClassID + end + self:F3( { "Schedule :", ObjectName, tostring( SchedulerObject ), Start, Repeat, RandomizeFactor, Stop } ) self.SchedulerObject = SchedulerObject local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule( diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index ed94d776b..f20832639 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -233,6 +233,7 @@ -- @field #table Filter -- @field #table Set -- @field #table List +-- @field Core.Scheduler#SCHEDULER CallScheduler -- @extends Core.Base#BASE SET_BASE = { ClassName = "SET_BASE", @@ -250,7 +251,7 @@ SET_BASE = { function SET_BASE:New( Database ) -- Inherits from BASE - local self = BASE:Inherit( self, BASE:New() ) + local self = BASE:Inherit( self, BASE:New() ) -- Core.Set#SET_BASE self.Database = Database @@ -260,6 +261,8 @@ function SET_BASE:New( Database ) self.List = {} self.List.__index = self.List self.List = setmetatable( { Count = 0 }, self.List ) + + self.CallScheduler = SCHEDULER:New( self ) return self end @@ -647,7 +650,7 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen return false end - local Scheduler = SCHEDULER:New( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) + self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) return self end diff --git a/Moose Development/Moose/Functional/Scoring.lua b/Moose Development/Moose/Functional/Scoring.lua index 3d1292c74..40e3496b9 100644 --- a/Moose Development/Moose/Functional/Scoring.lua +++ b/Moose Development/Moose/Functional/Scoring.lua @@ -436,7 +436,7 @@ function SCORING:_EventOnHit( Event ) ):ToAll() self:ScoreCSV( InitPlayerName, "HIT_PENALTY", 1, -25, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) else - self.Players[InitPlayerName].Score = self.Players[InitPlayerName].Score + 10 + self.Players[InitPlayerName].Score = self.Players[InitPlayerName].Score + 1 self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Score = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Score + 1 self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].ScoreHit = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].ScoreHit + 1 MESSAGE:New( "Player '" .. InitPlayerName .. "' hit a target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. diff --git a/Moose Development/Moose/Functional/Spawn.lua b/Moose Development/Moose/Functional/Spawn.lua index b5812fffa..6560044d5 100644 --- a/Moose Development/Moose/Functional/Spawn.lua +++ b/Moose Development/Moose/Functional/Spawn.lua @@ -207,6 +207,7 @@ SPAWN = { SpawnAliasPrefix = nil, } + --- @type SPAWN.SpawnZoneTable -- @list SpawnZone @@ -590,6 +591,7 @@ function SPAWN:ReSpawn( SpawnIndex ) -- TODO: This logic makes DCS crash and i don't know why (yet). local SpawnGroup = self:GetGroupFromIndex( SpawnIndex ) + local WayPoints = SpawnGroup and SpawnGroup.WayPoints or nil if SpawnGroup then local SpawnDCSGroup = SpawnGroup:GetDCSObject() if SpawnDCSGroup then @@ -597,7 +599,18 @@ function SPAWN:ReSpawn( SpawnIndex ) end end - return self:SpawnWithIndex( SpawnIndex ) + local SpawnGroup = self:SpawnWithIndex( SpawnIndex ) + if SpawnGroup and WayPoints then + -- If there were WayPoints set, then Re-Execute those WayPoints! + SpawnGroup:WayPointInitialize( WayPoints ) + SpawnGroup:WayPointExecute( 1, 5 ) + end + + if SpawnGroup.ReSpawnFunction then + SpawnGroup:ReSpawnFunction() + end + + return SpawnGroup end --- Will spawn a group with a specified index number. diff --git a/Moose Development/Moose/Moose.lua b/Moose Development/Moose/Moose.lua index 32b309b3b..ed13ffe2e 100644 --- a/Moose Development/Moose/Moose.lua +++ b/Moose Development/Moose/Moose.lua @@ -42,6 +42,8 @@ Include.File( "Functional/Detection" ) --- AI Classes Include.File( "AI/AI_Balancer" ) Include.File( "AI/AI_Patrol" ) +Include.File( "AI/AI_Cap" ) +Include.File( "AI/AI_Cas" ) Include.File( "AI/AI_Cargo" ) --- Actions diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index af21429ba..fd9ec7dec 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -123,7 +123,6 @@ -- === -- -- @module Controllable --- @author FlightControl --- The CONTROLLABLE class -- @type CONTROLLABLE @@ -144,6 +143,8 @@ function CONTROLLABLE:New( ControllableName ) local self = BASE:Inherit( self, POSITIONABLE:New( ControllableName ) ) self:F2( ControllableName ) self.ControllableName = ControllableName + + self.TaskScheduler = SCHEDULER:New( self ) return self end @@ -165,6 +166,58 @@ function CONTROLLABLE:_GetController() return nil end +-- Get methods + +--- Returns the UNITs wrappers of the DCS Units of the Controllable (default is a GROUP). +-- @param #CONTROLLABLE self +-- @return #list The UNITs wrappers. +function CONTROLLABLE:GetUnits() + self:F2( { self.ControllableName } ) + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + local DCSUnits = DCSControllable:getUnits() + local Units = {} + for Index, UnitData in pairs( DCSUnits ) do + Units[#Units+1] = UNIT:Find( UnitData ) + end + self:T3( Units ) + return Units + end + + return nil +end + + +--- Returns the health. Dead controllables have health <= 1.0. +-- @param #CONTROLLABLE self +-- @return #number The controllable health value (unit or group average). +-- @return #nil The controllable is not existing or alive. +function CONTROLLABLE:GetLife() + self:F2( self.ControllableName ) + + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + local UnitLife = 0 + local Units = self:GetUnits() + if #Units == 1 then + local Unit = Units[1] -- Wrapper.Unit#UNIT + UnitLife = Unit:GetLife() + else + local UnitLifeTotal = 0 + for UnitID, Unit in pairs( Units ) do + local Unit = Unit -- Wrapper.Unit#UNIT + UnitLifeTotal = UnitLifeTotal + Unit:GetLife() + end + UnitLife = UnitLifeTotal / #Units + end + return UnitLife + end + + return nil +end + -- Tasks @@ -202,7 +255,7 @@ function CONTROLLABLE:PushTask( DCSTask, WaitTime ) -- Controller:pushTask( DCSTask ) if WaitTime then - SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime ) + self.TaskScheduler:Schedule( Controller, Controller.pushTask, { DCSTask }, WaitTime ) else Controller:pushTask( DCSTask ) end @@ -224,7 +277,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime ) if DCSControllable then local Controller = self:_GetController() - self:E(Controller) + self:T3( Controller ) -- When a controllable SPAWNs, it takes about a second to get the controllable in the simulator. Setting tasks to unspawned controllables provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Controllable. @@ -233,7 +286,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime ) if not WaitTime then Controller:setTask( DCSTask ) else - SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime ) + self.TaskScheduler:Schedule( Controller, Controller.setTask, { DCSTask }, WaitTime ) end return self @@ -304,6 +357,10 @@ function CONTROLLABLE:TaskCombo( DCSTasks ) tasks = DCSTasks } } + + for TaskID, Task in ipairs( DCSTasks ) do + self:E( Task ) + end self:T3( { DCSTaskCombo } ) return DCSTaskCombo @@ -489,19 +546,24 @@ function CONTROLLABLE:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, Atta -- } local DCSTask - DCSTask = { id = 'AttackUnit', + DCSTask = { + id = 'AttackUnit', params = { + altitudeEnabled = true, unitId = AttackUnit:GetID(), - weaponType = WeaponType, - expend = WeaponExpend, - attackQty = AttackQty, - direction = Direction, - attackQtyLimit = AttackQtyLimit, - controllableAttack = ControllableAttack, - }, - }, + attackQtyLimit = AttackQtyLimit or false, + attackQty = AttackQty or 2, + expend = WeaponExpend or "Auto", + altitude = 2000, + directionEnabled = true, + groupAttack = true, + --weaponType = WeaponType or 1073741822, + direction = Direction or 0, + } + } - self:T3( { DCSTask } ) + self:E( DCSTask ) + return DCSTask end @@ -1494,7 +1556,7 @@ function CONTROLLABLE:Route( GoPoints ) local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } local Controller = self:_GetController() --Controller.setTask( Controller, MissionTask ) - SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 ) + self.TaskScheduler:Schedule( Controller, Controller.setTask, { MissionTask }, 1 ) return self end @@ -2122,7 +2184,7 @@ end -- @param #table WayPoints If WayPoints is given, then use the route. -- @return #CONTROLLABLE function CONTROLLABLE:WayPointInitialize( WayPoints ) - self:F( { WayPoint, WayPointIndex, WayPointFunction } ) + self:F( { WayPoints } ) if WayPoints then self.WayPoints = WayPoints @@ -2133,6 +2195,18 @@ function CONTROLLABLE:WayPointInitialize( WayPoints ) return self end +--- Get the current WayPoints set with the WayPoint functions( Note that the WayPoints can be nil, although there ARE waypoints). +-- @param #CONTROLLABLE self +-- @return #table WayPoints If WayPoints is given, then return the WayPoints structure. +function CONTROLLABLE:GetWayPoints() + self:F( ) + + if self.WayPoints then + return self.WayPoints + end + + return nil +end --- Registers a waypoint function that will be executed when the controllable moves over the WayPoint. -- @param #CONTROLLABLE self @@ -2201,6 +2275,4 @@ function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) return self end --- Message APIs - - +-- Message APIs \ No newline at end of file diff --git a/Moose Development/Moose/Wrapper/Group.lua b/Moose Development/Moose/Wrapper/Group.lua index a5ba2121e..8bcd18dfe 100644 --- a/Moose Development/Moose/Wrapper/Group.lua +++ b/Moose Development/Moose/Wrapper/Group.lua @@ -205,6 +205,23 @@ function GROUP:GetDCSObject() return nil end +--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3() + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p + self:T3( PositionablePosition ) + return PositionablePosition + end + + return nil +end --- Returns if the DCS Group is alive. -- When the group exists at run-time, this method will return true, otherwise false. @@ -391,26 +408,6 @@ function GROUP:GetInitialSize() return nil end ---- Returns the UNITs wrappers of the DCS Units of the DCS Group. --- @param #GROUP self --- @return #table The UNITs wrappers. -function GROUP:GetUnits() - self:F2( { self.GroupName } ) - local DCSGroup = self:GetDCSObject() - - if DCSGroup then - local DCSUnits = DCSGroup:getUnits() - local Units = {} - for Index, UnitData in pairs( DCSUnits ) do - Units[#Units+1] = UNIT:Find( UnitData ) - end - self:T3( Units ) - return Units - end - - return nil -end - --- Returns the DCS Units of the DCS Group. -- @param #GROUP self @@ -882,5 +879,30 @@ function GROUP:CalculateThreatLevelA2G() return MaxThreatLevelA2G end +--- Returns true if the first unit of the GROUP is in the air. +-- @param Wrapper.Group#GROUP self +-- @return #boolean true if in the first unit of the group is in the air. +-- @return #nil The GROUP is not existing or not alive. +function GROUP:InAir() + self:F2( self.GroupName ) + + local DCSGroup = self:GetDCSObject() + + if DCSGroup then + local DCSUnit = DCSGroup:getUnit(1) + if DCSUnit then + local GroupInAir = DCSGroup:getUnit(1):inAir() + self:T3( GroupInAir ) + return GroupInAir + end + end + + return nil +end + +function GROUP:OnReSpawn( ReSpawnFunction ) + + self.ReSpawnFunction = ReSpawnFunction +end diff --git a/Moose Development/Moose/Wrapper/Identifiable.lua b/Moose Development/Moose/Wrapper/Identifiable.lua index 34f87b25a..c11b5cee7 100644 --- a/Moose Development/Moose/Wrapper/Identifiable.lua +++ b/Moose Development/Moose/Wrapper/Identifiable.lua @@ -29,7 +29,6 @@ -- === -- -- @module Identifiable --- @author FlightControl --- The IDENTIFIABLE class -- @type IDENTIFIABLE diff --git a/Moose Development/Moose/Wrapper/Object.lua b/Moose Development/Moose/Wrapper/Object.lua index 3ac441fbd..14650e584 100644 --- a/Moose Development/Moose/Wrapper/Object.lua +++ b/Moose Development/Moose/Wrapper/Object.lua @@ -23,7 +23,6 @@ -- === -- -- @module Object --- @author FlightControl --- The OBJECT class -- @type OBJECT @@ -34,7 +33,6 @@ OBJECT = { ObjectName = "", } - --- A DCSObject -- @type DCSObject -- @field id_ The ID of the controllable in DCS @@ -43,10 +41,11 @@ OBJECT = { -- @param #OBJECT self -- @param Dcs.DCSWrapper.Object#Object ObjectName The Object name -- @return #OBJECT self -function OBJECT:New( ObjectName ) +function OBJECT:New( ObjectName, Test ) local self = BASE:Inherit( self, BASE:New() ) self:F2( ObjectName ) self.ObjectName = ObjectName + return self end diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index e011f6f8c..18886abd8 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -24,7 +24,6 @@ -- === -- -- @module Positionable --- @author FlightControl --- The POSITIONABLE class -- @type POSITIONABLE @@ -46,6 +45,7 @@ POSITIONABLE = { function POSITIONABLE:New( PositionableName ) local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) ) + self.PositionableName = PositionableName return self end @@ -54,12 +54,12 @@ end -- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPositionVec3() - self:F2( self.PositionableName ) + self:E( self.PositionableName ) local DCSPositionable = self:GetDCSObject() if DCSPositionable then - local PositionablePosition = DCSPositionable:getPosition() + local PositionablePosition = DCSPositionable:getPosition().p self:T3( PositionablePosition ) return PositionablePosition end @@ -111,6 +111,27 @@ function POSITIONABLE:GetPointVec2() return nil end +--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function POSITIONABLE:GetPointVec3() + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionableVec3 = self:GetPositionVec3() + + local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 ) + + self:T2( PositionablePointVec3 ) + return PositionablePointVec3 + end + + return nil +end + --- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission. -- @param Wrapper.Positionable#POSITIONABLE self @@ -220,20 +241,13 @@ end --- Returns true if the POSITIONABLE is in the air. +-- Polymorphic, is overridden in GROUP and UNIT. -- @param Wrapper.Positionable#POSITIONABLE self -- @return #boolean true if in the air. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:InAir() self:F2( self.PositionableName ) - local DCSPositionable = self:GetDCSObject() - - if DCSPositionable then - local PositionableInAir = DCSPositionable:inAir() - self:T3( PositionableInAir ) - return PositionableInAir - end - return nil end diff --git a/Moose Development/Moose/Wrapper/Unit.lua b/Moose Development/Moose/Wrapper/Unit.lua index 65657e3c5..2b9d30b89 100644 --- a/Moose Development/Moose/Wrapper/Unit.lua +++ b/Moose Development/Moose/Wrapper/Unit.lua @@ -467,6 +467,25 @@ function UNIT:GetFuel() return nil end +--- Returns the UNIT in a UNIT list of one element. +-- @param #UNIT self +-- @return #list The UNITs wrappers. +function UNIT:GetUnits() + self:F2( { self.UnitName } ) + local DCSUnit = self:GetDCSObject() + + if DCSUnit then + local DCSUnits = DCSUnit:getUnits() + local Units = {} + Units[1] = UNIT:Find( DCSUnit ) + self:T3( Units ) + return Units + end + + return nil +end + + --- Returns the unit's health. Dead units has health <= 1.0. -- @param #UNIT self -- @return #number The Unit's health value. @@ -799,3 +818,21 @@ function UNIT:IsShip() return nil end +--- Returns true if the UNIT is in the air. +-- @param Wrapper.Positionable#UNIT self +-- @return #boolean true if in the air. +-- @return #nil The UNIT is not existing or alive. +function UNIT:InAir() + self:F2( self.UnitName ) + + local DCSUnit = self:GetDCSObject() + + if DCSUnit then + local UnitInAir = DCSUnit:inAir() + self:T3( UnitInAir ) + return UnitInAir + end + + return nil +end + diff --git a/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat b/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat index 7db429fef..5ccbaab56 100644 --- a/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat +++ b/Moose Mission Setup/Moose Mission Update/Moose_Update_Missions.bat @@ -5,4 +5,19 @@ rem Provide as the only parameter the path to the .miz files, which can be embed echo Path to Mission Files: %1 -For /R %1 %%G IN (*.miz) do 7z u "%%G" "l10n\DEFAULT\Moose.lua" +rem For /R %1 %%G IN (*.miz) do 7z u "%%G" "l10n\DEFAULT\Moose.lua" +For /R %1 %%M IN (*.miz) do ( + echo off + cd + echo "Mission: %%M" + mkdir Temp + cd Temp + mkdir l10n + mkdir l10n\DEFAULT + copy ..\..\Moose.lua l10n\DEFAULT + copy "%%~pM%%~nM.lua" l10n\DEFAULT\*.* + dir l10n\DEFAULT + 7z -bb0 u "%%M" "l10n\DEFAULT\*.lua" + cd .. + rmdir /S /Q Temp +) \ No newline at end of file diff --git a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua index 0624636f1..e02bdb889 100644 --- a/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua +++ b/Moose Mission Setup/Moose Mission Update/l10n/DEFAULT/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE STATIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20170105_0841' ) +env.info( 'Moose Generation Timestamp: 20170117_1202' ) local base = _G Include = {} @@ -3857,6 +3857,8 @@ function SCHEDULER:New( SchedulerObject, SchedulerFunction, SchedulerArguments, local ScheduleID = nil + self.MasterObject = SchedulerObject + if SchedulerFunction then ScheduleID = self:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop ) end @@ -3884,7 +3886,11 @@ function SCHEDULER:Schedule( SchedulerObject, SchedulerFunction, SchedulerArgume self:F2( { Start, Repeat, RandomizeFactor, Stop } ) self:T3( { SchedulerArguments } ) - + local ObjectName = "-" + if SchedulerObject and SchedulerObject.ClassName and SchedulerObject.ClassID then + ObjectName = SchedulerObject.ClassName .. SchedulerObject.ClassID + end + self:F3( { "Schedule :", ObjectName, tostring( SchedulerObject ), Start, Repeat, RandomizeFactor, Stop } ) self.SchedulerObject = SchedulerObject local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule( @@ -4011,21 +4017,21 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr -- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array. self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } ) - if Scheduler.SchedulerObject then + if Scheduler.MasterObject then self.ObjectSchedulers[self.CallID] = Scheduler - self:T3( { self.CallID, self.ObjectSchedulers[self.CallID] } ) + self:F3( { CallID = self.CallID, ObjectScheduler = tostring(self.ObjectSchedulers[self.CallID]), MasterObject = tostring(Scheduler.MasterObject) } ) else self.PersistentSchedulers[self.CallID] = Scheduler - self:T3( { self.CallID, self.PersistentSchedulers[self.CallID] } ) + self:F3( { CallID = self.CallID, PersistentScheduler = self.PersistentSchedulers[self.CallID] } ) end self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } ) - self.Schedule[Scheduler] = {} + self.Schedule[Scheduler] = self.Schedule[Scheduler] or {} self.Schedule[Scheduler][self.CallID] = {} self.Schedule[Scheduler][self.CallID].Function = ScheduleFunction self.Schedule[Scheduler][self.CallID].Arguments = ScheduleArguments self.Schedule[Scheduler][self.CallID].StartTime = timer.getTime() + ( Start or 0 ) - self.Schedule[Scheduler][self.CallID].Start = Start + .001 + self.Schedule[Scheduler][self.CallID].Start = Start + .1 self.Schedule[Scheduler][self.CallID].Repeat = Repeat self.Schedule[Scheduler][self.CallID].Randomize = Randomize self.Schedule[Scheduler][self.CallID].Stop = Stop @@ -4101,7 +4107,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr self:Stop( Scheduler, CallID ) end else - --self:E( "Scheduled obscolete call for CallID: " .. CallID ) + self:E( "Scheduled obscolete call for CallID: " .. CallID ) end return nil @@ -7667,6 +7673,7 @@ end -- @field #table Filter -- @field #table Set -- @field #table List +-- @field Core.Scheduler#SCHEDULER CallScheduler -- @extends Core.Base#BASE SET_BASE = { ClassName = "SET_BASE", @@ -7684,7 +7691,7 @@ SET_BASE = { function SET_BASE:New( Database ) -- Inherits from BASE - local self = BASE:Inherit( self, BASE:New() ) + local self = BASE:Inherit( self, BASE:New() ) -- Core.Set#SET_BASE self.Database = Database @@ -7694,6 +7701,8 @@ function SET_BASE:New( Database ) self.List = {} self.List.__index = self.List self.List = setmetatable( { Count = 0 }, self.List ) + + self.CallScheduler = SCHEDULER:New( self ) return self end @@ -8081,7 +8090,7 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen return false end - local Scheduler = SCHEDULER:New( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) + self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) return self end @@ -9786,9 +9795,11 @@ POINT_VEC3 = { BARO = "BARO", }, RoutePointType = { + TakeOffParking = "TakeOffParking", TurningPoint = "Turning Point", }, RoutePointAction = { + FromParkingArea = "From Parking Area", TurningPoint = "Turning Point", }, } @@ -9811,10 +9822,12 @@ do -- POINT_VEC3 --- RoutePoint Types -- @type POINT_VEC3.RoutePointType +-- @field TakeOffParking "TakeOffParking" -- @field TurningPoint "Turning Point" --- RoutePoint Actions -- @type POINT_VEC3.RoutePointAction +-- @field FromParkingArea "From Parking Area" -- @field TurningPoint "Turning Point" -- Constructor. @@ -10699,50 +10712,85 @@ end ----- The _MessageQueue object is created when the MESSAGE class module is loaded. ----_MessageQueue = MESSAGEQUEUE:New( 0.5 ) -- ---- This module contains the FSM class and derived FSM_ classes. +--- This module contains the **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes. +-- ## Finite State Machines (FSM) are design patterns allowing efficient (long-lasting) processes and workflows. +-- +-- ![Banner Image](..\Presentations\FSM\Dia1.JPG) +-- +-- A FSM can only be in one of a finite number of states. +-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**. +-- It can change from one state to another when initiated by an **__internal__ or __external__ triggering event**, which is called a **transition**. +-- An **FSM implementation** is defined by **a list of its states**, **its initial state**, and **the triggering events** for **each possible transition**. +-- An FSM implementation is composed out of **two parts**, a set of **state transition rules**, and an implementation set of **state transition handlers**, implementing those transitions. +-- +-- The FSM class supports a **hierarchical implementation of a Finite State Machine**, +-- that is, it allows to **embed existing FSM implementations in a master FSM**. +-- FSM hierarchies allow for efficient FSM re-use, **not having to re-invent the wheel every time again** when designing complex processes. +-- +-- ![Workflow Example](..\Presentations\FSM\Dia2.JPG) +-- +-- The above diagram shows a graphical representation of a FSM implementation for a **Task**, which guides a Human towards a Zone, +-- orders him to destroy x targets and account the results. +-- Other examples of ready made FSM could be: +-- +-- * route a plane to a zone flown by a human +-- * detect targets by an AI and report to humans +-- * account for destroyed targets by human players +-- * handle AI infantry to deploy from or embark to a helicopter or airplane or vehicle +-- * let an AI patrol a zone +-- +-- The **MOOSE framework** uses extensively the FSM class and derived FSM\_ classes, +-- because **the goal of MOOSE is to simplify mission design complexity for mission building**. +-- By efficiently utilizing the FSM class and derived classes, MOOSE allows mission designers to quickly build processes. +-- **Ready made FSM-based implementations classes** exist within the MOOSE framework that **can easily be re-used, +-- and tailored** by mission designers through **the implementation of Transition Handlers**. +-- Each of these FSM implementation classes start either with: +-- +-- * an acronym **AI\_**, which indicates an FSM implementation directing **AI controlled** @{GROUP} and/or @{UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class. +-- * an acronym **TASK\_**, which indicates an FSM implementation executing a @{TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class. +-- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{TASK}, seated in a @{CLIENT} (slot) or a @{UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class. +-- +-- Detailed explanations and API specifics are further below clarified and FSM derived class specifics are described in those class documentation sections. +-- +-- ##__Dislaimer:__ +-- The FSM class development is based on a finite state machine implementation made by Conroy Kyle. +-- The state machine can be found on [github](https://github.com/kyleconroy/lua-state-machine) +-- I've reworked this development (taken the concept), and created a **hierarchical state machine** out of it, embedded within the DCS simulator. +-- Additionally, I've added extendability and created an API that allows seamless FSM implementation. -- --- This development is based on a state machine implementation made by Conroy Kyle. --- The state machine can be found here: https://github.com/kyleconroy/lua-state-machine --- --- I've taken the development and enhanced it (actually rewrote it) to make the state machine hierarchical... --- It is a fantastic development, this module. --- -- === -- --- ![Banner Image](..\Presentations\FSM\Dia1.jpg) --- -- # 1) @{Core.Fsm#FSM} class, extends @{Core.Base#BASE} -- --- A Finite State Machine (FSM) defines the rules of transitioning between various States triggered by Events. +-- ![Transition Rules and Transition Handlers and Event Triggers](..\Presentations\FSM\Dia3.JPG) -- --- * A **State** defines a moment in the process. --- * An **Event** describes an action, that can be triggered both internally as externally in the FSM. +-- The FSM class is the base class of all FSM\_ derived classes. It implements the main functionality to define and execute Finite State Machines. +-- The derived FSM\_ classes extend the Finite State Machine functionality to run a workflow process for a specific purpose or component. -- --- ## 1.1) Event Handling +-- Finite State Machines have **Transition Rules**, **Transition Handlers** and **Event Triggers**. -- --- ![Event Handlers](..\Presentations\FSM\Dia3.jpg) +-- The **Transition Rules** define the "Process Flow Boundaries", that is, +-- the path that can be followed hopping from state to state upon triggered events. +-- If an event is triggered, and there is no valid path found for that event, +-- an error will be raised and the FSM will stop functioning. -- --- An FSM transitions in **4 moments** when an Event is being handled. --- Each moment can be catched by handling methods defined by the mission designer, --- that will be called by the FSM while executing the transition. --- These methods define the flow of the FSM process; because in those methods the FSM Internal Events will be fired. --- --- * To handle **State** moments, create methods starting with OnLeave or OnEnter concatenated with the State name. --- * To handle **Event** moments, create methods starting with OnBefore or OnAfter concatenated with the Event name. +-- The **Transition Handlers** are special methods that can be defined by the mission designer, following a defined syntax. +-- If the FSM object finds a method of such a handler, then the method will be called by the FSM, passing specific parameters. +-- The method can then define its own custom logic to implement the FSM workflow, and to conduct other actions. -- --- **The OnLeave and OnBefore transition methods may return false, which will cancel the transition.** +-- The **Event Triggers** are methods that are defined by the FSM, which the mission designer can use to implement the workflow. +-- Most of the time, these Event Triggers are used within the Transition Handler methods, so that a workflow is created running through the state machine. -- --- ## 1.2) Event Triggers +-- As explained above, a FSM supports **Linear State Transitions** and **Hierarchical State Transitions**, and both can be mixed to make a comprehensive FSM implementation. +-- The below documentation has a seperate chapter explaining both transition modes, taking into account the **Transition Rules**, **Transition Handlers** and **Event Triggers**. -- --- ![Event Triggers](..\Presentations\FSM\Dia4.jpg) +-- ## 1.1) FSM Linear Transitions -- --- The FSM creates for each Event **two Event Trigger methods**. --- There are two modes how Events can be triggered, which is **embedded** and **delayed**: +-- Linear Transitions are Transition Rules allowing an FSM to transition from one or multiple possible **From** state(s) towards a **To** state upon a Triggered **Event**. +-- The Lineair transition rule evaluation will always be done from the **current state** of the FSM. +-- If no valid Transition Rule can be found in the FSM, the FSM will log an error and stop. -- --- * The method **FSM:Event()** triggers an Event that will be processed **embedded** or **immediately**. --- * The method **FSM:__Event( seconds )** triggers an Event that will be processed **delayed** over time, waiting x seconds. --- --- ## 1.3) FSM Transition Rules +-- ### 1.1.1) FSM Transition Rules -- -- The FSM has transition rules that it follows and validates, as it walks the process. -- These rules define when an FSM can transition from a specific state towards an other specific state upon a triggered event. @@ -10751,12 +10799,107 @@ end -- -- The initial state can be defined using the method @{#FSM.SetStartState}(). The default start state of an FSM is "None". -- --- ### Example +-- Find below an example of a Linear Transition Rule definition for an FSM. -- --- This example creates a new FsmDemo object from class FSM. --- It will set the start state of FsmDemo to Green. --- 2 Transition Rules are created, where upon the event Switch, --- the FsmDemo will transition from state Green to Red and vise versa. +-- local Fsm3Switch = FSM:New() -- #FsmDemo +-- FsmSwitch:SetStartState( "Off" ) +-- FsmSwitch:AddTransition( "Off", "SwitchOn", "On" ) +-- FsmSwitch:AddTransition( "Off", "SwitchMiddle", "Middle" ) +-- FsmSwitch:AddTransition( "On", "SwitchOff", "Off" ) +-- FsmSwitch:AddTransition( "Middle", "SwitchOff", "Off" ) +-- +-- The above code snippet models a 3-way switch Linear Transition: +-- +-- * It can be switched **On** by triggering event **SwitchOn**. +-- * It can be switched to the **Middle** position, by triggering event **SwitchMiddle**. +-- * It can be switched **Off** by triggering event **SwitchOff**. +-- * Note that once the Switch is **On** or **Middle**, it can only be switched **Off**. +-- +-- ### Some additional comments: +-- +-- Note that Linear Transition Rules **can be declared in a few variations**: +-- +-- * The From states can be **a table of strings**, indicating that the transition rule will be valid **if the current state** of the FSM will be **one of the given From states**. +-- * The From state can be a **"*"**, indicating that **the transition rule will always be valid**, regardless of the current state of the FSM. +-- +-- The below code snippet shows how the two last lines can be rewritten and consensed. +-- +-- FsmSwitch:AddTransition( { "On", "Middle" }, "SwitchOff", "Off" ) +-- +-- ### 1.1.2) Transition Handling +-- +-- ![Transition Handlers](..\Presentations\FSM\Dia4.JPG) +-- +-- An FSM transitions in **4 moments** when an Event is being triggered and processed. +-- The mission designer can define for each moment specific logic within methods implementations following a defined API syntax. +-- These methods define the flow of the FSM process; because in those methods the FSM Internal Events will be triggered. +-- +-- * To handle **State** transition moments, create methods starting with OnLeave or OnEnter concatenated with the State name. +-- * To handle **Event** transition moments, create methods starting with OnBefore or OnAfter concatenated with the Event name. +-- +-- **The OnLeave and OnBefore transition methods may return false, which will cancel the transition!** +-- +-- Transition Handler methods need to follow the above specified naming convention, but are also passed parameters from the FSM. +-- These parameters are on the correct order: From, Event, To: +-- +-- * From = A string containing the From state. +-- * Event = A string containing the Event name that was triggered. +-- * To = A string containing the To state. +-- +-- On top, each of these methods can have a variable amount of parameters passed. See the example in section [1.1.3](#1.1.3\)-event-triggers). +-- +-- ### 1.1.3) Event Triggers +-- +-- ![Event Triggers](..\Presentations\FSM\Dia5.JPG) +-- +-- The FSM creates for each Event two **Event Trigger methods**. +-- There are two modes how Events can be triggered, which is **synchronous** and **asynchronous**: +-- +-- * The method **FSM:Event()** triggers an Event that will be processed **synchronously** or **immediately**. +-- * The method **FSM:__Event( __seconds__ )** triggers an Event that will be processed **asynchronously** over time, waiting __x seconds__. +-- +-- The destinction between these 2 Event Trigger methods are important to understand. An asynchronous call will "log" the Event Trigger to be executed at a later time. +-- Processing will just continue. Synchronous Event Trigger methods are useful to change states of the FSM immediately, but may have a larger processing impact. +-- +-- The following example provides a little demonstration on the difference between synchronous and asynchronous Event Triggering. +-- +-- function FSM:OnAfterEvent( From, Event, To, Amount ) +-- self:E( { Amount = Amount } ) +-- end +-- +-- local Amount = 1 +-- FSM:__Event( 5, Amount ) +-- +-- Amount = Amount + 1 +-- FSM:Event( Text, Amount ) +-- +-- In this example, the **:OnAfterEvent**() Transition Handler implementation will get called when **Event** is being triggered. +-- Before we go into more detail, let's look at the last 4 lines of the example. +-- The last line triggers synchronously the **Event**, and passes Amount as a parameter. +-- The 3rd last line of the example triggers asynchronously **Event**. +-- Event will be processed after 5 seconds, and Amount is given as a parameter. +-- +-- The output of this little code fragment will be: +-- +-- * Amount = 2 +-- * Amount = 2 +-- +-- Because ... When Event was asynchronously processed after 5 seconds, Amount was set to 2. So be careful when processing and passing values and objects in asynchronous processing! +-- +-- ### 1.1.4) Linear Transition Example +-- +-- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua) +-- +-- It models a unit standing still near Batumi, and flaring every 5 seconds while switching between a Green flare and a Red flare. +-- The purpose of this example is not to show how exciting flaring is, but it demonstrates how a Linear Transition FSM can be build. +-- Have a look at the source code. The source code is also further explained below in this section. +-- +-- The example creates a new FsmDemo object from class FSM. +-- It will set the start state of FsmDemo to state **Green**. +-- Two Linear Transition Rules are created, where upon the event **Switch**, +-- the FsmDemo will transition from state **Green** to **Red** and from **Red** back to **Green**. +-- +-- ![Transition Example](..\Presentations\FSM\Dia6.JPG) -- -- local FsmDemo = FSM:New() -- #FsmDemo -- FsmDemo:SetStartState( "Green" ) @@ -10766,6 +10909,8 @@ end -- In the above example, the FsmDemo could flare every 5 seconds a Green or a Red flare into the air. -- The next code implements this through the event handling method **OnAfterSwitch**. -- +-- ![Transition Flow](..\Presentations\FSM\Dia7.JPG) +-- -- function FsmDemo:OnAfterSwitch( From, Event, To, FsmUnit ) -- self:E( { From, Event, To, FsmUnit } ) -- @@ -10776,7 +10921,7 @@ end -- FsmUnit:Flare(FLARECOLOR.Red) -- end -- end --- FsmDemo:__Switch( 5, FsmUnit ) -- Trigger the next Switch event to happen in 5 seconds. +-- self:__Switch( 5, FsmUnit ) -- Trigger the next Switch event to happen in 5 seconds. -- end -- -- FsmDemo:__Switch( 5, FsmUnit ) -- Trigger the first Switch event to happen in 5 seconds. @@ -10806,20 +10951,9 @@ end -- -- FsmDemo:__Switch( 5, FsmUnit ) -- Trigger the next Switch event to happen in 5 seconds. -- --- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua) --- --- ### Some additional comments: --- --- Note that transition rules can be declared with a few variations: --- --- * The From states can be a table of strings, indicating that the transition rule will be valid if the current state of the FSM will be one of the given From states. --- * The From state can be a "*", indicating that the transition rule will always be valid, regardless of the current state of the FSM. --- --- This transition will create a new FsmDemo object from class FSM. --- It will set the start state of FsmDemo to Green. --- A new event is added in addition to the above example. --- The new event Stop will cancel the Switching process. --- So, the transtion for event Stop can be executed if the current state of the FSM is either "Red" or "Green". +-- The below code fragment extends the FsmDemo, demonstrating multiple **From states declared as a table**, adding a **Linear Transition Rule**. +-- The new event **Stop** will cancel the Switching process. +-- The transition for event Stop can be executed if the current state of the FSM is either "Red" or "Green". -- -- local FsmDemo = FSM:New() -- #FsmDemo -- FsmDemo:SetStartState( "Green" ) @@ -10830,15 +10964,20 @@ end -- The transition for event Stop can also be simplified, as any current state of the FSM is valid. -- -- FsmDemo:AddTransition( "*", "Stop", "Stopped" ) +-- +-- So... When FsmDemo:Stop() is being triggered, the state of FsmDemo will transition from Red or Green to Stopped. +-- And there is no transition handling method defined for that transition, thus, no new event is being triggered causing the FsmDemo process flow to halt. -- --- ## 1.4) FSM Process Rules +-- ## 1.5) FSM Hierarchical Transitions -- --- The FSM can implement sub-processes that will execute and return multiple possible states. --- Depending upon which state is returned, the main FSM can continue tiggering different events. +-- Hierarchical Transitions allow to re-use readily available and implemented FSMs. +-- This becomes in very useful for mission building, where mission designers build complex processes and workflows, +-- combining smaller FSMs to one single FSM. -- --- The method @{#FSM.AddProcess}() adds a new Sub-Process FSM to the FSM. --- A Sub-Process will start the Sub-Process of the FSM upon the defined triggered Event, --- with multiple possible States as a result. +-- The FSM can embed **Sub-FSMs** that will execute and return **multiple possible Return (End) States**. +-- Depending upon **which state is returned**, the main FSM can continue the flow **triggering specific events**. +-- +-- The method @{#FSM.AddProcess}() adds a new Sub-FSM to the FSM. -- -- ==== -- @@ -10862,11 +11001,11 @@ end -- -- ### Contributions: -- --- * None. +-- * [**Pikey**](https://forums.eagle.ru/member.php?u=62835): Review of documentation & advice for improvements. -- -- ### Authors: -- --- * **FlightControl**: Design & Programming +-- * [**FlightControl**](https://forums.eagle.ru/member.php?u=89536): Design & Programming & documentation. -- -- @module Fsm @@ -10885,7 +11024,7 @@ do -- FSM function FSM:New( FsmT ) -- Inherits from BASE - local self = BASE:Inherit( self, BASE:New() ) + self = BASE:Inherit( self, BASE:New() ) self.options = options or {} self.options.subs = self.options.subs or {} @@ -11110,19 +11249,26 @@ do -- FSM function FSM._handler( self, EventName, ... ) - self:E( { EventName, ... } ) + local Can, to = self:can( EventName ) - local can, to = self:can( EventName ) - self:E( { EventName, self.current, can, to } ) + if to == "*" then + to = self.current + end - local ReturnValues = nil - - if can then + if Can then local from = self.current local params = { from, EventName, to, ... } + + if self.Controllable then + self:E( "FSM Transition for " .. self.Controllable.ControllableName .. " :" .. self.current .. " --> " .. EventName .. " --> " .. to ) + else + self:E( "FSM Transition:" .. self.current .. " --> " .. EventName .. " --> " .. to ) + end if self:_call_handler("onbefore" .. EventName, params) == false - or self:_call_handler("onleave" .. from, params) == false then + or self:_call_handler("OnBefore" .. EventName, params) == false + or self:_call_handler("onleave" .. from, params) == false + or self:_call_handler("OnLeave" .. from, params) == false then return false end @@ -11140,14 +11286,16 @@ do -- FSM sub.fsm.fsmparent = self sub.fsm.ReturnEvents = sub.ReturnEvents sub.fsm[sub.StartEvent]( sub.fsm ) - execute = true + execute = false end local fsmparent, Event = self:_isendstate( to ) if fsmparent and Event then self:F2( { "end state: ", fsmparent, Event } ) self:_call_handler("onenter" .. to, params) + self:_call_handler("OnEnter" .. to, params) self:_call_handler("onafter" .. EventName, params) + self:_call_handler("OnAfter" .. EventName, params) self:_call_handler("onstatechange", params) fsmparent[Event]( fsmparent ) execute = false @@ -11155,25 +11303,19 @@ do -- FSM if execute then -- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute! - if from ~= to then - self:T3( { onenter = "onenter" .. to, callback = self["onenter" .. to] } ) + --if from ~= to then self:_call_handler("onenter" .. to, params) - end + self:_call_handler("OnEnter" .. to, params) + --end - self:T3( { On = "OnBefore" .. to, callback = self["OnBefore" .. to] } ) - if ( self:_call_handler("OnBefore" .. to, params ) ~= false ) then - - self:T3( { onafter = "onafter" .. EventName, callback = self["onafter" .. EventName] } ) - self:_call_handler("onafter" .. EventName, params) - - self:T3( { On = "OnAfter" .. EventName, callback = self["OnAfter" .. EventName] } ) - ReturnValues = self:_call_handler("OnAfter" .. EventName, params ) - end + self:_call_handler("onafter" .. EventName, params) + self:_call_handler("OnAfter" .. EventName, params) self:_call_handler("onstatechange", params) end - - return ReturnValues + else + self:E( "Cannot execute transition." ) + self:E( { From = self.current, Event = EventName, To = to, Can = Can } ) end return nil @@ -11249,7 +11391,6 @@ do -- FSM end function FSM:can(e) - self:E( { e, self.Events, self.Events[e] } ) local Event = self.Events[e] self:F3( { self.current, Event } ) local To = Event and Event.map[self.current] or Event.map['*'] @@ -11318,7 +11459,7 @@ do -- FSM_CONTROLLABLE end if self[handler] then - self:E( "Calling " .. handler ) + self:F3( "Calling " .. handler ) return xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler ) --return self[handler]( self, self.Controllable, unpack( params ) ) end @@ -11582,7 +11723,7 @@ do -- FSM_SET function FSM_SET:New( FSMSet ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET + self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET if FSMSet then self:Set( FSMSet ) @@ -11609,7 +11750,7 @@ do -- FSM_SET function FSM_SET:_call_handler( handler, params ) if self[handler] then - self:E( "Calling " .. handler ) + self:T( "Calling " .. handler ) return self[handler]( self, self.Set, unpack( params ) ) end end @@ -11641,7 +11782,6 @@ end -- FSM_SET -- === -- -- @module Object --- @author FlightControl --- The OBJECT class -- @type OBJECT @@ -11652,7 +11792,6 @@ OBJECT = { ObjectName = "", } - --- A DCSObject -- @type DCSObject -- @field id_ The ID of the controllable in DCS @@ -11661,10 +11800,11 @@ OBJECT = { -- @param #OBJECT self -- @param Dcs.DCSWrapper.Object#Object ObjectName The Object name -- @return #OBJECT self -function OBJECT:New( ObjectName ) +function OBJECT:New( ObjectName, Test ) local self = BASE:Inherit( self, BASE:New() ) self:F2( ObjectName ) self.ObjectName = ObjectName + return self end @@ -11736,7 +11876,6 @@ end -- === -- -- @module Identifiable --- @author FlightControl --- The IDENTIFIABLE class -- @type IDENTIFIABLE @@ -11958,7 +12097,6 @@ end -- === -- -- @module Positionable --- @author FlightControl --- The POSITIONABLE class -- @type POSITIONABLE @@ -11980,6 +12118,7 @@ POSITIONABLE = { function POSITIONABLE:New( PositionableName ) local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) ) + self.PositionableName = PositionableName return self end @@ -11988,12 +12127,12 @@ end -- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPositionVec3() - self:F2( self.PositionableName ) + self:E( self.PositionableName ) local DCSPositionable = self:GetDCSObject() if DCSPositionable then - local PositionablePosition = DCSPositionable:getPosition() + local PositionablePosition = DCSPositionable:getPosition().p self:T3( PositionablePosition ) return PositionablePosition end @@ -12045,6 +12184,27 @@ function POSITIONABLE:GetPointVec2() return nil end +--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function POSITIONABLE:GetPointVec3() + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionableVec3 = self:GetPositionVec3() + + local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 ) + + self:T2( PositionablePointVec3 ) + return PositionablePointVec3 + end + + return nil +end + --- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission. -- @param Wrapper.Positionable#POSITIONABLE self @@ -12154,20 +12314,13 @@ end --- Returns true if the POSITIONABLE is in the air. +-- Polymorphic, is overridden in GROUP and UNIT. -- @param Wrapper.Positionable#POSITIONABLE self -- @return #boolean true if in the air. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:InAir() self:F2( self.PositionableName ) - local DCSPositionable = self:GetDCSObject() - - if DCSPositionable then - local PositionableInAir = DCSPositionable:inAir() - self:T3( PositionableInAir ) - return PositionableInAir - end - return nil end @@ -12480,7 +12633,6 @@ end -- === -- -- @module Controllable --- @author FlightControl --- The CONTROLLABLE class -- @type CONTROLLABLE @@ -12501,6 +12653,8 @@ function CONTROLLABLE:New( ControllableName ) local self = BASE:Inherit( self, POSITIONABLE:New( ControllableName ) ) self:F2( ControllableName ) self.ControllableName = ControllableName + + self.TaskScheduler = SCHEDULER:New( self ) return self end @@ -12522,6 +12676,58 @@ function CONTROLLABLE:_GetController() return nil end +-- Get methods + +--- Returns the UNITs wrappers of the DCS Units of the Controllable (default is a GROUP). +-- @param #CONTROLLABLE self +-- @return #list The UNITs wrappers. +function CONTROLLABLE:GetUnits() + self:F2( { self.ControllableName } ) + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + local DCSUnits = DCSControllable:getUnits() + local Units = {} + for Index, UnitData in pairs( DCSUnits ) do + Units[#Units+1] = UNIT:Find( UnitData ) + end + self:T3( Units ) + return Units + end + + return nil +end + + +--- Returns the health. Dead controllables have health <= 1.0. +-- @param #CONTROLLABLE self +-- @return #number The controllable health value (unit or group average). +-- @return #nil The controllable is not existing or alive. +function CONTROLLABLE:GetLife() + self:F2( self.ControllableName ) + + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + local UnitLife = 0 + local Units = self:GetUnits() + if #Units == 1 then + local Unit = Units[1] -- Wrapper.Unit#UNIT + UnitLife = Unit:GetLife() + else + local UnitLifeTotal = 0 + for UnitID, Unit in pairs( Units ) do + local Unit = Unit -- Wrapper.Unit#UNIT + UnitLifeTotal = UnitLifeTotal + Unit:GetLife() + end + UnitLife = UnitLifeTotal / #Units + end + return UnitLife + end + + return nil +end + -- Tasks @@ -12559,7 +12765,7 @@ function CONTROLLABLE:PushTask( DCSTask, WaitTime ) -- Controller:pushTask( DCSTask ) if WaitTime then - SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime ) + self.TaskScheduler:Schedule( Controller, Controller.pushTask, { DCSTask }, WaitTime ) else Controller:pushTask( DCSTask ) end @@ -12581,7 +12787,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime ) if DCSControllable then local Controller = self:_GetController() - self:E(Controller) + self:T3( Controller ) -- When a controllable SPAWNs, it takes about a second to get the controllable in the simulator. Setting tasks to unspawned controllables provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Controllable. @@ -12590,7 +12796,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime ) if not WaitTime then Controller:setTask( DCSTask ) else - SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime ) + self.TaskScheduler:Schedule( Controller, Controller.setTask, { DCSTask }, WaitTime ) end return self @@ -12661,6 +12867,10 @@ function CONTROLLABLE:TaskCombo( DCSTasks ) tasks = DCSTasks } } + + for TaskID, Task in ipairs( DCSTasks ) do + self:E( Task ) + end self:T3( { DCSTaskCombo } ) return DCSTaskCombo @@ -12846,19 +13056,24 @@ function CONTROLLABLE:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, Atta -- } local DCSTask - DCSTask = { id = 'AttackUnit', + DCSTask = { + id = 'AttackUnit', params = { + altitudeEnabled = true, unitId = AttackUnit:GetID(), - weaponType = WeaponType, - expend = WeaponExpend, - attackQty = AttackQty, - direction = Direction, - attackQtyLimit = AttackQtyLimit, - controllableAttack = ControllableAttack, - }, - }, + attackQtyLimit = AttackQtyLimit or false, + attackQty = AttackQty or 2, + expend = WeaponExpend or "Auto", + altitude = 2000, + directionEnabled = true, + groupAttack = true, + --weaponType = WeaponType or 1073741822, + direction = Direction or 0, + } + } - self:T3( { DCSTask } ) + self:E( DCSTask ) + return DCSTask end @@ -13851,7 +14066,7 @@ function CONTROLLABLE:Route( GoPoints ) local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } local Controller = self:_GetController() --Controller.setTask( Controller, MissionTask ) - SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 ) + self.TaskScheduler:Schedule( Controller, Controller.setTask, { MissionTask }, 1 ) return self end @@ -14479,7 +14694,7 @@ end -- @param #table WayPoints If WayPoints is given, then use the route. -- @return #CONTROLLABLE function CONTROLLABLE:WayPointInitialize( WayPoints ) - self:F( { WayPoint, WayPointIndex, WayPointFunction } ) + self:F( { WayPoints } ) if WayPoints then self.WayPoints = WayPoints @@ -14490,6 +14705,18 @@ function CONTROLLABLE:WayPointInitialize( WayPoints ) return self end +--- Get the current WayPoints set with the WayPoint functions( Note that the WayPoints can be nil, although there ARE waypoints). +-- @param #CONTROLLABLE self +-- @return #table WayPoints If WayPoints is given, then return the WayPoints structure. +function CONTROLLABLE:GetWayPoints() + self:F( ) + + if self.WayPoints then + return self.WayPoints + end + + return nil +end --- Registers a waypoint function that will be executed when the controllable moves over the WayPoint. -- @param #CONTROLLABLE self @@ -14558,10 +14785,7 @@ function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) return self end --- Message APIs - - ---- This module contains the GROUP class. +-- Message APIs--- This module contains the GROUP class. -- -- 1) @{Wrapper.Group#GROUP} class, extends @{Wrapper.Controllable#CONTROLLABLE} -- ============================================================= @@ -14768,6 +14992,23 @@ function GROUP:GetDCSObject() return nil end +--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3() + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p + self:T3( PositionablePosition ) + return PositionablePosition + end + + return nil +end --- Returns if the DCS Group is alive. -- When the group exists at run-time, this method will return true, otherwise false. @@ -14954,26 +15195,6 @@ function GROUP:GetInitialSize() return nil end ---- Returns the UNITs wrappers of the DCS Units of the DCS Group. --- @param #GROUP self --- @return #table The UNITs wrappers. -function GROUP:GetUnits() - self:F2( { self.GroupName } ) - local DCSGroup = self:GetDCSObject() - - if DCSGroup then - local DCSUnits = DCSGroup:getUnits() - local Units = {} - for Index, UnitData in pairs( DCSUnits ) do - Units[#Units+1] = UNIT:Find( UnitData ) - end - self:T3( Units ) - return Units - end - - return nil -end - --- Returns the DCS Units of the DCS Group. -- @param #GROUP self @@ -15445,6 +15666,31 @@ function GROUP:CalculateThreatLevelA2G() return MaxThreatLevelA2G end +--- Returns true if the first unit of the GROUP is in the air. +-- @param Wrapper.Group#GROUP self +-- @return #boolean true if in the first unit of the group is in the air. +-- @return #nil The GROUP is not existing or not alive. +function GROUP:InAir() + self:F2( self.GroupName ) + + local DCSGroup = self:GetDCSObject() + + if DCSGroup then + local DCSUnit = DCSGroup:getUnit(1) + if DCSUnit then + local GroupInAir = DCSGroup:getUnit(1):inAir() + self:T3( GroupInAir ) + return GroupInAir + end + end + + return nil +end + +function GROUP:OnReSpawn( ReSpawnFunction ) + + self.ReSpawnFunction = ReSpawnFunction +end --- This module contains the UNIT class. @@ -15916,6 +16162,25 @@ function UNIT:GetFuel() return nil end +--- Returns the UNIT in a UNIT list of one element. +-- @param #UNIT self +-- @return #list The UNITs wrappers. +function UNIT:GetUnits() + self:F2( { self.UnitName } ) + local DCSUnit = self:GetDCSObject() + + if DCSUnit then + local DCSUnits = DCSUnit:getUnits() + local Units = {} + Units[1] = UNIT:Find( DCSUnit ) + self:T3( Units ) + return Units + end + + return nil +end + + --- Returns the unit's health. Dead units has health <= 1.0. -- @param #UNIT self -- @return #number The Unit's health value. @@ -16248,6 +16513,24 @@ function UNIT:IsShip() return nil end +--- Returns true if the UNIT is in the air. +-- @param Wrapper.Positionable#UNIT self +-- @return #boolean true if in the air. +-- @return #nil The UNIT is not existing or alive. +function UNIT:InAir() + self:F2( self.UnitName ) + + local DCSUnit = self:GetDCSObject() + + if DCSUnit then + local UnitInAir = DCSUnit:inAir() + self:T3( UnitInAir ) + return UnitInAir + end + + return nil +end + --- This module contains the CLIENT class. -- -- 1) @{Wrapper.Client#CLIENT} class, extends @{Wrapper.Unit#UNIT} @@ -17350,7 +17633,7 @@ function SCORING:_EventOnHit( Event ) ):ToAll() self:ScoreCSV( InitPlayerName, "HIT_PENALTY", 1, -25, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) else - self.Players[InitPlayerName].Score = self.Players[InitPlayerName].Score + 10 + self.Players[InitPlayerName].Score = self.Players[InitPlayerName].Score + 1 self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Score = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Score + 1 self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].ScoreHit = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].ScoreHit + 1 MESSAGE:New( "Player '" .. InitPlayerName .. "' hit a target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. @@ -18266,6 +18549,7 @@ SPAWN = { SpawnAliasPrefix = nil, } + --- @type SPAWN.SpawnZoneTable -- @list SpawnZone @@ -18649,6 +18933,7 @@ function SPAWN:ReSpawn( SpawnIndex ) -- TODO: This logic makes DCS crash and i don't know why (yet). local SpawnGroup = self:GetGroupFromIndex( SpawnIndex ) + local WayPoints = SpawnGroup and SpawnGroup.WayPoints or nil if SpawnGroup then local SpawnDCSGroup = SpawnGroup:GetDCSObject() if SpawnDCSGroup then @@ -18656,7 +18941,18 @@ function SPAWN:ReSpawn( SpawnIndex ) end end - return self:SpawnWithIndex( SpawnIndex ) + local SpawnGroup = self:SpawnWithIndex( SpawnIndex ) + if SpawnGroup and WayPoints then + -- If there were WayPoints set, then Re-Execute those WayPoints! + SpawnGroup:WayPointInitialize( WayPoints ) + SpawnGroup:WayPointExecute( 1, 5 ) + end + + if SpawnGroup.ReSpawnFunction then + SpawnGroup:ReSpawnFunction() + end + + return SpawnGroup end --- Will spawn a group with a specified index number. @@ -21673,6 +21969,10 @@ function MISSILETRAINER:_EventShot( Event ) else -- TODO: some weapons don't know the target unit... Need to develop a workaround for this. SCHEDULER:New( TrainerWeapon, TrainerWeapon.destroy, {}, 2 ) + if ( TrainerWeapon:getTypeName() == "9M311" ) then + SCHEDULER:New( TrainerWeapon, TrainerWeapon.destroy, {}, 2 ) + else + end end end @@ -24052,43 +24352,72 @@ function DETECTION_AREAS:CreateDetectionSets() end ---- This module contains the AI_BALANCER class. +--- Single-Player:**No** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**All** -- **AI Balancing will replace in multi player missions +-- non-occupied human slots with AI groups, in order to provide an engaging simulation environment, +-- even when there are hardly any players in the mission.** +-- +-- ![Banner Image](..\Presentations\AI_Balancer\Dia1.JPG) +-- -- -- === -- --- 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET} --- =================================================================================== --- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many AI GROUPS as there are --- CLIENTS in a SET_CLIENT collection not occupied by players. --- The AI_BALANCER class manages internally a collection of AI management objects, which govern the behaviour --- of the underlying AI GROUPS. +-- # 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET} -- --- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM) --- and calls for each event the state transition methods providing the internal @{Core.Fsm#FSM_SET.Set} object containing the --- SET_GROUP and additional event parameters provided during the event. +-- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many replacement AI groups as there are +-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players. +-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions. -- --- 1.1) AI_BALANCER construction method --- --------------------------------------- --- Create a new AI_BALANCER object with the @{#AI_BALANCER.New} method: +-- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM). +-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods. +-- An explanation about state and event transition methods can be found in the @{FSM} module documentation. -- --- * @{#AI_BALANCER.New}: Creates a new AI_BALANCER object. +-- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following: +-- +-- * **@{#AI_BALANCER.OnAfterSpawned}**( AISet, From, Event, To, AIGroup ): Define to add extra logic when an AI is spawned. +-- +-- ## 1.1) AI_BALANCER construction +-- +-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New}() method: +-- +-- ## 1.2) AI_BALANCER is a FSM +-- +-- ![Process](..\Presentations\AI_Balancer\Dia13.JPG) +-- +-- ### 1.2.1) AI_BALANCER States +-- +-- * **Monitoring** ( Set ): Monitoring the Set if all AI is spawned for the Clients. +-- * **Spawning** ( Set, ClientName ): There is a new AI group spawned with ClientName as the name of reference. +-- * **Spawned** ( Set, AIGroup ): A new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes. +-- * **Destroying** ( Set, AIGroup ): The AI is being destroyed. +-- * **Returning** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. Handle this state to customize the return behaviour of the AI, if any. +-- +-- ### 1.2.2) AI_BALANCER Events +-- +-- * **Monitor** ( Set ): Every 10 seconds, the Monitor event is triggered to monitor the Set. +-- * **Spawn** ( Set, ClientName ): Triggers when there is a new AI group to be spawned with ClientName as the name of reference. +-- * **Spawned** ( Set, AIGroup ): Triggers when a new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes. +-- * **Destroy** ( Set, AIGroup ): The AI is being destroyed. +-- * **Return** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. -- --- 1.2) --- ---- --- * Add --- * Remove +-- ## 1.3) AI_BALANCER spawn interval for replacement AI -- --- 1.2) AI_BALANCER returns AI to Airbases --- ------------------------------------------ --- You can configure to have the AI to return to: +-- Use the method @{#AI_BALANCER.InitSpawnInterval}() to set the earliest and latest interval in seconds that is waited until a new replacement AI is spawned. -- --- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the home @{Wrapper.Airbase#AIRBASE}. --- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}. --- -- +-- ## 1.4) AI_BALANCER returns AI to Airbases +-- +-- By default, When a human player joins a slot that is AI_BALANCED, the AI group will be destroyed by default. +-- However, there are 2 additional options that you can use to customize the destroy behaviour. +-- When a human player joins a slot, you can configure to let the AI return to: +-- +-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Wrapper.Airbase#AIRBASE}. +-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Wrapper.Airbase#AIRBASE}. +-- +-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return, +-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed. +-- -- === -- --- **API CHANGE HISTORY** --- ====================== +-- # **API CHANGE HISTORY** -- -- The underlying change log documents the API changes. Please read this carefully. The following notation is used: -- @@ -24097,78 +24426,86 @@ end -- -- Hereby the change log: -- --- 2016-08-17: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval ) +-- 2017-01-17: There is still a problem with AI being destroyed, but not respawned. Need to check further upon that. -- --- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called! --- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods. +-- 2017-01-08: AI_BALANCER:**InitSpawnInterval( Earliest, Latest )** added. -- -- === -- --- AUTHORS and CONTRIBUTIONS --- ========================= +-- # **AUTHORS and CONTRIBUTIONS** -- -- ### Contributions: -- --- * **Dutch_Baron (James)**: Who you can search on the Eagle Dynamics Forums. --- Working together with James has resulted in the creation of the AI_BALANCER class. --- James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) --- --- * **SNAFU**: --- Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. --- None of the script code has been used however within the new AI_BALANCER moose class. +-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) +-- * **SNAFU**: Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. None of the script code has been used however within the new AI_BALANCER moose class. -- -- ### Authors: -- --- * FlightControl: Framework Design & Programming +-- * FlightControl: Framework Design & Programming and Documentation. -- -- @module AI_Balancer - - --- AI_BALANCER class -- @type AI_BALANCER -- @field Core.Set#SET_CLIENT SetClient +-- @field Functional.Spawn#SPAWN SpawnAI +-- @field Wrapper.Group#GROUP Test -- @extends Core.Fsm#FSM_SET AI_BALANCER = { ClassName = "AI_BALANCER", PatrolZones = {}, AIGroups = {}, + Earliest = 5, -- Earliest a new AI can be spawned is in 5 seconds. + Latest = 60, -- Latest a new AI can be spawned is in 60 seconds. } + + --- Creates a new AI_BALANCER object -- @param #AI_BALANCER self -- @param Core.Set#SET_CLIENT SetClient A SET\_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player). -- @param Functional.Spawn#SPAWN SpawnAI The default Spawn object to spawn new AI Groups when needed. -- @return #AI_BALANCER --- @usage --- -- Define a new AI_BALANCER Object. function AI_BALANCER:New( SetClient, SpawnAI ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- Core.Fsm#FSM_SET + local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- AI.AI_Balancer#AI_BALANCER self:SetStartState( "None" ) - self:AddTransition( "*", "Start", "Monitoring" ) self:AddTransition( "*", "Monitor", "Monitoring" ) self:AddTransition( "*", "Spawn", "Spawning" ) self:AddTransition( "Spawning", "Spawned", "Spawned" ) self:AddTransition( "*", "Destroy", "Destroying" ) self:AddTransition( "*", "Return", "Returning" ) - self:AddTransition( "*", "End", "End" ) - self:AddTransition( "*", "Dead", "End" ) - - self.SetClient = SetClient + self.SetClient:FilterOnce() self.SpawnAI = SpawnAI + + self.SpawnQueue = {} + self.ToNearestAirbase = false self.ToHomeAirbase = false - self:__Start( 1 ) + self:__Monitor( 1 ) return self end +--- Sets the earliest to the latest interval in seconds how long AI_BALANCER will wait to spawn a new AI. +-- Provide 2 identical seconds if the interval should be a fixed amount of seconds. +-- @param #AI_BALANCER self +-- @param #number Earliest The earliest a new AI can be spawned in seconds. +-- @param #number Latest The latest a new AI can be spawned in seconds. +-- @return self +function AI_BALANCER:InitSpawnInterval( Earliest, Latest ) + + self.Earliest = Earliest + self.Latest = Latest + + return self +end + --- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}. -- @param #AI_BALANCER self -- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}. @@ -24196,23 +24533,27 @@ end function AI_BALANCER:onenterSpawning( SetGroup, From, Event, To, ClientName ) -- OK, Spawn a new group from the default SpawnAI object provided. - local AIGroup = self.SpawnAI:Spawn() + local AIGroup = self.SpawnAI:Spawn() -- Wrapper.Group#GROUP AIGroup:E( "Spawning new AIGroup" ) --TODO: need to rework UnitName thing ... SetGroup:Add( ClientName, AIGroup ) + self.SpawnQueue[ClientName] = nil -- Fire the Spawned event. The first parameter is the AIGroup just Spawned. -- Mission designers can catch this event to bind further actions to the AIGroup. - self:Spawned( AIGroup ) + self:Spawned( AIGroup ) end --- @param #AI_BALANCER self -- @param Core.Set#SET_GROUP SetGroup -- @param Wrapper.Group#GROUP AIGroup -function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, AIGroup ) +function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup ) AIGroup:Destroy() + SetGroup:Flush() + SetGroup:Remove( ClientName ) + SetGroup:Flush() end --- @param #AI_BALANCER self @@ -24244,10 +24585,13 @@ end --- @param #AI_BALANCER self function AI_BALANCER:onenterMonitoring( SetGroup ) + self:T2( { self.SetClient:Count() } ) + --self.SetClient:Flush() + self.SetClient:ForEachClient( --- @param Wrapper.Client#CLIENT Client function( Client ) - self:E(Client.ClientName) + self:T3(Client.ClientName) local AIGroup = self.Set:Get( Client.UnitName ) -- Wrapper.Group#GROUP if Client:IsAlive() then @@ -24255,7 +24599,7 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) if AIGroup and AIGroup:IsAlive() == true then if self.ToNearestAirbase == false and self.ToHomeAirbase == false then - self:Destroy( AIGroup ) + self:Destroy( Client.UnitName, AIGroup ) else -- We test if there is no other CLIENT within the self.ReturnTresholdRange of the first unit of the AI group. -- If there is a CLIENT, the AI stays engaged and will not return. @@ -24264,16 +24608,16 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) local PlayerInRange = { Value = false } local RangeZone = ZONE_RADIUS:New( 'RangeZone', AIGroup:GetVec2(), self.ReturnTresholdRange ) - self:E( RangeZone ) + self:T2( RangeZone ) _DATABASE:ForEachPlayer( --- @param Wrapper.Unit#UNIT RangeTestUnit function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange ) - self:E( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } ) + self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } ) if RangeTestUnit:IsInZone( RangeZone ) == true then - self:E( "in zone" ) + self:T2( "in zone" ) if RangeTestUnit:GetCoalition() ~= AIGroup:GetCoalition() then - self:E( "in range" ) + self:T2( "in range" ) PlayerInRange.Value = true end end @@ -24294,9 +24638,13 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) end else if not AIGroup or not AIGroup:IsAlive() == true then - self:E("client not alive") - self:Spawn( Client.UnitName ) - self:E("text after spawn") + self:T( "Client " .. Client.UnitName .. " not alive." ) + if not self.SpawnQueue[Client.UnitName] then + -- Spawn a new AI taking into account the spawn interval Earliest, Latest + self:__Spawn( math.random( self.Earliest, self.Latest ), Client.UnitName ) + self.SpawnQueue[Client.UnitName] = true + self:E( "New AI Spawned for Client " .. Client.UnitName ) + end end end return true @@ -24308,113 +24656,125 @@ end ---- (AI) (FSM) Make AI patrol routes or zones. +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Air Patrolling or Staging.** +-- +-- ![Banner Image](..\Presentations\AI_Patrol\Dia1.JPG) +-- -- -- === -- --- 1) @{#AI_PATROLZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE} --- ================================================================ --- The @{#AI_PATROLZONE} class implements the core functions to patrol a @{Zone} by an AIR @{Controllable} @{Group}. --- The patrol algorithm works that for each airplane patrolling, upon arrival at the patrol zone, --- a random point is selected as the route point within the 3D space, within the given boundary limits. --- The airplane will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. --- Upon arrival at the random 3D point, a new 3D random point will be selected within the patrol zone using the given limits. --- This cycle will continue until a fuel treshold has been reached by the airplane. +-- # 1) @{#AI_PATROL_ZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE} +-- +-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia3.JPG) +-- +-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia9.JPG) +-- +---- Note that the enemy is not engaged! To model enemy engagement, either tailor the **Detected** event, or +-- use derived AI_ classes to model AI offensive or defensive behaviour. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. -- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. -- --- 1.1) AI_PATROLZONE constructor: --- ---------------------------- +-- ![Process](..\Presentations\AI_Patrol\Dia11.JPG) +-- +-- ## 1.1) AI_PATROL_ZONE constructor -- --- * @{#AI_PATROLZONE.New}(): Creates a new AI_PATROLZONE object. +-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object. -- --- 1.2) AI_PATROLZONE state machine: --- ---------------------------------- --- The AI_PATROLZONE is a state machine: it manages the different events and states of the AIControllable it is controlling. +-- ## 1.2) AI_PATROL_ZONE is a FSM -- --- ### 1.2.1) AI_PATROLZONE Events: +-- ![Process](..\Presentations\AI_Patrol\Dia2.JPG) -- --- * @{#AI_PATROLZONE.Route}( AIControllable ): A new 3D route point is selected and the AIControllable will fly towards that point with the given speed. --- * @{#AI_PATROLZONE.Patrol}( AIControllable ): The AIControllable reports it is patrolling. This event is called every 30 seconds. --- * @{#AI_PATROLZONE.RTB}( AIControllable ): The AIControllable will report return to base. --- * @{#AI_PATROLZONE.End}( AIControllable ): The end of the AI_PATROLZONE process. --- * @{#AI_PATROLZONE.Dead}( AIControllable ): The AIControllable is dead. The AI_PATROLZONE process will be ended. +-- ### 1.2.1) AI_PATROL_ZONE States -- --- ### 1.2.2) AI_PATROLZONE States: +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Returning** ( Group ): The AI is returning to Base.. -- --- * **Route**: A new 3D route point is selected and the AIControllable will fly towards that point with the given speed. --- * **Patrol**: The AIControllable is patrolling. This state is set every 30 seconds, so every 30 seconds, a state transition method can be used. --- * **RTB**: The AIControllable reports it wants to return to the base. --- * **Dead**: The AIControllable is dead ... --- * **End**: The process has come to an end. --- --- ### 1.2.3) AI_PATROLZONE state transition methods: +-- ### 1.2.2) AI_PATROL_ZONE Events -- --- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state. --- There are 2 moments when state transition methods will be called by the state machine: --- --- * **Before** the state transition. --- The state transition method needs to start with the name **OnBefore + the name of the state**. --- If the state transition method returns false, then the processing of the state transition will not be done! --- If you want to change the behaviour of the AIControllable at this event, return false, --- but then you'll need to specify your own logic using the AIControllable! --- --- * **After** the state transition. --- The state transition method needs to start with the name **OnAfter + the name of the state**. --- These state transition methods need to provide a return value, which is specified at the function description. --- --- An example how to manage a state transition for an AI_PATROLZONE object **Patrol** for the state **RTB**: --- --- local PatrolZoneGroup = GROUP:FindByName( "Patrol Zone" ) --- local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) --- --- local PatrolSpawn = SPAWN:New( "Patrol Group" ) --- local PatrolGroup = PatrolSpawn:Spawn() --- --- local Patrol = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 300, 600 ) --- Patrol:SetControllable( PatrolGroup ) --- Patrol:ManageFuel( 0.2, 60 ) --- --- **OnBefore**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **before** the RTB default action is processed by the AI_PATROLZONE object. --- --- --- State transition function for the AI_PATROLZONE **Patrol** object --- -- @param #AI_PATROLZONE self --- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup --- -- @return #boolean If false is returned, then the OnAfter state transition method will not be called. --- function Patrol:OnBeforeRTB( AIGroup ) --- AIGroup:MessageToRed( "Returning to base", 20 ) --- end --- --- **OnAfter**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **after** the RTB default action was processed by the AI_PATROLZONE object. --- --- --- State transition function for the AI_PATROLZONE **Patrol** object --- -- @param #AI_PATROLZONE self --- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup --- -- @return #Wrapper.Controllable#CONTROLLABLE The new AIGroup object that is set to be patrolling the zone. --- function Patrol:OnAfterRTB( AIGroup ) --- return PatrolSpawn:Spawn() --- end +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- --- 1.3) Manage the AI_PATROLZONE parameters: --- ------------------------------------------ --- The following methods are available to modify the parameters of a AI_PATROLZONE object: +-- ## 1.3) Set or Get the AI controllable -- --- * @{#AI_PATROLZONE.SetControllable}(): Set the AIControllable. --- * @{#AI_PATROLZONE.GetControllable}(): Get the AIControllable. --- * @{#AI_PATROLZONE.SetSpeed}(): Set the patrol speed of the AI, for the next patrol. --- * @{#AI_PATROLZONE.SetAltitude}(): Set altitude of the AI, for the next patrol. +-- * @{#AI_PATROL_ZONE.SetControllable}(): Set the AIControllable. +-- * @{#AI_PATROL_ZONE.GetControllable}(): Get the AIControllable. +-- +-- ## 1.4) Set the Speed and Altitude boundaries of the AI controllable +-- +-- * @{#AI_PATROL_ZONE.SetSpeed}(): Set the patrol speed boundaries of the AI, for the next patrol. +-- * @{#AI_PATROL_ZONE.SetAltitude}(): Set altitude boundaries of the AI, for the next patrol. -- --- 1.3) Manage the out of fuel in the AI_PATROLZONE: --- ---------------------------------------------- --- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base. +-- ## 1.5) Manage the detection process of the AI controllable +-- +-- The detection process of the AI controllable can be manipulated. +-- Detection requires an amount of CPU power, which has an impact on your mission performance. +-- Only put detection on when absolutely necessary, and the frequency of the detection can also be set. +-- +-- * @{#AI_PATROL_ZONE.SetDetectionOn}(): Set the detection on. The AI will detect for targets. +-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. +-- +-- The detection frequency can be set with @{#AI_PATROL_ZONE.SetDetectionInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection. +-- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI. +-- +-- The detection can be filtered to potential targets in a specific zone. +-- Use the method @{#AI_PATROL_ZONE.SetDetectionZone}() to set the zone where targets need to be detected. +-- Note that when the zone is too far away, or the AI is not heading towards the zone, or the AI is too high, no targets may be detected +-- according the weather conditions. +-- +-- ## 1.6) Manage the "out of fuel" in the AI_PATROL_ZONE +-- +-- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. --- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE. --- Once the time is finished, the old AIControllable will return to the base. --- Use the method @{#AI_PATROLZONE.ManageFuel}() to have this proces in place. +-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, +-- while a new AI is targetted to the AI_PATROL_ZONE. +-- Once the time is finished, the old AI will return to the base. +-- Use the method @{#AI_PATROL_ZONE.ManageFuel}() to have this proces in place. +-- +-- ## 1.7) Manage "damage" behaviour of the AI in the AI_PATROL_ZONE +-- +-- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on. +-- Therefore, when the damage treshold is reached, the AI will return immediately to the home base (RTB). +-- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this proces in place. -- -- ==== -- --- **API CHANGE HISTORY** --- ====================== +-- # **OPEN ISSUES** +-- +-- 2017-01-17: When Spawned AI is located at an airbase, it will be routed first back to the airbase after take-off. +-- +-- 2016-01-17: +-- -- Fixed problem with AI returning to base too early and unexpected. +-- -- ReSpawning of AI will reset the AI_PATROL and derived classes. +-- -- Checked the correct workings of SCHEDULER, and it DOES work correctly. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** -- -- The underlying change log documents the API changes. Please read this carefully. The following notation is used: -- @@ -24423,87 +24783,283 @@ end -- -- Hereby the change log: -- +-- 2017-01-17: Rename of class: **AI\_PATROL\_ZONE** is the new name for the old _AI\_PATROLZONE_. +-- +-- 2017-01-15: Complete revision. AI_PATROL_ZONE is the base class for other AI_PATROL like classes. +-- -- 2016-09-01: Initial class and API. -- -- === -- --- AUTHORS and CONTRIBUTIONS --- ========================= +-- # **AUTHORS and CONTRIBUTIONS** -- -- ### Contributions: -- --- * **DutchBaron**: Testing. --- * **Pikey**: Testing and API concept review. +-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. -- -- ### Authors: -- -- * **FlightControl**: Design & Programming. -- --- --- @module Patrol +-- @module AI_Patrol --- State Transition Functions - ---- OnBefore State Transition Function --- @function [parent=#AI_PATROLZONE] OnBeforeRoute --- @param #AI_PATROLZONE self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- OnAfter State Transition Function --- @function [parent=#AI_PATROLZONE] OnAfterRoute --- @param #AI_PATROLZONE self --- @param Wrapper.Controllable#CONTROLLABLE Controllable - - - ---- AI_PATROLZONE class --- @type AI_PATROLZONE +--- AI_PATROL_ZONE class +-- @type AI_PATROL_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @field Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @field Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @field Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @field Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @field Functional.Spawn#SPAWN CoordTest -- @extends Core.Fsm#FSM_CONTROLLABLE -AI_PATROLZONE = { - ClassName = "AI_PATROLZONE", +AI_PATROL_ZONE = { + ClassName = "AI_PATROL_ZONE", } - - ---- Creates a new AI_PATROLZONE object --- @param #AI_PATROLZONE self +--- Creates a new AI_PATROL_ZONE object +-- @param #AI_PATROL_ZONE self -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. --- @return #AI_PATROLZONE self +-- @return #AI_PATROL_ZONE self -- @usage --- -- Define a new AI_PATROLZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. +-- -- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. -- PatrolZone = ZONE:New( 'PatrolZone' ) -- PatrolSpawn = SPAWN:New( 'Patrol Group' ) --- PatrolArea = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 600, 900 ) -function AI_PATROLZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) +-- PatrolArea = AI_PATROL_ZONE:New( PatrolZone, 3000, 6000, 600, 900 ) +function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_CONTROLLABLE + local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_PATROL_ZONE - self:SetStartState( "None" ) - self:AddTransition( "*", "Start", "Route" ) - self:AddTransition( "*", "Route", "Route" ) - self:AddTransition( { "Patrol", "Route" }, "Patrol", "Patrol" ) - self:AddTransition( "Patrol", "RTB", "RTB" ) - self:AddTransition( "*", "End", "End" ) - self:AddTransition( "*", "Dead", "End" ) self.PatrolZone = PatrolZone self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude self.PatrolMinSpeed = PatrolMinSpeed self.PatrolMaxSpeed = PatrolMaxSpeed + + self:SetDetectionOn() + self.CheckStatus = true + + self:ManageFuel( .2, 60 ) + self:ManageDamage( 1 ) + + self:SetDetectionInterval( 30 ) + + self.DetectedUnits = {} -- This table contains the targets detected during patrol. + + self:SetStartState( "None" ) + + self:AddTransition( "None", "Start", "Patrolling" ) + +--- OnBefore Transition Handler for Event Start. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeStart +-- @param #AI_PATROL_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 Start. +-- @function [parent=#AI_PATROL_ZONE] OnAfterStart +-- @param #AI_PATROL_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 Start. +-- @function [parent=#AI_PATROL_ZONE] Start +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Start. +-- @function [parent=#AI_PATROL_ZONE] __Start +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Patrolling. +-- @function [parent=#AI_PATROL_ZONE] OnLeavePatrolling +-- @param #AI_PATROL_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 Patrolling. +-- @function [parent=#AI_PATROL_ZONE] OnEnterPatrolling +-- @param #AI_PATROL_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( "Patrolling", "Route", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Route. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeRoute +-- @param #AI_PATROL_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 Route. +-- @function [parent=#AI_PATROL_ZONE] OnAfterRoute +-- @param #AI_PATROL_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 Route. +-- @function [parent=#AI_PATROL_ZONE] Route +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Route. +-- @function [parent=#AI_PATROL_ZONE] __Route +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Status", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Status. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeStatus +-- @param #AI_PATROL_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 Status. +-- @function [parent=#AI_PATROL_ZONE] OnAfterStatus +-- @param #AI_PATROL_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 Status. +-- @function [parent=#AI_PATROL_ZONE] Status +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Status. +-- @function [parent=#AI_PATROL_ZONE] __Status +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Detect", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Detect. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeDetect +-- @param #AI_PATROL_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 Detect. +-- @function [parent=#AI_PATROL_ZONE] OnAfterDetect +-- @param #AI_PATROL_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 Detect. +-- @function [parent=#AI_PATROL_ZONE] Detect +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Detect. +-- @function [parent=#AI_PATROL_ZONE] __Detect +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Detected", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Detected. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeDetected +-- @param #AI_PATROL_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 Detected. +-- @function [parent=#AI_PATROL_ZONE] OnAfterDetected +-- @param #AI_PATROL_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 Detected. +-- @function [parent=#AI_PATROL_ZONE] Detected +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Detected. +-- @function [parent=#AI_PATROL_ZONE] __Detected +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "RTB", "Returning" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event RTB. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeRTB +-- @param #AI_PATROL_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 RTB. +-- @function [parent=#AI_PATROL_ZONE] OnAfterRTB +-- @param #AI_PATROL_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 RTB. +-- @function [parent=#AI_PATROL_ZONE] RTB +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event RTB. +-- @function [parent=#AI_PATROL_ZONE] __RTB +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Returning. +-- @function [parent=#AI_PATROL_ZONE] OnLeaveReturning +-- @param #AI_PATROL_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 Returning. +-- @function [parent=#AI_PATROL_ZONE] OnEnterReturning +-- @param #AI_PATROL_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( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + return self end @@ -24511,11 +25067,11 @@ end --- Sets (modifies) the minimum and maximum speed of the patrol. --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) self.PatrolMinSpeed = PatrolMinSpeed @@ -24525,39 +25081,92 @@ end --- Sets the floor and ceiling altitude of the patrol. --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @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. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude end +-- * @{#AI_PATROL_ZONE.SetDetectionOn}(): Set the detection on. The AI will detect for targets. +-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. +--- Set the detection on. The AI will detect for targets. +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionOn() + self:F2() + + self.DetectUnits = true +end ---- @param Wrapper.Controllable#CONTROLLABLE AIControllable -function _NewPatrolRoute( AIControllable ) +--- Set the detection off. The AI will NOT detect for targets. +-- However, the list of already detected targets will be kept and can be enquired! +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionOff() + self:F2() + + self.DetectUnits = false +end - AIControllable:T( "NewPatrolRoute" ) - local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROLZONE - PatrolZone:__Route( 1 ) +--- Set the interval in seconds between each detection executed by the AI. +-- The list of already detected targets will be kept and updated. +-- Newly detected targets will be added, but already detected targets that were +-- not detected in this cycle, will NOT be removed! +-- The default interval is 30 seconds. +-- @param #AI_PATROL_ZONE self +-- @param #number Seconds The interval in seconds. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionInterval( Seconds ) + self:F2() + + if Seconds then + self.DetectInterval = Seconds + else + self.DetectInterval = 30 + end +end + +--- Set the detection zone where the AI is detecting targets. +-- @param #AI_PATROL_ZONE self +-- @param Core.Zone#ZONE DetectionZone The zone where to detect targets. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionZone( DetectionZone ) + self:F2() + + if DetectionZone then + self.DetectZone = DetectionZone + else + self.DetectZone = nil + end +end + +--- Gets a list of @{Wrapper.Unit#UNIT}s that were detected by the AI. +-- No filtering is applied, so, ANY detected UNIT can be in this list. +-- It is up to the mission designer to use the @{Unit} class and methods to filter the targets. +-- @param #AI_PATROL_ZONE self +-- @return #table The list of @{Wrapper.Unit#UNIT}s +function AI_PATROL_ZONE:GetDetectedUnits() + self:F2() + + return self.DetectedUnits end - - ---- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base. +--- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. --- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE. --- Once the time is finished, the old AIControllable will return to the base. --- @param #AI_PATROLZONE self +-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROL_ZONE. +-- Once the time is finished, the old AI will return to the base. +-- @param #AI_PATROL_ZONE self -- @param #number PatrolFuelTresholdPercentage The treshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel. -- @param #number PatrolOutOfFuelOrbitTime The amount of seconds the out of fuel AIControllable will orbit before returning to the base. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime ) self.PatrolManageFuel = true self.PatrolFuelTresholdPercentage = PatrolFuelTresholdPercentage @@ -24566,60 +25175,165 @@ function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuel return self end +--- When the AI is damaged beyond a certain treshold, it is required that the AI returns to the home base. +-- However, damage cannot be foreseen early on. +-- Therefore, when the damage treshold is reached, +-- the AI will return immediately to the home base (RTB). +-- Note that for groups, the average damage of the complete group will be calculated. +-- So, in a group of 4 airplanes, 2 lost and 2 with damage 0.2, the damage treshold will be 0.25. +-- @param #AI_PATROL_ZONE self +-- @param #number PatrolDamageTreshold The treshold in percentage (between 0 and 1) when the AI is considered to be damaged. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:ManageDamage( PatrolDamageTreshold ) + + self.PatrolManageDamage = true + self.PatrolDamageTreshold = PatrolDamageTreshold + + return self +end + --- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. --- @param #AI_PATROLZONE self --- @return #AI_PATROLZONE self -function AI_PATROLZONE:onenterRoute() +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_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_PATROL_ZONE:onafterStart( Controllable, From, Event, To ) + self:F2() + + self:__Route( 5 ) -- Route to the patrol point. The asynchronous trigger is important, because a spawned group and units takes at least one second to come live. + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every 30 seconds. + + Controllable:OptionROEHoldFire() + Controllable:OptionROTVertical() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + + +--- @param #AI_PATROL_ZONE self +--- @param Wrapper.Controllable#CONTROLLABLE Controllable +function AI_PATROL_ZONE:onbeforeDetect( Controllable, From, Event, To ) + + return self.DetectUnits +end + +--- @param #AI_PATROL_ZONE self +--- @param Wrapper.Controllable#CONTROLLABLE Controllable +function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To ) + + local Detected = false + + local DetectedTargets = Controllable:GetDetectedTargets() + for TargetID, Target in pairs( DetectedTargets or {} ) do + local TargetObject = Target.object + self:T( TargetObject ) + if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then + + local TargetUnit = UNIT:Find( TargetObject ) + local TargetUnitName = TargetUnit:GetName() + + if self.DetectionZone then + if TargetUnit:IsInZone( self.DetectionZone ) then + self:T( {"Detected ", TargetUnit } ) + self.DetectedUnits[TargetUnit] = TargetUnit + Detected = true + end + else + self.DetectedUnits[TargetUnit] = TargetUnit + Detected = true + end + end + end + + if Detected == true then + self:__Detected( 1 ) + end + + self:__Detect( self.DetectInterval ) +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +-- This statis method is called from the route path within the last task at the last waaypoint of the Controllable. +-- Note that this method is required, as triggers the next route when patrolling for the Controllable. +function AI_PATROL_ZONE:_NewPatrolRoute( AIControllable ) + + local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROL_ZONE + PatrolZone:__Route( 1 ) +end + + +--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +-- @param #AI_PATROL_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_PATROL_ZONE:onafterRoute( Controllable, From, Event, To ) self:F2() - local PatrolRoute = {} + -- When RTB, don't allow anymore the routing. + if From == "RTB" then + return + end + if self.Controllable:IsAlive() then - --- Determine if the AIControllable is within the PatrolZone. + -- Determine if the AIControllable is within the PatrolZone. -- If not, make a waypoint within the to that the AIControllable will fly at maximum speed to that point. --- --- Calculate the current route point. --- local CurrentVec2 = self.Controllable:GetVec2() --- local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() --- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) --- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( --- POINT_VEC3.RoutePointAltType.BARO, --- POINT_VEC3.RoutePointType.TurningPoint, --- POINT_VEC3.RoutePointAction.TurningPoint, --- ToPatrolZoneSpeed, --- true --- ) --- --- PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + local PatrolRoute = {} + + -- Calculate the current route point of the controllable as the start point of the route. + -- However, when the controllable is not in the air, + -- the controllable current waypoint is probably the airbase... + -- Thus, if we would take the current waypoint as the startpoint, upon take-off, the controllable flies + -- immediately back to the airbase, and this is not correct. + -- Therefore, when on a runway, get as the current route point a random point within the PatrolZone. + -- This will make the plane fly immediately to the patrol zone. - self:T2( PatrolRoute ) - - if self.Controllable:IsNotInZone( self.PatrolZone ) then - --- Find a random 2D point in PatrolZone. - local ToPatrolZoneVec2 = self.PatrolZone:GetRandomVec2() - self:T2( ToPatrolZoneVec2 ) - - --- Define Speed and Altitude. - local ToPatrolZoneAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ) + if self.Controllable:InAir() == false then + self:E( "Not in the air, finding route path within PatrolZone" ) + 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed - self:T2( ToPatrolZoneSpeed ) - - --- Obtain a 3D @{Point} from the 2D point + altitude. - local ToPatrolZonePointVec3 = POINT_VEC3:New( ToPatrolZoneVec2.x, ToPatrolZoneAltitude, ToPatrolZoneVec2.y ) - - --- Create a route point of type air. - local ToPatrolZoneRoutePoint = ToPatrolZonePointVec3:RoutePointAir( - POINT_VEC3.RoutePointAltType.BARO, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToPatrolZoneSpeed, - true - ) - - PatrolRoute[#PatrolRoute+1] = ToPatrolZoneRoutePoint - - end + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TakeOffParking, + POINT_VEC3.RoutePointAction.FromParkingArea, + ToPatrolZoneSpeed, + true + ) + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + else + self:E( "In the air, finding route path within PatrolZone" ) + 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToPatrolZoneSpeed, + true + ) + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + end + --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. @@ -24644,6 +25358,8 @@ function AI_PATROLZONE:onenterRoute() true ) + --self.CoordTest:SpawnFromVec3( ToTargetPointVec3:GetVec3() ) + --ToTargetPointVec3:SmokeRed() PatrolRoute[#PatrolRoute+1] = ToTargetRoutePoint @@ -24653,25 +25369,31 @@ function AI_PATROLZONE:onenterRoute() --- Do a trick, link the NewPatrolRoute function of the PATROLGROUP object to the AIControllable in a temporary variable ... self.Controllable:SetState( self.Controllable, "PatrolZone", self ) - self.Controllable:WayPointFunction( #PatrolRoute, 1, "_NewPatrolRoute" ) + self.Controllable:WayPointFunction( #PatrolRoute, 1, "AI_PATROL_ZONE:_NewPatrolRoute" ) - --- NOW ACT_ROUTE THE GROUP! - self.Controllable:WayPointExecute( 1 ) - - self:__Patrol( 30 ) + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) end - + end +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onbeforeStatus() ---- @param #AI_PATROLZONE self -function AI_PATROLZONE:onenterPatrol() + return self.CheckStatus +end + +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onafterStatus() self:F2() if self.Controllable and self.Controllable:IsAlive() then + local RTB = false + local Fuel = self.Controllable:GetUnit(1):GetFuel() if Fuel < self.PatrolFuelTresholdPercentage then + self:E( self.Controllable:GetName() .. " is out of fuel:" .. Fuel .. ", RTB!" ) local OldAIControllable = self.Controllable local AIControllableTemplate = self.Controllable:GetTemplate() @@ -24679,14 +25401,1145 @@ function AI_PATROLZONE:onenterPatrol() local TimedOrbitTask = OldAIControllable:TaskControlled( OrbitTask, OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil ) ) OldAIControllable:SetTask( TimedOrbitTask, 10 ) + RTB = true + else + end + + -- TODO: Check GROUP damage function. + local Damage = self.Controllable:GetLife() + if Damage <= self.PatrolDamageTreshold then + self:E( self.Controllable:GetName() .. " is damaged:" .. Damage .. ", RTB!" ) + RTB = true + end + + if RTB == true then self:RTB() else - self:__Patrol( 30 ) -- Execute the Patrol event after 30 seconds. + self:__Status( 30 ) -- Execute the Patrol event after 30 seconds. end end +end + +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onafterRTB() + self:F2() + + if self.Controllable and self.Controllable:IsAlive() then + + self:SetDetectionOff() + self.CheckStatus = false + + local PatrolRoute = {} + + --- 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToPatrolZoneSpeed, + true + ) + + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( PatrolRoute ) + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 1 ) + + end + +end +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.** +-- +-- ![Banner Image](..\Presentations\AI_Cas\Dia1.JPG) +-- +-- +-- === +-- +-- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE} +-- +-- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour. +-- +-- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}. +-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. +-- +-- ![HoldAndEngage](..\Presentations\AI_Cas\Dia3.JPG) +-- +-- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event. +-- +-- ![Start Event](..\Presentations\AI_Cas\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_Cas\Dia5.JPG) +-- +-- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone. +-- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia6.JPG) +-- +-- The AI will detect the targets and will only destroy the targets within the Engage Zone. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia7.JPG) +-- +-- Every target that is destroyed, is reported< by the AI. +-- +-- ![Engage Event](..\Presentations\AI_Cas\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_Cas\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_Cas\Dia10.JPG) +-- +-- When the AI has accomplished the CAS, it will fly back to the Patrol Zone. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia11.JPG) +-- +-- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone. +-- It can be notified to go RTB through the **RTB** event. +-- +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia12.JPG) +-- +-- # 1.1) AI_CAS_ZONE constructor +-- +-- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object. +-- +-- ## 1.2) AI_CAS_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_Cas\Dia2.JPG) +-- +-- ### 1.2.1) AI_CAS_ZONE States +-- +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Engaging** ( Group ): The AI is engaging the targets in the Engage Zone, executing CAS. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 1.2.2) AI_CAS_ZONE Events +-- +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** +-- +-- The underlying change log documents the API changes. Please read this carefully. The following notation is used: +-- +-- * **Added** parts are expressed in bold type face. +-- * _Removed_ parts are expressed in italic type face. +-- +-- Hereby the change log: +-- +-- 2017-01-15: Initial class and API. +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Cas + + +--- AI_CAS_ZONE class +-- @type AI_CAS_ZONE +-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @extends AI.AI_Patrol#AI_CAS_ZONE +AI_CAS_ZONE = { + ClassName = "AI_CAS_ZONE", +} + + + +--- Creates a new AI_CAS_ZONE object +-- @param #AI_CAS_ZONE self +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. +-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @param Core.Zone#ZONE EngageZone +-- @return #AI_CAS_ZONE self +function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE + + self.EngageZone = EngageZone + self.Accomplished = false + + self:SetDetectionZone( self.EngageZone ) + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Engage. + -- @function [parent=#AI_CAS_ZONE] OnAfterEngage + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAS_ZONE] Engage + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAS_ZONE] __Engage + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @return #boolean Return false to cancel Transition. + +--- OnEnter Transition Handler for State Engaging. +-- @function [parent=#AI_CAS_ZONE] OnEnterEngaging +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_CAS_ZONE] OnBeforeFired + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Fired. + -- @function [parent=#AI_CAS_ZONE] OnAfterFired + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAS_ZONE] Fired + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAS_ZONE] __Fired + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] Destroy + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] __Destroy + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Abort. + -- @function [parent=#AI_CAS_ZONE] OnAfterAbort + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAS_ZONE] Abort + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAS_ZONE] __Abort + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] Accomplish + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] __Accomplish + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets. +-- @param #AI_CAS_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS. +-- @return #AI_CAS_ZONE self +function AI_CAS_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + + + +--- onafter State Transition for Event Start. +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To ) + + + self:Route() + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone. + + self:EventOnDead( self.OnDead ) + + Controllable:OptionROEHoldFire() + Controllable:OptionROTVertical() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) end ---- Management of logical cargo objects, that can be transported from and to transportation carriers. + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE + EngageZone:__Engage( 1 ) +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To ) + + if Controllable:IsAlive() then + + self:Detect( self.EngageZone ) + + local EngageRoute = {} + + --- Calculate the current route point. + local CurrentVec2 = self.Controllable:GetVec2() + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() + local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + + if self.Controllable:IsNotInZone( self.EngageZone ) then + + -- Find a random 2D point in EngageZone. + local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2() + self:T2( ToEngageZoneVec2 ) + + -- Define Speed and Altitude. + local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + self:T2( ToEngageZoneSpeed ) + + -- Obtain a 3D @{Point} from the 2D point + altitude. + local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y ) + + -- Create a route point of type air. + local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint + + end + + --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. + + --- Find a random 2D point in EngageZone. + local ToTargetVec2 = self.EngageZone:GetRandomVec2() + self:T2( ToTargetVec2 ) + + --- Define Speed and Altitude. + local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + ToTargetPointVec3:SmokeBlue() + + EngageRoute[#EngageRoute+1] = ToTargetRoutePoint + + + Controllable:OptionROEOpenFire() + Controllable:OptionROTPassiveDefense() + + local AttackTasks = {} + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:E( {"Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + + EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( EngageRoute ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + self.Controllable:SetState( self.Controllable, "EngageZone", self ) + + self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" ) + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) + end +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @param Core.Event#EVENTDATA EventData +function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end + + Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" ) +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self.DetectUnits = false +end + +--- @param #AI_CAS_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_CAS_ZONE:OnDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Destroy( 1, EventData ) + end +end + + +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Execute Combat Air Patrol (CAP).** +-- +-- ![Banner Image](..\Presentations\AI_Cap\Dia1.JPG) +-- +-- +-- === +-- +-- # 1) @{#AI_CAP_ZONE} class, extends @{AI.AI_Cap#AI_PATROL_ZONE} +-- +-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group} +-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. +-- +-- ![Process](..\Presentations\AI_Cap\Dia3.JPG) +-- +-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_Cap\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_Cap\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_Cap\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_Cap\Dia9.JPG) +-- +-- When enemies are detected, the AI will automatically engage the enemy. +-- +-- ![Process](..\Presentations\AI_Cap\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Process](..\Presentations\AI_Cap\Dia13.JPG) +-- +-- ## 1.1) AI_CAP_ZONE constructor +-- +-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object. +-- +-- ## 1.2) AI_CAP_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_Cap\Dia2.JPG) +-- +-- ### 1.2.1) AI_CAP_ZONE States +-- +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Engaging** ( Group ): The AI is engaging the bogeys. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 1.2.2) AI_CAP_ZONE Events +-- +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **Engage** ( Group ): Let the AI engage the bogeys. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ## 1.3) Set the Range of Engagement +-- +-- ![Range](..\Presentations\AI_Cap\Dia11.JPG) +-- +-- An optional range can be set in meters, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- The range can be beyond or smaller than the range of the Patrol Zone. +-- The range is applied at the position of the AI. +-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageRange}() to define that range. +-- +-- ## 1.4) Set the Zone of Engagement +-- +-- ![Zone](..\Presentations\AI_Cap\Dia12.JPG) +-- +-- An optional @{Zone} can be set, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** +-- +-- The underlying change log documents the API changes. Please read this carefully. The following notation is used: +-- +-- * **Added** parts are expressed in bold type face. +-- * _Removed_ parts are expressed in italic type face. +-- +-- Hereby the change log: +-- +-- 2017-01-15: Initial class and API. +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Cap + + +--- AI_CAP_ZONE class +-- @type AI_CAP_ZONE +-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @extends AI.AI_Patrol#AI_PATROL_ZONE +AI_CAP_ZONE = { + ClassName = "AI_CAP_ZONE", +} + + + +--- Creates a new AI_CAP_ZONE object +-- @param #AI_CAP_ZONE self +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. +-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAP_ZONE + + self.Accomplished = false + self.Engaging = false + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_CAP_ZONE] OnBeforeEngage + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Engage. + -- @function [parent=#AI_CAP_ZONE] OnAfterEngage + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAP_ZONE] Engage + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAP_ZONE] __Engage + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_CAP_ZONE] OnLeaveEngaging +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @return #boolean Return false to cancel Transition. + +--- OnEnter Transition Handler for State Engaging. +-- @function [parent=#AI_CAP_ZONE] OnEnterEngaging +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_CAP_ZONE] OnBeforeFired + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Fired. + -- @function [parent=#AI_CAP_ZONE] OnAfterFired + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAP_ZONE] Fired + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAP_ZONE] __Fired + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] OnBeforeDestroy + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] Destroy + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] __Destroy + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_CAP_ZONE] OnBeforeAbort + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Abort. + -- @function [parent=#AI_CAP_ZONE] OnAfterAbort + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAP_ZONE] Abort + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAP_ZONE] __Abort + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] OnBeforeAccomplish + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] Accomplish + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] __Accomplish + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone which defines where the AI will engage bogies. +-- @param #AI_CAP_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + +--- Set the Engage Range when the AI will engage with airborne enemies. +-- @param #AI_CAP_ZONE self +-- @param #number EngageRange The Engage Range. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:SetEngageRange( EngageRange ) + self:F2() + + if EngageRange then + self.EngageRange = EngageRange + else + self.EngageRange = nil + end +end + +--- onafter State Transition for Event Start. +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To ) + + + self:Route() + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone. + + self:EventOnDead( self.OnDead ) + + Controllable:OptionROEOpenFire() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageCapRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_CAP_ZONE + EngageZone:__Engage( 1 ) +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To ) + + if From ~= "Engaging" then + + local Engage = false + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then + Engage = true + break + end + end + + if Engage == true then + self:E( 'Detected -> Engaging' ) + self:__Engage( 1 ) + end + end +end + + + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) + + if Controllable:IsAlive() then + + self:Detect( self.EngageZone ) + + local EngageRoute = {} + + --- Calculate the current route point. + local CurrentVec2 = self.Controllable:GetVec2() + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() + local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + + --- Find a random 2D point in PatrolZone. + local ToTargetVec2 = self.PatrolZone:GetRandomVec2() + self:T2( ToTargetVec2 ) + + --- Define Speed and Altitude. + local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToPatrolRoutePoint = ToTargetPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint + + Controllable:OptionROEOpenFire() + Controllable:OptionROTPassiveDefense() + + local AttackTasks = {} + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then + if self.EngageZone then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:E( {"Within Zone and Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + if self.EngageRange then + if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then + self:E( {"Within Range and Engaging", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( EngageRoute ) + + + if #AttackTasks == 0 then + self:E("No targets found -> Going back to Patrolling") + self:Accomplish() + self:Route() + else + EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + self.Controllable:SetState( self.Controllable, "EngageZone", self ) + + self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" ) + + end + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) + + end +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @param Core.Event#EVENTDATA EventData +function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end + + Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" ) +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self.DetectUnits = false +end + +--- @param #AI_CAP_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_CAP_ZONE:OnDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Destroy( 1, EventData ) + end +end + + +--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers. -- -- === -- @@ -24730,14 +26583,14 @@ end -- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state. -- There are 2 moments when state transition methods will be called by the state machine: -- --- * **Before** the state transition. --- The state transition method needs to start with the name **OnBefore + the name of the state**. +-- * **Leaving** the state. +-- The state transition method needs to start with the name **OnLeave + the name of the state**. -- If the state transition method returns false, then the processing of the state transition will not be done! -- If you want to change the behaviour of the AIControllable at this event, return false, -- but then you'll need to specify your own logic using the AIControllable! -- --- * **After** the state transition. --- The state transition method needs to start with the name **OnAfter + the name of the state**. +-- * **Entering** the state. +-- The state transition method needs to start with the name **OnEnter + the name of the state**. -- These state transition methods need to provide a return value, which is specified at the function description. -- -- 2) #AI_CARGO_UNIT class @@ -24823,45 +26676,45 @@ end -- UnLoaded ---- @function [parent=#AI_CARGO] OnBeforeUnLoaded +--- @function [parent=#AI_CARGO] OnLeaveUnLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterUnLoaded +--- @function [parent=#AI_CARGO] OnEnterUnLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- Loaded ---- @function [parent=#AI_CARGO] OnBeforeLoaded +--- @function [parent=#AI_CARGO] OnLeaveLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterLoaded +--- @function [parent=#AI_CARGO] OnEnterLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- Boarding ---- @function [parent=#AI_CARGO] OnBeforeBoarding +--- @function [parent=#AI_CARGO] OnLeaveBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterBoarding +--- @function [parent=#AI_CARGO] OnEnterBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- UnBoarding ---- @function [parent=#AI_CARGO] OnBeforeUnBoarding +--- @function [parent=#AI_CARGO] OnLeaveUnBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterUnBoarding +--- @function [parent=#AI_CARGO] OnEnterUnBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable @@ -29677,6 +31530,8 @@ Include.File( "Functional/Detection" ) --- AI Classes Include.File( "AI/AI_Balancer" ) Include.File( "AI/AI_Patrol" ) +Include.File( "AI/AI_Cap" ) +Include.File( "AI/AI_Cas" ) Include.File( "AI/AI_Cargo" ) --- Actions diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index 98d6002bc..e02bdb889 100644 --- a/Moose Mission Setup/Moose.lua +++ b/Moose Mission Setup/Moose.lua @@ -1,5 +1,5 @@ env.info( '*** MOOSE STATIC INCLUDE START *** ' ) -env.info( 'Moose Generation Timestamp: 20170105_0841' ) +env.info( 'Moose Generation Timestamp: 20170117_1202' ) local base = _G Include = {} @@ -3857,6 +3857,8 @@ function SCHEDULER:New( SchedulerObject, SchedulerFunction, SchedulerArguments, local ScheduleID = nil + self.MasterObject = SchedulerObject + if SchedulerFunction then ScheduleID = self:Schedule( SchedulerObject, SchedulerFunction, SchedulerArguments, Start, Repeat, RandomizeFactor, Stop ) end @@ -3884,7 +3886,11 @@ function SCHEDULER:Schedule( SchedulerObject, SchedulerFunction, SchedulerArgume self:F2( { Start, Repeat, RandomizeFactor, Stop } ) self:T3( { SchedulerArguments } ) - + local ObjectName = "-" + if SchedulerObject and SchedulerObject.ClassName and SchedulerObject.ClassID then + ObjectName = SchedulerObject.ClassName .. SchedulerObject.ClassID + end + self:F3( { "Schedule :", ObjectName, tostring( SchedulerObject ), Start, Repeat, RandomizeFactor, Stop } ) self.SchedulerObject = SchedulerObject local ScheduleID = _SCHEDULEDISPATCHER:AddSchedule( @@ -4011,21 +4017,21 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr -- If the object used as the key is nil, then the garbage collector will remove the item from the Functions array. self.ObjectSchedulers = self.ObjectSchedulers or setmetatable( {}, { __mode = "v" } ) - if Scheduler.SchedulerObject then + if Scheduler.MasterObject then self.ObjectSchedulers[self.CallID] = Scheduler - self:T3( { self.CallID, self.ObjectSchedulers[self.CallID] } ) + self:F3( { CallID = self.CallID, ObjectScheduler = tostring(self.ObjectSchedulers[self.CallID]), MasterObject = tostring(Scheduler.MasterObject) } ) else self.PersistentSchedulers[self.CallID] = Scheduler - self:T3( { self.CallID, self.PersistentSchedulers[self.CallID] } ) + self:F3( { CallID = self.CallID, PersistentScheduler = self.PersistentSchedulers[self.CallID] } ) end self.Schedule = self.Schedule or setmetatable( {}, { __mode = "k" } ) - self.Schedule[Scheduler] = {} + self.Schedule[Scheduler] = self.Schedule[Scheduler] or {} self.Schedule[Scheduler][self.CallID] = {} self.Schedule[Scheduler][self.CallID].Function = ScheduleFunction self.Schedule[Scheduler][self.CallID].Arguments = ScheduleArguments self.Schedule[Scheduler][self.CallID].StartTime = timer.getTime() + ( Start or 0 ) - self.Schedule[Scheduler][self.CallID].Start = Start + .001 + self.Schedule[Scheduler][self.CallID].Start = Start + .1 self.Schedule[Scheduler][self.CallID].Repeat = Repeat self.Schedule[Scheduler][self.CallID].Randomize = Randomize self.Schedule[Scheduler][self.CallID].Stop = Stop @@ -4101,7 +4107,7 @@ function SCHEDULEDISPATCHER:AddSchedule( Scheduler, ScheduleFunction, ScheduleAr self:Stop( Scheduler, CallID ) end else - --self:E( "Scheduled obscolete call for CallID: " .. CallID ) + self:E( "Scheduled obscolete call for CallID: " .. CallID ) end return nil @@ -7667,6 +7673,7 @@ end -- @field #table Filter -- @field #table Set -- @field #table List +-- @field Core.Scheduler#SCHEDULER CallScheduler -- @extends Core.Base#BASE SET_BASE = { ClassName = "SET_BASE", @@ -7684,7 +7691,7 @@ SET_BASE = { function SET_BASE:New( Database ) -- Inherits from BASE - local self = BASE:Inherit( self, BASE:New() ) + local self = BASE:Inherit( self, BASE:New() ) -- Core.Set#SET_BASE self.Database = Database @@ -7694,6 +7701,8 @@ function SET_BASE:New( Database ) self.List = {} self.List.__index = self.List self.List = setmetatable( { Count = 0 }, self.List ) + + self.CallScheduler = SCHEDULER:New( self ) return self end @@ -8081,7 +8090,7 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen return false end - local Scheduler = SCHEDULER:New( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) + self.CallScheduler:Schedule( self, Schedule, {}, self.TimeInterval, self.TimeInterval, 0 ) return self end @@ -9786,9 +9795,11 @@ POINT_VEC3 = { BARO = "BARO", }, RoutePointType = { + TakeOffParking = "TakeOffParking", TurningPoint = "Turning Point", }, RoutePointAction = { + FromParkingArea = "From Parking Area", TurningPoint = "Turning Point", }, } @@ -9811,10 +9822,12 @@ do -- POINT_VEC3 --- RoutePoint Types -- @type POINT_VEC3.RoutePointType +-- @field TakeOffParking "TakeOffParking" -- @field TurningPoint "Turning Point" --- RoutePoint Actions -- @type POINT_VEC3.RoutePointAction +-- @field FromParkingArea "From Parking Area" -- @field TurningPoint "Turning Point" -- Constructor. @@ -10699,50 +10712,85 @@ end ----- The _MessageQueue object is created when the MESSAGE class module is loaded. ----_MessageQueue = MESSAGEQUEUE:New( 0.5 ) -- ---- This module contains the FSM class and derived FSM_ classes. +--- This module contains the **FSM** (**F**inite **S**tate **M**achine) class and derived **FSM\_** classes. +-- ## Finite State Machines (FSM) are design patterns allowing efficient (long-lasting) processes and workflows. +-- +-- ![Banner Image](..\Presentations\FSM\Dia1.JPG) +-- +-- A FSM can only be in one of a finite number of states. +-- The machine is in only one state at a time; the state it is in at any given time is called the **current state**. +-- It can change from one state to another when initiated by an **__internal__ or __external__ triggering event**, which is called a **transition**. +-- An **FSM implementation** is defined by **a list of its states**, **its initial state**, and **the triggering events** for **each possible transition**. +-- An FSM implementation is composed out of **two parts**, a set of **state transition rules**, and an implementation set of **state transition handlers**, implementing those transitions. +-- +-- The FSM class supports a **hierarchical implementation of a Finite State Machine**, +-- that is, it allows to **embed existing FSM implementations in a master FSM**. +-- FSM hierarchies allow for efficient FSM re-use, **not having to re-invent the wheel every time again** when designing complex processes. +-- +-- ![Workflow Example](..\Presentations\FSM\Dia2.JPG) +-- +-- The above diagram shows a graphical representation of a FSM implementation for a **Task**, which guides a Human towards a Zone, +-- orders him to destroy x targets and account the results. +-- Other examples of ready made FSM could be: +-- +-- * route a plane to a zone flown by a human +-- * detect targets by an AI and report to humans +-- * account for destroyed targets by human players +-- * handle AI infantry to deploy from or embark to a helicopter or airplane or vehicle +-- * let an AI patrol a zone +-- +-- The **MOOSE framework** uses extensively the FSM class and derived FSM\_ classes, +-- because **the goal of MOOSE is to simplify mission design complexity for mission building**. +-- By efficiently utilizing the FSM class and derived classes, MOOSE allows mission designers to quickly build processes. +-- **Ready made FSM-based implementations classes** exist within the MOOSE framework that **can easily be re-used, +-- and tailored** by mission designers through **the implementation of Transition Handlers**. +-- Each of these FSM implementation classes start either with: +-- +-- * an acronym **AI\_**, which indicates an FSM implementation directing **AI controlled** @{GROUP} and/or @{UNIT}. These AI\_ classes derive the @{#FSM_CONTROLLABLE} class. +-- * an acronym **TASK\_**, which indicates an FSM implementation executing a @{TASK} executed by Groups of players. These TASK\_ classes derive the @{#FSM_TASK} class. +-- * an acronym **ACT\_**, which indicates an Sub-FSM implementation, directing **Humans actions** that need to be done in a @{TASK}, seated in a @{CLIENT} (slot) or a @{UNIT} (CA join). These ACT\_ classes derive the @{#FSM_PROCESS} class. +-- +-- Detailed explanations and API specifics are further below clarified and FSM derived class specifics are described in those class documentation sections. +-- +-- ##__Dislaimer:__ +-- The FSM class development is based on a finite state machine implementation made by Conroy Kyle. +-- The state machine can be found on [github](https://github.com/kyleconroy/lua-state-machine) +-- I've reworked this development (taken the concept), and created a **hierarchical state machine** out of it, embedded within the DCS simulator. +-- Additionally, I've added extendability and created an API that allows seamless FSM implementation. -- --- This development is based on a state machine implementation made by Conroy Kyle. --- The state machine can be found here: https://github.com/kyleconroy/lua-state-machine --- --- I've taken the development and enhanced it (actually rewrote it) to make the state machine hierarchical... --- It is a fantastic development, this module. --- -- === -- --- ![Banner Image](..\Presentations\FSM\Dia1.jpg) --- -- # 1) @{Core.Fsm#FSM} class, extends @{Core.Base#BASE} -- --- A Finite State Machine (FSM) defines the rules of transitioning between various States triggered by Events. +-- ![Transition Rules and Transition Handlers and Event Triggers](..\Presentations\FSM\Dia3.JPG) -- --- * A **State** defines a moment in the process. --- * An **Event** describes an action, that can be triggered both internally as externally in the FSM. +-- The FSM class is the base class of all FSM\_ derived classes. It implements the main functionality to define and execute Finite State Machines. +-- The derived FSM\_ classes extend the Finite State Machine functionality to run a workflow process for a specific purpose or component. -- --- ## 1.1) Event Handling +-- Finite State Machines have **Transition Rules**, **Transition Handlers** and **Event Triggers**. -- --- ![Event Handlers](..\Presentations\FSM\Dia3.jpg) +-- The **Transition Rules** define the "Process Flow Boundaries", that is, +-- the path that can be followed hopping from state to state upon triggered events. +-- If an event is triggered, and there is no valid path found for that event, +-- an error will be raised and the FSM will stop functioning. -- --- An FSM transitions in **4 moments** when an Event is being handled. --- Each moment can be catched by handling methods defined by the mission designer, --- that will be called by the FSM while executing the transition. --- These methods define the flow of the FSM process; because in those methods the FSM Internal Events will be fired. --- --- * To handle **State** moments, create methods starting with OnLeave or OnEnter concatenated with the State name. --- * To handle **Event** moments, create methods starting with OnBefore or OnAfter concatenated with the Event name. +-- The **Transition Handlers** are special methods that can be defined by the mission designer, following a defined syntax. +-- If the FSM object finds a method of such a handler, then the method will be called by the FSM, passing specific parameters. +-- The method can then define its own custom logic to implement the FSM workflow, and to conduct other actions. -- --- **The OnLeave and OnBefore transition methods may return false, which will cancel the transition.** +-- The **Event Triggers** are methods that are defined by the FSM, which the mission designer can use to implement the workflow. +-- Most of the time, these Event Triggers are used within the Transition Handler methods, so that a workflow is created running through the state machine. -- --- ## 1.2) Event Triggers +-- As explained above, a FSM supports **Linear State Transitions** and **Hierarchical State Transitions**, and both can be mixed to make a comprehensive FSM implementation. +-- The below documentation has a seperate chapter explaining both transition modes, taking into account the **Transition Rules**, **Transition Handlers** and **Event Triggers**. -- --- ![Event Triggers](..\Presentations\FSM\Dia4.jpg) +-- ## 1.1) FSM Linear Transitions -- --- The FSM creates for each Event **two Event Trigger methods**. --- There are two modes how Events can be triggered, which is **embedded** and **delayed**: +-- Linear Transitions are Transition Rules allowing an FSM to transition from one or multiple possible **From** state(s) towards a **To** state upon a Triggered **Event**. +-- The Lineair transition rule evaluation will always be done from the **current state** of the FSM. +-- If no valid Transition Rule can be found in the FSM, the FSM will log an error and stop. -- --- * The method **FSM:Event()** triggers an Event that will be processed **embedded** or **immediately**. --- * The method **FSM:__Event( seconds )** triggers an Event that will be processed **delayed** over time, waiting x seconds. --- --- ## 1.3) FSM Transition Rules +-- ### 1.1.1) FSM Transition Rules -- -- The FSM has transition rules that it follows and validates, as it walks the process. -- These rules define when an FSM can transition from a specific state towards an other specific state upon a triggered event. @@ -10751,12 +10799,107 @@ end -- -- The initial state can be defined using the method @{#FSM.SetStartState}(). The default start state of an FSM is "None". -- --- ### Example +-- Find below an example of a Linear Transition Rule definition for an FSM. -- --- This example creates a new FsmDemo object from class FSM. --- It will set the start state of FsmDemo to Green. --- 2 Transition Rules are created, where upon the event Switch, --- the FsmDemo will transition from state Green to Red and vise versa. +-- local Fsm3Switch = FSM:New() -- #FsmDemo +-- FsmSwitch:SetStartState( "Off" ) +-- FsmSwitch:AddTransition( "Off", "SwitchOn", "On" ) +-- FsmSwitch:AddTransition( "Off", "SwitchMiddle", "Middle" ) +-- FsmSwitch:AddTransition( "On", "SwitchOff", "Off" ) +-- FsmSwitch:AddTransition( "Middle", "SwitchOff", "Off" ) +-- +-- The above code snippet models a 3-way switch Linear Transition: +-- +-- * It can be switched **On** by triggering event **SwitchOn**. +-- * It can be switched to the **Middle** position, by triggering event **SwitchMiddle**. +-- * It can be switched **Off** by triggering event **SwitchOff**. +-- * Note that once the Switch is **On** or **Middle**, it can only be switched **Off**. +-- +-- ### Some additional comments: +-- +-- Note that Linear Transition Rules **can be declared in a few variations**: +-- +-- * The From states can be **a table of strings**, indicating that the transition rule will be valid **if the current state** of the FSM will be **one of the given From states**. +-- * The From state can be a **"*"**, indicating that **the transition rule will always be valid**, regardless of the current state of the FSM. +-- +-- The below code snippet shows how the two last lines can be rewritten and consensed. +-- +-- FsmSwitch:AddTransition( { "On", "Middle" }, "SwitchOff", "Off" ) +-- +-- ### 1.1.2) Transition Handling +-- +-- ![Transition Handlers](..\Presentations\FSM\Dia4.JPG) +-- +-- An FSM transitions in **4 moments** when an Event is being triggered and processed. +-- The mission designer can define for each moment specific logic within methods implementations following a defined API syntax. +-- These methods define the flow of the FSM process; because in those methods the FSM Internal Events will be triggered. +-- +-- * To handle **State** transition moments, create methods starting with OnLeave or OnEnter concatenated with the State name. +-- * To handle **Event** transition moments, create methods starting with OnBefore or OnAfter concatenated with the Event name. +-- +-- **The OnLeave and OnBefore transition methods may return false, which will cancel the transition!** +-- +-- Transition Handler methods need to follow the above specified naming convention, but are also passed parameters from the FSM. +-- These parameters are on the correct order: From, Event, To: +-- +-- * From = A string containing the From state. +-- * Event = A string containing the Event name that was triggered. +-- * To = A string containing the To state. +-- +-- On top, each of these methods can have a variable amount of parameters passed. See the example in section [1.1.3](#1.1.3\)-event-triggers). +-- +-- ### 1.1.3) Event Triggers +-- +-- ![Event Triggers](..\Presentations\FSM\Dia5.JPG) +-- +-- The FSM creates for each Event two **Event Trigger methods**. +-- There are two modes how Events can be triggered, which is **synchronous** and **asynchronous**: +-- +-- * The method **FSM:Event()** triggers an Event that will be processed **synchronously** or **immediately**. +-- * The method **FSM:__Event( __seconds__ )** triggers an Event that will be processed **asynchronously** over time, waiting __x seconds__. +-- +-- The destinction between these 2 Event Trigger methods are important to understand. An asynchronous call will "log" the Event Trigger to be executed at a later time. +-- Processing will just continue. Synchronous Event Trigger methods are useful to change states of the FSM immediately, but may have a larger processing impact. +-- +-- The following example provides a little demonstration on the difference between synchronous and asynchronous Event Triggering. +-- +-- function FSM:OnAfterEvent( From, Event, To, Amount ) +-- self:E( { Amount = Amount } ) +-- end +-- +-- local Amount = 1 +-- FSM:__Event( 5, Amount ) +-- +-- Amount = Amount + 1 +-- FSM:Event( Text, Amount ) +-- +-- In this example, the **:OnAfterEvent**() Transition Handler implementation will get called when **Event** is being triggered. +-- Before we go into more detail, let's look at the last 4 lines of the example. +-- The last line triggers synchronously the **Event**, and passes Amount as a parameter. +-- The 3rd last line of the example triggers asynchronously **Event**. +-- Event will be processed after 5 seconds, and Amount is given as a parameter. +-- +-- The output of this little code fragment will be: +-- +-- * Amount = 2 +-- * Amount = 2 +-- +-- Because ... When Event was asynchronously processed after 5 seconds, Amount was set to 2. So be careful when processing and passing values and objects in asynchronous processing! +-- +-- ### 1.1.4) Linear Transition Example +-- +-- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua) +-- +-- It models a unit standing still near Batumi, and flaring every 5 seconds while switching between a Green flare and a Red flare. +-- The purpose of this example is not to show how exciting flaring is, but it demonstrates how a Linear Transition FSM can be build. +-- Have a look at the source code. The source code is also further explained below in this section. +-- +-- The example creates a new FsmDemo object from class FSM. +-- It will set the start state of FsmDemo to state **Green**. +-- Two Linear Transition Rules are created, where upon the event **Switch**, +-- the FsmDemo will transition from state **Green** to **Red** and from **Red** back to **Green**. +-- +-- ![Transition Example](..\Presentations\FSM\Dia6.JPG) -- -- local FsmDemo = FSM:New() -- #FsmDemo -- FsmDemo:SetStartState( "Green" ) @@ -10766,6 +10909,8 @@ end -- In the above example, the FsmDemo could flare every 5 seconds a Green or a Red flare into the air. -- The next code implements this through the event handling method **OnAfterSwitch**. -- +-- ![Transition Flow](..\Presentations\FSM\Dia7.JPG) +-- -- function FsmDemo:OnAfterSwitch( From, Event, To, FsmUnit ) -- self:E( { From, Event, To, FsmUnit } ) -- @@ -10776,7 +10921,7 @@ end -- FsmUnit:Flare(FLARECOLOR.Red) -- end -- end --- FsmDemo:__Switch( 5, FsmUnit ) -- Trigger the next Switch event to happen in 5 seconds. +-- self:__Switch( 5, FsmUnit ) -- Trigger the next Switch event to happen in 5 seconds. -- end -- -- FsmDemo:__Switch( 5, FsmUnit ) -- Trigger the first Switch event to happen in 5 seconds. @@ -10806,20 +10951,9 @@ end -- -- FsmDemo:__Switch( 5, FsmUnit ) -- Trigger the next Switch event to happen in 5 seconds. -- --- This example is fully implemented in the MOOSE test mission on GITHUB: [FSM-100 - Transition Explanation](https://github.com/FlightControl-Master/MOOSE/blob/master/Moose%20Test%20Missions/FSM%20-%20Finite%20State%20Machine/FSM-100%20-%20Transition%20Explanation/FSM-100%20-%20Transition%20Explanation.lua) --- --- ### Some additional comments: --- --- Note that transition rules can be declared with a few variations: --- --- * The From states can be a table of strings, indicating that the transition rule will be valid if the current state of the FSM will be one of the given From states. --- * The From state can be a "*", indicating that the transition rule will always be valid, regardless of the current state of the FSM. --- --- This transition will create a new FsmDemo object from class FSM. --- It will set the start state of FsmDemo to Green. --- A new event is added in addition to the above example. --- The new event Stop will cancel the Switching process. --- So, the transtion for event Stop can be executed if the current state of the FSM is either "Red" or "Green". +-- The below code fragment extends the FsmDemo, demonstrating multiple **From states declared as a table**, adding a **Linear Transition Rule**. +-- The new event **Stop** will cancel the Switching process. +-- The transition for event Stop can be executed if the current state of the FSM is either "Red" or "Green". -- -- local FsmDemo = FSM:New() -- #FsmDemo -- FsmDemo:SetStartState( "Green" ) @@ -10830,15 +10964,20 @@ end -- The transition for event Stop can also be simplified, as any current state of the FSM is valid. -- -- FsmDemo:AddTransition( "*", "Stop", "Stopped" ) +-- +-- So... When FsmDemo:Stop() is being triggered, the state of FsmDemo will transition from Red or Green to Stopped. +-- And there is no transition handling method defined for that transition, thus, no new event is being triggered causing the FsmDemo process flow to halt. -- --- ## 1.4) FSM Process Rules +-- ## 1.5) FSM Hierarchical Transitions -- --- The FSM can implement sub-processes that will execute and return multiple possible states. --- Depending upon which state is returned, the main FSM can continue tiggering different events. +-- Hierarchical Transitions allow to re-use readily available and implemented FSMs. +-- This becomes in very useful for mission building, where mission designers build complex processes and workflows, +-- combining smaller FSMs to one single FSM. -- --- The method @{#FSM.AddProcess}() adds a new Sub-Process FSM to the FSM. --- A Sub-Process will start the Sub-Process of the FSM upon the defined triggered Event, --- with multiple possible States as a result. +-- The FSM can embed **Sub-FSMs** that will execute and return **multiple possible Return (End) States**. +-- Depending upon **which state is returned**, the main FSM can continue the flow **triggering specific events**. +-- +-- The method @{#FSM.AddProcess}() adds a new Sub-FSM to the FSM. -- -- ==== -- @@ -10862,11 +11001,11 @@ end -- -- ### Contributions: -- --- * None. +-- * [**Pikey**](https://forums.eagle.ru/member.php?u=62835): Review of documentation & advice for improvements. -- -- ### Authors: -- --- * **FlightControl**: Design & Programming +-- * [**FlightControl**](https://forums.eagle.ru/member.php?u=89536): Design & Programming & documentation. -- -- @module Fsm @@ -10885,7 +11024,7 @@ do -- FSM function FSM:New( FsmT ) -- Inherits from BASE - local self = BASE:Inherit( self, BASE:New() ) + self = BASE:Inherit( self, BASE:New() ) self.options = options or {} self.options.subs = self.options.subs or {} @@ -11110,19 +11249,26 @@ do -- FSM function FSM._handler( self, EventName, ... ) - self:E( { EventName, ... } ) + local Can, to = self:can( EventName ) - local can, to = self:can( EventName ) - self:E( { EventName, self.current, can, to } ) + if to == "*" then + to = self.current + end - local ReturnValues = nil - - if can then + if Can then local from = self.current local params = { from, EventName, to, ... } + + if self.Controllable then + self:E( "FSM Transition for " .. self.Controllable.ControllableName .. " :" .. self.current .. " --> " .. EventName .. " --> " .. to ) + else + self:E( "FSM Transition:" .. self.current .. " --> " .. EventName .. " --> " .. to ) + end if self:_call_handler("onbefore" .. EventName, params) == false - or self:_call_handler("onleave" .. from, params) == false then + or self:_call_handler("OnBefore" .. EventName, params) == false + or self:_call_handler("onleave" .. from, params) == false + or self:_call_handler("OnLeave" .. from, params) == false then return false end @@ -11140,14 +11286,16 @@ do -- FSM sub.fsm.fsmparent = self sub.fsm.ReturnEvents = sub.ReturnEvents sub.fsm[sub.StartEvent]( sub.fsm ) - execute = true + execute = false end local fsmparent, Event = self:_isendstate( to ) if fsmparent and Event then self:F2( { "end state: ", fsmparent, Event } ) self:_call_handler("onenter" .. to, params) + self:_call_handler("OnEnter" .. to, params) self:_call_handler("onafter" .. EventName, params) + self:_call_handler("OnAfter" .. EventName, params) self:_call_handler("onstatechange", params) fsmparent[Event]( fsmparent ) execute = false @@ -11155,25 +11303,19 @@ do -- FSM if execute then -- only execute the call if the From state is not equal to the To state! Otherwise this function should never execute! - if from ~= to then - self:T3( { onenter = "onenter" .. to, callback = self["onenter" .. to] } ) + --if from ~= to then self:_call_handler("onenter" .. to, params) - end + self:_call_handler("OnEnter" .. to, params) + --end - self:T3( { On = "OnBefore" .. to, callback = self["OnBefore" .. to] } ) - if ( self:_call_handler("OnBefore" .. to, params ) ~= false ) then - - self:T3( { onafter = "onafter" .. EventName, callback = self["onafter" .. EventName] } ) - self:_call_handler("onafter" .. EventName, params) - - self:T3( { On = "OnAfter" .. EventName, callback = self["OnAfter" .. EventName] } ) - ReturnValues = self:_call_handler("OnAfter" .. EventName, params ) - end + self:_call_handler("onafter" .. EventName, params) + self:_call_handler("OnAfter" .. EventName, params) self:_call_handler("onstatechange", params) end - - return ReturnValues + else + self:E( "Cannot execute transition." ) + self:E( { From = self.current, Event = EventName, To = to, Can = Can } ) end return nil @@ -11249,7 +11391,6 @@ do -- FSM end function FSM:can(e) - self:E( { e, self.Events, self.Events[e] } ) local Event = self.Events[e] self:F3( { self.current, Event } ) local To = Event and Event.map[self.current] or Event.map['*'] @@ -11318,7 +11459,7 @@ do -- FSM_CONTROLLABLE end if self[handler] then - self:E( "Calling " .. handler ) + self:F3( "Calling " .. handler ) return xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler ) --return self[handler]( self, self.Controllable, unpack( params ) ) end @@ -11582,7 +11723,7 @@ do -- FSM_SET function FSM_SET:New( FSMSet ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET + self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM_SET if FSMSet then self:Set( FSMSet ) @@ -11609,7 +11750,7 @@ do -- FSM_SET function FSM_SET:_call_handler( handler, params ) if self[handler] then - self:E( "Calling " .. handler ) + self:T( "Calling " .. handler ) return self[handler]( self, self.Set, unpack( params ) ) end end @@ -11641,7 +11782,6 @@ end -- FSM_SET -- === -- -- @module Object --- @author FlightControl --- The OBJECT class -- @type OBJECT @@ -11652,7 +11792,6 @@ OBJECT = { ObjectName = "", } - --- A DCSObject -- @type DCSObject -- @field id_ The ID of the controllable in DCS @@ -11661,10 +11800,11 @@ OBJECT = { -- @param #OBJECT self -- @param Dcs.DCSWrapper.Object#Object ObjectName The Object name -- @return #OBJECT self -function OBJECT:New( ObjectName ) +function OBJECT:New( ObjectName, Test ) local self = BASE:Inherit( self, BASE:New() ) self:F2( ObjectName ) self.ObjectName = ObjectName + return self end @@ -11736,7 +11876,6 @@ end -- === -- -- @module Identifiable --- @author FlightControl --- The IDENTIFIABLE class -- @type IDENTIFIABLE @@ -11958,7 +12097,6 @@ end -- === -- -- @module Positionable --- @author FlightControl --- The POSITIONABLE class -- @type POSITIONABLE @@ -11980,6 +12118,7 @@ POSITIONABLE = { function POSITIONABLE:New( PositionableName ) local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) ) + self.PositionableName = PositionableName return self end @@ -11988,12 +12127,12 @@ end -- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:GetPositionVec3() - self:F2( self.PositionableName ) + self:E( self.PositionableName ) local DCSPositionable = self:GetDCSObject() if DCSPositionable then - local PositionablePosition = DCSPositionable:getPosition() + local PositionablePosition = DCSPositionable:getPosition().p self:T3( PositionablePosition ) return PositionablePosition end @@ -12045,6 +12184,27 @@ function POSITIONABLE:GetPointVec2() return nil end +--- Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Core.Point#POINT_VEC3 The 3D point vector of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function POSITIONABLE:GetPointVec3() + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionableVec3 = self:GetPositionVec3() + + local PositionablePointVec3 = POINT_VEC3:NewFromVec3( PositionableVec3 ) + + self:T2( PositionablePointVec3 ) + return PositionablePointVec3 + end + + return nil +end + --- Returns a random @{Dcs.DCSTypes#Vec3} vector within a range, indicating the point in 3D of the POSITIONABLE within the mission. -- @param Wrapper.Positionable#POSITIONABLE self @@ -12154,20 +12314,13 @@ end --- Returns true if the POSITIONABLE is in the air. +-- Polymorphic, is overridden in GROUP and UNIT. -- @param Wrapper.Positionable#POSITIONABLE self -- @return #boolean true if in the air. -- @return #nil The POSITIONABLE is not existing or alive. function POSITIONABLE:InAir() self:F2( self.PositionableName ) - local DCSPositionable = self:GetDCSObject() - - if DCSPositionable then - local PositionableInAir = DCSPositionable:inAir() - self:T3( PositionableInAir ) - return PositionableInAir - end - return nil end @@ -12480,7 +12633,6 @@ end -- === -- -- @module Controllable --- @author FlightControl --- The CONTROLLABLE class -- @type CONTROLLABLE @@ -12501,6 +12653,8 @@ function CONTROLLABLE:New( ControllableName ) local self = BASE:Inherit( self, POSITIONABLE:New( ControllableName ) ) self:F2( ControllableName ) self.ControllableName = ControllableName + + self.TaskScheduler = SCHEDULER:New( self ) return self end @@ -12522,6 +12676,58 @@ function CONTROLLABLE:_GetController() return nil end +-- Get methods + +--- Returns the UNITs wrappers of the DCS Units of the Controllable (default is a GROUP). +-- @param #CONTROLLABLE self +-- @return #list The UNITs wrappers. +function CONTROLLABLE:GetUnits() + self:F2( { self.ControllableName } ) + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + local DCSUnits = DCSControllable:getUnits() + local Units = {} + for Index, UnitData in pairs( DCSUnits ) do + Units[#Units+1] = UNIT:Find( UnitData ) + end + self:T3( Units ) + return Units + end + + return nil +end + + +--- Returns the health. Dead controllables have health <= 1.0. +-- @param #CONTROLLABLE self +-- @return #number The controllable health value (unit or group average). +-- @return #nil The controllable is not existing or alive. +function CONTROLLABLE:GetLife() + self:F2( self.ControllableName ) + + local DCSControllable = self:GetDCSObject() + + if DCSControllable then + local UnitLife = 0 + local Units = self:GetUnits() + if #Units == 1 then + local Unit = Units[1] -- Wrapper.Unit#UNIT + UnitLife = Unit:GetLife() + else + local UnitLifeTotal = 0 + for UnitID, Unit in pairs( Units ) do + local Unit = Unit -- Wrapper.Unit#UNIT + UnitLifeTotal = UnitLifeTotal + Unit:GetLife() + end + UnitLife = UnitLifeTotal / #Units + end + return UnitLife + end + + return nil +end + -- Tasks @@ -12559,7 +12765,7 @@ function CONTROLLABLE:PushTask( DCSTask, WaitTime ) -- Controller:pushTask( DCSTask ) if WaitTime then - SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime ) + self.TaskScheduler:Schedule( Controller, Controller.pushTask, { DCSTask }, WaitTime ) else Controller:pushTask( DCSTask ) end @@ -12581,7 +12787,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime ) if DCSControllable then local Controller = self:_GetController() - self:E(Controller) + self:T3( Controller ) -- When a controllable SPAWNs, it takes about a second to get the controllable in the simulator. Setting tasks to unspawned controllables provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Controllable. @@ -12590,7 +12796,7 @@ function CONTROLLABLE:SetTask( DCSTask, WaitTime ) if not WaitTime then Controller:setTask( DCSTask ) else - SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime ) + self.TaskScheduler:Schedule( Controller, Controller.setTask, { DCSTask }, WaitTime ) end return self @@ -12661,6 +12867,10 @@ function CONTROLLABLE:TaskCombo( DCSTasks ) tasks = DCSTasks } } + + for TaskID, Task in ipairs( DCSTasks ) do + self:E( Task ) + end self:T3( { DCSTaskCombo } ) return DCSTaskCombo @@ -12846,19 +13056,24 @@ function CONTROLLABLE:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, Atta -- } local DCSTask - DCSTask = { id = 'AttackUnit', + DCSTask = { + id = 'AttackUnit', params = { + altitudeEnabled = true, unitId = AttackUnit:GetID(), - weaponType = WeaponType, - expend = WeaponExpend, - attackQty = AttackQty, - direction = Direction, - attackQtyLimit = AttackQtyLimit, - controllableAttack = ControllableAttack, - }, - }, + attackQtyLimit = AttackQtyLimit or false, + attackQty = AttackQty or 2, + expend = WeaponExpend or "Auto", + altitude = 2000, + directionEnabled = true, + groupAttack = true, + --weaponType = WeaponType or 1073741822, + direction = Direction or 0, + } + } - self:T3( { DCSTask } ) + self:E( DCSTask ) + return DCSTask end @@ -13851,7 +14066,7 @@ function CONTROLLABLE:Route( GoPoints ) local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } local Controller = self:_GetController() --Controller.setTask( Controller, MissionTask ) - SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 ) + self.TaskScheduler:Schedule( Controller, Controller.setTask, { MissionTask }, 1 ) return self end @@ -14479,7 +14694,7 @@ end -- @param #table WayPoints If WayPoints is given, then use the route. -- @return #CONTROLLABLE function CONTROLLABLE:WayPointInitialize( WayPoints ) - self:F( { WayPoint, WayPointIndex, WayPointFunction } ) + self:F( { WayPoints } ) if WayPoints then self.WayPoints = WayPoints @@ -14490,6 +14705,18 @@ function CONTROLLABLE:WayPointInitialize( WayPoints ) return self end +--- Get the current WayPoints set with the WayPoint functions( Note that the WayPoints can be nil, although there ARE waypoints). +-- @param #CONTROLLABLE self +-- @return #table WayPoints If WayPoints is given, then return the WayPoints structure. +function CONTROLLABLE:GetWayPoints() + self:F( ) + + if self.WayPoints then + return self.WayPoints + end + + return nil +end --- Registers a waypoint function that will be executed when the controllable moves over the WayPoint. -- @param #CONTROLLABLE self @@ -14558,10 +14785,7 @@ function CONTROLLABLE:WayPointExecute( WayPoint, WaitTime ) return self end --- Message APIs - - ---- This module contains the GROUP class. +-- Message APIs--- This module contains the GROUP class. -- -- 1) @{Wrapper.Group#GROUP} class, extends @{Wrapper.Controllable#CONTROLLABLE} -- ============================================================= @@ -14768,6 +14992,23 @@ function GROUP:GetDCSObject() return nil end +--- Returns the @{Dcs.DCSTypes#Position3} position vectors indicating the point and direction vectors in 3D of the POSITIONABLE within the mission. +-- @param Wrapper.Positionable#POSITIONABLE self +-- @return Dcs.DCSTypes#Position The 3D position vectors of the POSITIONABLE. +-- @return #nil The POSITIONABLE is not existing or alive. +function GROUP:GetPositionVec3() -- Overridden from POSITIONABLE:GetPositionVec3() + self:F2( self.PositionableName ) + + local DCSPositionable = self:GetDCSObject() + + if DCSPositionable then + local PositionablePosition = DCSPositionable:getUnits()[1]:getPosition().p + self:T3( PositionablePosition ) + return PositionablePosition + end + + return nil +end --- Returns if the DCS Group is alive. -- When the group exists at run-time, this method will return true, otherwise false. @@ -14954,26 +15195,6 @@ function GROUP:GetInitialSize() return nil end ---- Returns the UNITs wrappers of the DCS Units of the DCS Group. --- @param #GROUP self --- @return #table The UNITs wrappers. -function GROUP:GetUnits() - self:F2( { self.GroupName } ) - local DCSGroup = self:GetDCSObject() - - if DCSGroup then - local DCSUnits = DCSGroup:getUnits() - local Units = {} - for Index, UnitData in pairs( DCSUnits ) do - Units[#Units+1] = UNIT:Find( UnitData ) - end - self:T3( Units ) - return Units - end - - return nil -end - --- Returns the DCS Units of the DCS Group. -- @param #GROUP self @@ -15445,6 +15666,31 @@ function GROUP:CalculateThreatLevelA2G() return MaxThreatLevelA2G end +--- Returns true if the first unit of the GROUP is in the air. +-- @param Wrapper.Group#GROUP self +-- @return #boolean true if in the first unit of the group is in the air. +-- @return #nil The GROUP is not existing or not alive. +function GROUP:InAir() + self:F2( self.GroupName ) + + local DCSGroup = self:GetDCSObject() + + if DCSGroup then + local DCSUnit = DCSGroup:getUnit(1) + if DCSUnit then + local GroupInAir = DCSGroup:getUnit(1):inAir() + self:T3( GroupInAir ) + return GroupInAir + end + end + + return nil +end + +function GROUP:OnReSpawn( ReSpawnFunction ) + + self.ReSpawnFunction = ReSpawnFunction +end --- This module contains the UNIT class. @@ -15916,6 +16162,25 @@ function UNIT:GetFuel() return nil end +--- Returns the UNIT in a UNIT list of one element. +-- @param #UNIT self +-- @return #list The UNITs wrappers. +function UNIT:GetUnits() + self:F2( { self.UnitName } ) + local DCSUnit = self:GetDCSObject() + + if DCSUnit then + local DCSUnits = DCSUnit:getUnits() + local Units = {} + Units[1] = UNIT:Find( DCSUnit ) + self:T3( Units ) + return Units + end + + return nil +end + + --- Returns the unit's health. Dead units has health <= 1.0. -- @param #UNIT self -- @return #number The Unit's health value. @@ -16248,6 +16513,24 @@ function UNIT:IsShip() return nil end +--- Returns true if the UNIT is in the air. +-- @param Wrapper.Positionable#UNIT self +-- @return #boolean true if in the air. +-- @return #nil The UNIT is not existing or alive. +function UNIT:InAir() + self:F2( self.UnitName ) + + local DCSUnit = self:GetDCSObject() + + if DCSUnit then + local UnitInAir = DCSUnit:inAir() + self:T3( UnitInAir ) + return UnitInAir + end + + return nil +end + --- This module contains the CLIENT class. -- -- 1) @{Wrapper.Client#CLIENT} class, extends @{Wrapper.Unit#UNIT} @@ -17350,7 +17633,7 @@ function SCORING:_EventOnHit( Event ) ):ToAll() self:ScoreCSV( InitPlayerName, "HIT_PENALTY", 1, -25, InitUnitName, InitUnitCoalition, InitUnitCategory, InitUnitType, TargetUnitName, TargetUnitCoalition, TargetUnitCategory, TargetUnitType ) else - self.Players[InitPlayerName].Score = self.Players[InitPlayerName].Score + 10 + self.Players[InitPlayerName].Score = self.Players[InitPlayerName].Score + 1 self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Score = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].Score + 1 self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].ScoreHit = self.Players[InitPlayerName].Hit[TargetCategory][TargetUnitName].ScoreHit + 1 MESSAGE:New( "Player '" .. InitPlayerName .. "' hit a target " .. TargetUnitCategory .. " ( " .. TargetType .. " ) " .. @@ -18266,6 +18549,7 @@ SPAWN = { SpawnAliasPrefix = nil, } + --- @type SPAWN.SpawnZoneTable -- @list SpawnZone @@ -18649,6 +18933,7 @@ function SPAWN:ReSpawn( SpawnIndex ) -- TODO: This logic makes DCS crash and i don't know why (yet). local SpawnGroup = self:GetGroupFromIndex( SpawnIndex ) + local WayPoints = SpawnGroup and SpawnGroup.WayPoints or nil if SpawnGroup then local SpawnDCSGroup = SpawnGroup:GetDCSObject() if SpawnDCSGroup then @@ -18656,7 +18941,18 @@ function SPAWN:ReSpawn( SpawnIndex ) end end - return self:SpawnWithIndex( SpawnIndex ) + local SpawnGroup = self:SpawnWithIndex( SpawnIndex ) + if SpawnGroup and WayPoints then + -- If there were WayPoints set, then Re-Execute those WayPoints! + SpawnGroup:WayPointInitialize( WayPoints ) + SpawnGroup:WayPointExecute( 1, 5 ) + end + + if SpawnGroup.ReSpawnFunction then + SpawnGroup:ReSpawnFunction() + end + + return SpawnGroup end --- Will spawn a group with a specified index number. @@ -24056,43 +24352,72 @@ function DETECTION_AREAS:CreateDetectionSets() end ---- This module contains the AI_BALANCER class. +--- Single-Player:**No** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**All** -- **AI Balancing will replace in multi player missions +-- non-occupied human slots with AI groups, in order to provide an engaging simulation environment, +-- even when there are hardly any players in the mission.** +-- +-- ![Banner Image](..\Presentations\AI_Balancer\Dia1.JPG) +-- -- -- === -- --- 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET} --- =================================================================================== --- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many AI GROUPS as there are --- CLIENTS in a SET_CLIENT collection not occupied by players. --- The AI_BALANCER class manages internally a collection of AI management objects, which govern the behaviour --- of the underlying AI GROUPS. +-- # 1) @{AI.AI_Balancer#AI_BALANCER} class, extends @{Core.Fsm#FSM_SET} -- --- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM) --- and calls for each event the state transition methods providing the internal @{Core.Fsm#FSM_SET.Set} object containing the --- SET_GROUP and additional event parameters provided during the event. +-- The @{AI.AI_Balancer#AI_BALANCER} class monitors and manages as many replacement AI groups as there are +-- CLIENTS in a SET_CLIENT collection, which are not occupied by human players. +-- In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions. -- --- 1.1) AI_BALANCER construction method --- --------------------------------------- --- Create a new AI_BALANCER object with the @{#AI_BALANCER.New} method: +-- The parent class @{Core.Fsm#FSM_SET} manages the functionality to control the Finite State Machine (FSM). +-- The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods. +-- An explanation about state and event transition methods can be found in the @{FSM} module documentation. -- --- * @{#AI_BALANCER.New}: Creates a new AI_BALANCER object. +-- The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following: +-- +-- * **@{#AI_BALANCER.OnAfterSpawned}**( AISet, From, Event, To, AIGroup ): Define to add extra logic when an AI is spawned. +-- +-- ## 1.1) AI_BALANCER construction +-- +-- Create a new AI_BALANCER object with the @{#AI_BALANCER.New}() method: +-- +-- ## 1.2) AI_BALANCER is a FSM +-- +-- ![Process](..\Presentations\AI_Balancer\Dia13.JPG) +-- +-- ### 1.2.1) AI_BALANCER States +-- +-- * **Monitoring** ( Set ): Monitoring the Set if all AI is spawned for the Clients. +-- * **Spawning** ( Set, ClientName ): There is a new AI group spawned with ClientName as the name of reference. +-- * **Spawned** ( Set, AIGroup ): A new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes. +-- * **Destroying** ( Set, AIGroup ): The AI is being destroyed. +-- * **Returning** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. Handle this state to customize the return behaviour of the AI, if any. +-- +-- ### 1.2.2) AI_BALANCER Events +-- +-- * **Monitor** ( Set ): Every 10 seconds, the Monitor event is triggered to monitor the Set. +-- * **Spawn** ( Set, ClientName ): Triggers when there is a new AI group to be spawned with ClientName as the name of reference. +-- * **Spawned** ( Set, AIGroup ): Triggers when a new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes. +-- * **Destroy** ( Set, AIGroup ): The AI is being destroyed. +-- * **Return** ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. -- --- 1.2) --- ---- --- * Add --- * Remove +-- ## 1.3) AI_BALANCER spawn interval for replacement AI -- --- 1.2) AI_BALANCER returns AI to Airbases --- ------------------------------------------ --- You can configure to have the AI to return to: +-- Use the method @{#AI_BALANCER.InitSpawnInterval}() to set the earliest and latest interval in seconds that is waited until a new replacement AI is spawned. -- --- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the home @{Wrapper.Airbase#AIRBASE}. --- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}. --- -- +-- ## 1.4) AI_BALANCER returns AI to Airbases +-- +-- By default, When a human player joins a slot that is AI_BALANCED, the AI group will be destroyed by default. +-- However, there are 2 additional options that you can use to customize the destroy behaviour. +-- When a human player joins a slot, you can configure to let the AI return to: +-- +-- * @{#AI_BALANCER.ReturnToHomeAirbase}: Returns the AI to the **home** @{Wrapper.Airbase#AIRBASE}. +-- * @{#AI_BALANCER.ReturnToNearestAirbases}: Returns the AI to the **nearest friendly** @{Wrapper.Airbase#AIRBASE}. +-- +-- Note that when AI returns to an airbase, the AI_BALANCER will trigger the **Return** event and the AI will return, +-- otherwise the AI_BALANCER will trigger a **Destroy** event, and the AI will be destroyed. +-- -- === -- --- **API CHANGE HISTORY** --- ====================== +-- # **API CHANGE HISTORY** -- -- The underlying change log documents the API changes. Please read this carefully. The following notation is used: -- @@ -24101,78 +24426,86 @@ end -- -- Hereby the change log: -- --- 2016-08-17: SPAWN:**InitCleanUp**( SpawnCleanUpInterval ) replaces SPAWN:_CleanUp_( SpawnCleanUpInterval ) +-- 2017-01-17: There is still a problem with AI being destroyed, but not respawned. Need to check further upon that. -- --- * Want to ensure that the methods starting with **Init** are the first called methods before any _Spawn_ method is called! --- * This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods. +-- 2017-01-08: AI_BALANCER:**InitSpawnInterval( Earliest, Latest )** added. -- -- === -- --- AUTHORS and CONTRIBUTIONS --- ========================= +-- # **AUTHORS and CONTRIBUTIONS** -- -- ### Contributions: -- --- * **Dutch_Baron (James)**: Who you can search on the Eagle Dynamics Forums. --- Working together with James has resulted in the creation of the AI_BALANCER class. --- James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) --- --- * **SNAFU**: --- Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. --- None of the script code has been used however within the new AI_BALANCER moose class. +-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) +-- * **SNAFU**: Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. None of the script code has been used however within the new AI_BALANCER moose class. -- -- ### Authors: -- --- * FlightControl: Framework Design & Programming +-- * FlightControl: Framework Design & Programming and Documentation. -- -- @module AI_Balancer - - --- AI_BALANCER class -- @type AI_BALANCER -- @field Core.Set#SET_CLIENT SetClient +-- @field Functional.Spawn#SPAWN SpawnAI +-- @field Wrapper.Group#GROUP Test -- @extends Core.Fsm#FSM_SET AI_BALANCER = { ClassName = "AI_BALANCER", PatrolZones = {}, AIGroups = {}, + Earliest = 5, -- Earliest a new AI can be spawned is in 5 seconds. + Latest = 60, -- Latest a new AI can be spawned is in 60 seconds. } + + --- Creates a new AI_BALANCER object -- @param #AI_BALANCER self -- @param Core.Set#SET_CLIENT SetClient A SET\_CLIENT object that will contain the CLIENT objects to be monitored if they are alive or not (joined by a player). -- @param Functional.Spawn#SPAWN SpawnAI The default Spawn object to spawn new AI Groups when needed. -- @return #AI_BALANCER --- @usage --- -- Define a new AI_BALANCER Object. function AI_BALANCER:New( SetClient, SpawnAI ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- Core.Fsm#FSM_SET + local self = BASE:Inherit( self, FSM_SET:New( SET_GROUP:New() ) ) -- AI.AI_Balancer#AI_BALANCER self:SetStartState( "None" ) - self:AddTransition( "*", "Start", "Monitoring" ) self:AddTransition( "*", "Monitor", "Monitoring" ) self:AddTransition( "*", "Spawn", "Spawning" ) self:AddTransition( "Spawning", "Spawned", "Spawned" ) self:AddTransition( "*", "Destroy", "Destroying" ) self:AddTransition( "*", "Return", "Returning" ) - self:AddTransition( "*", "End", "End" ) - self:AddTransition( "*", "Dead", "End" ) - - self.SetClient = SetClient + self.SetClient:FilterOnce() self.SpawnAI = SpawnAI + + self.SpawnQueue = {} + self.ToNearestAirbase = false self.ToHomeAirbase = false - self:__Start( 1 ) + self:__Monitor( 1 ) return self end +--- Sets the earliest to the latest interval in seconds how long AI_BALANCER will wait to spawn a new AI. +-- Provide 2 identical seconds if the interval should be a fixed amount of seconds. +-- @param #AI_BALANCER self +-- @param #number Earliest The earliest a new AI can be spawned in seconds. +-- @param #number Latest The latest a new AI can be spawned in seconds. +-- @return self +function AI_BALANCER:InitSpawnInterval( Earliest, Latest ) + + self.Earliest = Earliest + self.Latest = Latest + + return self +end + --- Returns the AI to the nearest friendly @{Wrapper.Airbase#AIRBASE}. -- @param #AI_BALANCER self -- @param Dcs.DCSTypes#Distance ReturnTresholdRange If there is an enemy @{Wrapper.Client#CLIENT} within the ReturnTresholdRange given in meters, the AI will not return to the nearest @{Wrapper.Airbase#AIRBASE}. @@ -24200,23 +24533,27 @@ end function AI_BALANCER:onenterSpawning( SetGroup, From, Event, To, ClientName ) -- OK, Spawn a new group from the default SpawnAI object provided. - local AIGroup = self.SpawnAI:Spawn() + local AIGroup = self.SpawnAI:Spawn() -- Wrapper.Group#GROUP AIGroup:E( "Spawning new AIGroup" ) --TODO: need to rework UnitName thing ... SetGroup:Add( ClientName, AIGroup ) + self.SpawnQueue[ClientName] = nil -- Fire the Spawned event. The first parameter is the AIGroup just Spawned. -- Mission designers can catch this event to bind further actions to the AIGroup. - self:Spawned( AIGroup ) + self:Spawned( AIGroup ) end --- @param #AI_BALANCER self -- @param Core.Set#SET_GROUP SetGroup -- @param Wrapper.Group#GROUP AIGroup -function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, AIGroup ) +function AI_BALANCER:onenterDestroying( SetGroup, From, Event, To, ClientName, AIGroup ) AIGroup:Destroy() + SetGroup:Flush() + SetGroup:Remove( ClientName ) + SetGroup:Flush() end --- @param #AI_BALANCER self @@ -24248,10 +24585,13 @@ end --- @param #AI_BALANCER self function AI_BALANCER:onenterMonitoring( SetGroup ) + self:T2( { self.SetClient:Count() } ) + --self.SetClient:Flush() + self.SetClient:ForEachClient( --- @param Wrapper.Client#CLIENT Client function( Client ) - self:E(Client.ClientName) + self:T3(Client.ClientName) local AIGroup = self.Set:Get( Client.UnitName ) -- Wrapper.Group#GROUP if Client:IsAlive() then @@ -24259,7 +24599,7 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) if AIGroup and AIGroup:IsAlive() == true then if self.ToNearestAirbase == false and self.ToHomeAirbase == false then - self:Destroy( AIGroup ) + self:Destroy( Client.UnitName, AIGroup ) else -- We test if there is no other CLIENT within the self.ReturnTresholdRange of the first unit of the AI group. -- If there is a CLIENT, the AI stays engaged and will not return. @@ -24268,16 +24608,16 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) local PlayerInRange = { Value = false } local RangeZone = ZONE_RADIUS:New( 'RangeZone', AIGroup:GetVec2(), self.ReturnTresholdRange ) - self:E( RangeZone ) + self:T2( RangeZone ) _DATABASE:ForEachPlayer( --- @param Wrapper.Unit#UNIT RangeTestUnit function( RangeTestUnit, RangeZone, AIGroup, PlayerInRange ) - self:E( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } ) + self:T2( { PlayerInRange, RangeTestUnit.UnitName, RangeZone.ZoneName } ) if RangeTestUnit:IsInZone( RangeZone ) == true then - self:E( "in zone" ) + self:T2( "in zone" ) if RangeTestUnit:GetCoalition() ~= AIGroup:GetCoalition() then - self:E( "in range" ) + self:T2( "in range" ) PlayerInRange.Value = true end end @@ -24298,9 +24638,13 @@ function AI_BALANCER:onenterMonitoring( SetGroup ) end else if not AIGroup or not AIGroup:IsAlive() == true then - self:E("client not alive") - self:Spawn( Client.UnitName ) - self:E("text after spawn") + self:T( "Client " .. Client.UnitName .. " not alive." ) + if not self.SpawnQueue[Client.UnitName] then + -- Spawn a new AI taking into account the spawn interval Earliest, Latest + self:__Spawn( math.random( self.Earliest, self.Latest ), Client.UnitName ) + self.SpawnQueue[Client.UnitName] = true + self:E( "New AI Spawned for Client " .. Client.UnitName ) + end end end return true @@ -24312,113 +24656,125 @@ end ---- (AI) (FSM) Make AI patrol routes or zones. +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Air Patrolling or Staging.** +-- +-- ![Banner Image](..\Presentations\AI_Patrol\Dia1.JPG) +-- -- -- === -- --- 1) @{#AI_PATROLZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE} --- ================================================================ --- The @{#AI_PATROLZONE} class implements the core functions to patrol a @{Zone} by an AIR @{Controllable} @{Group}. --- The patrol algorithm works that for each airplane patrolling, upon arrival at the patrol zone, --- a random point is selected as the route point within the 3D space, within the given boundary limits. --- The airplane will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. --- Upon arrival at the random 3D point, a new 3D random point will be selected within the patrol zone using the given limits. --- This cycle will continue until a fuel treshold has been reached by the airplane. +-- # 1) @{#AI_PATROL_ZONE} class, extends @{Core.Fsm#FSM_CONTROLLABLE} +-- +-- The @{#AI_PATROL_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group}. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia3.JPG) +-- +-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia9.JPG) +-- +---- Note that the enemy is not engaged! To model enemy engagement, either tailor the **Detected** event, or +-- use derived AI_ classes to model AI offensive or defensive behaviour. +-- +-- ![Process](..\Presentations\AI_Patrol\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. -- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. -- --- 1.1) AI_PATROLZONE constructor: --- ---------------------------- +-- ![Process](..\Presentations\AI_Patrol\Dia11.JPG) +-- +-- ## 1.1) AI_PATROL_ZONE constructor -- --- * @{#AI_PATROLZONE.New}(): Creates a new AI_PATROLZONE object. +-- * @{#AI_PATROL_ZONE.New}(): Creates a new AI_PATROL_ZONE object. -- --- 1.2) AI_PATROLZONE state machine: --- ---------------------------------- --- The AI_PATROLZONE is a state machine: it manages the different events and states of the AIControllable it is controlling. +-- ## 1.2) AI_PATROL_ZONE is a FSM -- --- ### 1.2.1) AI_PATROLZONE Events: +-- ![Process](..\Presentations\AI_Patrol\Dia2.JPG) -- --- * @{#AI_PATROLZONE.Route}( AIControllable ): A new 3D route point is selected and the AIControllable will fly towards that point with the given speed. --- * @{#AI_PATROLZONE.Patrol}( AIControllable ): The AIControllable reports it is patrolling. This event is called every 30 seconds. --- * @{#AI_PATROLZONE.RTB}( AIControllable ): The AIControllable will report return to base. --- * @{#AI_PATROLZONE.End}( AIControllable ): The end of the AI_PATROLZONE process. --- * @{#AI_PATROLZONE.Dead}( AIControllable ): The AIControllable is dead. The AI_PATROLZONE process will be ended. +-- ### 1.2.1) AI_PATROL_ZONE States -- --- ### 1.2.2) AI_PATROLZONE States: +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Returning** ( Group ): The AI is returning to Base.. -- --- * **Route**: A new 3D route point is selected and the AIControllable will fly towards that point with the given speed. --- * **Patrol**: The AIControllable is patrolling. This state is set every 30 seconds, so every 30 seconds, a state transition method can be used. --- * **RTB**: The AIControllable reports it wants to return to the base. --- * **Dead**: The AIControllable is dead ... --- * **End**: The process has come to an end. --- --- ### 1.2.3) AI_PATROLZONE state transition methods: +-- ### 1.2.2) AI_PATROL_ZONE Events -- --- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state. --- There are 2 moments when state transition methods will be called by the state machine: --- --- * **Before** the state transition. --- The state transition method needs to start with the name **OnBefore + the name of the state**. --- If the state transition method returns false, then the processing of the state transition will not be done! --- If you want to change the behaviour of the AIControllable at this event, return false, --- but then you'll need to specify your own logic using the AIControllable! --- --- * **After** the state transition. --- The state transition method needs to start with the name **OnAfter + the name of the state**. --- These state transition methods need to provide a return value, which is specified at the function description. --- --- An example how to manage a state transition for an AI_PATROLZONE object **Patrol** for the state **RTB**: --- --- local PatrolZoneGroup = GROUP:FindByName( "Patrol Zone" ) --- local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) --- --- local PatrolSpawn = SPAWN:New( "Patrol Group" ) --- local PatrolGroup = PatrolSpawn:Spawn() --- --- local Patrol = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 300, 600 ) --- Patrol:SetControllable( PatrolGroup ) --- Patrol:ManageFuel( 0.2, 60 ) --- --- **OnBefore**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **before** the RTB default action is processed by the AI_PATROLZONE object. --- --- --- State transition function for the AI_PATROLZONE **Patrol** object --- -- @param #AI_PATROLZONE self --- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup --- -- @return #boolean If false is returned, then the OnAfter state transition method will not be called. --- function Patrol:OnBeforeRTB( AIGroup ) --- AIGroup:MessageToRed( "Returning to base", 20 ) --- end --- --- **OnAfter**RTB( AIGroup ) will be called by the AI_PATROLZONE object when the AIGroup reports RTB, but **after** the RTB default action was processed by the AI_PATROLZONE object. --- --- --- State transition function for the AI_PATROLZONE **Patrol** object --- -- @param #AI_PATROLZONE self --- -- @param Wrapper.Controllable#CONTROLLABLE AIGroup --- -- @return #Wrapper.Controllable#CONTROLLABLE The new AIGroup object that is set to be patrolling the zone. --- function Patrol:OnAfterRTB( AIGroup ) --- return PatrolSpawn:Spawn() --- end +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. -- --- 1.3) Manage the AI_PATROLZONE parameters: --- ------------------------------------------ --- The following methods are available to modify the parameters of a AI_PATROLZONE object: +-- ## 1.3) Set or Get the AI controllable -- --- * @{#AI_PATROLZONE.SetControllable}(): Set the AIControllable. --- * @{#AI_PATROLZONE.GetControllable}(): Get the AIControllable. --- * @{#AI_PATROLZONE.SetSpeed}(): Set the patrol speed of the AI, for the next patrol. --- * @{#AI_PATROLZONE.SetAltitude}(): Set altitude of the AI, for the next patrol. +-- * @{#AI_PATROL_ZONE.SetControllable}(): Set the AIControllable. +-- * @{#AI_PATROL_ZONE.GetControllable}(): Get the AIControllable. +-- +-- ## 1.4) Set the Speed and Altitude boundaries of the AI controllable +-- +-- * @{#AI_PATROL_ZONE.SetSpeed}(): Set the patrol speed boundaries of the AI, for the next patrol. +-- * @{#AI_PATROL_ZONE.SetAltitude}(): Set altitude boundaries of the AI, for the next patrol. -- --- 1.3) Manage the out of fuel in the AI_PATROLZONE: --- ---------------------------------------------- --- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base. +-- ## 1.5) Manage the detection process of the AI controllable +-- +-- The detection process of the AI controllable can be manipulated. +-- Detection requires an amount of CPU power, which has an impact on your mission performance. +-- Only put detection on when absolutely necessary, and the frequency of the detection can also be set. +-- +-- * @{#AI_PATROL_ZONE.SetDetectionOn}(): Set the detection on. The AI will detect for targets. +-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. +-- +-- The detection frequency can be set with @{#AI_PATROL_ZONE.SetDetectionInterval}( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection. +-- Use the method @{#AI_PATROL_ZONE.GetDetectedUnits}() to obtain a list of the @{Unit}s detected by the AI. +-- +-- The detection can be filtered to potential targets in a specific zone. +-- Use the method @{#AI_PATROL_ZONE.SetDetectionZone}() to set the zone where targets need to be detected. +-- Note that when the zone is too far away, or the AI is not heading towards the zone, or the AI is too high, no targets may be detected +-- according the weather conditions. +-- +-- ## 1.6) Manage the "out of fuel" in the AI_PATROL_ZONE +-- +-- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. --- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE. --- Once the time is finished, the old AIControllable will return to the base. --- Use the method @{#AI_PATROLZONE.ManageFuel}() to have this proces in place. +-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, +-- while a new AI is targetted to the AI_PATROL_ZONE. +-- Once the time is finished, the old AI will return to the base. +-- Use the method @{#AI_PATROL_ZONE.ManageFuel}() to have this proces in place. +-- +-- ## 1.7) Manage "damage" behaviour of the AI in the AI_PATROL_ZONE +-- +-- When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on. +-- Therefore, when the damage treshold is reached, the AI will return immediately to the home base (RTB). +-- Use the method @{#AI_PATROL_ZONE.ManageDamage}() to have this proces in place. -- -- ==== -- --- **API CHANGE HISTORY** --- ====================== +-- # **OPEN ISSUES** +-- +-- 2017-01-17: When Spawned AI is located at an airbase, it will be routed first back to the airbase after take-off. +-- +-- 2016-01-17: +-- -- Fixed problem with AI returning to base too early and unexpected. +-- -- ReSpawning of AI will reset the AI_PATROL and derived classes. +-- -- Checked the correct workings of SCHEDULER, and it DOES work correctly. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** -- -- The underlying change log documents the API changes. Please read this carefully. The following notation is used: -- @@ -24427,87 +24783,283 @@ end -- -- Hereby the change log: -- +-- 2017-01-17: Rename of class: **AI\_PATROL\_ZONE** is the new name for the old _AI\_PATROLZONE_. +-- +-- 2017-01-15: Complete revision. AI_PATROL_ZONE is the base class for other AI_PATROL like classes. +-- -- 2016-09-01: Initial class and API. -- -- === -- --- AUTHORS and CONTRIBUTIONS --- ========================= +-- # **AUTHORS and CONTRIBUTIONS** -- -- ### Contributions: -- --- * **DutchBaron**: Testing. --- * **Pikey**: Testing and API concept review. +-- * **[Dutch_Baron](https://forums.eagle.ru/member.php?u=112075)**: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-) +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Testing and API concept review. -- -- ### Authors: -- -- * **FlightControl**: Design & Programming. -- --- --- @module Patrol +-- @module AI_Patrol --- State Transition Functions - ---- OnBefore State Transition Function --- @function [parent=#AI_PATROLZONE] OnBeforeRoute --- @param #AI_PATROLZONE self --- @param Wrapper.Controllable#CONTROLLABLE Controllable --- @return #boolean - ---- OnAfter State Transition Function --- @function [parent=#AI_PATROLZONE] OnAfterRoute --- @param #AI_PATROLZONE self --- @param Wrapper.Controllable#CONTROLLABLE Controllable - - - ---- AI_PATROLZONE class --- @type AI_PATROLZONE +--- AI_PATROL_ZONE class +-- @type AI_PATROL_ZONE -- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. -- @field Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @field Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @field Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @field Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @field Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @field Functional.Spawn#SPAWN CoordTest -- @extends Core.Fsm#FSM_CONTROLLABLE -AI_PATROLZONE = { - ClassName = "AI_PATROLZONE", +AI_PATROL_ZONE = { + ClassName = "AI_PATROL_ZONE", } - - ---- Creates a new AI_PATROLZONE object --- @param #AI_PATROLZONE self +--- Creates a new AI_PATROL_ZONE object +-- @param #AI_PATROL_ZONE self -- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. -- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. -- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. -- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. --- @return #AI_PATROLZONE self +-- @return #AI_PATROL_ZONE self -- @usage --- -- Define a new AI_PATROLZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. +-- -- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h. -- PatrolZone = ZONE:New( 'PatrolZone' ) -- PatrolSpawn = SPAWN:New( 'Patrol Group' ) --- PatrolArea = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 600, 900 ) -function AI_PATROLZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) +-- PatrolArea = AI_PATROL_ZONE:New( PatrolZone, 3000, 6000, 600, 900 ) +function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) -- Inherits from BASE - local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- Core.Fsm#FSM_CONTROLLABLE + local self = BASE:Inherit( self, FSM_CONTROLLABLE:New() ) -- #AI_PATROL_ZONE - self:SetStartState( "None" ) - self:AddTransition( "*", "Start", "Route" ) - self:AddTransition( "*", "Route", "Route" ) - self:AddTransition( { "Patrol", "Route" }, "Patrol", "Patrol" ) - self:AddTransition( "Patrol", "RTB", "RTB" ) - self:AddTransition( "*", "End", "End" ) - self:AddTransition( "*", "Dead", "End" ) self.PatrolZone = PatrolZone self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude self.PatrolMinSpeed = PatrolMinSpeed self.PatrolMaxSpeed = PatrolMaxSpeed + + self:SetDetectionOn() + self.CheckStatus = true + + self:ManageFuel( .2, 60 ) + self:ManageDamage( 1 ) + + self:SetDetectionInterval( 30 ) + + self.DetectedUnits = {} -- This table contains the targets detected during patrol. + + self:SetStartState( "None" ) + + self:AddTransition( "None", "Start", "Patrolling" ) + +--- OnBefore Transition Handler for Event Start. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeStart +-- @param #AI_PATROL_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 Start. +-- @function [parent=#AI_PATROL_ZONE] OnAfterStart +-- @param #AI_PATROL_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 Start. +-- @function [parent=#AI_PATROL_ZONE] Start +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Start. +-- @function [parent=#AI_PATROL_ZONE] __Start +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Patrolling. +-- @function [parent=#AI_PATROL_ZONE] OnLeavePatrolling +-- @param #AI_PATROL_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 Patrolling. +-- @function [parent=#AI_PATROL_ZONE] OnEnterPatrolling +-- @param #AI_PATROL_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( "Patrolling", "Route", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Route. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeRoute +-- @param #AI_PATROL_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 Route. +-- @function [parent=#AI_PATROL_ZONE] OnAfterRoute +-- @param #AI_PATROL_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 Route. +-- @function [parent=#AI_PATROL_ZONE] Route +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Route. +-- @function [parent=#AI_PATROL_ZONE] __Route +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Status", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Status. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeStatus +-- @param #AI_PATROL_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 Status. +-- @function [parent=#AI_PATROL_ZONE] OnAfterStatus +-- @param #AI_PATROL_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 Status. +-- @function [parent=#AI_PATROL_ZONE] Status +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Status. +-- @function [parent=#AI_PATROL_ZONE] __Status +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Detect", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Detect. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeDetect +-- @param #AI_PATROL_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 Detect. +-- @function [parent=#AI_PATROL_ZONE] OnAfterDetect +-- @param #AI_PATROL_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 Detect. +-- @function [parent=#AI_PATROL_ZONE] Detect +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Detect. +-- @function [parent=#AI_PATROL_ZONE] __Detect +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Detected", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event Detected. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeDetected +-- @param #AI_PATROL_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 Detected. +-- @function [parent=#AI_PATROL_ZONE] OnAfterDetected +-- @param #AI_PATROL_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 Detected. +-- @function [parent=#AI_PATROL_ZONE] Detected +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event Detected. +-- @function [parent=#AI_PATROL_ZONE] __Detected +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "RTB", "Returning" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + +--- OnBefore Transition Handler for Event RTB. +-- @function [parent=#AI_PATROL_ZONE] OnBeforeRTB +-- @param #AI_PATROL_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 RTB. +-- @function [parent=#AI_PATROL_ZONE] OnAfterRTB +-- @param #AI_PATROL_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 RTB. +-- @function [parent=#AI_PATROL_ZONE] RTB +-- @param #AI_PATROL_ZONE self + +--- Asynchronous Event Trigger for Event RTB. +-- @function [parent=#AI_PATROL_ZONE] __RTB +-- @param #AI_PATROL_ZONE self +-- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Returning. +-- @function [parent=#AI_PATROL_ZONE] OnLeaveReturning +-- @param #AI_PATROL_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 Returning. +-- @function [parent=#AI_PATROL_ZONE] OnEnterReturning +-- @param #AI_PATROL_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( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE. + return self end @@ -24515,11 +25067,11 @@ end --- Sets (modifies) the minimum and maximum speed of the patrol. --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. -- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetSpeed( PatrolMinSpeed, PatrolMaxSpeed ) self:F2( { PatrolMinSpeed, PatrolMaxSpeed } ) self.PatrolMinSpeed = PatrolMinSpeed @@ -24529,39 +25081,92 @@ end --- Sets the floor and ceiling altitude of the patrol. --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @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. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetAltitude( PatrolFloorAltitude, PatrolCeilingAltitude ) self:F2( { PatrolFloorAltitude, PatrolCeilingAltitude } ) self.PatrolFloorAltitude = PatrolFloorAltitude self.PatrolCeilingAltitude = PatrolCeilingAltitude end +-- * @{#AI_PATROL_ZONE.SetDetectionOn}(): Set the detection on. The AI will detect for targets. +-- * @{#AI_PATROL_ZONE.SetDetectionOff}(): Set the detection off, the AI will not detect for targets. The existing target list will NOT be erased. +--- Set the detection on. The AI will detect for targets. +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionOn() + self:F2() + + self.DetectUnits = true +end ---- @param Wrapper.Controllable#CONTROLLABLE AIControllable -function _NewPatrolRoute( AIControllable ) +--- Set the detection off. The AI will NOT detect for targets. +-- However, the list of already detected targets will be kept and can be enquired! +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionOff() + self:F2() + + self.DetectUnits = false +end - AIControllable:T( "NewPatrolRoute" ) - local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROLZONE - PatrolZone:__Route( 1 ) +--- Set the interval in seconds between each detection executed by the AI. +-- The list of already detected targets will be kept and updated. +-- Newly detected targets will be added, but already detected targets that were +-- not detected in this cycle, will NOT be removed! +-- The default interval is 30 seconds. +-- @param #AI_PATROL_ZONE self +-- @param #number Seconds The interval in seconds. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionInterval( Seconds ) + self:F2() + + if Seconds then + self.DetectInterval = Seconds + else + self.DetectInterval = 30 + end +end + +--- Set the detection zone where the AI is detecting targets. +-- @param #AI_PATROL_ZONE self +-- @param Core.Zone#ZONE DetectionZone The zone where to detect targets. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:SetDetectionZone( DetectionZone ) + self:F2() + + if DetectionZone then + self.DetectZone = DetectionZone + else + self.DetectZone = nil + end +end + +--- Gets a list of @{Wrapper.Unit#UNIT}s that were detected by the AI. +-- No filtering is applied, so, ANY detected UNIT can be in this list. +-- It is up to the mission designer to use the @{Unit} class and methods to filter the targets. +-- @param #AI_PATROL_ZONE self +-- @return #table The list of @{Wrapper.Unit#UNIT}s +function AI_PATROL_ZONE:GetDetectedUnits() + self:F2() + + return self.DetectedUnits end - - ---- When the AIControllable is out of fuel, it is required that a new AIControllable is started, before the old AIControllable can return to the home base. +--- When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. -- Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. --- When the fuel treshold is reached, the AIControllable will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROLZONE. --- Once the time is finished, the old AIControllable will return to the base. --- @param #AI_PATROLZONE self +-- When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AI_PATROL_ZONE. +-- Once the time is finished, the old AI will return to the base. +-- @param #AI_PATROL_ZONE self -- @param #number PatrolFuelTresholdPercentage The treshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel. -- @param #number PatrolOutOfFuelOrbitTime The amount of seconds the out of fuel AIControllable will orbit before returning to the base. --- @return #AI_PATROLZONE self -function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime ) +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime ) self.PatrolManageFuel = true self.PatrolFuelTresholdPercentage = PatrolFuelTresholdPercentage @@ -24570,60 +25175,165 @@ function AI_PATROLZONE:ManageFuel( PatrolFuelTresholdPercentage, PatrolOutOfFuel return self end +--- When the AI is damaged beyond a certain treshold, it is required that the AI returns to the home base. +-- However, damage cannot be foreseen early on. +-- Therefore, when the damage treshold is reached, +-- the AI will return immediately to the home base (RTB). +-- Note that for groups, the average damage of the complete group will be calculated. +-- So, in a group of 4 airplanes, 2 lost and 2 with damage 0.2, the damage treshold will be 0.25. +-- @param #AI_PATROL_ZONE self +-- @param #number PatrolDamageTreshold The treshold in percentage (between 0 and 1) when the AI is considered to be damaged. +-- @return #AI_PATROL_ZONE self +function AI_PATROL_ZONE:ManageDamage( PatrolDamageTreshold ) + + self.PatrolManageDamage = true + self.PatrolDamageTreshold = PatrolDamageTreshold + + return self +end + --- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. --- @param #AI_PATROLZONE self --- @return #AI_PATROLZONE self -function AI_PATROLZONE:onenterRoute() +-- @param #AI_PATROL_ZONE self +-- @return #AI_PATROL_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_PATROL_ZONE:onafterStart( Controllable, From, Event, To ) + self:F2() + + self:__Route( 5 ) -- Route to the patrol point. The asynchronous trigger is important, because a spawned group and units takes at least one second to come live. + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every 30 seconds. + + Controllable:OptionROEHoldFire() + Controllable:OptionROTVertical() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + + +--- @param #AI_PATROL_ZONE self +--- @param Wrapper.Controllable#CONTROLLABLE Controllable +function AI_PATROL_ZONE:onbeforeDetect( Controllable, From, Event, To ) + + return self.DetectUnits +end + +--- @param #AI_PATROL_ZONE self +--- @param Wrapper.Controllable#CONTROLLABLE Controllable +function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To ) + + local Detected = false + + local DetectedTargets = Controllable:GetDetectedTargets() + for TargetID, Target in pairs( DetectedTargets or {} ) do + local TargetObject = Target.object + self:T( TargetObject ) + if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then + + local TargetUnit = UNIT:Find( TargetObject ) + local TargetUnitName = TargetUnit:GetName() + + if self.DetectionZone then + if TargetUnit:IsInZone( self.DetectionZone ) then + self:T( {"Detected ", TargetUnit } ) + self.DetectedUnits[TargetUnit] = TargetUnit + Detected = true + end + else + self.DetectedUnits[TargetUnit] = TargetUnit + Detected = true + end + end + end + + if Detected == true then + self:__Detected( 1 ) + end + + self:__Detect( self.DetectInterval ) +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +-- This statis method is called from the route path within the last task at the last waaypoint of the Controllable. +-- Note that this method is required, as triggers the next route when patrolling for the Controllable. +function AI_PATROL_ZONE:_NewPatrolRoute( AIControllable ) + + local PatrolZone = AIControllable:GetState( AIControllable, "PatrolZone" ) -- PatrolCore.Zone#AI_PATROL_ZONE + PatrolZone:__Route( 1 ) +end + + +--- Defines a new patrol route using the @{Process_PatrolZone} parameters and settings. +-- @param #AI_PATROL_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_PATROL_ZONE:onafterRoute( Controllable, From, Event, To ) self:F2() - local PatrolRoute = {} + -- When RTB, don't allow anymore the routing. + if From == "RTB" then + return + end + if self.Controllable:IsAlive() then - --- Determine if the AIControllable is within the PatrolZone. + -- Determine if the AIControllable is within the PatrolZone. -- If not, make a waypoint within the to that the AIControllable will fly at maximum speed to that point. --- --- Calculate the current route point. --- local CurrentVec2 = self.Controllable:GetVec2() --- local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() --- local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) --- local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( --- POINT_VEC3.RoutePointAltType.BARO, --- POINT_VEC3.RoutePointType.TurningPoint, --- POINT_VEC3.RoutePointAction.TurningPoint, --- ToPatrolZoneSpeed, --- true --- ) --- --- PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + local PatrolRoute = {} + + -- Calculate the current route point of the controllable as the start point of the route. + -- However, when the controllable is not in the air, + -- the controllable current waypoint is probably the airbase... + -- Thus, if we would take the current waypoint as the startpoint, upon take-off, the controllable flies + -- immediately back to the airbase, and this is not correct. + -- Therefore, when on a runway, get as the current route point a random point within the PatrolZone. + -- This will make the plane fly immediately to the patrol zone. - self:T2( PatrolRoute ) - - if self.Controllable:IsNotInZone( self.PatrolZone ) then - --- Find a random 2D point in PatrolZone. - local ToPatrolZoneVec2 = self.PatrolZone:GetRandomVec2() - self:T2( ToPatrolZoneVec2 ) - - --- Define Speed and Altitude. - local ToPatrolZoneAltitude = math.random( self.PatrolFloorAltitude, self.PatrolCeilingAltitude ) + if self.Controllable:InAir() == false then + self:E( "Not in the air, finding route path within PatrolZone" ) + 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed - self:T2( ToPatrolZoneSpeed ) - - --- Obtain a 3D @{Point} from the 2D point + altitude. - local ToPatrolZonePointVec3 = POINT_VEC3:New( ToPatrolZoneVec2.x, ToPatrolZoneAltitude, ToPatrolZoneVec2.y ) - - --- Create a route point of type air. - local ToPatrolZoneRoutePoint = ToPatrolZonePointVec3:RoutePointAir( - POINT_VEC3.RoutePointAltType.BARO, - POINT_VEC3.RoutePointType.TurningPoint, - POINT_VEC3.RoutePointAction.TurningPoint, - ToPatrolZoneSpeed, - true - ) - - PatrolRoute[#PatrolRoute+1] = ToPatrolZoneRoutePoint - - end + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TakeOffParking, + POINT_VEC3.RoutePointAction.FromParkingArea, + ToPatrolZoneSpeed, + true + ) + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + else + self:E( "In the air, finding route path within PatrolZone" ) + 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToPatrolZoneSpeed, + true + ) + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + end + --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. @@ -24648,6 +25358,8 @@ function AI_PATROLZONE:onenterRoute() true ) + --self.CoordTest:SpawnFromVec3( ToTargetPointVec3:GetVec3() ) + --ToTargetPointVec3:SmokeRed() PatrolRoute[#PatrolRoute+1] = ToTargetRoutePoint @@ -24657,25 +25369,31 @@ function AI_PATROLZONE:onenterRoute() --- Do a trick, link the NewPatrolRoute function of the PATROLGROUP object to the AIControllable in a temporary variable ... self.Controllable:SetState( self.Controllable, "PatrolZone", self ) - self.Controllable:WayPointFunction( #PatrolRoute, 1, "_NewPatrolRoute" ) + self.Controllable:WayPointFunction( #PatrolRoute, 1, "AI_PATROL_ZONE:_NewPatrolRoute" ) - --- NOW ACT_ROUTE THE GROUP! - self.Controllable:WayPointExecute( 1 ) - - self:__Patrol( 30 ) + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) end - + end +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onbeforeStatus() ---- @param #AI_PATROLZONE self -function AI_PATROLZONE:onenterPatrol() + return self.CheckStatus +end + +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onafterStatus() self:F2() if self.Controllable and self.Controllable:IsAlive() then + local RTB = false + local Fuel = self.Controllable:GetUnit(1):GetFuel() if Fuel < self.PatrolFuelTresholdPercentage then + self:E( self.Controllable:GetName() .. " is out of fuel:" .. Fuel .. ", RTB!" ) local OldAIControllable = self.Controllable local AIControllableTemplate = self.Controllable:GetTemplate() @@ -24683,14 +25401,1145 @@ function AI_PATROLZONE:onenterPatrol() local TimedOrbitTask = OldAIControllable:TaskControlled( OrbitTask, OldAIControllable:TaskCondition(nil,nil,nil,nil,self.PatrolOutOfFuelOrbitTime,nil ) ) OldAIControllable:SetTask( TimedOrbitTask, 10 ) + RTB = true + else + end + + -- TODO: Check GROUP damage function. + local Damage = self.Controllable:GetLife() + if Damage <= self.PatrolDamageTreshold then + self:E( self.Controllable:GetName() .. " is damaged:" .. Damage .. ", RTB!" ) + RTB = true + end + + if RTB == true then self:RTB() else - self:__Patrol( 30 ) -- Execute the Patrol event after 30 seconds. + self:__Status( 30 ) -- Execute the Patrol event after 30 seconds. end end +end + +--- @param #AI_PATROL_ZONE self +function AI_PATROL_ZONE:onafterRTB() + self:F2() + + if self.Controllable and self.Controllable:IsAlive() then + + self:SetDetectionOff() + self.CheckStatus = false + + local PatrolRoute = {} + + --- 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 ToPatrolZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToPatrolZoneSpeed, + true + ) + + PatrolRoute[#PatrolRoute+1] = CurrentRoutePoint + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( PatrolRoute ) + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 1 ) + + end + +end +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.** +-- +-- ![Banner Image](..\Presentations\AI_Cas\Dia1.JPG) +-- +-- +-- === +-- +-- # 1) @{#AI_CAS_ZONE} class, extends @{AI.AI_Patrol#AI_PATROL_ZONE} +-- +-- @{#AI_CAS_ZONE} derives from the @{AI.AI_Patrol#AI_PATROL_ZONE}, inheriting its methods and behaviour. +-- +-- The @{#AI_CAS_ZONE} class implements the core functions to provide Close Air Support in an Engage @{Zone} by an AIR @{Controllable} or @{Group}. +-- The AI_CAS_ZONE runs a process. It holds an AI in a Patrol Zone and when the AI is commanded to engage, it will fly to an Engage Zone. +-- +-- ![HoldAndEngage](..\Presentations\AI_Cas\Dia3.JPG) +-- +-- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event. +-- +-- ![Start Event](..\Presentations\AI_Cas\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_Cas\Dia5.JPG) +-- +-- When the AI is commanded to provide Close Air Support (through the event **Engage**), the AI will fly towards the Engage Zone. +-- Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia6.JPG) +-- +-- The AI will detect the targets and will only destroy the targets within the Engage Zone. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia7.JPG) +-- +-- Every target that is destroyed, is reported< by the AI. +-- +-- ![Engage Event](..\Presentations\AI_Cas\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_Cas\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_Cas\Dia10.JPG) +-- +-- When the AI has accomplished the CAS, it will fly back to the Patrol Zone. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia11.JPG) +-- +-- It will keep patrolling there, until it is notified to RTB or move to another CAS Zone. +-- It can be notified to go RTB through the **RTB** event. +-- +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Engage Event](..\Presentations\AI_Cas\Dia12.JPG) +-- +-- # 1.1) AI_CAS_ZONE constructor +-- +-- * @{#AI_CAS_ZONE.New}(): Creates a new AI_CAS_ZONE object. +-- +-- ## 1.2) AI_CAS_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_Cas\Dia2.JPG) +-- +-- ### 1.2.1) AI_CAS_ZONE States +-- +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Engaging** ( Group ): The AI is engaging the targets in the Engage Zone, executing CAS. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 1.2.2) AI_CAS_ZONE Events +-- +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **Engage** ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** +-- +-- The underlying change log documents the API changes. Please read this carefully. The following notation is used: +-- +-- * **Added** parts are expressed in bold type face. +-- * _Removed_ parts are expressed in italic type face. +-- +-- Hereby the change log: +-- +-- 2017-01-15: Initial class and API. +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Cas + + +--- AI_CAS_ZONE class +-- @type AI_CAS_ZONE +-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @extends AI.AI_Patrol#AI_CAS_ZONE +AI_CAS_ZONE = { + ClassName = "AI_CAS_ZONE", +} + + + +--- Creates a new AI_CAS_ZONE object +-- @param #AI_CAS_ZONE self +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. +-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @param Core.Zone#ZONE EngageZone +-- @return #AI_CAS_ZONE self +function AI_CAS_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed, EngageZone ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAS_ZONE + + self.EngageZone = EngageZone + self.Accomplished = false + + self:SetDetectionZone( self.EngageZone ) + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_CAS_ZONE] OnBeforeEngage + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Engage. + -- @function [parent=#AI_CAS_ZONE] OnAfterEngage + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAS_ZONE] Engage + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAS_ZONE] __Engage + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_CAS_ZONE] OnLeaveEngaging +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @return #boolean Return false to cancel Transition. + +--- OnEnter Transition Handler for State Engaging. +-- @function [parent=#AI_CAS_ZONE] OnEnterEngaging +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_CAS_ZONE] OnBeforeFired + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Fired. + -- @function [parent=#AI_CAS_ZONE] OnAfterFired + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAS_ZONE] Fired + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAS_ZONE] __Fired + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] OnBeforeDestroy + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] OnAfterDestroy + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] Destroy + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAS_ZONE] __Destroy + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_CAS_ZONE] OnBeforeAbort + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Abort. + -- @function [parent=#AI_CAS_ZONE] OnAfterAbort + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAS_ZONE] Abort + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAS_ZONE] __Abort + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAS_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] OnBeforeAccomplish + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] OnAfterAccomplish + -- @param #AI_CAS_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] Accomplish + -- @param #AI_CAS_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAS_ZONE] __Accomplish + -- @param #AI_CAS_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone where the AI is performing CAS. Note that if the EngageZone is changed, the AI needs to re-detect targets. +-- @param #AI_CAS_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAS. +-- @return #AI_CAS_ZONE self +function AI_CAS_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + + + +--- onafter State Transition for Event Start. +-- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To ) + + + self:Route() + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone. + + self:EventOnDead( self.OnDead ) + + Controllable:OptionROEHoldFire() + Controllable:OptionROTVertical() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) end ---- Management of logical cargo objects, that can be transported from and to transportation carriers. + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cas#AI_CAS_ZONE + EngageZone:__Engage( 1 ) +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To ) + + if Controllable:IsAlive() then + + self:Detect( self.EngageZone ) + + local EngageRoute = {} + + --- Calculate the current route point. + local CurrentVec2 = self.Controllable:GetVec2() + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() + local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + + if self.Controllable:IsNotInZone( self.EngageZone ) then + + -- Find a random 2D point in EngageZone. + local ToEngageZoneVec2 = self.EngageZone:GetRandomVec2() + self:T2( ToEngageZoneVec2 ) + + -- Define Speed and Altitude. + local ToEngageZoneAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + self:T2( ToEngageZoneSpeed ) + + -- Obtain a 3D @{Point} from the 2D point + altitude. + local ToEngageZonePointVec3 = POINT_VEC3:New( ToEngageZoneVec2.x, ToEngageZoneAltitude, ToEngageZoneVec2.y ) + + -- Create a route point of type air. + local ToEngageZoneRoutePoint = ToEngageZonePointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToEngageZoneRoutePoint + + end + + --- Define a random point in the @{Zone}. The AI will fly to that point within the zone. + + --- Find a random 2D point in EngageZone. + local ToTargetVec2 = self.EngageZone:GetRandomVec2() + self:T2( ToTargetVec2 ) + + --- Define Speed and Altitude. + local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToTargetRoutePoint = ToTargetPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + ToTargetPointVec3:SmokeBlue() + + EngageRoute[#EngageRoute+1] = ToTargetRoutePoint + + + Controllable:OptionROEOpenFire() + Controllable:OptionROTPassiveDefense() + + local AttackTasks = {} + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:E( {"Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + + EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( EngageRoute ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + self.Controllable:SetState( self.Controllable, "EngageZone", self ) + + self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageRoute" ) + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) + end +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @param Core.Event#EVENTDATA EventData +function AI_CAS_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end + + Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" ) +end + +--- @param #AI_CAS_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self.DetectUnits = false +end + +--- @param #AI_CAS_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_CAS_ZONE:OnDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Destroy( 1, EventData ) + end +end + + +--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Execute Combat Air Patrol (CAP).** +-- +-- ![Banner Image](..\Presentations\AI_Cap\Dia1.JPG) +-- +-- +-- === +-- +-- # 1) @{#AI_CAP_ZONE} class, extends @{AI.AI_Cap#AI_PATROL_ZONE} +-- +-- The @{#AI_CAP_ZONE} class implements the core functions to patrol a @{Zone} by an AI @{Controllable} or @{Group} +-- and automatically engage any airborne enemies that are within a certain range or within a certain zone. +-- +-- ![Process](..\Presentations\AI_Cap\Dia3.JPG) +-- +-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event. +-- +-- ![Process](..\Presentations\AI_Cap\Dia4.JPG) +-- +-- The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +-- Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits. +-- +-- ![Process](..\Presentations\AI_Cap\Dia5.JPG) +-- +-- This cycle will continue. +-- +-- ![Process](..\Presentations\AI_Cap\Dia6.JPG) +-- +-- During the patrol, the AI will detect enemy targets, which are reported through the **Detected** event. +-- +-- ![Process](..\Presentations\AI_Cap\Dia9.JPG) +-- +-- When enemies are detected, the AI will automatically engage the enemy. +-- +-- ![Process](..\Presentations\AI_Cap\Dia10.JPG) +-- +-- Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. +-- When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land. +-- +-- ![Process](..\Presentations\AI_Cap\Dia13.JPG) +-- +-- ## 1.1) AI_CAP_ZONE constructor +-- +-- * @{#AI_CAP_ZONE.New}(): Creates a new AI_CAP_ZONE object. +-- +-- ## 1.2) AI_CAP_ZONE is a FSM +-- +-- ![Process](..\Presentations\AI_Cap\Dia2.JPG) +-- +-- ### 1.2.1) AI_CAP_ZONE States +-- +-- * **None** ( Group ): The process is not started yet. +-- * **Patrolling** ( Group ): The AI is patrolling the Patrol Zone. +-- * **Engaging** ( Group ): The AI is engaging the bogeys. +-- * **Returning** ( Group ): The AI is returning to Base.. +-- +-- ### 1.2.2) AI_CAP_ZONE Events +-- +-- * **Start** ( Group ): Start the process. +-- * **Route** ( Group ): Route the AI to a new random 3D point within the Patrol Zone. +-- * **Engage** ( Group ): Let the AI engage the bogeys. +-- * **RTB** ( Group ): Route the AI to the home base. +-- * **Detect** ( Group ): The AI is detecting targets. +-- * **Detected** ( Group ): The AI has detected new targets. +-- * **Status** ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB. +-- +-- ## 1.3) Set the Range of Engagement +-- +-- ![Range](..\Presentations\AI_Cap\Dia11.JPG) +-- +-- An optional range can be set in meters, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- The range can be beyond or smaller than the range of the Patrol Zone. +-- The range is applied at the position of the AI. +-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageRange}() to define that range. +-- +-- ## 1.4) Set the Zone of Engagement +-- +-- ![Zone](..\Presentations\AI_Cap\Dia12.JPG) +-- +-- An optional @{Zone} can be set, +-- that will define when the AI will engage with the detected airborne enemy targets. +-- Use the method @{AI.AI_Cap#AI_CAP_ZONE.SetEngageZone}() to define that Zone. +-- +-- ==== +-- +-- # **API CHANGE HISTORY** +-- +-- The underlying change log documents the API changes. Please read this carefully. The following notation is used: +-- +-- * **Added** parts are expressed in bold type face. +-- * _Removed_ parts are expressed in italic type face. +-- +-- Hereby the change log: +-- +-- 2017-01-15: Initial class and API. +-- +-- === +-- +-- # **AUTHORS and CONTRIBUTIONS** +-- +-- ### Contributions: +-- +-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing. +-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing. +-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision. +-- +-- ### Authors: +-- +-- * **FlightControl**: Concept, Design & Programming. +-- +-- @module AI_Cap + + +--- AI_CAP_ZONE class +-- @type AI_CAP_ZONE +-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling. +-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed. +-- @extends AI.AI_Patrol#AI_PATROL_ZONE +AI_CAP_ZONE = { + ClassName = "AI_CAP_ZONE", +} + + + +--- Creates a new AI_CAP_ZONE object +-- @param #AI_CAP_ZONE self +-- @param Core.Zone#ZONE_BASE PatrolZone The @{Zone} where the patrol needs to be executed. +-- @param Dcs.DCSTypes#Altitude PatrolFloorAltitude The lowest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Altitude PatrolCeilingAltitude The highest altitude in meters where to execute the patrol. +-- @param Dcs.DCSTypes#Speed PatrolMinSpeed The minimum speed of the @{Controllable} in km/h. +-- @param Dcs.DCSTypes#Speed PatrolMaxSpeed The maximum speed of the @{Controllable} in km/h. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) + + -- Inherits from BASE + local self = BASE:Inherit( self, AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed ) ) -- #AI_CAP_ZONE + + self.Accomplished = false + self.Engaging = false + + self:AddTransition( { "Patrolling", "Engaging" }, "Engage", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Engage. + -- @function [parent=#AI_CAP_ZONE] OnBeforeEngage + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Engage. + -- @function [parent=#AI_CAP_ZONE] OnAfterEngage + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAP_ZONE] Engage + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Engage. + -- @function [parent=#AI_CAP_ZONE] __Engage + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + +--- OnLeave Transition Handler for State Engaging. +-- @function [parent=#AI_CAP_ZONE] OnLeaveEngaging +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @return #boolean Return false to cancel Transition. + +--- OnEnter Transition Handler for State Engaging. +-- @function [parent=#AI_CAP_ZONE] OnEnterEngaging +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. + + self:AddTransition( "Engaging", "Fired", "Engaging" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Fired. + -- @function [parent=#AI_CAP_ZONE] OnBeforeFired + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Fired. + -- @function [parent=#AI_CAP_ZONE] OnAfterFired + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAP_ZONE] Fired + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Fired. + -- @function [parent=#AI_CAP_ZONE] __Fired + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "*", "Destroy", "*" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] OnBeforeDestroy + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] OnAfterDestroy + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] Destroy + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Destroy. + -- @function [parent=#AI_CAP_ZONE] __Destroy + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + + self:AddTransition( "Engaging", "Abort", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Abort. + -- @function [parent=#AI_CAP_ZONE] OnBeforeAbort + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Abort. + -- @function [parent=#AI_CAP_ZONE] OnAfterAbort + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAP_ZONE] Abort + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Abort. + -- @function [parent=#AI_CAP_ZONE] __Abort + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + self:AddTransition( "Engaging", "Accomplish", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_CAP_ZONE. + + --- OnBefore Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] OnBeforeAccomplish + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + -- @return #boolean Return false to cancel Transition. + + --- OnAfter Transition Handler for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] OnAfterAccomplish + -- @param #AI_CAP_ZONE self + -- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. + -- @param #string From The From State string. + -- @param #string Event The Event string. + -- @param #string To The To State string. + + --- Synchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] Accomplish + -- @param #AI_CAP_ZONE self + + --- Asynchronous Event Trigger for Event Accomplish. + -- @function [parent=#AI_CAP_ZONE] __Accomplish + -- @param #AI_CAP_ZONE self + -- @param #number Delay The delay in seconds. + + return self +end + + +--- Set the Engage Zone which defines where the AI will engage bogies. +-- @param #AI_CAP_ZONE self +-- @param Core.Zone#ZONE EngageZone The zone where the AI is performing CAP. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:SetEngageZone( EngageZone ) + self:F2() + + if EngageZone then + self.EngageZone = EngageZone + else + self.EngageZone = nil + end +end + +--- Set the Engage Range when the AI will engage with airborne enemies. +-- @param #AI_CAP_ZONE self +-- @param #number EngageRange The Engage Range. +-- @return #AI_CAP_ZONE self +function AI_CAP_ZONE:SetEngageRange( EngageRange ) + self:F2() + + if EngageRange then + self.EngageRange = EngageRange + else + self.EngageRange = nil + end +end + +--- onafter State Transition for Event Start. +-- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To ) + + + self:Route() + self:__Status( 30 ) -- Check status status every 30 seconds. + self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone. + + self:EventOnDead( self.OnDead ) + + Controllable:OptionROEOpenFire() + + self.Controllable:OnReSpawn( + function( PatrolGroup ) + self:E( "ReSpawn" ) + self:__Reset() + self:__Route( 5 ) + end + ) + +end + +--- @param Wrapper.Controllable#CONTROLLABLE AIControllable +function _NewEngageCapRoute( AIControllable ) + + AIControllable:T( "NewEngageRoute" ) + local EngageZone = AIControllable:GetState( AIControllable, "EngageZone" ) -- AI.AI_Cap#AI_CAP_ZONE + EngageZone:__Engage( 1 ) +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onbeforeEngage( Controllable, From, Event, To ) + + if self.Accomplished == true then + return false + end +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterDetected( Controllable, From, Event, To ) + + if From ~= "Engaging" then + + local Engage = false + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then + Engage = true + break + end + end + + if Engage == true then + self:E( 'Detected -> Engaging' ) + self:__Engage( 1 ) + end + end +end + + + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To ) + + if Controllable:IsAlive() then + + self:Detect( self.EngageZone ) + + local EngageRoute = {} + + --- Calculate the current route point. + local CurrentVec2 = self.Controllable:GetVec2() + + --TODO: Create GetAltitude function for GROUP, and delete GetUnit(1). + local CurrentAltitude = self.Controllable:GetUnit(1):GetAltitude() + local CurrentPointVec3 = POINT_VEC3:New( CurrentVec2.x, CurrentAltitude, CurrentVec2.y ) + local ToEngageZoneSpeed = self.PatrolMaxSpeed + local CurrentRoutePoint = CurrentPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToEngageZoneSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = CurrentRoutePoint + + + --- Find a random 2D point in PatrolZone. + local ToTargetVec2 = self.PatrolZone:GetRandomVec2() + self:T2( ToTargetVec2 ) + + --- Define Speed and Altitude. + local ToTargetAltitude = math.random( self.EngageFloorAltitude, self.EngageCeilingAltitude ) + local ToTargetSpeed = math.random( self.PatrolMinSpeed, self.PatrolMaxSpeed ) + self:T2( { self.PatrolMinSpeed, self.PatrolMaxSpeed, ToTargetSpeed } ) + + --- Obtain a 3D @{Point} from the 2D point + altitude. + local ToTargetPointVec3 = POINT_VEC3:New( ToTargetVec2.x, ToTargetAltitude, ToTargetVec2.y ) + + --- Create a route point of type air. + local ToPatrolRoutePoint = ToTargetPointVec3:RoutePointAir( + POINT_VEC3.RoutePointAltType.BARO, + POINT_VEC3.RoutePointType.TurningPoint, + POINT_VEC3.RoutePointAction.TurningPoint, + ToTargetSpeed, + true + ) + + EngageRoute[#EngageRoute+1] = ToPatrolRoutePoint + + Controllable:OptionROEOpenFire() + Controllable:OptionROTPassiveDefense() + + local AttackTasks = {} + + for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do + local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT + self:T( DetectedUnit ) + if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then + if self.EngageZone then + if DetectedUnit:IsInZone( self.EngageZone ) then + self:E( {"Within Zone and Engaging ", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + if self.EngageRange then + if DetectedUnit:GetPointVec3():Get2DDistance(Controllable:GetPointVec3() ) <= self.EngageRange then + self:E( {"Within Range and Engaging", DetectedUnit } ) + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + else + AttackTasks[#AttackTasks+1] = Controllable:TaskAttackUnit( DetectedUnit ) + end + end + else + self.DetectedUnits[DetectedUnit] = nil + end + end + + --- Now we're going to do something special, we're going to call a function from a waypoint action at the AIControllable... + self.Controllable:WayPointInitialize( EngageRoute ) + + + if #AttackTasks == 0 then + self:E("No targets found -> Going back to Patrolling") + self:Accomplish() + self:Route() + else + EngageRoute[1].task = Controllable:TaskCombo( AttackTasks ) + + --- Do a trick, link the NewEngageRoute function of the object to the AIControllable in a temporary variable ... + self.Controllable:SetState( self.Controllable, "EngageZone", self ) + + self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" ) + + end + + --- NOW ROUTE THE GROUP! + self.Controllable:WayPointExecute( 1, 2 ) + + end +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +-- @param Core.Event#EVENTDATA EventData +function AI_CAP_ZONE:onafterDestroy( Controllable, From, Event, To, EventData ) + + if EventData.IniUnit then + self.DetectedUnits[EventData.IniUnit] = nil + end + + Controllable:MessageToAll( "Destroyed a target", 15 , "Destroyed!" ) +end + +--- @param #AI_CAP_ZONE self +-- @param Wrapper.Controllable#CONTROLLABLE Controllable The Controllable Object managed by the FSM. +-- @param #string From The From State string. +-- @param #string Event The Event string. +-- @param #string To The To State string. +function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To ) + self.Accomplished = true + self.DetectUnits = false +end + +--- @param #AI_CAP_ZONE self +-- @param Core.Event#EVENTDATA EventData +function AI_CAP_ZONE:OnDead( EventData ) + self:T( { "EventDead", EventData } ) + + if EventData.IniDCSUnit then + self:__Destroy( 1, EventData ) + end +end + + +--- Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers. -- -- === -- @@ -24734,14 +26583,14 @@ end -- State transition functions can be set **by the mission designer** customizing or improving the behaviour of the state. -- There are 2 moments when state transition methods will be called by the state machine: -- --- * **Before** the state transition. --- The state transition method needs to start with the name **OnBefore + the name of the state**. +-- * **Leaving** the state. +-- The state transition method needs to start with the name **OnLeave + the name of the state**. -- If the state transition method returns false, then the processing of the state transition will not be done! -- If you want to change the behaviour of the AIControllable at this event, return false, -- but then you'll need to specify your own logic using the AIControllable! -- --- * **After** the state transition. --- The state transition method needs to start with the name **OnAfter + the name of the state**. +-- * **Entering** the state. +-- The state transition method needs to start with the name **OnEnter + the name of the state**. -- These state transition methods need to provide a return value, which is specified at the function description. -- -- 2) #AI_CARGO_UNIT class @@ -24827,45 +26676,45 @@ end -- UnLoaded ---- @function [parent=#AI_CARGO] OnBeforeUnLoaded +--- @function [parent=#AI_CARGO] OnLeaveUnLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterUnLoaded +--- @function [parent=#AI_CARGO] OnEnterUnLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- Loaded ---- @function [parent=#AI_CARGO] OnBeforeLoaded +--- @function [parent=#AI_CARGO] OnLeaveLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterLoaded +--- @function [parent=#AI_CARGO] OnEnterLoaded -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- Boarding ---- @function [parent=#AI_CARGO] OnBeforeBoarding +--- @function [parent=#AI_CARGO] OnLeaveBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterBoarding +--- @function [parent=#AI_CARGO] OnEnterBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- UnBoarding ---- @function [parent=#AI_CARGO] OnBeforeUnBoarding +--- @function [parent=#AI_CARGO] OnLeaveUnBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable -- @return #boolean ---- @function [parent=#AI_CARGO] OnAfterUnBoarding +--- @function [parent=#AI_CARGO] OnEnterUnBoarding -- @param #AI_CARGO self -- @param Wrapper.Controllable#CONTROLLABLE Controllable @@ -29681,6 +31530,8 @@ Include.File( "Functional/Detection" ) --- AI Classes Include.File( "AI/AI_Balancer" ) Include.File( "AI/AI_Patrol" ) +Include.File( "AI/AI_Cap" ) +Include.File( "AI/AI_Cas" ) Include.File( "AI/AI_Cargo" ) --- Actions diff --git a/Moose Mission Setup/Moose_Create.bat b/Moose Mission Setup/Moose_Create.bat index 151558dbe..ea27cb4f9 100644 --- a/Moose Mission Setup/Moose_Create.bat +++ b/Moose Mission Setup/Moose_Create.bat @@ -80,6 +80,8 @@ COPY /b Moose.lua + %1\Functional\Detection.lua Moose.lua rem AI Classes COPY /b Moose.lua + %1\AI\AI_Balancer.lua Moose.lua COPY /b Moose.lua + %1\AI\AI_Patrol.lua Moose.lua +COPY /b Moose.lua + %1\AI\AI_Cas.lua Moose.lua +COPY /b Moose.lua + %1\AI\AI_Cap.lua Moose.lua COPY /b Moose.lua + %1\AI\AI_Cargo.lua Moose.lua diff --git a/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz b/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz index 538b163e9..69b8190b6 100644 Binary files a/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz and b/Moose Test Missions/ABP - Airbase Police/APL-001 - Caucasus/APL-001 - Caucasus.miz differ diff --git a/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz b/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz index 317d23ea6..1f42080a9 100644 Binary files a/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz and b/Moose Test Missions/ABP - Airbase Police/APL-002 - Nevada/APL-002 - Nevada.miz differ diff --git a/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz b/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz index dc6469d77..196e7125e 100644 Binary files a/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz and b/Moose Test Missions/ACL - Airbase Cleaner/ACL-001 - Airbase CleanUp/ACL-001 - Airbase CleanUp.miz differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.lua b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.lua index bf9376140..5315ae2e7 100644 --- a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.lua +++ b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.lua @@ -1,8 +1,4 @@ ---- AI Spawning and Decomissioning --- --- === --- --- Name: Spawned AI +-- Name: AIB-001 - Spawned AI -- Author: FlightControl -- Date Created: 07 Dec 2016 -- @@ -18,13 +14,9 @@ -- 1. If no player is logging into the red slots, 2 red AI planes should be alive. -- 2. If a player joins one red slot, one red AI plane should return to the nearest home base. -- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base. --- --- # Status: TESTED 07 Dec 2016 --- --- @module TEST.AI_BALANCER.T001 -- Define the SET of CLIENTs from the red coalition. This SET is filled during startup. -local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ):FilterStart() +local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) -- Define the SPAWN object for the red AI plane template. -- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off. diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz new file mode 100644 index 000000000..d081431ac Binary files /dev/null and b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 - Spawned AI.miz differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 -Spawned AI.miz b/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 -Spawned AI.miz deleted file mode 100644 index 6b76be0dd..000000000 Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-001 - Spawned AI/AIB-001 -Spawned AI.miz and /dev/null differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.lua b/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.lua index a1347dbbe..158a8f5ee 100644 --- a/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.lua +++ b/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.lua @@ -1,8 +1,4 @@ ---- AI Patrolling --- --- === --- --- Name: Patrol AI +-- Name: AIB-002 - Patrol AI.lua -- Author: FlightControl -- Date Created: 7 December 2016 -- @@ -19,13 +15,9 @@ -- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base. -- 4. Spawned AI should take-off from the airbase, and start patrolling the area around Anapa. -- 5. When the AI is out-of-fuel, it should report it is returning to the home base, and land at Anapa. --- --- # Status: DEVELOP 07 Dec 2016 --- --- @module TEST.AI_BALANCER.T002 -- Define the SET of CLIENTs from the red coalition. This SET is filled during startup. -local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ):FilterStart() +local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) -- Define the SPAWN object for the red AI plane template. -- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off. @@ -35,15 +27,17 @@ local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) -- Start the AI_BALANCER, using the SET of red CLIENTs, and the SPAWN object as a parameter. local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) +local PatrolZones = {} + function RU_AI_Balancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) local PatrolZoneGroup = GROUP:FindByName( "PatrolZone" ) local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) - local Patrol = AI_PATROLZONE:New( PatrolZone, 3000, 6000, 400, 600 ) - Patrol:ManageFuel( 0.2, 60 ) - Patrol:SetControllable( AIGroup ) - Patrol:__Start( 5 ) + PatrolZones[AIGroup] = AI_PATROL_ZONE:New( PatrolZone, 3000, 6000, 400, 600 ) + PatrolZones[AIGroup]:ManageFuel( 0.2, 60 ) + PatrolZones[AIGroup]:SetControllable( AIGroup ) + PatrolZones[AIGroup]:__Start( 5 ) -end \ No newline at end of file +end diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz b/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz index ae5c9f127..ff179b0c7 100644 Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-002 - Patrol AI/AIB-002 - Patrol AI.miz differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.lua b/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.lua index ff37d8cdd..2f4a137ab 100644 --- a/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.lua +++ b/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.lua @@ -1,24 +1,24 @@ +RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) +RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) +RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) -local US_PlanesClientSet = SET_CLIENT:New():FilterCountries( "USA" ):FilterCategories( "plane" ):FilterStart() - -local US_PlanesSpawn = SPAWN:New( "AI US" ):InitCleanUp( 20 ) -local US_AI_Balancer = AI_BALANCER:New( US_PlanesClientSet, US_PlanesSpawn ) - -local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ):FilterStart() -local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) -local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) - -local RU_AirbasesSet = SET_AIRBASE:New():FilterCoalitions("red"):FilterStart() +RU_AirbasesSet = SET_AIRBASE:New():FilterCoalitions("red"):FilterStart() RU_AirbasesSet:Flush() RU_AI_Balancer:ReturnToNearestAirbases( 10000, RU_AirbasesSet ) + + +US_PlanesClientSet = SET_CLIENT:New():FilterCountries( "USA" ):FilterCategories( "plane" ) +US_PlanesSpawn = SPAWN:New( "AI US" ):InitCleanUp( 20 ) +US_AI_Balancer = AI_BALANCER:New( US_PlanesClientSet, US_PlanesSpawn ) + --RU_AI_Balancer:ReturnToHomeAirbase( 10000 ) --local PatrolZoneGroup = GROUP:FindByName( "Patrol Zone Blue" ) --local PatrolZoneBlue = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) ---local PatrolZoneB = AI_PATROLZONE:New( PatrolZoneBlue, 3000, 6000, 900, 1100 ):ManageFuel( 0.2, 180 ) +--local PatrolZoneB = AI_PATROL_ZONE:New( PatrolZoneBlue, 3000, 6000, 900, 1100 ):ManageFuel( 0.2, 180 ) --US_AI_Balancer:SetPatrolZone( PatrolZoneB ) -- --local PatrolZoneGroup = GROUP:FindByName( "Patrol Zone Red" ) --local PatrolZoneRed = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) ---local PatrolZoneR = AI_PATROLZONE:New( PatrolZoneRed, 3000, 6000, 900, 1100 ):ManageFuel( 0.2, 180 ) +--local PatrolZoneR = AI_PATROL_ZONE:New( PatrolZoneRed, 3000, 6000, 900, 1100 ):ManageFuel( 0.2, 180 ) --RU_AI_Balancer:SetPatrolZone( PatrolZoneR ) diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz b/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz index 219ba64bc..3a89510dd 100644 Binary files a/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz and b/Moose Test Missions/AIB - AI Balancing/AIB-003 - Two coalitions InitCleanUp test/AIB-003 - Two coalitions InitCleanUp test.miz differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.lua b/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.lua new file mode 100644 index 000000000..222c56980 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.lua @@ -0,0 +1,46 @@ +-- Name: AIB-004 - Respawn Test when Destroyed.lua +-- Author: FlightControl +-- Date Created: 7 January 2017 +-- +-- # Situation: +-- +-- For the red coalition, 2 client slots are foreseen. +-- For those players that have not joined the mission, red AI is spawned. +-- The red AI should start patrolling an area. +-- +-- The blue side has SAMs nearby. +-- Once the red AI takes off, the red AI is attacked by the blue SAMs. +-- Red AI should be killed and once that happens, a Respawn of the group should happen! +-- The Respawn happens through the InitCleanUp() API of SPAWN. +-- +-- # Test cases: +-- +-- 1. If no player is logging into the red slots, 2 red AI planes should be alive. +-- 2. If a player joins one red slot, one red AI plane should return to the nearest home base. +-- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base. +-- 4. Monitor that once a red AI is destroyed, that it ReSpawns... + + +-- Define the SET of CLIENTs from the red coalition. This SET is filled during startup. +local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) + +-- Define the SPAWN object for the red AI plane template. +-- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off. +-- If a blocked plane exists, this red plane will be ReSpawned. +local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) + +-- Start the AI_BALANCER, using the SET of red CLIENTs, and the SPAWN object as a parameter. +local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) + +function RU_AI_Balancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) + + local PatrolZoneGroup = GROUP:FindByName( "PatrolZone" ) + local PatrolZone = ZONE_POLYGON:New( "PatrolZone", PatrolZoneGroup ) + + + local Patrol = AI_PATROL_ZONE:New( PatrolZone, 3000, 6000, 400, 600 ) + Patrol:ManageFuel( 0.2, 60 ) + Patrol:SetControllable( AIGroup ) + Patrol:__Start( 5 ) + +end diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz b/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz new file mode 100644 index 000000000..ecc8c46cd Binary files /dev/null and b/Moose Test Missions/AIB - AI Balancing/AIB-004 - Respawn Test when Destroyed/AIB-004 - Respawn Test when Destroyed.miz differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.lua new file mode 100644 index 000000000..eab2c2e22 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.lua @@ -0,0 +1,51 @@ +-- Name: AIB-005 - Patrol AI and Randomize Zones +-- Author: FlightControl +-- Date Created: 10 Jan 2016 +-- +-- # Situation: +-- +-- For the red coalition, 2 client slots are foreseen. +-- For those players that have not joined the mission, red AI is spawned. +-- The red AI should start patrolling an area until fuel is empty and return to the home base. +-- For each AI being spawned, ensure that they fly to a random zone defined within the mission editor. +-- Right now there are two patrol zones defined, so the AI should start patrolliing in one of these zones. +-- +-- # Test cases: +-- +-- 1. If no player is logging into the red slots, 2 red AI planes should be alive. +-- 2. If a player joins one red slot, one red AI plane should return to the nearest home base. +-- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base. +-- 4. Spawned AI should take-off from the airbase, and start patrolling the area around Anapa. +-- 5. When the AI is out-of-fuel, it should report it is returning to the home base, and land at Anapa. +-- 6. Ensure that you see the AI patrol in one of the two zones ... + +-- Define the SET of CLIENTs from the red coalition. This SET is filled during startup. +local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) + +-- Define the SPAWN object for the red AI plane template. +-- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off. +-- If a blocked plane exists, this red plane will be ReSpawned. +local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) + +-- Start the AI_BALANCER, using the SET of red CLIENTs, and the SPAWN object as a parameter. +local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) + +-- Create the first polygon zone ... +local PatrolZoneGroup1 = GROUP:FindByName( "PatrolZone1" ) +local PatrolZone1 = ZONE_POLYGON:New( "PatrolZone1", PatrolZoneGroup1 ) + +-- Create the second polygon zone ... +local PatrolZoneGroup2 = GROUP:FindByName( "PatrolZone2" ) +local PatrolZone2 = ZONE_POLYGON:New( "PatrolZone2", PatrolZoneGroup2 ) + +-- Now, create an array of these zones ... +local PatrolZoneArray = { PatrolZone1, PatrolZone2 } + +function RU_AI_Balancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) + + local Patrol = AI_PATROL_ZONE:New( PatrolZoneArray[math.random( 1, 2 )], 3000, 6000, 400, 600 ) + Patrol:ManageFuel( 0.2, 60 ) + Patrol:SetControllable( AIGroup ) + Patrol:Start() + +end diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz new file mode 100644 index 000000000..772b3d939 Binary files /dev/null and b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones.miz differ diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/Server.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/Server.lua new file mode 100644 index 000000000..c7db44162 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/Server.lua @@ -0,0 +1,210 @@ +-- View scripts +-- Copyright (C) 2004, Eagle Dynamics. +DisableCombatViews = false -- F5 & Ctrl-F5 +ExternalObjectsLockDistance = 10000.0 +ShowTargetInfo = false +CameraTerrainRestriction = true +hAngleRearDefault = 180 +vAngleRearDefault = -8.0 +vAngleRearMin = -90 -- -8.0 +vAngleRearMax = 90.0 + +dbg_shell = "weapons.shells.PKT_7_62_T" -- 23mm shell +dbg_shell = "weapons.nurs.WGr21" +-- dbg_shell = "weapons.shells.2A64_152" -- 152mm shell +dbg_shell_v0 = -1 -- Muzzle speed m/s (-1 - speed from shall database) +dbg_shell_fire_rate = 60 +--reformatted per-unit data to be mod system friendly +--this file is no longer should be edited for adding new flyable aircraft , DCS automatically check core database (i.e. where you define your aircraft in aircraft table just define ViewSettings and SnapViews tables) + +function default_fighter_player(t) + local res = { + CameraViewAngleLimits = {20.000000,140.000000}, + CameraAngleRestriction = {false ,90.000000,0.500000}, + EyePoint = {0.05 ,0.000000 ,0.000000}, + limits_6DOF = {x = {-0.050000,0.4500000},y ={-0.300000,0.100000},z = {-0.220000,0.220000},roll = 90.000000}, + Allow360rotation = false, + CameraAngleLimits = {200,-80.000000,110.000000}, + ShoulderSize = 0.2, -- move body when azimuth value more then 90 degrees + } + if t then + for i,o in pairs(t) do + res[i] = o + end + end + return res +end + +function fulcrum() + return { + Cockpit = { + default_fighter_player({CockpitLocalPoint = {4.71,1.28,0.000000}}) + }, + Chase = { + LocalPoint = {1.220000,3.750000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-15.080000,6.350000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade + } +end + +ViewSettings = {} +ViewSettings["A-10A"] = { + Cockpit = { + [1] = default_fighter_player({CockpitLocalPoint = {4.300000,1.282000,0.000000}, + EyePoint = {0.000000,0.000000,0.000000}, + limits_6DOF = {x = {-0.050000,0.600000}, + y = {-0.300000,0.100000}, + z = {-0.250000,0.250000}, + roll = 90.000000}}), + }, -- Cockpit + Chase = { + LocalPoint = {0.600000,3.682000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-27.000000,12.000000,0.000000}, + AnglesDefault = {0.000000,-12.000000}, + }, -- Arcade +} +ViewSettings["A-10C"] = { + Cockpit = { + [1] = default_fighter_player({CockpitLocalPoint = {4.300000,1.282000,0.000000}, + EyePoint = {0.000000,0.000000,0.000000}, + limits_6DOF = {x = {-0.050000,0.600000}, + y = {-0.300000,0.100000}, + z = {-0.250000,0.250000}, + roll = 90.000000}}), + }, -- Cockpit + Chase = { + LocalPoint = {0.600000,3.682000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-27.000000,12.000000,0.000000}, + AnglesDefault = {0.000000,-12.000000}, + }, -- Arcade +} +ViewSettings["F-15C"] = { + Cockpit = { + [1] = default_fighter_player({CockpitLocalPoint = {6.210000,1.204000,0.000000}})-- player slot 1 + }, -- Cockpit + Chase = { + LocalPoint = {2.510000,3.604000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-13.790000,6.204000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade +} +ViewSettings["Ka-50"] = { + Cockpit = { + [1] = {-- player slot 1 + CockpitLocalPoint = {3.188000,0.390000,0.000000}, + CameraViewAngleLimits = {20.000000,120.000000}, + CameraAngleRestriction = {false,60.000000,0.400000}, + CameraAngleLimits = {140.000000,-65.000000,90.000000}, + EyePoint = {0.090000,0.000000,0.000000}, + limits_6DOF = {x = {-0.020000,0.350000},y ={-0.150000,0.165000},z = {-0.170000,0.170000},roll = 90.000000}, + }, + }, -- Cockpit + Chase = { + LocalPoint = {-0.512000,2.790000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-16.812000,5.390000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade +} +ViewSettings["MiG-29A"] = fulcrum() +ViewSettings["MiG-29G"] = fulcrum() +ViewSettings["MiG-29S"] = fulcrum() + +ViewSettings["P-51D"] = { + Cockpit = { + [1] = {-- player slot 1 + CockpitLocalPoint = {-1.500000,0.618000,0.000000}, + CameraViewAngleLimits = {20.000000,120.000000}, + CameraAngleRestriction = {false,90.000000,0.500000}, + CameraAngleLimits = {200,-80.000000,90.000000}, + EyePoint = {0.025000,0.100000,0.000000}, + ShoulderSize = 0.15, + Allow360rotation = false, + limits_6DOF = {x = {-0.050000,0.450000},y ={-0.200000,0.200000},z = {-0.220000,0.220000},roll = 90.000000}, + }, + }, -- Cockpit + Chase = { + LocalPoint = {0.200000,-0.652000,-0.650000}, + AnglesDefault = {0.000000,0.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-21.500000,5.618000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade +} +ViewSettings["Su-25"] = { + Cockpit = { + [1] = default_fighter_player({CockpitLocalPoint = {3.352000,0.506000,0.000000}}),-- player slot 1 + }, -- Cockpit + Chase = { + LocalPoint = {-0.348000,2.906000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-16.648001,5.506000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade +} +ViewSettings["Su-25T"] = { + Cockpit = { + [1] = default_fighter_player({CockpitLocalPoint = {3.406000,0.466000,0.000000}}),-- player slot 1 + }, -- Cockpit + Chase = { + LocalPoint = {-0.294000,2.866000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-16.594000,5.466000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade +} +ViewSettings["Su-25TM"] = { + Cockpit = { + [1] = {-- player slot 1 + CockpitLocalPoint = {4.000000,1.000000,0.000000}, + CameraViewAngleLimits = {20.000000,140.000000}, + CameraAngleRestriction = {true,90.000000,0.400000}, + CameraAngleLimits = {160.000000,-70.000000,90.000000}, + EyePoint = {0.000000,0.000000,0.000000}, + limits_6DOF = {x = {-0.200000,0.200000},y ={-0.200000,0.200000},z = {-0.200000,0.200000},roll = 60.000000}, + }, + }, -- Cockpit + Chase = { + LocalPoint = {4.000000,2.000000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {4.000000,2.000000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Arcade +} +ViewSettings["Su-27"] = { + Cockpit = { + [1] = default_fighter_player({CockpitLocalPoint = {7.959000,1.419000,0.000000}})-- player slot 1 + }, -- Cockpit + Chase = { + LocalPoint = {4.259000,3.819000,0.000000}, + AnglesDefault = {180.000000,-8.000000}, + }, -- Chase + Arcade = { + LocalPoint = {-12.041000,6.419000,0.000000}, + AnglesDefault = {0.000000,-8.000000}, + }, -- Arcade +} + +ViewSettings["Su-33"] = ViewSettings["Su-27"] diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/SnapViews.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/SnapViews.lua new file mode 100644 index 000000000..412686113 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/SnapViews.lua @@ -0,0 +1,2780 @@ +SnapViews = {} +SnapViews["A-10A"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 65.000000,--FOV + hAngle = 0.000000, + vAngle = -26.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 49.626770,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.180499, + y_trans = -0.137064, + z_trans = -0.250000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 30.395041,--FOV + hAngle = 0.000000, + vAngle = -94.329208, + x_trans = 0.372718, + y_trans = -0.054055, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 55.238567,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.158523, + y_trans = -0.137064, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = -0.244799, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 34.340549,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = 0.244799, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 68.628296,--FOV + hAngle = 68.292320, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 68.628296,--FOV + hAngle = 0.000000, + vAngle = 30.227919, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 68.628296,--FOV + hAngle = -67.172974, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 70.000000,--FOV + hAngle = 20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 70.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 75.000000,--FOV + hAngle = 0.000000, + vAngle = -23.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["A-10C"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 65.000000,--FOV + hAngle = 0.000000, + vAngle = -26.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 49.626770,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.180499, + y_trans = -0.137064, + z_trans = -0.250000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 30.395041,--FOV + hAngle = 0.000000, + vAngle = -94.329208, + x_trans = 0.372718, + y_trans = -0.054055, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 55.238567,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.158523, + y_trans = -0.137064, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = -0.244799, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 34.340549,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = 0.244799, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 68.628296,--FOV + hAngle = 68.292320, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 68.628296,--FOV + hAngle = 0.000000, + vAngle = 30.227919, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 68.628296,--FOV + hAngle = -67.172974, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 70.000000,--FOV + hAngle = 20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 70.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 75.000000,--FOV + hAngle = 0.000000, + vAngle = -23.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Bf-109K-4"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["C-101CC"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +[2] = {-- player slot 2 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["C-101EB"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +[2] = {-- player slot 2 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["F-15C"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 70.611748,--FOV + hAngle = -1.240272, + vAngle = -33.850250, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 32.704346,--FOV + hAngle = 25.696522, + vAngle = -34.778103, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 32.704346,--FOV + hAngle = 0.000000, + vAngle = -47.845268, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 36.106045,--FOV + hAngle = -28.878576, + vAngle = -36.780628, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 88.727844,--FOV + hAngle = 128.508865, + vAngle = 13.131046, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 41.928593,--FOV + hAngle = 0.000000, + vAngle = -4.630446, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 88.727844,--FOV + hAngle = -128.508865, + vAngle = 13.131046, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 88.727844,--FOV + hAngle = 81.648369, + vAngle = -9.500000, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 88.727844,--FOV + hAngle = 0.000000, + vAngle = 34.180634, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 88.727844,--FOV + hAngle = -80.997551, + vAngle = -9.500000, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 56.032040,--FOV + hAngle = 14.803060, + vAngle = 3.332499, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 56.032040,--FOV + hAngle = -14.414484, + vAngle = 3.332499, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 88.727844,--FOV + hAngle = 0.000000, + vAngle = -9.678451, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["FW-190D9"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Hawk"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Ka-50"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 67.452896,--FOV + hAngle = 0.000000, + vAngle = -40.067383, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 37.846794,--FOV + hAngle = 51.644135, + vAngle = -51.870411, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 36.178646,--FOV + hAngle = -1.912186, + vAngle = -34.446247, + x_trans = 0.000000, + y_trans = -0.025421, + z_trans = 0.073226, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 73.605141,--FOV + hAngle = -90.361992, + vAngle = -44.103138, + x_trans = 0.169696, + y_trans = -0.073508, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 91.348198,--FOV + hAngle = 109.752129, + vAngle = 1.484382, + x_trans = 0.190306, + y_trans = 0.044778, + z_trans = -0.150335, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 42.512844,--FOV + hAngle = 0.000000, + vAngle = -4.478010, + x_trans = 0.154018, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 91.348198,--FOV + hAngle = -108.852020, + vAngle = 0.085984, + x_trans = 0.190306, + y_trans = 0.044778, + z_trans = 0.139404, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 89.777542,--FOV + hAngle = 16.411518, + vAngle = -27.209915, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = -0.218292, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 88.727844,--FOV + hAngle = 0.000000, + vAngle = 34.042202, + x_trans = 0.142145, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 59.208893,--FOV + hAngle = -32.128311, + vAngle = -5.720805, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 56.032040,--FOV + hAngle = 14.803060, + vAngle = 3.332499, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 56.032040,--FOV + hAngle = -14.414484, + vAngle = 3.332499, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 89.777542,--FOV + hAngle = 0.000000, + vAngle = -15.592758, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MQ-9 Reaper"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = 0.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29A"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 76.124840,--FOV + hAngle = -2.623254, + vAngle = -26.566959, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 34.911949,--FOV + hAngle = 24.601770, + vAngle = -32.350807, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 26.184198,--FOV + hAngle = 12.026249, + vAngle = -40.075508, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 39.454399,--FOV + hAngle = -26.664328, + vAngle = -32.355324, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 81.240005,--FOV + hAngle = 131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 44.201855,--FOV + hAngle = 0.000000, + vAngle = -2.378299, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 81.240005,--FOV + hAngle = -131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 81.240005,--FOV + hAngle = 76.013145, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = 36.304676, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 81.240005,--FOV + hAngle = -74.774559, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29G"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 76.124840,--FOV + hAngle = -2.623254, + vAngle = -26.566959, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 34.911949,--FOV + hAngle = 24.601770, + vAngle = -32.350807, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 26.184198,--FOV + hAngle = 12.026249, + vAngle = -40.075508, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 39.454399,--FOV + hAngle = -26.664328, + vAngle = -32.355324, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 81.240005,--FOV + hAngle = 131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 44.201855,--FOV + hAngle = 0.000000, + vAngle = -2.378299, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 81.240005,--FOV + hAngle = -131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 81.240005,--FOV + hAngle = 76.013145, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = 36.304676, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 81.240005,--FOV + hAngle = -74.774559, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29K"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 65.000000,--FOV + hAngle = 0.000000, + vAngle = -26.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 30.000000,--FOV + hAngle = 20.000000, + vAngle = -43.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 30.000000,--FOV + hAngle = 0.000000, + vAngle = -43.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 30.000000,--FOV + hAngle = -20.000000, + vAngle = -43.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 30.000000,--FOV + hAngle = 20.000000, + vAngle = -23.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 30.000000,--FOV + hAngle = 0.000000, + vAngle = -23.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 30.000000,--FOV + hAngle = -20.000000, + vAngle = -23.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 30.000000,--FOV + hAngle = 20.000000, + vAngle = 2.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 30.000000,--FOV + hAngle = 0.000000, + vAngle = 2.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 30.000000,--FOV + hAngle = -20.000000, + vAngle = 2.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29S"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 76.124840,--FOV + hAngle = -2.623254, + vAngle = -26.566959, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 34.911949,--FOV + hAngle = 24.601770, + vAngle = -32.350807, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 26.184198,--FOV + hAngle = 12.026249, + vAngle = -40.075508, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 39.454399,--FOV + hAngle = -26.664328, + vAngle = -32.355324, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 81.240005,--FOV + hAngle = 131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 44.201855,--FOV + hAngle = 0.000000, + vAngle = -2.378299, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 81.240005,--FOV + hAngle = -131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 81.240005,--FOV + hAngle = 76.013145, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = 36.304676, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 81.240005,--FOV + hAngle = -74.774559, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["P-51D"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 80.000000,--FOV + hAngle = 45.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -75.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 80.000000,--FOV + hAngle = -45.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 91.040001,--FOV + hAngle = 157.332764, + vAngle = -28.359503, + x_trans = 0.063872, + y_trans = 0.082888, + z_trans = -0.116148, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 50.000000,--FOV + hAngle = 0.000000, + vAngle = -8.722581, + x_trans = 0.212078, + y_trans = 0.057813, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 80.000000,--FOV + hAngle = -143.000000, + vAngle = 0.000000, + x_trans = 0.350000, + y_trans = 0.059000, + z_trans = 0.100000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 80.000000,--FOV + hAngle = 45.000000, + vAngle = -5.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = 10.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 80.000000,--FOV + hAngle = -45.000000, + vAngle = -5.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = 10.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 80.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-25"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 68.767799,--FOV + hAngle = 1.929517, + vAngle = -30.846605, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 29.223452,--FOV + hAngle = 37.489525, + vAngle = -38.883888, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 40.635601,--FOV + hAngle = -0.438357, + vAngle = -33.138290, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 24.797405,--FOV + hAngle = -34.382549, + vAngle = -34.808853, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 69.302101,--FOV + hAngle = 89.405373, + vAngle = 1.213156, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 29.761202,--FOV + hAngle = 0.000000, + vAngle = -6.880077, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 69.302101,--FOV + hAngle = -89.691940, + vAngle = 4.554290, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 69.302101,--FOV + hAngle = 52.113377, + vAngle = -3.970644, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 72.856201,--FOV + hAngle = 0.000000, + vAngle = 30.866713, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 69.302101,--FOV + hAngle = -50.664936, + vAngle = -3.970644, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 47.680202,--FOV + hAngle = 43.054649, + vAngle = -7.799250, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 47.680202,--FOV + hAngle = -41.743240, + vAngle = -7.799250, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 69.302101,--FOV + hAngle = 0.000000, + vAngle = -15.137112, + x_trans = 0.050000, + y_trans = 0.010000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-25T"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 80.663399,--FOV + hAngle = 0.000000, + vAngle = -30.619938, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 39.764698,--FOV + hAngle = 28.661316, + vAngle = -41.406044, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 38.090847,--FOV + hAngle = -24.622110, + vAngle = -45.153934, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 36.062012,--FOV + hAngle = -20.779360, + vAngle = -23.755520, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 80.663399,--FOV + hAngle = 99.816956, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 58.718098,--FOV + hAngle = 0.000000, + vAngle = -5.000803, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 80.663399,--FOV + hAngle = -99.999687, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 80.663399,--FOV + hAngle = 58.382488, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 94.037704,--FOV + hAngle = 0.000000, + vAngle = 41.421227, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 80.663399,--FOV + hAngle = -57.531212, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.203396,--FOV + hAngle = 55.124939, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.203396,--FOV + hAngle = -52.633553, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 90.000000,--FOV + hAngle = 0.000000, + vAngle = -18.382137, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-25TM"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 80.663399,--FOV + hAngle = 0.000000, + vAngle = -30.619938, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 39.764698,--FOV + hAngle = 28.661316, + vAngle = -41.406044, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 38.090847,--FOV + hAngle = -24.622110, + vAngle = -45.153934, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 33.645596,--FOV + hAngle = -36.653450, + vAngle = -23.703861, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 80.663399,--FOV + hAngle = 99.816956, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 58.718098,--FOV + hAngle = 0.000000, + vAngle = -5.000803, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 80.663399,--FOV + hAngle = -99.999687, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 80.663399,--FOV + hAngle = 58.382488, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 94.037704,--FOV + hAngle = 0.000000, + vAngle = 41.421227, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 80.663399,--FOV + hAngle = -57.531212, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.203396,--FOV + hAngle = 55.124939, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.203396,--FOV + hAngle = -52.633553, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 90.000000,--FOV + hAngle = 0.000000, + vAngle = -18.382137, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-27"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 89.752197,--FOV + hAngle = 7.104492, + vAngle = 52.525635, + x_trans = 0.016405, + y_trans = 0.011140, + z_trans = -0.053543, + rollAngle = -7.110901, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 33.361835,--FOV + hAngle = 41.045925, + vAngle = -40.805656, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 30.427544,--FOV + hAngle = 0.000000, + vAngle = -41.808968, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 34.392349,--FOV + hAngle = -32.597401, + vAngle = -35.293747, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 87.468338,--FOV + hAngle = 129.012665, + vAngle = 14.547977, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 43.977936,--FOV + hAngle = 0.000000, + vAngle = -4.951577, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 87.468338,--FOV + hAngle = -129.012665, + vAngle = 14.491872, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 87.468338,--FOV + hAngle = 82.862923, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = 38.979362, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 87.468338,--FOV + hAngle = -82.461266, + vAngle = -12.843998, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.786629,--FOV + hAngle = 15.618313, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 69.165199,--FOV + hAngle = -15.683434, + vAngle = 8.549150, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.113927, + y_trans = -0.004946, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-33"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 71.824692,--FOV + hAngle = 0.000000, + vAngle = -32.458889, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 33.361835,--FOV + hAngle = 41.045925, + vAngle = -40.805656, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 30.427544,--FOV + hAngle = 0.000000, + vAngle = -41.808968, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 34.392349,--FOV + hAngle = -32.597401, + vAngle = -35.293747, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 87.468338,--FOV + hAngle = 129.012665, + vAngle = 14.547977, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 43.977936,--FOV + hAngle = 0.000000, + vAngle = -4.951577, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 87.468338,--FOV + hAngle = -129.012665, + vAngle = 14.491872, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 87.468338,--FOV + hAngle = 82.862923, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = 38.979362, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 87.468338,--FOV + hAngle = -82.461266, + vAngle = -12.843998, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.786629,--FOV + hAngle = 15.618313, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 69.165199,--FOV + hAngle = -15.683434, + vAngle = 8.549150, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.113927, + y_trans = -0.004946, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["TF-51D"] = { +[1] = {-- player slot 1 + [1] = {--LWin + Num0 : Snap View 0 + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = {--LWin + Num1 : Snap View 1 + viewAngle = 80.000000,--FOV + hAngle = 45.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = {--LWin + Num2 : Snap View 2 + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -75.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = {--LWin + Num3 : Snap View 3 + viewAngle = 80.000000,--FOV + hAngle = -45.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = {--LWin + Num4 : Snap View 4 + viewAngle = 91.040001,--FOV + hAngle = 157.332764, + vAngle = -28.359503, + x_trans = 0.063872, + y_trans = 0.082888, + z_trans = -0.116148, + rollAngle = 0.000000, + }, + [6] = {--LWin + Num5 : Snap View 5 + viewAngle = 50.000000,--FOV + hAngle = 0.000000, + vAngle = -8.722581, + x_trans = 0.212078, + y_trans = 0.057813, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = {--LWin + Num6 : Snap View 6 + viewAngle = 80.000000,--FOV + hAngle = -143.000000, + vAngle = 0.000000, + x_trans = 0.350000, + y_trans = 0.059000, + z_trans = 0.100000, + rollAngle = 0.000000, + }, + [8] = {--LWin + Num7 : Snap View 7 + viewAngle = 80.000000,--FOV + hAngle = 45.000000, + vAngle = -5.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = {--LWin + Num8 : Snap View 8 + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = 10.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = {--LWin + Num9 : Snap View 9 + viewAngle = 80.000000,--FOV + hAngle = -45.000000, + vAngle = -5.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = 10.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 80.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/SnapViewsDefault.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/SnapViewsDefault.lua new file mode 100644 index 000000000..754522d55 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/SnapViewsDefault.lua @@ -0,0 +1,1698 @@ +--reformatted per-unit data to be mod system friendly +--this file is no longer should be edited for adding new flyable aircraft , DCS automatically check core database for this data(i.e. where you define your aircraft in aircraft table just define ViewSettings and SnapViews tables) +-- result of ingame editing is saved to Saved Games//DCS/Config/View/SnapViews.lua +SnapViews = {} +SnapViews["A-10A"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 65.000000,--FOV + hAngle = 0.000000, + vAngle = -26.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 49.626770,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.180499, + y_trans = -0.137064, + z_trans = -0.250000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 30.395041,--FOV + hAngle = 0.000000, + vAngle = -94.329208, + x_trans = 0.372718, + y_trans = -0.054055, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 55.238567,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.158523, + y_trans = -0.137064, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = -0.244799, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 34.340549,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = 0.244799, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 68.628296,--FOV + hAngle = 68.292320, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 68.628296,--FOV + hAngle = 0.000000, + vAngle = 30.227919, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 68.628296,--FOV + hAngle = -67.172974, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 70.000000,--FOV + hAngle = 20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 70.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 75.000000,--FOV + hAngle = 0.000000, + vAngle = -23.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["A-10C"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 65.000000,--FOV + hAngle = 0.000000, + vAngle = -26.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 49.626770,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.180499, + y_trans = -0.137064, + z_trans = -0.250000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 30.395041,--FOV + hAngle = 0.000000, + vAngle = -94.329208, + x_trans = 0.372718, + y_trans = -0.054055, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 55.238567,--FOV + hAngle = 0.000000, + vAngle = -90.631294, + x_trans = 0.158523, + y_trans = -0.137064, + z_trans = 0.250000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = -0.244799, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 34.340549,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 35.000000,--FOV + hAngle = 0.000000, + vAngle = -10.651850, + x_trans = 0.327622, + y_trans = -0.278207, + z_trans = 0.244799, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 68.628296,--FOV + hAngle = 68.292320, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 68.628296,--FOV + hAngle = 0.000000, + vAngle = 30.227919, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 68.628296,--FOV + hAngle = -67.172974, + vAngle = -11.477349, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 70.000000,--FOV + hAngle = 20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 70.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 75.000000,--FOV + hAngle = 0.000000, + vAngle = -23.000000, + x_trans = 0.360000, + y_trans = -0.041337, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["F-15C"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 70.611748,--FOV + hAngle = -1.240272, + vAngle = -33.850250, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 32.704346,--FOV + hAngle = 25.696522, + vAngle = -34.778103, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 32.704346,--FOV + hAngle = 0.000000, + vAngle = -47.845268, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 36.106045,--FOV + hAngle = -28.878576, + vAngle = -36.780628, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 88.727844,--FOV + hAngle = 128.508865, + vAngle = 13.131046, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 41.928593,--FOV + hAngle = 0.000000, + vAngle = -4.630446, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 88.727844,--FOV + hAngle = -128.508865, + vAngle = 13.131046, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 88.727844,--FOV + hAngle = 81.648369, + vAngle = -9.500000, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 88.727844,--FOV + hAngle = 0.000000, + vAngle = 34.180634, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 88.727844,--FOV + hAngle = -80.997551, + vAngle = -9.500000, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 56.032040,--FOV + hAngle = 14.803060, + vAngle = 3.332499, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 56.032040,--FOV + hAngle = -14.414484, + vAngle = 3.332499, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 88.727844,--FOV + hAngle = 0.000000, + vAngle = -9.678451, + x_trans = 0.264295, + y_trans = -0.064373, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Ka-50"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 67.452896,--FOV + hAngle = 0.000000, + vAngle = -40.067383, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 37.846794,--FOV + hAngle = 51.644135, + vAngle = -51.870411, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 36.178646,--FOV + hAngle = -1.912186, + vAngle = -34.446247, + x_trans = 0.000000, + y_trans = -0.025421, + z_trans = 0.073226, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 73.605141,--FOV + hAngle = -90.361992, + vAngle = -44.103138, + x_trans = 0.169696, + y_trans = -0.073508, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 91.348198,--FOV + hAngle = 109.752129, + vAngle = 1.484382, + x_trans = 0.190306, + y_trans = 0.044778, + z_trans = -0.150335, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 42.512844,--FOV + hAngle = 0.000000, + vAngle = -4.478010, + x_trans = 0.154018, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 91.348198,--FOV + hAngle = -108.852020, + vAngle = 0.085984, + x_trans = 0.190306, + y_trans = 0.044778, + z_trans = 0.139404, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 89.777542,--FOV + hAngle = 16.411518, + vAngle = -27.209915, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = -0.218292, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 88.727844,--FOV + hAngle = 0.000000, + vAngle = 34.042202, + x_trans = 0.142145, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 59.208893,--FOV + hAngle = -32.128311, + vAngle = -5.720805, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 56.032040,--FOV + hAngle = 14.803060, + vAngle = 3.332499, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 56.032040,--FOV + hAngle = -14.414484, + vAngle = 3.332499, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 89.777542,--FOV + hAngle = 0.000000, + vAngle = -15.592758, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29A"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 76.124840,--FOV + hAngle = -2.623254, + vAngle = -26.566959, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 34.911949,--FOV + hAngle = 24.601770, + vAngle = -32.350807, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 26.184198,--FOV + hAngle = 12.026249, + vAngle = -40.075508, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 39.454399,--FOV + hAngle = -26.664328, + vAngle = -32.355324, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 81.240005,--FOV + hAngle = 131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 44.201855,--FOV + hAngle = 0.000000, + vAngle = -2.378299, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 81.240005,--FOV + hAngle = -131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 81.240005,--FOV + hAngle = 76.013145, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = 36.304676, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 81.240005,--FOV + hAngle = -74.774559, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29G"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 76.124840,--FOV + hAngle = -2.623254, + vAngle = -26.566959, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 34.911949,--FOV + hAngle = 24.601770, + vAngle = -32.350807, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 26.184198,--FOV + hAngle = 12.026249, + vAngle = -40.075508, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 39.454399,--FOV + hAngle = -26.664328, + vAngle = -32.355324, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 81.240005,--FOV + hAngle = 131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 44.201855,--FOV + hAngle = 0.000000, + vAngle = -2.378299, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 81.240005,--FOV + hAngle = -131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 81.240005,--FOV + hAngle = 76.013145, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = 36.304676, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 81.240005,--FOV + hAngle = -74.774559, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29K"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 65.000000,--FOV + hAngle = 0.000000, + vAngle = -26.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 30.000000,--FOV + hAngle = 20.000000, + vAngle = -43.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 30.000000,--FOV + hAngle = 0.000000, + vAngle = -43.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 30.000000,--FOV + hAngle = -20.000000, + vAngle = -43.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 30.000000,--FOV + hAngle = 20.000000, + vAngle = -23.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 30.000000,--FOV + hAngle = 0.000000, + vAngle = -23.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 30.000000,--FOV + hAngle = -20.000000, + vAngle = -23.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 30.000000,--FOV + hAngle = 20.000000, + vAngle = 2.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 30.000000,--FOV + hAngle = 0.000000, + vAngle = 2.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 30.000000,--FOV + hAngle = -20.000000, + vAngle = 2.000000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 60.000000,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["MiG-29S"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 76.124840,--FOV + hAngle = -2.623254, + vAngle = -26.566959, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 34.911949,--FOV + hAngle = 24.601770, + vAngle = -32.350807, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 26.184198,--FOV + hAngle = 12.026249, + vAngle = -40.075508, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 39.454399,--FOV + hAngle = -26.664328, + vAngle = -32.355324, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 81.240005,--FOV + hAngle = 131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 44.201855,--FOV + hAngle = 0.000000, + vAngle = -2.378299, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 81.240005,--FOV + hAngle = -131.503998, + vAngle = 10.804660, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 81.240005,--FOV + hAngle = 76.013145, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = 36.304676, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 81.240005,--FOV + hAngle = -74.774559, + vAngle = 2.248441, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.250000,--FOV + hAngle = 13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 68.250000,--FOV + hAngle = -13.070938, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 81.240005,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["P-51D"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 80.000000,--FOV + hAngle = 45.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -75.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 80.000000,--FOV + hAngle = -45.000000, + vAngle = -45.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 91.040001,--FOV + hAngle = 157.332764, + vAngle = -28.359503, + x_trans = 0.063872, + y_trans = 0.082888, + z_trans = -0.116148, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 50.000000,--FOV + hAngle = 0.000000, + vAngle = -8.722581, + x_trans = 0.212078, + y_trans = 0.057813, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 80.000000,--FOV + hAngle = -143.000000, + vAngle = 0.000000, + x_trans = 0.350000, + y_trans = 0.059000, + z_trans = 0.100000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 80.000000,--FOV + hAngle = 45.000000, + vAngle = -5.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = 10.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 80.000000,--FOV + hAngle = -45.000000, + vAngle = -5.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = 10.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 80.000000,--FOV + hAngle = -20.000000, + vAngle = 8.000000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 80.000000,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.120000, + y_trans = 0.059000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-25"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 68.767799,--FOV + hAngle = 1.929517, + vAngle = -30.846605, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 29.223452,--FOV + hAngle = 37.489525, + vAngle = -38.883888, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 40.635601,--FOV + hAngle = -0.438357, + vAngle = -33.138290, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 24.797405,--FOV + hAngle = -34.382549, + vAngle = -34.808853, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 69.302101,--FOV + hAngle = 89.405373, + vAngle = 1.213156, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 29.761202,--FOV + hAngle = 0.000000, + vAngle = -6.880077, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 69.302101,--FOV + hAngle = -89.691940, + vAngle = 4.554290, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 69.302101,--FOV + hAngle = 52.113377, + vAngle = -3.970644, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 72.856201,--FOV + hAngle = 0.000000, + vAngle = 30.866713, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 69.302101,--FOV + hAngle = -50.664936, + vAngle = -3.970644, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 47.680202,--FOV + hAngle = 43.054649, + vAngle = -7.799250, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 47.680202,--FOV + hAngle = -41.743240, + vAngle = -7.799250, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 69.302101,--FOV + hAngle = 0.000000, + vAngle = -15.137112, + x_trans = 0.050000, + y_trans = 0.010000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-25T"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 80.663399,--FOV + hAngle = 0.000000, + vAngle = -30.619938, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 39.764698,--FOV + hAngle = 28.661316, + vAngle = -41.406044, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 38.090847,--FOV + hAngle = -24.622110, + vAngle = -45.153934, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 36.062012,--FOV + hAngle = -20.779360, + vAngle = -23.755520, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 80.663399,--FOV + hAngle = 99.816956, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 58.718098,--FOV + hAngle = 0.000000, + vAngle = -5.000803, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 80.663399,--FOV + hAngle = -99.999687, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 80.663399,--FOV + hAngle = 58.382488, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 94.037704,--FOV + hAngle = 0.000000, + vAngle = 41.421227, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 80.663399,--FOV + hAngle = -57.531212, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.203396,--FOV + hAngle = 55.124939, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.203396,--FOV + hAngle = -52.633553, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 90.000000,--FOV + hAngle = 0.000000, + vAngle = -18.382137, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-25TM"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 80.663399,--FOV + hAngle = 0.000000, + vAngle = -30.619938, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 39.764698,--FOV + hAngle = 28.661316, + vAngle = -41.406044, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 38.090847,--FOV + hAngle = -24.622110, + vAngle = -45.153934, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 33.645596,--FOV + hAngle = -36.653450, + vAngle = -23.703861, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 80.663399,--FOV + hAngle = 99.816956, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 58.718098,--FOV + hAngle = 0.000000, + vAngle = -5.000803, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 80.663399,--FOV + hAngle = -99.999687, + vAngle = 8.032285, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 80.663399,--FOV + hAngle = 58.382488, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 94.037704,--FOV + hAngle = 0.000000, + vAngle = 41.421227, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 80.663399,--FOV + hAngle = -57.531212, + vAngle = -6.648195, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 60.203396,--FOV + hAngle = 55.124939, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 60.203396,--FOV + hAngle = -52.633553, + vAngle = -8.400513, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 90.000000,--FOV + hAngle = 0.000000, + vAngle = -18.382137, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-27"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 71.824692,--FOV + hAngle = 0.000000, + vAngle = -32.458889, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 33.361835,--FOV + hAngle = 41.045925, + vAngle = -40.805656, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 30.427544,--FOV + hAngle = 0.000000, + vAngle = -41.808968, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 34.392349,--FOV + hAngle = -32.597401, + vAngle = -35.293747, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 87.468338,--FOV + hAngle = 129.012665, + vAngle = 14.547977, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 43.977936,--FOV + hAngle = 0.000000, + vAngle = -4.951577, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 87.468338,--FOV + hAngle = -129.012665, + vAngle = 14.491872, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 87.468338,--FOV + hAngle = 82.862923, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = 38.979362, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 87.468338,--FOV + hAngle = -82.461266, + vAngle = -12.843998, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.786629,--FOV + hAngle = 15.618313, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 69.165199,--FOV + hAngle = -15.683434, + vAngle = 8.549150, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.113927, + y_trans = -0.004946, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} +SnapViews["Su-33"] = { +[1] = {-- player slot 1 + [1] = { + viewAngle = 71.824692,--FOV + hAngle = 0.000000, + vAngle = -32.458889, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [2] = { + viewAngle = 33.361835,--FOV + hAngle = 41.045925, + vAngle = -40.805656, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [3] = { + viewAngle = 30.427544,--FOV + hAngle = 0.000000, + vAngle = -41.808968, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [4] = { + viewAngle = 34.392349,--FOV + hAngle = -32.597401, + vAngle = -35.293747, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [5] = { + viewAngle = 87.468338,--FOV + hAngle = 129.012665, + vAngle = 14.547977, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [6] = { + viewAngle = 43.977936,--FOV + hAngle = 0.000000, + vAngle = -4.951577, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [7] = { + viewAngle = 87.468338,--FOV + hAngle = -129.012665, + vAngle = 14.491872, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [8] = { + viewAngle = 87.468338,--FOV + hAngle = 82.862923, + vAngle = -9.500000, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [9] = { + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = 38.979362, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [10] = { + viewAngle = 87.468338,--FOV + hAngle = -82.461266, + vAngle = -12.843998, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [11] = {--look at left mirror + viewAngle = 68.786629,--FOV + hAngle = 15.618313, + vAngle = 7.522498, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [12] = {--look at right mirror + viewAngle = 69.165199,--FOV + hAngle = -15.683434, + vAngle = 8.549150, + x_trans = 0.000000, + y_trans = 0.000000, + z_trans = 0.000000, + rollAngle = 0.000000, + }, + [13] = {--default view + viewAngle = 87.468338,--FOV + hAngle = 0.000000, + vAngle = -9.500000, + x_trans = 0.113927, + y_trans = -0.004946, + z_trans = 0.000000, + rollAngle = 0.000000, + }, +}, +} \ No newline at end of file diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/View.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/View.lua new file mode 100644 index 000000000..9baf3b7df --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Config/View/View.lua @@ -0,0 +1,128 @@ +-- View scripts +-- Copyright (C) 2004, Eagle Dynamics. + +CockpitMouse = true --false +CockpitMouseSpeedSlow = 1.0 +CockpitMouseSpeedNormal = 10.0 +CockpitMouseSpeedFast = 20.0 +CockpitKeyboardAccelerationSlow = 5.0 +CockpitKeyboardAccelerationNormal = 30.0 +CockpitKeyboardAccelerationFast = 80.0 +CockpitKeyboardZoomAcceleration = 300.0 +DisableSnapViewsSaving = false +UseDefaultSnapViews = true +CockpitPanStepHor = 45.0 +CockpitPanStepVert = 30.0 +CockpitNyMove = true + +CockpitHAngleAccelerateTimeMax = 0.15 +CockpitVAngleAccelerateTimeMax = 0.15 +CockpitZoomAccelerateTimeMax = 0.2 + +function NaturalHeadMoving(tang, roll, omz) + local r = roll + if r > 90.0 then + r = 180.0 - r + elseif roll < -90.0 then + r = -180.0 - r + end + local hAngle = -0.25 * r + local vAngle = math.min(math.max(0.0, 0.4 * tang + 45.0 * omz), 90.0) + return hAngle, vAngle +end + +ExternalMouse = true +ExternalMouseSpeedSlow = 1.0 +ExternalMouseSpeedNormal = 5.0 +ExternalMouseSpeedFast = 20.0 +ExternalViewAngleMin = 3.0 +ExternalViewAngleMax = 170.0 +ExternalViewAngleDefault = 60.0 +ExternalKeyboardZoomAcceleration = 30.0 +ExternalKeyboardZoomAccelerateTimeMax = 1.0 +ExplosionExpoTime = 4.0 +ExternalKeyboardAccelerationSlow = 1.0 +ExternalKeyboardAccelerationNormal = 10.0 +ExternalKeyboardAccelerationFast = 30.0 +ExternalHAngleAccelerateTimeMax = 3.0 +ExternalVAngleAccelerateTimeMax = 3.0 +ExternalDistAccelerateTimeMax = 3.0 +ExternalHAngleLocalAccelerateTimeMax = 3.0 +ExternalVAngleLocalAccelerateTimeMax = 3.0 +ExternalAngleNormalDiscreteStep = 15.0/ExternalKeyboardAccelerationNormal -- When 'S' is pressed only +ChaseCameraNyMove = true +FreeCameraAngleIncrement = 3.0 +FreeCameraDistanceIncrement = 200.0 +FreeCameraLeftRightIncrement = 2.0 +FreeCameraAltitudeIncrement = 2.0 +FreeCameraScalarSpeedAcceleration = 0.1 +xMinMap = -300000 +xMaxMap = 500000 +yMinMap = -400000 +yMaxMap = 200000 +dxMap = 150000 +dyMap = 100000 + +head_roll_shaking = true +head_roll_shaking_max = 30.0 +head_roll_shaking_compensation_gain = 0.3 + +-- CameraJiggle() and CameraFloat() functions make camera position +-- dependent on FPS so be careful in using the Shift-J command with tracks, please. +-- uncomment to use custom jiggle functions +--[[ +function CameraJiggle(t,rnd1,rnd2,rnd3) + local rotX, rotY, rotZ + rotX = 0.05 * rnd1 * math.sin(37.0 * (t - 0.0)) + rotY = 0.05 * rnd2 * math.sin(41.0 * (t - 1.0)) + rotZ = 0.05 * rnd3 * math.sin(53.0 * (t - 2.0)) + return rotX, rotY, rotZ +end + +function CameraFloat(t) + local dX, dY, dZ + dX = 0.61 * math.sin(0.7 * t) + 0.047 * math.sin(1.6 * t); + dY = 0.43 * math.sin(0.6 * t) + 0.067 * math.sin(1.7 * t); + dZ = 0.53 * math.sin(1.0 * t) + 0.083 * math.sin(1.9 * t); + return dX, dY, dZ +end +--]] +--Debug keys + +DEBUG_TEXT = 1 +DEBUG_GEOMETRY = 2 + +debug_keys = { + [DEBUG_TEXT] = 1, + [DEBUG_GEOMETRY] = 1 +} + +function onDebugCommand(command) + if command == 10000 then + if debug_keys[DEBUG_TEXT] ~= 0 or debug_keys[DEBUG_GEOMETRY] ~= 0 then + debug_keys[DEBUG_GEOMETRY] = 0 + debug_keys[DEBUG_TEXT] = 0 + else + debug_keys[DEBUG_GEOMETRY] = 1 + debug_keys[DEBUG_TEXT] = 1 + end + elseif command == 10001 then + if debug_keys[DEBUG_TEXT] ~= 0 then + debug_keys[DEBUG_TEXT] = 0 + else + debug_keys[DEBUG_TEXT] = 1 + end + elseif command == 10002 then + if debug_keys[DEBUG_GEOMETRY] ~= 0 then + debug_keys[DEBUG_GEOMETRY] = 0 + else + debug_keys[DEBUG_GEOMETRY] = 1 + end + end +end + +-- gain values for TrackIR , to unify responce on diffrent types of aircraft +TrackIR_gain_x = -0.6 +TrackIR_gain_y = 0.3 +TrackIR_gain_z = -0.25 +TrackIR_gain_roll = -90 \ No newline at end of file diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Scripts/World/GPS_GNSS.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Scripts/World/GPS_GNSS.lua new file mode 100644 index 000000000..2cb4a8e8d --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Scripts/World/GPS_GNSS.lua @@ -0,0 +1,880 @@ +SAT_SYS_GLONASS = 0 +SAT_SYS_GPS = 1 + +almanac = {} +--GPS +almanac[0] = {} +almanac[0]["System"] = SAT_SYS_GPS +almanac[0]["Number"] = 1 +almanac[0]["Orbital"] = "F" +almanac[0]["Eccentricity"] = 6.294000e-003 +almanac[0]["Time_of_Applicability"] = 5.898240e+005 +almanac[0]["Orbital_Inclination"] = 9.885676e-001 +almanac[0]["Rate_of_Right_Ascen"] = -7.862702e-009 +almanac[0]["SQRT_A"] = 5.153700e+003 +almanac[0]["Right_Ascen_at_Week"] = 8.096750e-001 +almanac[0]["Argument_of_Perigee"] = -1.777773e+000 +almanac[0]["Mean_Anom"] = -5.315745e-001 +almanac[0]["week"] = 1390 + +almanac[1] = {} +almanac[1]["System"] = SAT_SYS_GPS +almanac[1]["Number"] = 2 +almanac[1]["Orbital"] = "C" +almanac[1]["Eccentricity"] = 8.794000e-003 +almanac[1]["Time_of_Applicability"] = 5.898240e+005 +almanac[1]["Orbital_Inclination"] = 9.487811e-001 +almanac[1]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[1]["SQRT_A"] = 5.153700e+003 +almanac[1]["Right_Ascen_at_Week"] = -1.329172e+000 +almanac[1]["Argument_of_Perigee"] = 2.138637e+000 +almanac[1]["Mean_Anom"] = 7.311702e-001 +almanac[1]["week"] = 1390 + +almanac[2] = {} +almanac[2]["System"] = SAT_SYS_GPS +almanac[2]["Number"] = 3 +almanac[2]["Orbital"] = "F" +almanac[2]["Eccentricity"] = 8.424000e-003 +almanac[2]["Time_of_Applicability"] = 5.898240e+005 +almanac[2]["Orbital_Inclination"] = 9.262804e-001 +almanac[2]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[2]["SQRT_A"] = 5.153600e+003 +almanac[2]["Right_Ascen_at_Week"] = -2.341514e+000 +almanac[2]["Argument_of_Perigee"] = 6.749357e-001 +almanac[2]["Mean_Anom"] = -2.296153e-001 +almanac[2]["week"] = 1389 + +almanac[3] = {} +almanac[3]["System"] = SAT_SYS_GPS +almanac[3]["Number"] = 4 +almanac[3]["Orbital"] = "D" +almanac[3]["Eccentricity"] = 7.413000e-003 +almanac[3]["Time_of_Applicability"] = 5.898240e+005 +almanac[3]["Orbital_Inclination"] = 9.482889e-001 +almanac[3]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[3]["SQRT_A"] = 5.153600e+003 +almanac[3]["Right_Ascen_at_Week"] = -1.309589e+000 +almanac[3]["Argument_of_Perigee"] = 1.623504e-001 +almanac[3]["Mean_Anom"] = -3.022943e+000 +almanac[3]["week"] = 1390 + +almanac[4] = {} +almanac[4]["System"] = SAT_SYS_GPS +almanac[4]["Number"] = 5 +almanac[4]["Orbital"] = "B" +almanac[4]["Eccentricity"] = 7.432000e-003 +almanac[4]["Time_of_Applicability"] = 5.898240e+005 +almanac[4]["Orbital_Inclination"] = 9.387437e-001 +almanac[4]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[4]["SQRT_A"] = 5.153700e+003 +almanac[4]["Right_Ascen_at_Week"] = 2.779487e+000 +almanac[4]["Argument_of_Perigee"] = 1.099033e+000 +almanac[4]["Mean_Anom"] = 2.970984e+000 +almanac[4]["week"] = 1390 + +almanac[5] = {} +almanac[5]["System"] = SAT_SYS_GPS +almanac[5]["Number"] = 6 +almanac[5]["Orbital"] = "C" +almanac[5]["Eccentricity"] = 6.020000e-003 +almanac[5]["Time_of_Applicability"] = 5.898240e+005 +almanac[5]["Orbital_Inclination"] = 9.337591e-001 +almanac[5]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[5]["SQRT_A"] = 5.153600e+003 +almanac[5]["Right_Ascen_at_Week"] = -2.407627e+000 +almanac[5]["Argument_of_Perigee"] = -1.788263e+000 +almanac[5]["Mean_Anom"] = -2.149877e+000 +almanac[5]["week"] = 1390 + +almanac[6] = {} +almanac[6]["System"] = SAT_SYS_GPS +almanac[6]["Number"] = 7 +almanac[6]["Orbital"] = "C" +almanac[6]["Eccentricity"] = 1.052400e-002 +almanac[6]["Time_of_Applicability"] = 5.898240e+005 +almanac[6]["Orbital_Inclination"] = 9.353229e-001 +almanac[6]["Rate_of_Right_Ascen"] = -8.080868e-009 +almanac[6]["SQRT_A"] = 5.153700e+003 +almanac[6]["Right_Ascen_at_Week"] = -2.433580e+000 +almanac[6]["Argument_of_Perigee"] = -1.767301e+000 +almanac[6]["Mean_Anom"] = -3.141503e+000 +almanac[6]["week"] = 1390 + +almanac[7] = {} +almanac[7]["System"] = SAT_SYS_GPS +almanac[7]["Number"] = 8 +almanac[7]["Orbital"] = "A" +almanac[7]["Eccentricity"] = 9.822000e-003 +almanac[7]["Time_of_Applicability"] = 5.898240e+005 +almanac[7]["Orbital_Inclination"] = 9.741390e-001 +almanac[7]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[7]["SQRT_A"] = 5.153600e+003 +almanac[7]["Right_Ascen_at_Week"] = 1.857849e+000 +almanac[7]["Argument_of_Perigee"] = 2.674034e+000 +almanac[7]["Mean_Anom"] = -2.009745e+000 +almanac[7]["week"] = 1390 + +almanac[8] = {} +almanac[8]["System"] = SAT_SYS_GPS +almanac[8]["Number"] = 9 +almanac[8]["Orbital"] = "A" +almanac[8]["Eccentricity"] = 1.839300e-002 +almanac[8]["Time_of_Applicability"] = 5.898240e+005 +almanac[8]["Orbital_Inclination"] = 9.617541e-001 +almanac[8]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[8]["SQRT_A"] = 5.153600e+003 +almanac[8]["Right_Ascen_at_Week"] = 1.777005e+000 +almanac[8]["Argument_of_Perigee"] = 1.274962e+000 +almanac[8]["Mean_Anom"] = -2.349578e+000 +almanac[8]["week"] = 1390 + +almanac[9] = {} +almanac[9]["System"] = SAT_SYS_GPS +almanac[9]["Number"] = 10 +almanac[9]["Orbital"] = "E" +almanac[9]["Eccentricity"] = 7.061000e-003 +almanac[9]["Time_of_Applicability"] = 5.898240e+005 +almanac[9]["Orbital_Inclination"] = 9.728876e-001 +almanac[9]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[9]["SQRT_A"] = 5.153600e+003 +almanac[9]["Right_Ascen_at_Week"] = -2.563014e-001 +almanac[9]["Argument_of_Perigee"] = 4.377980e-001 +almanac[9]["Mean_Anom"] = 1.210716e+000 +almanac[9]["week"] = 1390 + +almanac[10] = {} +almanac[10]["System"] = SAT_SYS_GPS +almanac[10]["Number"] = 11 +almanac[10]["Orbital"] = "D" +almanac[10]["Eccentricity"] = 5.744000e-003 +almanac[10]["Time_of_Applicability"] = 5.898240e+005 +almanac[10]["Orbital_Inclination"] = 8.959309e-001 +almanac[10]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[10]["SQRT_A"] = 5.153600e+003 +almanac[10]["Right_Ascen_at_Week"] = -1.478816e+000 +almanac[10]["Argument_of_Perigee"] = 3.750011e-001 +almanac[10]["Mean_Anom"] = -1.522048e+000 +almanac[10]["week"] = 1390 + +almanac[11] = {} +almanac[11]["System"] = SAT_SYS_GPS +almanac[11]["Number"] = 13 +almanac[11]["Orbital"] = "F" +almanac[11]["Eccentricity"] = 3.088000e-003 +almanac[11]["Time_of_Applicability"] = 5.898240e+005 +almanac[11]["Orbital_Inclination"] = 9.927564e-001 +almanac[11]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[11]["SQRT_A"] = 5.153700e+003 +almanac[11]["Right_Ascen_at_Week"] = 7.956600e-001 +almanac[11]["Argument_of_Perigee"] = 1.279395e+000 +almanac[11]["Mean_Anom"] = 1.004349e+000 +almanac[11]["week"] = 1390 + +almanac[12] = {} +almanac[12]["System"] = SAT_SYS_GPS +almanac[12]["Number"] = 14 +almanac[12]["Orbital"] = "F" +almanac[12]["Eccentricity"] = 2.591000e-003 +almanac[12]["Time_of_Applicability"] = 5.898240e+005 +almanac[12]["Orbital_Inclination"] = 9.868729e-001 +almanac[12]["Rate_of_Right_Ascen"] = -7.885391e-009 +almanac[12]["SQRT_A"] = 5.153600e+003 +almanac[12]["Right_Ascen_at_Week"] = 7.819592e-001 +almanac[12]["Argument_of_Perigee"] = -2.158621e+000 +almanac[12]["Mean_Anom"] = 5.412611e-001 +almanac[12]["week"] = 1390 + +almanac[13] = {} +almanac[13]["System"] = SAT_SYS_GPS +almanac[13]["Number"] = 15 +almanac[13]["Orbital"] = "D" +almanac[13]["Eccentricity"] = 9.828000e-003 +almanac[13]["Time_of_Applicability"] = 3.194880e+005 +almanac[13]["Orbital_Inclination"] = 9.554204e-001 +almanac[13]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[13]["SQRT_A"] = 5.153600e+003 +almanac[13]["Right_Ascen_at_Week"] = -1.123869e+000 +almanac[13]["Argument_of_Perigee"] = 2.690266e+000 +almanac[13]["Mean_Anom"] = 2.220476e+000 +almanac[13]["week"] = 1389 + +almanac[14] = {} +almanac[14]["System"] = SAT_SYS_GPS +almanac[14]["Number"] = 16 +almanac[14]["Orbital"] = "B" +almanac[14]["Eccentricity"] = 3.494000e-003 +almanac[14]["Time_of_Applicability"] = 5.898240e+005 +almanac[14]["Orbital_Inclination"] = 9.629340e-001 +almanac[14]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[14]["SQRT_A"] = 5.153700e+003 +almanac[14]["Right_Ascen_at_Week"] = 2.873124e+000 +almanac[14]["Argument_of_Perigee"] = -7.819243e-001 +almanac[14]["Mean_Anom"] = 2.623629e+000 +almanac[14]["week"] = 1390 + +almanac[15] = {} +almanac[15]["System"] = SAT_SYS_GPS +almanac[15]["Number"] = 17 +almanac[15]["Orbital"] = "C" +almanac[15]["Eccentricity"] = 2.141000e-003 +almanac[15]["Time_of_Applicability"] = 5.898240e+005 +almanac[15]["Orbital_Inclination"] = 9.601170e-001 +almanac[15]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[15]["SQRT_A"] = 5.153700e+003 +almanac[15]["Right_Ascen_at_Week"] = -2.371499e+000 +almanac[15]["Argument_of_Perigee"] = 3.087694e+000 +almanac[15]["Mean_Anom"] = 1.611217e+000 +almanac[15]["week"] = 1390 + +almanac[16] = {} +almanac[16]["System"] = SAT_SYS_GPS +almanac[16]["Number"] = 18 +almanac[16]["Orbital"] = "E" +almanac[16]["Eccentricity"] = 7.636000e-003 +almanac[16]["Time_of_Applicability"] = 5.898240e+005 +almanac[16]["Orbital_Inclination"] = 9.569597e-001 +almanac[16]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[16]["SQRT_A"] = 5.153700e+003 +almanac[16]["Right_Ascen_at_Week"] = -2.359858e-001 +almanac[16]["Argument_of_Perigee"] = -2.649216e+000 +almanac[16]["Mean_Anom"] = 2.675029e+000 +almanac[16]["week"] = 1390 + +almanac[17] = {} +almanac[17]["System"] = SAT_SYS_GPS +almanac[17]["Number"] = 19 +almanac[17]["Orbital"] = "C" +almanac[17]["Eccentricity"] = 3.602000e-003 +almanac[17]["Time_of_Applicability"] = 5.898240e+005 +almanac[17]["Orbital_Inclination"] = 9.580209e-001 +almanac[17]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[17]["SQRT_A"] = 5.153600e+003 +almanac[17]["Right_Ascen_at_Week"] = -2.312385e+000 +almanac[17]["Argument_of_Perigee"] = -1.161079e+000 +almanac[17]["Mean_Anom"] = 1.310619e+000 +almanac[17]["week"] = 1390 + +almanac[18] = {} +almanac[18]["System"] = SAT_SYS_GPS +almanac[18]["Number"] = 20 +almanac[18]["Orbital"] = "E" +almanac[18]["Eccentricity"] = 2.796000e-003 +almanac[18]["Time_of_Applicability"] = 5.898240e+005 +almanac[18]["Orbital_Inclination"] = 9.564693e-001 +almanac[18]["Rate_of_Right_Ascen"] = -7.908080e-009 +almanac[18]["SQRT_A"] = 5.153600e+003 +almanac[18]["Right_Ascen_at_Week"] = -2.889565e-001 +almanac[18]["Argument_of_Perigee"] = 1.379612e+000 +almanac[18]["Mean_Anom"] = 2.461750e+000 +almanac[18]["week"] = 1390 + +almanac[19] = {} +almanac[19]["System"] = SAT_SYS_GPS +almanac[19]["Number"] = 21 +almanac[19]["Orbital"] = "D" +almanac[19]["Eccentricity"] = 1.162900e-002 +almanac[19]["Time_of_Applicability"] = 5.898240e+005 +almanac[19]["Orbital_Inclination"] = 9.418592e-001 +almanac[19]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[19]["SQRT_A"] = 5.153600e+003 +almanac[19]["Right_Ascen_at_Week"] = -1.289972e+000 +almanac[19]["Argument_of_Perigee"] = -2.923686e+000 +almanac[19]["Mean_Anom"] = -2.349194e+000 +almanac[19]["week"] = 1390 + +almanac[20] = {} +almanac[20]["System"] = SAT_SYS_GPS +almanac[20]["Number"] = 22 +almanac[20]["Orbital"] = "E" +almanac[20]["Eccentricity"] = 4.893000e-003 +almanac[20]["Time_of_Applicability"] = 5.898240e+005 +almanac[20]["Orbital_Inclination"] = 9.545093e-001 +almanac[20]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[20]["SQRT_A"] = 5.153600e+003 +almanac[20]["Right_Ascen_at_Week"] = -2.280969e-001 +almanac[20]["Argument_of_Perigee"] = -1.674502e+000 +almanac[20]["Mean_Anom"] = 1.106852e+000 +almanac[20]["week"] = 1390 + +almanac[21] = {} +almanac[21]["System"] = SAT_SYS_GPS +almanac[21]["Number"] = 23 +almanac[21]["Orbital"] = "F" +almanac[21]["Eccentricity"] = 4.822000e-003 +almanac[21]["Time_of_Applicability"] = 5.898240e+005 +almanac[21]["Orbital_Inclination"] = 9.691247e-001 +almanac[21]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[21]["SQRT_A"] = 5.153700e+003 +almanac[21]["Right_Ascen_at_Week"] = 7.667399e-001 +almanac[21]["Argument_of_Perigee"] = 2.497634e+000 +almanac[21]["Mean_Anom"] = 3.184700e-001 +almanac[21]["week"] = 1390 + +almanac[22] = {} +almanac[22]["System"] = SAT_SYS_GPS +almanac[22]["Number"] = 24 +almanac[22]["Orbital"] = "D" +almanac[22]["Eccentricity"] = 9.277000e-003 +almanac[22]["Time_of_Applicability"] = 5.898240e+005 +almanac[22]["Orbital_Inclination"] = 9.585183e-001 +almanac[22]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[22]["SQRT_A"] = 5.153900e+003 +almanac[22]["Right_Ascen_at_Week"] = -1.274840e+000 +almanac[22]["Argument_of_Perigee"] = -8.815651e-001 +almanac[22]["Mean_Anom"] = -1.695551e+000 +almanac[22]["week"] = 1390 + +almanac[23] = {} +almanac[23]["System"] = SAT_SYS_GPS +almanac[23]["Number"] = 25 +almanac[23]["Orbital"] = "A" +almanac[23]["Eccentricity"] = 1.257400e-002 +almanac[23]["Time_of_Applicability"] = 5.898240e+005 +almanac[23]["Orbital_Inclination"] = 9.551027e-001 +almanac[23]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[23]["SQRT_A"] = 5.153600e+003 +almanac[23]["Right_Ascen_at_Week"] = 1.721853e+000 +almanac[23]["Argument_of_Perigee"] = -1.329870e+000 +almanac[23]["Mean_Anom"] = -1.769623e+000 +almanac[23]["week"] = 1390 + +almanac[24] = {} +almanac[24]["System"] = SAT_SYS_GPS +almanac[24]["Number"] = 26 +almanac[24]["Orbital"] = "F" +almanac[24]["Eccentricity"] = 1.745700e-002 +almanac[24]["Time_of_Applicability"] = 5.898240e+005 +almanac[24]["Orbital_Inclination"] = 9.908749e-001 +almanac[24]["Rate_of_Right_Ascen"] = -7.840012e-009 +almanac[24]["SQRT_A"] = 5.153700e+003 +almanac[24]["Right_Ascen_at_Week"] = 7.961836e-001 +almanac[24]["Argument_of_Perigee"] = 8.161502e-001 +almanac[24]["Mean_Anom"] = -5.841961e-001 +almanac[24]["week"] = 1390 + +almanac[25] = {} +almanac[25]["System"] = SAT_SYS_GPS +almanac[25]["Number"] = 27 +almanac[25]["Orbital"] = "A" +almanac[25]["Eccentricity"] = 1.991000e-002 +almanac[25]["Time_of_Applicability"] = 5.898240e+005 +almanac[25]["Orbital_Inclination"] = 9.596563e-001 +almanac[25]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[25]["SQRT_A"] = 5.153600e+003 +almanac[25]["Right_Ascen_at_Week"] = 1.754124e+000 +almanac[25]["Argument_of_Perigee"] = -1.900854e+000 +almanac[25]["Mean_Anom"] = 3.046487e+000 +almanac[25]["week"] = 1390 + +almanac[26] = {} +almanac[26]["System"] = SAT_SYS_GPS +almanac[26]["Number"] = 28 +almanac[26]["Orbital"] = "B" +almanac[26]["Eccentricity"] = 1.162800e-002 +almanac[26]["Time_of_Applicability"] = 5.898240e+005 +almanac[26]["Orbital_Inclination"] = 9.610106e-001 +almanac[26]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[26]["SQRT_A"] = 5.153600e+003 +almanac[26]["Right_Ascen_at_Week"] = 2.882583e+000 +almanac[26]["Argument_of_Perigee"] = -2.242868e+000 +almanac[26]["Mean_Anom"] = 1.860642e+000 +almanac[26]["week"] = 1390 + +almanac[27] = {} +almanac[27]["System"] = SAT_SYS_GPS +almanac[27]["Number"] = 29 +almanac[27]["Orbital"] = "F" +almanac[27]["Eccentricity"] = 9.462000e-003 +almanac[27]["Time_of_Applicability"] = 1.474560e+005 +almanac[27]["Orbital_Inclination"] = 9.874838e-001 +almanac[27]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[27]["SQRT_A"] = 5.153700e+003 +almanac[27]["Right_Ascen_at_Week"] = 7.647503e-001 +almanac[27]["Argument_of_Perigee"] = -8.614589e-001 +almanac[27]["Mean_Anom"] = -4.488983e-001 +almanac[27]["week"] = 1390 + +almanac[28] = {} +almanac[28]["System"] = SAT_SYS_GPS +almanac[28]["Number"] = 30 +almanac[28]["Orbital"] = "B" +almanac[28]["Eccentricity"] = 9.296000e-003 +almanac[28]["Time_of_Applicability"] = 5.898240e+005 +almanac[28]["Orbital_Inclination"] = 9.452992e-001 +almanac[28]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[28]["SQRT_A"] = 5.153600e+003 +almanac[28]["Right_Ascen_at_Week"] = 2.826698e+000 +almanac[28]["Argument_of_Perigee"] = 1.306413e+000 +almanac[28]["Mean_Anom"] = 2.148725e+000 +almanac[28]["week"] = 1390 + + + + + + +--GLONASS +--1 îðáèòàëüíàÿ ïëîñêîñòü, íîìåðà 1-8 +almanac[29] = {} +almanac[29]["System"] = SAT_SYS_GLONASS +almanac[29]["Number"] = 1 +almanac[29]["Orbital"] = 1 +almanac[29]["GLONASS_Data"] = {} +almanac[29]["GLONASS_Data"]["NKU_Number"] = 796 +almanac[29]["GLONASS_Data"]["Cosmos_Number"] = 2411 +almanac[29]["Eccentricity"] = 1.184000e-003 +almanac[29]["Time_of_Applicability"] = 0.000000e+000 +almanac[29]["Orbital_Inclination"] = 1.126443e+000 +almanac[29]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[29]["SQRT_A"] = 5.050500e+003 +almanac[29]["Right_Ascen_at_Week"] = 5.979807e+000 +almanac[29]["Argument_of_Perigee"] = 2.622634e+000 +almanac[29]["Mean_Anom"] = -5.519651e+000 +almanac[29]["week"] = 1390 +almanac[29]["Commit_date"] = "06.02.2005" +almanac[29]["Life_dates"] = {} + +almanac[30] = {} +almanac[30]["System"] = SAT_SYS_GLONASS +almanac[30]["Number"] = 2 +almanac[30]["Orbital"] = 1 +almanac[30]["GLONASS_Data"] = {} +almanac[30]["GLONASS_Data"]["NKU_Number"] = 794 +almanac[30]["GLONASS_Data"]["Cosmos_Number"] = 2401 +almanac[30]["Eccentricity"] = 4.486000e-003 +almanac[30]["Time_of_Applicability"] = 0.000000e+000 +almanac[30]["Orbital_Inclination"] = 1.128459e+000 +almanac[30]["Rate_of_Right_Ascen"] = -6.759654e-009 +almanac[30]["SQRT_A"] = 5.050500e+003 +almanac[30]["Right_Ascen_at_Week"] = 5.997871e+000 +almanac[30]["Argument_of_Perigee"] = 1.709531e+000 +almanac[30]["Mean_Anom"] = -5.367633e+000 +almanac[30]["week"] = 1390 +almanac[30]["Commit_date"] = "02.02.2004" +almanac[30]["Life_dates"] = {} + +almanac[31] = {} +almanac[31]["System"] = SAT_SYS_GLONASS +almanac[31]["Number"] = 3 +almanac[31]["Orbital"] = 1 +almanac[31]["GLONASS_Data"] = {} +almanac[31]["GLONASS_Data"]["NKU_Number"] = 789 +almanac[31]["GLONASS_Data"]["Cosmos_Number"] = 2381 +almanac[31]["Eccentricity"] = 2.459000e-003 +almanac[31]["Time_of_Applicability"] = 0.000000e+000 +almanac[31]["Orbital_Inclination"] = 1.122958e+000 +almanac[31]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[31]["SQRT_A"] = 5.050500e+003 +almanac[31]["Right_Ascen_at_Week"] = 5.960713e+000 +almanac[31]["Argument_of_Perigee"] = -2.683407e+000 +almanac[31]["Mean_Anom"] = -1.791788e+000 +almanac[31]["week"] = 1390 +almanac[31]["Commit_date"] = "04.01.2002" +almanac[31]["Life_dates"] = {} + +almanac[32] = {} +almanac[32]["System"] = SAT_SYS_GLONASS +almanac[32]["Number"] = 4 +almanac[32]["Orbital"] = 1 +almanac[32]["GLONASS_Data"] = {} +almanac[32]["GLONASS_Data"]["NKU_Number"] = 795 +almanac[29]["GLONASS_Data"]["Cosmos_Number"] = 2403 +almanac[32]["Eccentricity"] = 4.054000e-003 +almanac[32]["Time_of_Applicability"] = 0.000000e+000 +almanac[32]["Orbital_Inclination"] = 1.128543e+000 +almanac[32]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[32]["SQRT_A"] = 5.050500e+003 +almanac[32]["Right_Ascen_at_Week"] = 5.998081e+000 +almanac[32]["Argument_of_Perigee"] = 1.497160e+000 +almanac[32]["Mean_Anom"] = -4.293681e-001 +almanac[32]["week"] = 1390 +almanac[32]["Commit_date"] = "29.01.2004" +almanac[32]["Life_dates"] = {} + +almanac[33] = {} +almanac[33]["System"] = SAT_SYS_GLONASS +almanac[33]["Number"] = 5 +almanac[33]["Orbital"] = 1 +almanac[33]["GLONASS_Data"] = {} +almanac[33]["GLONASS_Data"]["NKU_Number"] = 711 +almanac[33]["GLONASS_Data"]["Cosmos_Number"] = 2382 +almanac[33]["Eccentricity"] = 7.040000e-004 +almanac[33]["Time_of_Applicability"] = 0.000000e+000 +almanac[33]["Orbital_Inclination"] = 1.122886e+000 +almanac[33]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[33]["SQRT_A"] = 5.050600e+003 +almanac[33]["Right_Ascen_at_Week"] = 5.960713e+000 +almanac[33]["Argument_of_Perigee"] = 2.740933e+000 +almanac[33]["Mean_Anom"] = -2.523604e+000 +almanac[33]["week"] = 1390 +almanac[33]["Commit_date"] = "13.02.2003" +almanac[33]["Life_dates"] = {} + +almanac[34] = {} +almanac[34]["System"] = SAT_SYS_GLONASS +almanac[34]["Number"] = 6 +almanac[34]["Orbital"] = 1 +almanac[34]["GLONASS_Data"] = {} +almanac[34]["GLONASS_Data"]["NKU_Number"] = 701 +almanac[34]["GLONASS_Data"]["Cosmos_Number"] = 2404 +almanac[34]["Eccentricity"] = 4.766000e-003 +almanac[34]["Time_of_Applicability"] = 0.000000e+000 +almanac[34]["Orbital_Inclination"] = 1.128276e+000 +almanac[34]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[34]["SQRT_A"] = 5.050500e+003 +almanac[34]["Right_Ascen_at_Week"] = 5.997906e+000 +almanac[34]["Argument_of_Perigee"] = 1.802417e+000 +almanac[34]["Mean_Anom"] = -2.426512e+000 +almanac[34]["week"] = 1390 +almanac[34]["Commit_date"] = "08.12.2004" +almanac[34]["Life_dates"] = {} + +almanac[35] = {} +almanac[35]["System"] = SAT_SYS_GLONASS +almanac[35]["Number"] = 7 +almanac[35]["Orbital"] = 1 +almanac[35]["GLONASS_Data"] = {} +almanac[35]["GLONASS_Data"]["NKU_Number"] = 712 +almanac[35]["GLONASS_Data"]["Cosmos_Number"] = 2413 +almanac[35]["Eccentricity"] = 7.570000e-004 +almanac[35]["Time_of_Applicability"] = 0.000000e+000 +almanac[35]["Orbital_Inclination"] = 1.126344e+000 +almanac[35]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[35]["SQRT_A"] = 5.050500e+003 +almanac[35]["Right_Ascen_at_Week"] = 5.979388e+000 +almanac[35]["Argument_of_Perigee"] = 2.566068e+000 +almanac[35]["Mean_Anom"] = -3.921228e+000 +almanac[35]["week"] = 1390 +almanac[35]["Commit_date"] = "07.10.2005" +almanac[35]["Life_dates"] = {} + +almanac[36] = {} +almanac[36]["System"] = SAT_SYS_GLONASS +almanac[36]["GLONASS_Data"] = {} +almanac[36]["Number"] = 8 +almanac[36]["Orbital"] = 1 +almanac[36]["GLONASS_Data"] = {} +almanac[36]["GLONASS_Data"]["NKU_Number"] = 797 +almanac[36]["GLONASS_Data"]["Cosmos_Number"] = 2412 +almanac[36]["Eccentricity"] = 4.060000e-004 +almanac[36]["Time_of_Applicability"] = 0.000000e+000 +almanac[36]["Orbital_Inclination"] = 1.126564e+000 +almanac[36]["Rate_of_Right_Ascen"] = -6.785834e-009 +almanac[36]["SQRT_A"] = 5.050600e+003 +almanac[36]["Right_Ascen_at_Week"] = 5.980069e+000 +almanac[36]["Argument_of_Perigee"] = 2.673633e+000 +almanac[36]["Mean_Anom"] = -4.812026e+000 +almanac[36]["week"] = 1390 +almanac[36]["Commit_date"] = "06.02.2005" +almanac[36]["Life_dates"] = {} + +--3 îðáèòàëüíàÿ ïëîñêîñòü, íîìåðà 17-24 +almanac[37] = {} +almanac[37]["System"] = SAT_SYS_GLONASS +almanac[37]["Number"] = 17 +almanac[37]["Orbital"] = 3 +almanac[37]["GLONASS_Data"] = {} +almanac[37]["GLONASS_Data"]["NKU_Number"] = 787 +almanac[37]["GLONASS_Data"]["Cosmos_Number"] = 2375 +almanac[37]["Eccentricity"] = 5.670000e-004 +almanac[37]["Time_of_Applicability"] = 0.000000e+000 +almanac[37]["Orbital_Inclination"] = 1.126524e+000 +almanac[37]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[37]["SQRT_A"] = 5.050500e+003 +almanac[37]["Right_Ascen_at_Week"] = 3.895554e+000 +almanac[37]["Argument_of_Perigee"] = 6.085085e-001 +almanac[37]["Mean_Anom"] = -2.977407e+000 +almanac[37]["week"] = 1390 +almanac[37]["Commit_date"] = "04.11.2000" +almanac[37]["Life_dates"] = {} + + +almanac[38] = {} +almanac[38]["System"] = SAT_SYS_GLONASS +almanac[38]["Number"] = 18 +almanac[38]["Orbital"] = 3 +almanac[38]["GLONASS_Data"] = {} +almanac[38]["GLONASS_Data"]["NKU_Number"] = 783 +almanac[38]["GLONASS_Data"]["Cosmos_Number"] = 2374 +almanac[38]["Eccentricity"] = 4.520000e-003 +almanac[38]["Time_of_Applicability"] = 0.000000e+000 +almanac[38]["Orbital_Inclination"] = 1.126239e+000 +almanac[38]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[38]["SQRT_A"] = 5.050600e+003 +almanac[38]["Right_Ascen_at_Week"] = 3.894071e+000 +almanac[38]["Argument_of_Perigee"] = -2.509589e+000 +almanac[38]["Mean_Anom"] = -1.020057e+000 +almanac[38]["week"] = 1390 +almanac[38]["Commit_date"] = "05.01.2001" +almanac[38]["Life_dates"] = {} + +almanac[39] = {} +almanac[39]["System"] = SAT_SYS_GLONASS +almanac[39]["Number"] = 19 +almanac[39]["Orbital"] = 3 +almanac[39]["GLONASS_Data"] = {} +almanac[39]["GLONASS_Data"]["NKU_Number"] = 798 +almanac[39]["GLONASS_Data"]["Cosmos_Number"] = 2417 +almanac[39]["Eccentricity"] = 2.023000e-003 +almanac[39]["Time_of_Applicability"] = 0.000000e+000 +almanac[39]["Orbital_Inclination"] = 1.132205e+000 +almanac[39]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[39]["SQRT_A"] = 5.050500e+003 +almanac[39]["Right_Ascen_at_Week"] = 3.884018e+000 +almanac[39]["Argument_of_Perigee"] = 2.718313e+000 +almanac[39]["Mean_Anom"] = -3.933620e-001 +almanac[39]["week"] = 1390 +almanac[39]["Commit_date"] = "22.01.2006" +almanac[39]["Life_dates"] = {} + +almanac[40] = {} +almanac[40]["System"] = SAT_SYS_GLONASS +almanac[40]["Number"] = 20 +almanac[40]["Orbital"] = 3 +almanac[40]["GLONASS_Data"] = {} +almanac[40]["GLONASS_Data"]["NKU_Number"] = 793 +almanac[40]["GLONASS_Data"]["Cosmos_Number"] = 2396 +almanac[40]["Eccentricity"] = 1.822000e-003 +almanac[40]["Time_of_Applicability"] = 0.000000e+000 +almanac[40]["Orbital_Inclination"] = 1.129789e+000 +almanac[40]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[40]["SQRT_A"] = 5.050500e+003 +almanac[40]["Right_Ascen_at_Week"] = 3.896863e+000 +almanac[40]["Argument_of_Perigee"] = 2.723776e+000 +almanac[40]["Mean_Anom"] = -1.193647e+000 +almanac[40]["week"] = 1390 +almanac[40]["Commit_date"] = "31.01.2003" +almanac[40]["Life_dates"] = {} + +almanac[41] = {} +almanac[41]["System"] = SAT_SYS_GLONASS +almanac[41]["Number"] = 21 +almanac[41]["Orbital"] = 3 +almanac[41]["GLONASS_Data"] = {} +almanac[41]["GLONASS_Data"]["NKU_Number"] = 792 +almanac[41]["GLONASS_Data"]["Cosmos_Number"] = 2395 +almanac[41]["Eccentricity"] = 5.290000e-004 +almanac[41]["Time_of_Applicability"] = 0.000000e+000 +almanac[41]["Orbital_Inclination"] = 1.129957e+000 +almanac[41]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[41]["SQRT_A"] = 5.050500e+003 +almanac[41]["Right_Ascen_at_Week"] = 3.897806e+000 +almanac[41]["Argument_of_Perigee"] = -9.519367e-001 +almanac[41]["Mean_Anom"] = -4.578920e+000 +almanac[41]["week"] = 1390 +almanac[41]["Commit_date"] = "31.01.2003" +almanac[41]["Life_dates"] = {} + +almanac[42] = {} +almanac[42]["System"] = SAT_SYS_GLONASS +almanac[42]["Number"] = 22 +almanac[42]["Orbital"] = 3 +almanac[42]["GLONASS_Data"] = {} +almanac[42]["GLONASS_Data"]["NKU_Number"] = 791 +almanac[42]["GLONASS_Data"]["Cosmos_Number"] = 2394 +almanac[42]["Eccentricity"] = 9.200000e-005 +almanac[42]["Time_of_Applicability"] = 0.000000e+000 +almanac[42]["Orbital_Inclination"] = 1.129742e+000 +almanac[42]["Rate_of_Right_Ascen"] = -6.740456e-009 +almanac[42]["SQRT_A"] = 5.050500e+003 +almanac[42]["Right_Ascen_at_Week"] = 3.897404e+000 +almanac[42]["Argument_of_Perigee"] = 2.518211e+000 +almanac[42]["Mean_Anom"] = -2.530167e+000 +almanac[42]["week"] = 1390 +almanac[42]["Commit_date"] = "21.01.2003" +almanac[42]["Life_dates"] = {} + +almanac[43] = {} +almanac[43]["System"] = SAT_SYS_GLONASS +almanac[43]["Number"] = 23 +almanac[43]["Orbital"] = 3 +almanac[43]["GLONASS_Data"] = {} +almanac[43]["GLONASS_Data"]["NKU_Number"] = 714 +almanac[43]["GLONASS_Data"]["Cosmos_Number"] = 2419 +almanac[43]["Eccentricity"] = 8.730000e-004 +almanac[43]["Time_of_Applicability"] = 0.000000e+000 +almanac[43]["Orbital_Inclination"] = 1.132105e+000 +almanac[43]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[43]["SQRT_A"] = 5.050500e+003 +almanac[43]["Right_Ascen_at_Week"] = 3.883808e+000 +almanac[43]["Argument_of_Perigee"] = -3.039139e-001 +almanac[43]["Mean_Anom"] = -5.228304e-001 +almanac[43]["week"] = 1390 +almanac[43]["Commit_date"] = "31.08.2006" +almanac[43]["Life_dates"] = {} + +almanac[44] = {} +almanac[44]["System"] = SAT_SYS_GLONASS +almanac[44]["Number"] = 24 +almanac[44]["Orbital"] = 3 +almanac[44]["GLONASS_Data"] = {} +almanac[44]["GLONASS_Data"]["NKU_Number"] = 713 +almanac[44]["GLONASS_Data"]["Cosmos_Number"] = 2418 +almanac[44]["Eccentricity"] = 2.044000e-003 +almanac[44]["Time_of_Applicability"] = 0.000000e+000 +almanac[44]["Orbital_Inclination"] = 1.132430e+000 +almanac[44]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[44]["SQRT_A"] = 5.050500e+003 +almanac[44]["Right_Ascen_at_Week"] = 3.883983e+000 +almanac[44]["Argument_of_Perigee"] = -3.722784e-001 +almanac[44]["Mean_Anom"] = -1.240457e+000 +almanac[44]["week"] = 1390 +almanac[44]["Commit_date"] = "31.08.2006" +almanac[44]["Life_dates"] = {} + +--2 îðáèòàëüíàÿ ïëîñêîñòü, íîìåðà 9-16 +almanac[45] = {} +almanac[45]["System"] = SAT_SYS_GLONASS +almanac[45]["Number"] = 9 +almanac[45]["Orbital"] = 2 +almanac[45]["GLONASS_Data"] = {} +almanac[45]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[45]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[45]["Eccentricity"] = 1.184000e-003 +almanac[45]["Time_of_Applicability"] = 0.000000e+000 +almanac[45]["Orbital_Inclination"] = 1.126443e+000 +almanac[45]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[45]["SQRT_A"] = 5.050500e+003 +almanac[45]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[45]["Argument_of_Perigee"] = 2.88430067 +almanac[45]["Mean_Anom"] = -5.519651e+000 +almanac[45]["week"] = 1390 +almanac[45]["Commit_date"] = "N/A" +almanac[45]["Life_dates"] = {} + +almanac[46] = {} +almanac[46]["System"] = SAT_SYS_GLONASS +almanac[46]["Number"] = 10 +almanac[46]["Orbital"] = 2 +almanac[46]["GLONASS_Data"] = {} +almanac[46]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[46]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[46]["Eccentricity"] = 1.184000e-003 +almanac[46]["Time_of_Applicability"] = 0.000000e+000 +almanac[46]["Orbital_Inclination"] = 1.126443e+000 +almanac[46]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[46]["SQRT_A"] = 5.050500e+003 +almanac[46]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[46]["Argument_of_Perigee"] = 3.66930067 +almanac[46]["Mean_Anom"] = -5.519651e+000 +almanac[46]["week"] = 1390 +almanac[46]["Commit_date"] = "N/A" +almanac[46]["Life_dates"] = {} + +almanac[47] = {} +almanac[47]["System"] = SAT_SYS_GLONASS +almanac[47]["Number"] = 11 +almanac[47]["Orbital"] = 2 +almanac[47]["GLONASS_Data"] = {} +almanac[47]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[47]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[47]["Eccentricity"] = 1.184000e-003 +almanac[47]["Time_of_Applicability"] = 0.000000e+000 +almanac[47]["Orbital_Inclination"] = 1.126443e+000 +almanac[47]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[47]["SQRT_A"] = 5.050500e+003 +almanac[47]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[47]["Argument_of_Perigee"] = 4.45430067 +almanac[47]["Mean_Anom"] = -5.519651e+000 +almanac[47]["week"] = 1390 +almanac[47]["Commit_date"] = "N/A" +almanac[47]["Life_dates"] = {} + +almanac[48] = {} +almanac[48]["System"] = SAT_SYS_GLONASS +almanac[48]["Number"] = 12 +almanac[48]["Orbital"] = 2 +almanac[48]["GLONASS_Data"] = {} +almanac[48]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[48]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[48]["Eccentricity"] = 1.184000e-003 +almanac[48]["Time_of_Applicability"] = 0.000000e+000 +almanac[48]["Orbital_Inclination"] = 1.126443e+000 +almanac[48]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[48]["SQRT_A"] = 5.050500e+003 +almanac[48]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[48]["Argument_of_Perigee"] = 5.23930067 +almanac[48]["Mean_Anom"] = -5.519651e+000 +almanac[48]["week"] = 1390 +almanac[48]["Commit_date"] = "N/A" +almanac[48]["Life_dates"] = {} + +almanac[49] = {} +almanac[49]["System"] = SAT_SYS_GLONASS +almanac[49]["Number"] = 13 +almanac[49]["Orbital"] = 2 +almanac[49]["GLONASS_Data"] = {} +almanac[49]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[49]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[49]["Eccentricity"] = 1.184000e-003 +almanac[49]["Time_of_Applicability"] = 0.000000e+000 +almanac[49]["Orbital_Inclination"] = 1.126443e+000 +almanac[49]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[49]["SQRT_A"] = 5.050500e+003 +almanac[49]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[49]["Argument_of_Perigee"] = 6.02430067 +almanac[49]["Mean_Anom"] = -5.519651e+000 +almanac[49]["week"] = 1390 +almanac[49]["Commit_date"] = "N/A" +almanac[49]["Life_dates"] = {} + +almanac[50] = {} +almanac[50]["System"] = SAT_SYS_GLONASS +almanac[50]["Number"] = 14 +almanac[50]["Orbital"] = 2 +almanac[50]["GLONASS_Data"] = {} +almanac[50]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[50]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[50]["Eccentricity"] = 1.184000e-003 +almanac[50]["Time_of_Applicability"] = 0.000000e+000 +almanac[50]["Orbital_Inclination"] = 1.126443e+000 +almanac[50]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[50]["SQRT_A"] = 5.050500e+003 +almanac[50]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[50]["Argument_of_Perigee"] = 0.52930067 +almanac[50]["Mean_Anom"] = -5.519651e+000 +almanac[50]["week"] = 1390 +almanac[50]["Commit_date"] = "N/A" +almanac[50]["Life_dates"] = {} + +almanac[51] = {} +almanac[51]["System"] = SAT_SYS_GLONASS +almanac[51]["Number"] = 15 +almanac[51]["Orbital"] = 2 +almanac[51]["GLONASS_Data"] = {} +almanac[51]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[51]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[51]["Eccentricity"] = 1.184000e-003 +almanac[51]["Time_of_Applicability"] = 0.000000e+000 +almanac[51]["Orbital_Inclination"] = 1.126443e+000 +almanac[51]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[51]["SQRT_A"] = 5.050500e+003 +almanac[51]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[51]["Argument_of_Perigee"] = 1.31430067 +almanac[51]["Mean_Anom"] = -5.519651e+000 +almanac[51]["week"] = 1390 +almanac[51]["Commit_date"] = "N/A" +almanac[51]["Life_dates"] = {} + +almanac[52] = {} +almanac[52]["System"] = SAT_SYS_GLONASS +almanac[52]["Number"] = 16 +almanac[52]["Orbital"] = 2 +almanac[52]["GLONASS_Data"] = {} +almanac[52]["GLONASS_Data"]["NKU_Number"] = "N/A" +almanac[52]["GLONASS_Data"]["Cosmos_Number"] = "N/A" +almanac[52]["Eccentricity"] = 1.184000e-003 +almanac[52]["Time_of_Applicability"] = 0.000000e+000 +almanac[52]["Orbital_Inclination"] = 1.126443e+000 +almanac[52]["Rate_of_Right_Ascen"] = 0.000000e+000 +almanac[52]["SQRT_A"] = 5.050500e+003 +almanac[52]["Right_Ascen_at_Week"] = 1.79067e+000 +almanac[52]["Argument_of_Perigee"] = 2.09930067 +almanac[52]["Mean_Anom"] = -5.519651e+000 +almanac[52]["week"] = 1390 +almanac[52]["Commit_date"] = "N/A" +almanac[52]["Life_dates"] = {} + +SA_mode = false +AS_mode = false diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Scripts/World/birds.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Scripts/World/birds.lua new file mode 100644 index 000000000..8aee1f700 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/Scripts/World/birds.lua @@ -0,0 +1,27 @@ +birds_avail = true --Birds availability. false - there is no birds +birds_maximum_hrad = 200 --Maximum altitude above ground al sea level bird could be met +birds_maximum_absolute_height = 8000 --Maximum absolute altitude bird could be met +birds_minimum_velocity = 40 --Minimum velocity bird could be met +birds_delta_time = 3.55 +birds_probability = {0.006333333*150, + 0.004166667*150, + 0.001966667*150, + 0.001090909*150, + 0.000741818*150, + 0.0006*150, + 0.000510545*150, + 0.000447273*150, + 0.000389455*150, + 0.000349091*150, + 0.000310909*150, + 0.000282545*150, + 0.000250909*150, + 0.000220364*150, + 0.000196364*150, + 0.000174545*150, + 0.000152727*150, + 0.000128727*150, + 0.000103636*150, + 7.63636E-05*150, + 0*150 +} diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/VHF_RADIO/SETTINGS.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/VHF_RADIO/SETTINGS.lua new file mode 100644 index 000000000..92c6a42c4 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/VHF_RADIO/SETTINGS.lua @@ -0,0 +1,14 @@ +settings= +{ + ["dials"]= + { + ["channel"]=-1, + }, + ["presets"]= + { + [1]=124000000, + [2]=124000000, + [3]=131000000, + [4]=139000000, + }, +} diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/AIB-005 - Patrol AI and Randomize Zones.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/AIB-005 - Patrol AI and Randomize Zones.lua new file mode 100644 index 000000000..eab2c2e22 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/AIB-005 - Patrol AI and Randomize Zones.lua @@ -0,0 +1,51 @@ +-- Name: AIB-005 - Patrol AI and Randomize Zones +-- Author: FlightControl +-- Date Created: 10 Jan 2016 +-- +-- # Situation: +-- +-- For the red coalition, 2 client slots are foreseen. +-- For those players that have not joined the mission, red AI is spawned. +-- The red AI should start patrolling an area until fuel is empty and return to the home base. +-- For each AI being spawned, ensure that they fly to a random zone defined within the mission editor. +-- Right now there are two patrol zones defined, so the AI should start patrolliing in one of these zones. +-- +-- # Test cases: +-- +-- 1. If no player is logging into the red slots, 2 red AI planes should be alive. +-- 2. If a player joins one red slot, one red AI plane should return to the nearest home base. +-- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base. +-- 4. Spawned AI should take-off from the airbase, and start patrolling the area around Anapa. +-- 5. When the AI is out-of-fuel, it should report it is returning to the home base, and land at Anapa. +-- 6. Ensure that you see the AI patrol in one of the two zones ... + +-- Define the SET of CLIENTs from the red coalition. This SET is filled during startup. +local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) + +-- Define the SPAWN object for the red AI plane template. +-- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off. +-- If a blocked plane exists, this red plane will be ReSpawned. +local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) + +-- Start the AI_BALANCER, using the SET of red CLIENTs, and the SPAWN object as a parameter. +local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) + +-- Create the first polygon zone ... +local PatrolZoneGroup1 = GROUP:FindByName( "PatrolZone1" ) +local PatrolZone1 = ZONE_POLYGON:New( "PatrolZone1", PatrolZoneGroup1 ) + +-- Create the second polygon zone ... +local PatrolZoneGroup2 = GROUP:FindByName( "PatrolZone2" ) +local PatrolZone2 = ZONE_POLYGON:New( "PatrolZone2", PatrolZoneGroup2 ) + +-- Now, create an array of these zones ... +local PatrolZoneArray = { PatrolZone1, PatrolZone2 } + +function RU_AI_Balancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) + + local Patrol = AI_PATROL_ZONE:New( PatrolZoneArray[math.random( 1, 2 )], 3000, 6000, 400, 600 ) + Patrol:ManageFuel( 0.2, 60 ) + Patrol:SetControllable( AIGroup ) + Patrol:Start() + +end diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/Moose.lua b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/Moose.lua new file mode 100644 index 000000000..8faec6fc4 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/Moose.lua @@ -0,0 +1,31 @@ +env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) +env.info( 'Moose Generation Timestamp: 20170116_2116' ) + +local base = _G + +Include = {} + +Include.File = function( IncludeFile ) + if not Include.Files[ IncludeFile ] then + Include.Files[IncludeFile] = IncludeFile + env.info( "Include:" .. IncludeFile .. " from " .. Include.ProgramPath ) + local f = assert( base.loadfile( Include.ProgramPath .. IncludeFile .. ".lua" ) ) + if f == nil then + error ("Could not load MOOSE file " .. IncludeFile .. ".lua" ) + else + env.info( "Include:" .. IncludeFile .. " loaded from " .. Include.ProgramPath ) + return f() + end + end +end + +Include.ProgramPath = "Scripts/Moose/" + +env.info( "Include.ProgramPath = " .. Include.ProgramPath) + +Include.Files = {} + +Include.File( "Moose" ) + +BASE:TraceOnOff( true ) +env.info( '*** MOOSE INCLUDE END *** ' ) diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/dictionary b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/dictionary new file mode 100644 index 000000000..c29347756 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/dictionary @@ -0,0 +1,416 @@ +dictionary = +{ + ["DictKey_UnitName_89"] = "", + ["DictKey_UnitName_67"] = "AI US 1", + ["DictKey_UnitName_156"] = "RU Client #020", + ["DictKey_UnitName_297"] = "US Client #023", + ["DictKey_WptName_310"] = "", + ["DictKey_GroupName_125"] = "RU Client #010", + ["DictKey_UnitName_135"] = "RU Client #013", + ["DictKey_UnitName_374"] = "RU Client #004", + ["DictKey_WptName_292"] = "", + ["DictKey_WptName_48"] = "", + ["DictKey_GroupName_137"] = "RU Client #014", + ["DictKey_WptName_70"] = "", + ["DictKey_WptName_295"] = "", + ["DictKey_UnitName_25"] = "AI RU", + ["DictKey_GroupName_113"] = "RU Client #006", + ["DictKey_GroupName_284"] = "US Client #019", + ["DictKey_UnitName_312"] = "US Client #028", + ["DictKey_WptName_13"] = "", + ["DictKey_WptName_124"] = "", + ["DictKey_WptName_217"] = "", + ["DictKey_GroupName_10"] = "Client Group 2", + ["DictKey_GroupName_302"] = "US Client #025", + ["DictKey_UnitName_258"] = "US Client #010", + ["DictKey_WptName_181"] = "", + ["DictKey_WptName_109"] = "", + ["DictKey_WptName_336"] = "", + ["DictKey_GroupName_311"] = "US Client #028", + ["DictKey_GroupName_242"] = "US Client #005", + ["DictKey_UnitName_74"] = "Pilot #004", + ["DictKey_WptName_136"] = "", + ["DictKey_WptName_99"] = "", + ["DictKey_UnitName_315"] = "US Client #029", + ["DictKey_UnitName_43"] = "Client 5", + ["DictKey_GroupName_331"] = "PatrolZone2", + ["DictKey_WptName_178"] = "", + ["DictKey_GroupName_30"] = "AI RU", + ["DictKey_UnitName_249"] = "US Client #007", + ["DictKey_WptName_53"] = "", + ["DictKey_UnitName_171"] = "RU Client #025", + ["DictKey_WptName_289"] = "", + ["DictKey_GroupName_352"] = "RU Client #008", + ["DictKey_GroupName_260"] = "US Client #011", + ["DictKey_descriptionRedTask_2"] = "", + ["DictKey_WptName_55"] = "", + ["DictKey_GroupName_33"] = "AI RU", + ["DictKey_UnitName_183"] = "RU Client #029", + ["DictKey_WptName_190"] = "", + ["DictKey_UnitName_216"] = "RU Client #040", + ["DictKey_WptName_286"] = "", + ["DictKey_UnitName_153"] = "RU Client #019", + ["DictKey_WptName_75"] = "", + ["DictKey_UnitName_105"] = "RU Client #003", + ["DictKey_GroupName_382"] = "RU Client #007", + ["DictKey_UnitName_270"] = "US Client #014", + ["DictKey_WptName_47"] = "", + ["DictKey_GroupName_170"] = "RU Client #025", + ["DictKey_UnitName_46"] = "Client 7", + ["DictKey_WptName_92"] = "", + ["DictKey_UnitName_380"] = "RU Client #006", + ["DictKey_GroupName_191"] = "RU Client #032", + ["DictKey_UnitName_40"] = "Client 6", + ["DictKey_UnitName_95"] = "Pilot #002", + ["DictKey_GroupName_296"] = "US Client #023", + ["DictKey_WptName_244"] = "", + ["DictKey_UnitName_377"] = "RU Client #005", + ["DictKey_WptName_9"] = "", + ["DictKey_UnitName_11"] = "Client 2", + ["DictKey_GroupName_308"] = "US Client #027", + ["DictKey_GroupName_27"] = "AI RU", + ["DictKey_UnitName_22"] = "Client 4", + ["DictKey_WptName_62"] = "", + ["DictKey_GroupName_367"] = "RU Client #002", + ["DictKey_sortie_4"] = "", + ["DictKey_WptName_333"] = "", + ["DictKey_UnitName_356"] = "RU Client #009", + ["DictKey_GroupName_152"] = "RU Client #019", + ["DictKey_GroupName_281"] = "US Client #018", + ["DictKey_WptName_235"] = "", + ["DictKey_UnitName_362"] = "RU Client #011", + ["DictKey_WptName_375"] = "", + ["DictKey_GroupName_379"] = "RU Client #006", + ["DictKey_UnitName_267"] = "US Client #013", + ["DictKey_GroupName_173"] = "RU Client #026", + ["DictKey_GroupName_248"] = "US Client #007", + ["DictKey_WptName_369"] = "", + ["DictKey_UnitName_58"] = "Pilot #003", + ["DictKey_WptName_160"] = "", + ["DictKey_UnitName_246"] = "US Client #006", + ["DictKey_WptName_163"] = "", + ["DictKey_WptName_98"] = "", + ["DictKey_GroupName_340"] = "RU Client #004", + ["DictKey_UnitName_365"] = "RU Client #012", + ["DictKey_GroupName_221"] = "RU Client #042", + ["DictKey_UnitName_318"] = "US Client #030", + ["DictKey_GroupName_158"] = "RU Client #021", + ["DictKey_GroupName_320"] = "US Client #031", + ["DictKey_UnitName_34"] = "AI RU", + ["DictKey_WptName_208"] = "", + ["DictKey_WptName_334"] = "", + ["DictKey_WptName_54"] = "", + ["DictKey_WptName_82"] = "", + ["DictKey_UnitName_383"] = "RU Client #007", + ["DictKey_UnitName_234"] = "US Client #002", + ["DictKey_GroupName_104"] = "RU Client #003", + ["DictKey_UnitName_368"] = "RU Client #002", + ["DictKey_WptName_366"] = "", + ["DictKey_GroupName_206"] = "RU Client #037", + ["DictKey_GroupName_24"] = "AI RU", + ["DictKey_GroupName_325"] = "PatrolZone1", + ["DictKey_UnitName_225"] = "RU Client #043", + ["DictKey_WptName_328"] = "", + ["DictKey_WptName_193"] = "", + ["DictKey_UnitName_219"] = "RU Client #041", + ["DictKey_WptName_68"] = "", + ["DictKey_GroupName_122"] = "RU Client #009", + ["DictKey_GroupName_266"] = "US Client #013", + ["DictKey_UnitName_350"] = "RU Client #007", + ["DictKey_UnitName_341"] = "RU Client #004", + ["DictKey_UnitName_228"] = "RU Client #044", + ["DictKey_UnitName_204"] = "RU Client #036", + ["DictKey_WptName_49"] = "", + ["DictKey_UnitName_303"] = "US Client #025", + ["DictKey_GroupName_245"] = "US Client #006", + ["DictKey_GroupName_275"] = "US Client #016", + ["DictKey_WptName_90"] = "", + ["DictKey_UnitName_222"] = "RU Client #042", + ["DictKey_GroupName_110"] = "RU Client #005", + ["DictKey_UnitName_120"] = "RU Client #008", + ["DictKey_WptName_280"] = "", + ["DictKey_UnitName_144"] = "RU Client #016", + ["DictKey_UnitName_306"] = "US Client #026", + ["DictKey_WptName_118"] = "", + ["DictKey_WptName_307"] = "", + ["DictKey_UnitName_129"] = "RU Client #011", + ["DictKey_GroupName_59"] = "Client Group Range 1", + ["DictKey_GroupName_164"] = "RU Client #023", + ["DictKey_UnitName_252"] = "US Client #008", + ["DictKey_WptName_61"] = "", + ["DictKey_WptName_184"] = "", + ["DictKey_GroupName_361"] = "RU Client #011", + ["DictKey_WptName_80"] = "", + ["DictKey_GroupName_299"] = "US Client #024", + ["DictKey_GroupName_314"] = "US Client #029", + ["DictKey_WptName_86"] = "", + ["DictKey_GroupName_346"] = "RU Client #006", + ["DictKey_WptName_205"] = "", + ["DictKey_WptName_390"] = "", + ["DictKey_WptName_196"] = "", + ["DictKey_GroupName_263"] = "US Client #012", + ["DictKey_WptName_238"] = "", + ["DictKey_WptName_51"] = "", + ["DictKey_UnitName_150"] = "RU Client #018", + ["DictKey_WptName_76"] = "", + ["DictKey_UnitName_291"] = "US Client #021", + ["DictKey_WptName_127"] = "", + ["DictKey_GroupName_21"] = "Client Group 4", + ["DictKey_GroupName_364"] = "RU Client #012", + ["DictKey_GroupName_278"] = "US Client #017", + ["DictKey_WptName_44"] = "", + ["DictKey_WptName_335"] = "", + ["DictKey_WptName_100"] = "", + ["DictKey_GroupName_185"] = "RU Client #030", + ["DictKey_UnitName_321"] = "US Client #031", + ["DictKey_WptName_112"] = "", + ["DictKey_GroupName_230"] = "RU Client #045", + ["DictKey_UnitName_201"] = "RU Client #035", + ["DictKey_WptName_145"] = "", + ["DictKey_GroupName_128"] = "RU Client #011", + ["DictKey_descriptionBlueTask_3"] = "", + ["DictKey_WptName_241"] = "", + ["DictKey_descriptionText_1"] = "-- Name: AIB-005 - Patrol AI and Randomize Zones\ +-- Author: FlightControl\ +-- Date Created: 10 Jan 2016\ +--\ +-- # Situation:\ +--\ +-- For the red coalition, 2 client slots are foreseen.\ +-- For those players that have not joined the mission, red AI is spawned.\ +-- The red AI should start patrolling an area until fuel is empty and return to the home base.\ +-- For each AI being spawned, ensure that they fly to a random zone defined within the mission editor.\ +-- Right now there are two patrol zones defined, so the AI should start patrolliing in one of these zones.\ +-- \ +-- # Test cases:\ +-- \ +-- 1. If no player is logging into the red slots, 2 red AI planes should be alive.\ +-- 2. If a player joins one red slot, one red AI plane should return to the nearest home base.\ +-- 3. If two players join the red slots, no AI plane should be spawned, and all airborne AI planes should return to the nearest home base.\ +-- 4. Spawned AI should take-off from the airbase, and start patrolling the area around Anapa.\ +-- 5. When the AI is out-of-fuel, it should report it is returning to the home base, and land at Anapa.\ +-- 6. Ensure that you see the AI patrol in one of the two zones ...\ +", + ["DictKey_GroupName_134"] = "RU Client #013", + ["DictKey_UnitName_102"] = "RU Client #002", + ["DictKey_WptName_378"] = "", + ["DictKey_GroupName_224"] = "RU Client #043", + ["DictKey_UnitName_371"] = "RU Client #003", + ["DictKey_UnitName_392"] = "RU Client #010", + ["DictKey_UnitName_108"] = "RU Client #004", + ["DictKey_UnitName_132"] = "RU Client #012", + ["DictKey_UnitName_174"] = "RU Client #026", + ["DictKey_WptName_274"] = "", + ["DictKey_GroupName_176"] = "RU Client #027", + ["DictKey_WptName_339"] = "", + ["DictKey_WptName_199"] = "", + ["DictKey_UnitName_123"] = "RU Client #009", + ["DictKey_WptName_81"] = "", + ["DictKey_UnitName_213"] = "RU Client #039", + ["DictKey_WptName_211"] = "", + ["DictKey_GroupName_227"] = "RU Client #044", + ["DictKey_WptName_77"] = "", + ["DictKey_WptName_29"] = "", + ["DictKey_WptName_166"] = "", + ["DictKey_WptName_396"] = "", + ["DictKey_UnitName_168"] = "RU Client #024", + ["DictKey_UnitName_210"] = "RU Client #038", + ["DictKey_WptName_169"] = "", + ["DictKey_GroupName_7"] = "US Client #001", + ["DictKey_WptName_384"] = "", + ["DictKey_WptName_354"] = "", + ["DictKey_GroupName_143"] = "RU Client #016", + ["DictKey_UnitName_288"] = "US Client #020", + ["DictKey_GroupName_155"] = "RU Client #020", + ["DictKey_GroupName_236"] = "US Client #003", + ["DictKey_ActionText_17"] = "", + ["DictKey_WptName_157"] = "", + ["DictKey_UnitName_114"] = "RU Client #006", + ["DictKey_WptName_298"] = "", + ["DictKey_WptName_142"] = "", + ["DictKey_GroupName_254"] = "US Client #009", + ["DictKey_WptName_91"] = "", + ["DictKey_WptName_259"] = "", + ["DictKey_WptName_23"] = "", + ["DictKey_WptName_172"] = "", + ["DictKey_WptName_214"] = "", + ["DictKey_UnitName_264"] = "US Client #012", + ["DictKey_WptName_151"] = "", + ["DictKey_UnitName_15"] = "AI US 2", + ["DictKey_GroupName_45"] = "Client Group 7", + ["DictKey_WptName_71"] = "", + ["DictKey_WptName_26"] = "", + ["DictKey_UnitName_57"] = "Pilot #002", + ["DictKey_UnitName_31"] = "AI RU", + ["DictKey_UnitName_111"] = "RU Client #005", + ["DictKey_WptName_12"] = "", + ["DictKey_GroupName_39"] = "Client Group 6", + ["DictKey_WptName_52"] = "", + ["DictKey_UnitName_159"] = "RU Client #021", + ["DictKey_WptName_38"] = "", + ["DictKey_UnitName_138"] = "RU Client #014", + ["DictKey_WptName_330"] = "", + ["DictKey_UnitName_309"] = "US Client #027", + ["DictKey_WptName_85"] = "", + ["DictKey_GroupName_290"] = "US Client #021", + ["DictKey_GroupName_373"] = "RU Client #004", + ["DictKey_UnitName_240"] = "US Client #004", + ["DictKey_GroupName_358"] = "RU Client #010", + ["DictKey_WptName_247"] = "", + ["DictKey_WptName_223"] = "", + ["DictKey_WptName_324"] = "", + ["DictKey_GroupName_18"] = "RU Client #001", + ["DictKey_WptName_148"] = "", + ["DictKey_GroupName_349"] = "RU Client #007", + ["DictKey_GroupName_36"] = "AI RU", + ["DictKey_WptName_130"] = "", + ["DictKey_WptName_381"] = "", + ["DictKey_UnitName_180"] = "RU Client #028", + ["DictKey_UnitName_117"] = "RU Client #007", + ["DictKey_WptName_329"] = "", + ["DictKey_GroupName_73"] = "Patrol Zone Blue", + ["DictKey_WptName_121"] = "", + ["DictKey_WptName_78"] = "", + ["DictKey_UnitName_147"] = "RU Client #017", + ["DictKey_UnitName_56"] = "Pilot #001", + ["DictKey_GroupName_203"] = "RU Client #036", + ["DictKey_GroupName_337"] = "RU Client #003", + ["DictKey_WptName_304"] = "", + ["DictKey_WptName_103"] = "", + ["DictKey_WptName_265"] = "", + ["DictKey_GroupName_14"] = "AI US 2", + ["DictKey_UnitName_282"] = "US Client #018", + ["DictKey_WptName_357"] = "", + ["DictKey_WptName_175"] = "", + ["DictKey_WptName_327"] = "", + ["DictKey_WptName_342"] = "", + ["DictKey_WptName_154"] = "", + ["DictKey_GroupName_391"] = "RU Client #010", + ["DictKey_UnitName_359"] = "RU Client #010", + ["DictKey_GroupName_197"] = "RU Client #034", + ["DictKey_GroupName_42"] = "Client Group 5", + ["DictKey_WptName_283"] = "", + ["DictKey_GroupName_161"] = "RU Client #022", + ["DictKey_UnitName_19"] = "RU Client #001", + ["DictKey_UnitName_237"] = "US Client #003", + ["DictKey_WptName_65"] = "", + ["DictKey_WptName_372"] = "", + ["DictKey_WptName_322"] = "", + ["DictKey_WptName_97"] = "", + ["DictKey_WptName_360"] = "", + ["DictKey_GroupName_131"] = "RU Client #012", + ["DictKey_WptName_16"] = "", + ["DictKey_GroupName_101"] = "RU Client #002", + ["DictKey_WptName_202"] = "", + ["DictKey_UnitName_198"] = "RU Client #034", + ["DictKey_WptName_253"] = "", + ["DictKey_GroupName_394"] = "RU Client #011", + ["DictKey_WptName_32"] = "", + ["DictKey_UnitName_279"] = "US Client #017", + ["DictKey_GroupName_305"] = "US Client #026", + ["DictKey_UnitName_141"] = "RU Client #015", + ["DictKey_WptName_79"] = "", + ["DictKey_UnitName_207"] = "RU Client #037", + ["DictKey_WptName_250"] = "", + ["DictKey_GroupName_116"] = "RU Client #007", + ["DictKey_GroupName_94"] = "Patrol Zone Red", + ["DictKey_GroupName_212"] = "RU Client #039", + ["DictKey_GroupName_233"] = "US Client #002", + ["DictKey_GroupName_200"] = "RU Client #035", + ["DictKey_WptName_96"] = "", + ["DictKey_WptName_50"] = "", + ["DictKey_WptName_115"] = "", + ["DictKey_WptName_226"] = "", + ["DictKey_UnitName_126"] = "RU Client #010", + ["DictKey_UnitName_243"] = "US Client #005", + ["DictKey_WptName_316"] = "", + ["DictKey_WptName_69"] = "", + ["DictKey_UnitName_347"] = "RU Client #006", + ["DictKey_GroupName_209"] = "RU Client #038", + ["DictKey_UnitName_28"] = "AI RU", + ["DictKey_GroupName_215"] = "RU Client #040", + ["DictKey_WptName_64"] = "", + ["DictKey_UnitName_192"] = "RU Client #032", + ["DictKey_UnitName_338"] = "RU Client #003", + ["DictKey_GroupName_257"] = "US Client #010", + ["DictKey_GroupName_188"] = "RU Client #031", + ["DictKey_GroupName_107"] = "RU Client #004", + ["DictKey_UnitName_255"] = "US Client #009", + ["DictKey_UnitName_231"] = "RU Client #045", + ["DictKey_UnitName_88"] = "Pilot #001", + ["DictKey_WptName_232"] = "", + ["DictKey_UnitName_195"] = "RU Client #033", + ["DictKey_GroupName_370"] = "RU Client #003", + ["DictKey_WptName_229"] = "", + ["DictKey_WptName_256"] = "", + ["DictKey_WptName_345"] = "", + ["DictKey_WptName_277"] = "", + ["DictKey_WptName_63"] = "", + ["DictKey_WptName_363"] = "", + ["DictKey_GroupName_167"] = "RU Client #024", + ["DictKey_GroupName_385"] = "RU Client #008", + ["DictKey_GroupName_376"] = "RU Client #005", + ["DictKey_UnitName_60"] = "Client Range 1", + ["DictKey_UnitName_326"] = "Pilot #001", + ["DictKey_GroupName_388"] = "RU Client #009", + ["DictKey_GroupName_251"] = "US Client #008", + ["DictKey_WptName_41"] = "", + ["DictKey_UnitName_273"] = "US Client #015", + ["DictKey_GroupName_66"] = "AI US", + ["DictKey_WptName_87"] = "", + ["DictKey_GroupName_343"] = "RU Client #005", + ["DictKey_GroupName_119"] = "RU Client #008", + ["DictKey_WptName_268"] = "", + ["DictKey_WptName_220"] = "", + ["DictKey_WptName_262"] = "", + ["DictKey_WptName_83"] = "", + ["DictKey_WptName_72"] = "", + ["DictKey_UnitName_276"] = "US Client #016", + ["DictKey_WptName_387"] = "", + ["DictKey_GroupName_272"] = "US Client #015", + ["DictKey_WptName_187"] = "", + ["DictKey_UnitName_189"] = "RU Client #031", + ["DictKey_UnitName_162"] = "RU Client #022", + ["DictKey_GroupName_146"] = "RU Client #017", + ["DictKey_GroupName_140"] = "RU Client #015", + ["DictKey_GroupName_239"] = "US Client #004", + ["DictKey_UnitName_353"] = "RU Client #008", + ["DictKey_UnitName_386"] = "RU Client #008", + ["DictKey_WptName_351"] = "", + ["DictKey_WptName_313"] = "", + ["DictKey_UnitName_93"] = "Pilot #001", + ["DictKey_GroupName_287"] = "US Client #020", + ["DictKey_UnitName_395"] = "RU Client #011", + ["DictKey_UnitName_332"] = "Pilot #002", + ["DictKey_WptName_133"] = "", + ["DictKey_UnitName_186"] = "RU Client #030", + ["DictKey_GroupName_194"] = "RU Client #033", + ["DictKey_GroupName_179"] = "RU Client #028", + ["DictKey_GroupName_269"] = "US Client #014", + ["DictKey_WptName_20"] = "", + ["DictKey_WptName_348"] = "", + ["DictKey_WptName_301"] = "", + ["DictKey_UnitName_285"] = "US Client #019", + ["DictKey_UnitName_344"] = "RU Client #005", + ["DictKey_WptName_393"] = "", + ["DictKey_WptName_84"] = "", + ["DictKey_GroupName_355"] = "RU Client #009", + ["DictKey_UnitName_177"] = "RU Client #027", + ["DictKey_UnitName_37"] = "AI RU", + ["DictKey_WptName_319"] = "", + ["DictKey_WptName_106"] = "", + ["DictKey_UnitName_294"] = "US Client #022", + ["DictKey_UnitName_165"] = "RU Client #023", + ["DictKey_WptName_35"] = "", + ["DictKey_UnitName_261"] = "US Client #011", + ["DictKey_GroupName_293"] = "US Client #022", + ["DictKey_UnitName_389"] = "RU Client #009", + ["DictKey_GroupName_182"] = "RU Client #029", + ["DictKey_UnitName_300"] = "US Client #024", + ["DictKey_GroupName_317"] = "US Client #030", + ["DictKey_WptName_271"] = "", + ["DictKey_WptName_139"] = "", + ["DictKey_GroupName_149"] = "RU Client #018", + ["DictKey_GroupName_218"] = "RU Client #041", + ["DictKey_UnitName_8"] = "US Client #001", +} -- end of dictionary diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/mapResource b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/mapResource new file mode 100644 index 000000000..dc130cd07 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/l10n/DEFAULT/mapResource @@ -0,0 +1,5 @@ +mapResource = +{ + ["ResKey_Action_323"] = "Moose.lua", + ["ResKey_Action_6"] = "AIB-005 - Patrol AI and Randomize Zones.lua", +} -- end of mapResource diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/mission b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/mission new file mode 100644 index 000000000..d243c5ada --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/mission @@ -0,0 +1,5000 @@ +mission = +{ + ["trig"] = + { + ["actions"] = + { + [1] = "a_do_script_file(getValueResourceByKey(\"ResKey_Action_323\"));", + [2] = "a_do_script(getValueDictByKey(\"DictKey_ActionText_17\"));", + [3] = "a_do_script_file(getValueResourceByKey(\"ResKey_Action_6\"));", + }, -- end of ["actions"] + ["events"] = + { + }, -- end of ["events"] + ["custom"] = + { + }, -- end of ["custom"] + ["func"] = + { + }, -- end of ["func"] + ["flag"] = + { + [1] = true, + [2] = true, + [3] = true, + }, -- end of ["flag"] + ["conditions"] = + { + [1] = "return(true)", + [2] = "return(true)", + [3] = "return(true)", + }, -- end of ["conditions"] + ["customStartup"] = + { + }, -- end of ["customStartup"] + ["funcStartup"] = + { + [1] = "if mission.trig.conditions[1]() then mission.trig.actions[1]() end", + [2] = "if mission.trig.conditions[2]() then mission.trig.actions[2]() end", + [3] = "if mission.trig.conditions[3]() then mission.trig.actions[3]() end", + }, -- end of ["funcStartup"] + }, -- end of ["trig"] + ["date"] = + { + ["Day"] = 1, + ["Year"] = 2011, + ["Month"] = 6, + }, -- end of ["date"] + ["maxDictId"] = 396, + ["result"] = + { + ["offline"] = + { + ["conditions"] = + { + }, -- end of ["conditions"] + ["actions"] = + { + }, -- end of ["actions"] + ["func"] = + { + }, -- end of ["func"] + }, -- end of ["offline"] + ["total"] = 0, + ["blue"] = + { + ["conditions"] = + { + }, -- end of ["conditions"] + ["actions"] = + { + }, -- end of ["actions"] + ["func"] = + { + }, -- end of ["func"] + }, -- end of ["blue"] + ["red"] = + { + ["conditions"] = + { + }, -- end of ["conditions"] + ["actions"] = + { + }, -- end of ["actions"] + ["func"] = + { + }, -- end of ["func"] + }, -- end of ["red"] + }, -- end of ["result"] + ["groundControl"] = + { + ["isPilotControlVehicles"] = false, + ["roles"] = + { + ["artillery_commander"] = + { + ["blue"] = 0, + ["red"] = 0, + }, -- end of ["artillery_commander"] + ["instructor"] = + { + ["blue"] = 0, + ["red"] = 0, + }, -- end of ["instructor"] + ["observer"] = + { + ["blue"] = 0, + ["red"] = 0, + }, -- end of ["observer"] + ["forward_observer"] = + { + ["blue"] = 0, + ["red"] = 0, + }, -- end of ["forward_observer"] + }, -- end of ["roles"] + }, -- end of ["groundControl"] + ["triggers"] = + { + ["zones"] = + { + }, -- end of ["zones"] + }, -- end of ["triggers"] + ["weather"] = + { + ["atmosphere_type"] = 0, + ["wind"] = + { + ["at8000"] = + { + ["speed"] = 0, + ["dir"] = 0, + }, -- end of ["at8000"] + ["atGround"] = + { + ["speed"] = 0, + ["dir"] = 0, + }, -- end of ["atGround"] + ["at2000"] = + { + ["speed"] = 0, + ["dir"] = 0, + }, -- end of ["at2000"] + }, -- end of ["wind"] + ["enable_fog"] = false, + ["season"] = + { + ["temperature"] = 20, + }, -- end of ["season"] + ["type_weather"] = 0, + ["qnh"] = 760, + ["cyclones"] = + { + }, -- end of ["cyclones"] + ["name"] = "Winter, clean sky", + ["fog"] = + { + ["thickness"] = 0, + ["visibility"] = 25, + ["density"] = 7, + }, -- end of ["fog"] + ["groundTurbulence"] = 0, + ["visibility"] = + { + ["distance"] = 80000, + }, -- end of ["visibility"] + ["clouds"] = + { + ["thickness"] = 200, + ["density"] = 0, + ["base"] = 300, + ["iprecptns"] = 0, + }, -- end of ["clouds"] + }, -- end of ["weather"] + ["theatre"] = "Caucasus", + ["needModules"] = + { + }, -- end of ["needModules"] + ["map"] = + { + ["centerY"] = 295177.98214286, + ["zoom"] = 25000, + ["centerX"] = -8598.8505859375, + }, -- end of ["map"] + ["coalitions"] = + { + ["blue"] = + { + [1] = 11, + [2] = 4, + [3] = 6, + [4] = 16, + [5] = 13, + [6] = 15, + [7] = 9, + [8] = 8, + [9] = 12, + [10] = 2, + [11] = 3, + [12] = 5, + [13] = 10, + [14] = 20, + [15] = 21, + [16] = 40, + [17] = 26, + [18] = 45, + [19] = 28, + }, -- end of ["blue"] + ["neutrals"] = + { + [1] = 7, + [2] = 17, + [3] = 22, + [4] = 23, + [5] = 25, + [6] = 29, + [7] = 30, + [8] = 31, + [9] = 32, + [10] = 33, + [11] = 35, + [12] = 36, + [13] = 39, + [14] = 41, + [15] = 42, + [16] = 44, + [17] = 46, + }, -- end of ["neutrals"] + ["red"] = + { + [1] = 0, + [2] = 1, + [3] = 18, + [4] = 19, + [5] = 37, + [6] = 24, + [7] = 27, + [8] = 43, + [9] = 47, + [10] = 34, + [11] = 38, + }, -- end of ["red"] + }, -- end of ["coalitions"] + ["descriptionText"] = "DictKey_descriptionText_1", + ["pictureFileNameR"] = + { + }, -- end of ["pictureFileNameR"] + ["descriptionBlueTask"] = "DictKey_descriptionBlueTask_3", + ["descriptionRedTask"] = "DictKey_descriptionRedTask_2", + ["pictureFileNameB"] = + { + }, -- end of ["pictureFileNameB"] + ["trigrules"] = + { + [1] = + { + ["rules"] = + { + }, -- end of ["rules"] + ["eventlist"] = "", + ["actions"] = + { + [1] = + { + ["file"] = "ResKey_Action_323", + ["predicate"] = "a_do_script_file", + ["ai_task"] = + { + [1] = "", + [2] = "", + }, -- end of ["ai_task"] + }, -- end of [1] + }, -- end of ["actions"] + ["predicate"] = "triggerStart", + ["comment"] = "Load Moose", + }, -- end of [1] + [2] = + { + ["rules"] = + { + }, -- end of ["rules"] + ["eventlist"] = "", + ["actions"] = + { + [1] = + { + ["KeyDict_text"] = "DictKey_ActionText_17", + ["text"] = "DictKey_ActionText_17", + ["predicate"] = "a_do_script", + ["ai_task"] = + { + [1] = "", + [2] = "", + }, -- end of ["ai_task"] + }, -- end of [1] + }, -- end of ["actions"] + ["predicate"] = "triggerStart", + ["comment"] = "Trace", + }, -- end of [2] + [3] = + { + ["rules"] = + { + }, -- end of ["rules"] + ["eventlist"] = "", + ["actions"] = + { + [1] = + { + ["file"] = "ResKey_Action_6", + ["predicate"] = "a_do_script_file", + ["ai_task"] = + { + [1] = "", + [2] = "", + }, -- end of ["ai_task"] + }, -- end of [1] + }, -- end of ["actions"] + ["predicate"] = "triggerStart", + ["comment"] = "Load Mission", + }, -- end of [3] + }, -- end of ["trigrules"] + ["coalition"] = + { + ["blue"] = + { + ["bullseye"] = + { + ["y"] = 617414, + ["x"] = -291014, + }, -- end of ["bullseye"] + ["nav_points"] = + { + }, -- end of ["nav_points"] + ["name"] = "blue", + ["country"] = + { + [1] = + { + ["id"] = 11, + ["name"] = "Belgium", + }, -- end of [1] + [2] = + { + ["id"] = 4, + ["name"] = "UK", + }, -- end of [2] + [3] = + { + ["id"] = 6, + ["name"] = "Germany", + }, -- end of [3] + [4] = + { + ["id"] = 16, + ["name"] = "Georgia", + }, -- end of [4] + [5] = + { + ["id"] = 13, + ["name"] = "Denmark", + }, -- end of [5] + [6] = + { + ["id"] = 15, + ["name"] = "Israel", + }, -- end of [6] + [7] = + { + ["id"] = 9, + ["name"] = "Spain", + }, -- end of [7] + [8] = + { + ["id"] = 8, + ["name"] = "Canada", + }, -- end of [8] + [9] = + { + ["id"] = 12, + ["name"] = "Norway", + }, -- end of [9] + [10] = + { + ["id"] = 2, + ["name"] = "USA", + }, -- end of [10] + [11] = + { + ["id"] = 3, + ["name"] = "Turkey", + }, -- end of [11] + [12] = + { + ["id"] = 5, + ["name"] = "France", + }, -- end of [12] + [13] = + { + ["id"] = 10, + ["name"] = "The Netherlands", + }, -- end of [13] + [14] = + { + ["id"] = 20, + ["name"] = "Italy", + }, -- end of [14] + [15] = + { + ["id"] = 21, + ["name"] = "Australia", + }, -- end of [15] + [16] = + { + ["id"] = 40, + ["name"] = "Poland", + }, -- end of [16] + [17] = + { + ["id"] = 26, + ["name"] = "Czech Republic", + }, -- end of [17] + [18] = + { + ["id"] = 45, + ["name"] = "South Korea", + }, -- end of [18] + [19] = + { + ["id"] = 28, + ["name"] = "Croatia", + }, -- end of [19] + }, -- end of ["country"] + }, -- end of ["blue"] + ["red"] = + { + ["bullseye"] = + { + ["y"] = 371700, + ["x"] = 11557, + }, -- end of ["bullseye"] + ["nav_points"] = + { + }, -- end of ["nav_points"] + ["name"] = "red", + ["country"] = + { + [1] = + { + ["helicopter"] = + { + ["group"] = + { + [1] = + { + ["lateActivation"] = true, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAS", + ["uncontrolled"] = false, + ["route"] = + { + ["routeRelativeTOT"] = true, + ["points"] = + { + [1] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["number"] = 1, + ["key"] = "CAS", + ["id"] = "EngageTargets", + ["enabled"] = true, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Helicopters", + [2] = "Ground Units", + [3] = "Light armed ships", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 325834.45982144, + ["x"] = 7740.8543526806, + ["name"] = "DictKey_WptName_327", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [1] + [2] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 614.57680810556, + ["ETA_locked"] = false, + ["y"] = 325977.31696429, + ["x"] = 41883.711495538, + ["name"] = "DictKey_WptName_328", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [2] + [3] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 903.60812481849, + ["ETA_locked"] = false, + ["y"] = 311263.03125001, + ["x"] = 48312.282924109, + ["name"] = "DictKey_WptName_329", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [3] + [4] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 1667.3397263538, + ["ETA_locked"] = false, + ["y"] = 310977.31696429, + ["x"] = 5883.7114955378, + ["name"] = "DictKey_WptName_330", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [4] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 19, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 500, + ["alt_type"] = "BARO", + ["livery_id"] = "Russia Standard Army", + ["skill"] = "High", + ["ropeLength"] = 15, + ["speed"] = 55.555555555556, + ["type"] = "Ka-50", + ["unitId"] = 24, + ["psi"] = -0.0041840760018655, + ["y"] = 325834.45982144, + ["x"] = 7740.8543526806, + ["name"] = "DictKey_UnitName_326", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = "1450", + ["flare"] = 128, + ["chaff"] = 0, + ["gun"] = 100, + }, -- end of ["payload"] + ["heading"] = 0.0041840760018655, + ["callsign"] = 105, + ["onboard_num"] = "050", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 325834.45982144, + ["x"] = 7740.8543526806, + ["name"] = "DictKey_GroupName_325", + ["communication"] = true, + ["start_time"] = 0, + ["modulation"] = 0, + ["frequency"] = 124, + }, -- end of [1] + [2] = + { + ["lateActivation"] = true, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAS", + ["uncontrolled"] = false, + ["route"] = + { + ["routeRelativeTOT"] = true, + ["points"] = + { + [1] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["number"] = 1, + ["key"] = "CAS", + ["id"] = "EngageTargets", + ["enabled"] = true, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Helicopters", + [2] = "Ground Units", + [3] = "Light armed ships", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 323894.45982144, + ["x"] = -71460.574218749, + ["name"] = "DictKey_WptName_333", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [1] + [2] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 829.44018494895, + ["ETA_locked"] = false, + ["y"] = 321608.74553573, + ["x"] = -7603.4313616057, + ["name"] = "DictKey_WptName_334", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [2] + [3] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 581.44512129878, + ["ETA_locked"] = false, + ["y"] = 309465.88839287, + ["x"] = -8174.8599330343, + ["name"] = "DictKey_WptName_335", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [3] + [4] = + { + ["alt"] = 500, + ["action"] = "Turning Point", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 55.555555555556, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "Turning Point", + ["ETA"] = 2541.8313343196, + ["ETA_locked"] = false, + ["y"] = 310894.45982144, + ["x"] = -73317.717075891, + ["name"] = "DictKey_WptName_336", + ["formation_template"] = "", + ["speed_locked"] = true, + }, -- end of [4] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 20, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 500, + ["alt_type"] = "BARO", + ["livery_id"] = "Russia Standard Army", + ["skill"] = "High", + ["ropeLength"] = 15, + ["speed"] = 55.555555555556, + ["type"] = "Ka-50", + ["unitId"] = 25, + ["psi"] = 0.035778908402037, + ["y"] = 323894.45982144, + ["x"] = -71460.574218749, + ["name"] = "DictKey_UnitName_332", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = "1450", + ["flare"] = 128, + ["chaff"] = 0, + ["gun"] = 100, + }, -- end of ["payload"] + ["heading"] = -0.035778908402037, + ["callsign"] = 105, + ["onboard_num"] = "050", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 323894.45982144, + ["x"] = -71460.574218749, + ["name"] = "DictKey_GroupName_331", + ["communication"] = true, + ["start_time"] = 0, + ["modulation"] = 0, + ["frequency"] = 124, + }, -- end of [2] + }, -- end of ["group"] + }, -- end of ["helicopter"] + ["name"] = "Russia", + ["id"] = 0, + ["plane"] = + { + ["group"] = + { + [1] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 293785.125, + ["x"] = -7523.8505859375, + ["name"] = "DictKey_WptName_20", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 4, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = 2, + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 4, + ["psi"] = 0, + ["parking_id"] = "04", + ["x"] = -7523.8505859375, + ["name"] = "DictKey_UnitName_19", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 293785.125, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 293785.125, + ["x"] = -7523.8505859375, + ["name"] = "DictKey_GroupName_18", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [1] + [2] = + { + ["lateActivation"] = true, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["routeRelativeTOT"] = true, + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area Hot", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 250, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParkingHot", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 294155.125, + ["x"] = -7498.103515625, + ["name"] = "DictKey_WptName_26", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 6, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["hardpoint_racks"] = true, + ["alt_type"] = "BARO", + ["livery_id"] = "`snow` test paint scheme", + ["skill"] = "High", + ["parking"] = 91, + ["speed"] = 250, + ["type"] = "Su-30", + ["unitId"] = 6, + ["psi"] = 1.7036072745551, + ["parking_id"] = "29", + ["x"] = -7498.103515625, + ["name"] = "DictKey_UnitName_25", + ["payload"] = + { + ["pylons"] = + { + [1] = + { + ["CLSID"] = "{44EE8698-89F9-48EE-AF36-5FD31896A82F}", + }, -- end of [1] + [2] = + { + ["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}", + }, -- end of [2] + [3] = + { + ["CLSID"] = "{88DAC840-9F75-4531-8689-B46E64E42E53}", + }, -- end of [3] + [4] = + { + ["CLSID"] = "{B79C379A-9E87-4E50-A1EE-7F7E29C2E87A}", + }, -- end of [4] + [5] = + { + ["CLSID"] = "{E8069896-8435-4B90-95C0-01A03AE6E400}", + }, -- end of [5] + [6] = + { + ["CLSID"] = "{E8069896-8435-4B90-95C0-01A03AE6E400}", + }, -- end of [6] + [7] = + { + ["CLSID"] = "{B79C379A-9E87-4E50-A1EE-7F7E29C2E87A}", + }, -- end of [7] + [8] = + { + ["CLSID"] = "{88DAC840-9F75-4531-8689-B46E64E42E53}", + }, -- end of [8] + [9] = + { + ["CLSID"] = "{FBC29BFE-3D24-4C64-B81D-941239D12249}", + }, -- end of [9] + [10] = + { + ["CLSID"] = "{44EE8698-89F9-48EE-AF36-5FD31896A82A}", + }, -- end of [10] + }, -- end of ["pylons"] + ["fuel"] = "9400", + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 294155.125, + ["heading"] = 0, + ["callsign"] = 104, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 294155.125, + ["x"] = -7498.103515625, + ["name"] = "DictKey_GroupName_24", + ["communication"] = true, + ["start_time"] = 0, + ["modulation"] = 0, + ["frequency"] = 251, + }, -- end of [2] + [3] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 294994.1875, + ["x"] = -6702.66796875, + ["name"] = "DictKey_WptName_369", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 21, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "75", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 26, + ["psi"] = 0, + ["parking_id"] = "44", + ["x"] = -6702.66796875, + ["name"] = "DictKey_UnitName_368", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 294994.1875, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 294994.1875, + ["x"] = -6702.66796875, + ["name"] = "DictKey_GroupName_367", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [3] + [4] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 295139.9375, + ["x"] = -6351.4077148438, + ["name"] = "DictKey_WptName_372", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 22, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "107", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 27, + ["psi"] = 0, + ["parking_id"] = "48", + ["x"] = -6351.4077148438, + ["name"] = "DictKey_UnitName_371", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 295139.9375, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 295139.9375, + ["x"] = -6351.4077148438, + ["name"] = "DictKey_GroupName_370", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [4] + [5] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 295287.09375, + ["x"] = -6172.1333007813, + ["name"] = "DictKey_WptName_375", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 23, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "62", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 28, + ["psi"] = 0, + ["parking_id"] = "51", + ["x"] = -6172.1333007813, + ["name"] = "DictKey_UnitName_374", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 295287.09375, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 295287.09375, + ["x"] = -6172.1333007813, + ["name"] = "DictKey_GroupName_373", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [5] + [6] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 295051.375, + ["x"] = -6629.2661132813, + ["name"] = "DictKey_WptName_378", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 24, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "76", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 29, + ["psi"] = 0, + ["parking_id"] = "43", + ["x"] = -6629.2661132813, + ["name"] = "DictKey_UnitName_377", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 295051.375, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 295051.375, + ["x"] = -6629.2661132813, + ["name"] = "DictKey_GroupName_376", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [6] + [7] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 293769.75, + ["x"] = -7511.0883789063, + ["name"] = "DictKey_WptName_381", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 25, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "6", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 30, + ["psi"] = 0, + ["parking_id"] = "03", + ["x"] = -7511.0883789063, + ["name"] = "DictKey_UnitName_380", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 293769.75, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 293769.75, + ["x"] = -7511.0883789063, + ["name"] = "DictKey_GroupName_379", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [7] + [8] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 295124.0625, + ["x"] = -6280.3999023438, + ["name"] = "DictKey_WptName_384", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 26, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "108", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 31, + ["psi"] = 0, + ["parking_id"] = "49", + ["x"] = -6280.3999023438, + ["name"] = "DictKey_UnitName_383", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 295124.0625, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 295124.0625, + ["x"] = -6280.3999023438, + ["name"] = "DictKey_GroupName_382", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [8] + [9] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 293890.4375, + ["x"] = -7713.9541015625, + ["name"] = "DictKey_WptName_387", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 27, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "124", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 32, + ["psi"] = 0, + ["parking_id"] = "09", + ["x"] = -7713.9541015625, + ["name"] = "DictKey_UnitName_386", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 293890.4375, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 293890.4375, + ["x"] = -7713.9541015625, + ["name"] = "DictKey_GroupName_385", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [9] + [10] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 295106.59375, + ["x"] = -6693.9848632813, + ["name"] = "DictKey_WptName_390", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 28, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "77", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 33, + ["psi"] = 0, + ["parking_id"] = "42", + ["x"] = -6693.9848632813, + ["name"] = "DictKey_UnitName_389", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 295106.59375, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 295106.59375, + ["x"] = -6693.9848632813, + ["name"] = "DictKey_GroupName_388", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [10] + [11] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 293815.90625, + ["x"] = -7549.3779296875, + ["name"] = "DictKey_WptName_393", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 29, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "12", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 34, + ["psi"] = 0, + ["parking_id"] = "06", + ["x"] = -7549.3779296875, + ["name"] = "DictKey_UnitName_392", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 293815.90625, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 293815.90625, + ["x"] = -7549.3779296875, + ["name"] = "DictKey_GroupName_391", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [11] + [12] = + { + ["modulation"] = 0, + ["tasks"] = + { + }, -- end of ["tasks"] + ["radioSet"] = false, + ["task"] = "CAP", + ["uncontrolled"] = false, + ["route"] = + { + ["points"] = + { + [1] = + { + ["alt"] = 88, + ["action"] = "From Parking Area", + ["alt_type"] = "BARO", + ["properties"] = + { + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, + }, -- end of ["properties"] + ["speed"] = 138.88888888889, + ["task"] = + { + ["id"] = "ComboTask", + ["params"] = + { + ["tasks"] = + { + [1] = + { + ["enabled"] = true, + ["key"] = "CAP", + ["id"] = "EngageTargets", + ["number"] = 1, + ["auto"] = true, + ["params"] = + { + ["targetTypes"] = + { + [1] = "Air", + }, -- end of ["targetTypes"] + ["priority"] = 0, + }, -- end of ["params"] + }, -- end of [1] + }, -- end of ["tasks"] + }, -- end of ["params"] + }, -- end of ["task"] + ["type"] = "TakeOffParking", + ["ETA"] = 0, + ["ETA_locked"] = true, + ["y"] = 293831.25, + ["x"] = -7562.1723632813, + ["name"] = "DictKey_WptName_396", + ["formation_template"] = "", + ["airdromeId"] = 15, + ["speed_locked"] = true, + }, -- end of [1] + }, -- end of ["points"] + }, -- end of ["route"] + ["groupId"] = 30, + ["hidden"] = false, + ["units"] = + { + [1] = + { + ["alt"] = 88, + ["alt_type"] = "BARO", + ["livery_id"] = "Air Force Standard", + ["skill"] = "Client", + ["parking"] = "14", + ["speed"] = 138.88888888889, + ["type"] = "Su-27", + ["unitId"] = 35, + ["psi"] = 0, + ["parking_id"] = "07", + ["x"] = -7562.1723632813, + ["name"] = "DictKey_UnitName_395", + ["payload"] = + { + ["pylons"] = + { + }, -- end of ["pylons"] + ["fuel"] = 5217, + ["flare"] = 96, + ["chaff"] = 96, + ["gun"] = 100, + }, -- end of ["payload"] + ["y"] = 293831.25, + ["heading"] = 0, + ["callsign"] = 103, + ["onboard_num"] = "013", + }, -- end of [1] + }, -- end of ["units"] + ["y"] = 293831.25, + ["x"] = -7562.1723632813, + ["name"] = "DictKey_GroupName_394", + ["communication"] = true, + ["start_time"] = 0, + ["frequency"] = 127.5, + }, -- end of [12] + }, -- end of ["group"] + }, -- end of ["plane"] + }, -- end of [1] + [2] = + { + ["id"] = 1, + ["name"] = "Ukraine", + }, -- end of [2] + [3] = + { + ["id"] = 18, + ["name"] = "Abkhazia", + }, -- end of [3] + [4] = + { + ["id"] = 19, + ["name"] = "South Ossetia", + }, -- end of [4] + [5] = + { + ["id"] = 37, + ["name"] = "Kazakhstan", + }, -- end of [5] + [6] = + { + ["id"] = 24, + ["name"] = "Belarus", + }, -- end of [6] + [7] = + { + ["id"] = 27, + ["name"] = "China", + }, -- end of [7] + [8] = + { + ["id"] = 43, + ["name"] = "Serbia", + }, -- end of [8] + [9] = + { + ["id"] = 47, + ["name"] = "Syria", + }, -- end of [9] + [10] = + { + ["id"] = 34, + ["name"] = "Iran", + }, -- end of [10] + [11] = + { + ["id"] = 38, + ["name"] = "North Korea", + }, -- end of [11] + }, -- end of ["country"] + }, -- end of ["red"] + }, -- end of ["coalition"] + ["sortie"] = "DictKey_sortie_4", + ["version"] = 12, + ["goals"] = + { + }, -- end of ["goals"] + ["currentKey"] = 12213, + ["start_time"] = 43200, + ["forcedOptions"] = + { + }, -- end of ["forcedOptions"] + ["failures"] = + { + ["OIL_RADIATOR_SENSOR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "OIL_RADIATOR_SENSOR", + ["mm"] = 0, + }, -- end of ["OIL_RADIATOR_SENSOR"] + ["TURNIND_POINTER_FAILS_NO_VACUUM"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_POINTER_FAILS_NO_VACUUM", + ["mm"] = 0, + }, -- end of ["TURNIND_POINTER_FAILS_NO_VACUUM"] + ["helmet"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "helmet", + ["mm"] = 0, + }, -- end of ["helmet"] + ["GUN_LEFT_IN_MOUNT_LOOSE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_IN_MOUNT_LOOSE", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_IN_MOUNT_LOOSE"] + ["es_damage_MainInverter"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_MainInverter", + ["mm"] = 0, + }, -- end of ["es_damage_MainInverter"] + ["rws"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "rws", + ["mm"] = 0, + }, -- end of ["rws"] + ["AN_ALR69V_FAILURE_SENSOR_TAIL_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALR69V_FAILURE_SENSOR_TAIL_RIGHT", + ["mm"] = 0, + }, -- end of ["AN_ALR69V_FAILURE_SENSOR_TAIL_RIGHT"] + ["MainReductor_ShaveInOil"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MainReductor_ShaveInOil", + ["mm"] = 0, + }, -- end of ["MainReductor_ShaveInOil"] + ["asc_y"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "asc_y", + ["mm"] = 0, + }, -- end of ["asc_y"] + ["MAIN_L_GEAR_D_LOCK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MAIN_L_GEAR_D_LOCK", + ["mm"] = 0, + }, -- end of ["MAIN_L_GEAR_D_LOCK"] + ["AAR_47_FAILURE_SENSOR_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AAR_47_FAILURE_SENSOR_LEFT", + ["mm"] = 0, + }, -- end of ["AAR_47_FAILURE_SENSOR_LEFT"] + ["tail_reductor_chip"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "tail_reductor_chip", + ["mm"] = 0, + }, -- end of ["tail_reductor_chip"] + ["TACAN_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACAN_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["TACAN_FAILURE_TOTAL"] + ["OIL_RADIATOR_MOTOR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "OIL_RADIATOR_MOTOR", + ["mm"] = 0, + }, -- end of ["OIL_RADIATOR_MOTOR"] + ["SUPERCHARGER_WIRE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SUPERCHARGER_WIRE", + ["mm"] = 0, + }, -- end of ["SUPERCHARGER_WIRE"] + ["CADC_FAILURE_TEMPERATURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_TEMPERATURE", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_TEMPERATURE"] + ["FUSELAGE_TANK_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FUSELAGE_TANK_LEAK", + ["mm"] = 0, + }, -- end of ["FUSELAGE_TANK_LEAK"] + ["AN_ALE_40V_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALE_40V_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["AN_ALE_40V_FAILURE_TOTAL"] + ["HORIZON_BAR_NOT_SETTLE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "HORIZON_BAR_NOT_SETTLE", + ["mm"] = 0, + }, -- end of ["HORIZON_BAR_NOT_SETTLE"] + ["AN_ALE_40V_FAILURE_CONTAINER_LEFT_WING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALE_40V_FAILURE_CONTAINER_LEFT_WING", + ["mm"] = 0, + }, -- end of ["AN_ALE_40V_FAILURE_CONTAINER_LEFT_WING"] + ["OIL_DILUTION_WIRE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "OIL_DILUTION_WIRE", + ["mm"] = 0, + }, -- end of ["OIL_DILUTION_WIRE"] + ["FLEX_S_BKP_LAMP_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FLEX_S_BKP_LAMP_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["FLEX_S_BKP_LAMP_DEFECTIVE"] + ["TAIL_GEAR_FAIL_GO_DOWN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TAIL_GEAR_FAIL_GO_DOWN", + ["mm"] = 0, + }, -- end of ["TAIL_GEAR_FAIL_GO_DOWN"] + ["GUN_FAIL_RIGHT_CENTER_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_FAIL_RIGHT_CENTER_GUN", + ["mm"] = 0, + }, -- end of ["GUN_FAIL_RIGHT_CENTER_GUN"] + ["LeftEngine_ShaveInOil"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "LeftEngine_ShaveInOil", + ["mm"] = 0, + }, -- end of ["LeftEngine_ShaveInOil"] + ["MAIN_R_GEAR_D_LOCK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MAIN_R_GEAR_D_LOCK", + ["mm"] = 0, + }, -- end of ["MAIN_R_GEAR_D_LOCK"] + ["R_GEAR_DLK_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "R_GEAR_DLK_FAULT", + ["mm"] = 0, + }, -- end of ["R_GEAR_DLK_FAULT"] + ["GMC_GYRO_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GMC_GYRO_FAILURE", + ["mm"] = 0, + }, -- end of ["GMC_GYRO_FAILURE"] + ["L_GEAR_DLK_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "L_GEAR_DLK_FAULT", + ["mm"] = 0, + }, -- end of ["L_GEAR_DLK_FAULT"] + ["K14_FIXED_LAMP_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "K14_FIXED_LAMP_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["K14_FIXED_LAMP_DEFECTIVE"] + ["GUN_FAIL_LEFT_CENTER_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_FAIL_LEFT_CENTER_GUN", + ["mm"] = 0, + }, -- end of ["GUN_FAIL_LEFT_CENTER_GUN"] + ["engine_droop_failure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "engine_droop_failure", + ["mm"] = 0, + }, -- end of ["engine_droop_failure"] + ["IGNITION_TERM_CONNECT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "IGNITION_TERM_CONNECT", + ["mm"] = 0, + }, -- end of ["IGNITION_TERM_CONNECT"] + ["CADC_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_TOTAL"] + ["COOLANT_POOR_CONNTECT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_POOR_CONNTECT", + ["mm"] = 0, + }, -- end of ["COOLANT_POOR_CONNTECT"] + ["TURNIND_POINTER_FAILS_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_POINTER_FAILS_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["TURNIND_POINTER_FAILS_DEFECTIVE"] + ["GUN_FAIL_RIGHT_OUT_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_FAIL_RIGHT_OUT_GUN", + ["mm"] = 0, + }, -- end of ["GUN_FAIL_RIGHT_OUT_GUN"] + ["BOMBS_DAMAGE_LINKAGE_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_DAMAGE_LINKAGE_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_DAMAGE_LINKAGE_LEFT"] + ["FUSELAGE_TANK_PUMP_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FUSELAGE_TANK_PUMP_FAULT", + ["mm"] = 0, + }, -- end of ["FUSELAGE_TANK_PUMP_FAULT"] + ["hydro_main"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hydro_main", + ["mm"] = 0, + }, -- end of ["hydro_main"] + ["CICU_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CICU_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["CICU_FAILURE_TOTAL"] + ["GUN_LEFT_OUT_MOUNT_LOOSE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_OUT_MOUNT_LOOSE", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_OUT_MOUNT_LOOSE"] + ["TAIL_GEAR_U_LOCK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TAIL_GEAR_U_LOCK", + ["mm"] = 0, + }, -- end of ["TAIL_GEAR_U_LOCK"] + ["RADAR_ALT_TOTAL_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RADAR_ALT_TOTAL_FAILURE", + ["mm"] = 0, + }, -- end of ["RADAR_ALT_TOTAL_FAILURE"] + ["GUN_RIGHT_CENTER_MOUNT_LOOSE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_CENTER_MOUNT_LOOSE", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_CENTER_MOUNT_LOOSE"] + ["TAIL_GEAR_FAIL_GO_UP"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TAIL_GEAR_FAIL_GO_UP", + ["mm"] = 0, + }, -- end of ["TAIL_GEAR_FAIL_GO_UP"] + ["asc_r"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "asc_r", + ["mm"] = 0, + }, -- end of ["asc_r"] + ["BOMBS_SOLENOID_FAULT_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_SOLENOID_FAULT_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_SOLENOID_FAULT_LEFT"] + ["sas_yaw_left"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "sas_yaw_left", + ["mm"] = 0, + }, -- end of ["sas_yaw_left"] + ["BOMBS_ARMING_NO_VOLATAGE_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_NO_VOLATAGE_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_NO_VOLATAGE_LEFT"] + ["PITOT_HEAT_ELEMENT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PITOT_HEAT_ELEMENT", + ["mm"] = 0, + }, -- end of ["PITOT_HEAT_ELEMENT"] + ["ILS_FAILURE_ANT_LOCALIZER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ILS_FAILURE_ANT_LOCALIZER", + ["mm"] = 0, + }, -- end of ["ILS_FAILURE_ANT_LOCALIZER"] + ["AN_ALE_40V_FAILURE_CONTAINER_LEFT_GEAR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALE_40V_FAILURE_CONTAINER_LEFT_GEAR", + ["mm"] = 0, + }, -- end of ["AN_ALE_40V_FAILURE_CONTAINER_LEFT_GEAR"] + ["CARBAIR_SHORT_CIRCUIT_BLB"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CARBAIR_SHORT_CIRCUIT_BLB", + ["mm"] = 0, + }, -- end of ["CARBAIR_SHORT_CIRCUIT_BLB"] + ["LEFT_TANK_PUMP_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "LEFT_TANK_PUMP_FAULT", + ["mm"] = 0, + }, -- end of ["LEFT_TANK_PUMP_FAULT"] + ["Surge_RightEngine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "Surge_RightEngine", + ["mm"] = 0, + }, -- end of ["Surge_RightEngine"] + ["RightEngine_Fire"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["mm"] = 0, + }, -- end of ["RightEngine_Fire"] + ["GUN_FAIL_LEFT_IN_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_FAIL_LEFT_IN_GUN", + ["mm"] = 0, + }, -- end of ["GUN_FAIL_LEFT_IN_GUN"] + ["CADC_FAILURE_TAS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_TAS", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_TAS"] + ["STARTER_SOL_SHORT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "STARTER_SOL_SHORT", + ["mm"] = 0, + }, -- end of ["STARTER_SOL_SHORT"] + ["asc_p"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "asc_p", + ["mm"] = 0, + }, -- end of ["asc_p"] + ["COOLANT_SHORT_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_SHORT_CIRCUIT", + ["mm"] = 0, + }, -- end of ["COOLANT_SHORT_CIRCUIT"] + ["GUN_LEFT_IN_AMMUN_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_IN_AMMUN_FAULT", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_IN_AMMUN_FAULT"] + ["PUMP_RELIEF_VALVE_SCREEN_CLOGGED"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PUMP_RELIEF_VALVE_SCREEN_CLOGGED", + ["mm"] = 0, + }, -- end of ["PUMP_RELIEF_VALVE_SCREEN_CLOGGED"] + ["abris_hardware"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "abris_hardware", + ["mm"] = 0, + }, -- end of ["abris_hardware"] + ["EEC_Failure_LeftEngine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "EEC_Failure_LeftEngine", + ["mm"] = 0, + }, -- end of ["EEC_Failure_LeftEngine"] + ["COMPASS_POINTER_PULLS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COMPASS_POINTER_PULLS", + ["mm"] = 0, + }, -- end of ["COMPASS_POINTER_PULLS"] + ["GUN_RIGHT_OUT_OPEN_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_OUT_OPEN_CIRCUIT", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_OUT_OPEN_CIRCUIT"] + ["VHF_SHORTED_CTL_BOX"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_SHORTED_CTL_BOX", + ["mm"] = 0, + }, -- end of ["VHF_SHORTED_CTL_BOX"] + ["CLOCK_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CLOCK_FAILURE", + ["mm"] = 0, + }, -- end of ["CLOCK_FAILURE"] + ["TURNIND_INCORRECT_SENS_VAC_HIGH"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_INCORRECT_SENS_VAC_HIGH", + ["mm"] = 0, + }, -- end of ["TURNIND_INCORRECT_SENS_VAC_HIGH"] + ["OIL_RADIATOR_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "OIL_RADIATOR_WIRING", + ["mm"] = 0, + }, -- end of ["OIL_RADIATOR_WIRING"] + ["IGNITION_NO_OUTPUT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "IGNITION_NO_OUTPUT", + ["mm"] = 0, + }, -- end of ["IGNITION_NO_OUTPUT"] + ["AAR_47_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AAR_47_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["AAR_47_FAILURE_TOTAL"] + ["PILOT_KILLED_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PILOT_KILLED_FAILURE", + ["mm"] = 0, + }, -- end of ["PILOT_KILLED_FAILURE"] + ["GUN_LEFT_CENTER_MOUNT_LOOSE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_CENTER_MOUNT_LOOSE", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_CENTER_MOUNT_LOOSE"] + ["GUN_LEFT_OUT_AMMUN_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_OUT_AMMUN_FAULT", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_OUT_AMMUN_FAULT"] + ["COMPASS_ERRATIC_OPERATION"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COMPASS_ERRATIC_OPERATION", + ["mm"] = 0, + }, -- end of ["COMPASS_ERRATIC_OPERATION"] + ["asc_a"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "asc_a", + ["mm"] = 0, + }, -- end of ["asc_a"] + ["AIRSPEED_INDICATOR_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AIRSPEED_INDICATOR_FAILURE", + ["mm"] = 0, + }, -- end of ["AIRSPEED_INDICATOR_FAILURE"] + ["GUN_LEFT_CENTER_BARREL_WORN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_CENTER_BARREL_WORN", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_CENTER_BARREL_WORN"] + ["abris_software"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "abris_software", + ["mm"] = 0, + }, -- end of ["abris_software"] + ["GUN_FAIL_LEFT_OUT_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_FAIL_LEFT_OUT_GUN", + ["mm"] = 0, + }, -- end of ["GUN_FAIL_LEFT_OUT_GUN"] + ["SAR_1_101"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SAR_1_101", + ["mm"] = 0, + }, -- end of ["SAR_1_101"] + ["ROCKETS_INTERVALOMETER_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ROCKETS_INTERVALOMETER_WIRING", + ["mm"] = 0, + }, -- end of ["ROCKETS_INTERVALOMETER_WIRING"] + ["MainReductor_LowOilPressure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MainReductor_LowOilPressure", + ["mm"] = 0, + }, -- end of ["MainReductor_LowOilPressure"] + ["GUN_RIGHT_IN_AMMUN_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_IN_AMMUN_FAULT", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_IN_AMMUN_FAULT"] + ["D2_LEFT_CYLINDER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "D2_LEFT_CYLINDER", + ["mm"] = 0, + }, -- end of ["D2_LEFT_CYLINDER"] + ["Surge_LeftEngine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "Surge_LeftEngine", + ["mm"] = 0, + }, -- end of ["Surge_LeftEngine"] + ["BOMBS_RUST_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_RUST_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_RUST_LEFT"] + ["GUN_RIGHT_CENTER_BARREL_WORN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_CENTER_BARREL_WORN", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_CENTER_BARREL_WORN"] + ["asc"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "asc", + ["mm"] = 0, + }, -- end of ["asc"] + ["COMPASS_NO_TORQUE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COMPASS_NO_TORQUE", + ["mm"] = 0, + }, -- end of ["COMPASS_NO_TORQUE"] + ["COOLANT_BREAK_BULB"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_BREAK_BULB", + ["mm"] = 0, + }, -- end of ["COOLANT_BREAK_BULB"] + ["PROP_GOVERNOR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PROP_GOVERNOR", + ["mm"] = 0, + }, -- end of ["PROP_GOVERNOR"] + ["MANIFOLD_SHIFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MANIFOLD_SHIFT", + ["mm"] = 0, + }, -- end of ["MANIFOLD_SHIFT"] + ["RIGHT_GUNNER_KILLED_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RIGHT_GUNNER_KILLED_FAILURE", + ["mm"] = 0, + }, -- end of ["RIGHT_GUNNER_KILLED_FAILURE"] + ["UNLOAD_VALVE_NOT_UNLOAD"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "UNLOAD_VALVE_NOT_UNLOAD", + ["mm"] = 0, + }, -- end of ["UNLOAD_VALVE_NOT_UNLOAD"] + ["STARTER_BURNOUT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "STARTER_BURNOUT", + ["mm"] = 0, + }, -- end of ["STARTER_BURNOUT"] + ["UNLOAD_VALVE_NOT_LOAD"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "UNLOAD_VALVE_NOT_LOAD", + ["mm"] = 0, + }, -- end of ["UNLOAD_VALVE_NOT_LOAD"] + ["TURNIND_INCORRECT_SENS_VAC_LOW"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_INCORRECT_SENS_VAC_LOW", + ["mm"] = 0, + }, -- end of ["TURNIND_INCORRECT_SENS_VAC_LOW"] + ["Failure_LeftEngine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "Failure_LeftEngine", + ["mm"] = 0, + }, -- end of ["Failure_LeftEngine"] + ["GUN_RIGHT_IN_BARREL_WORN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_IN_BARREL_WORN", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_IN_BARREL_WORN"] + ["K14_MOV_LAMP_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "K14_MOV_LAMP_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["K14_MOV_LAMP_DEFECTIVE"] + ["ILS_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ILS_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["ILS_FAILURE_TOTAL"] + ["GUN_RIGHT_OUT_BARREL_WORN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_OUT_BARREL_WORN", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_OUT_BARREL_WORN"] + ["fuel_sys_transfer_pumps"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "fuel_sys_transfer_pumps", + ["mm"] = 0, + }, -- end of ["fuel_sys_transfer_pumps"] + ["PITOT_HEAT_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PITOT_HEAT_WIRING", + ["mm"] = 0, + }, -- end of ["PITOT_HEAT_WIRING"] + ["TURNIND_POINTER_NOT_SET_ZERO"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_POINTER_NOT_SET_ZERO", + ["mm"] = 0, + }, -- end of ["TURNIND_POINTER_NOT_SET_ZERO"] + ["MD1_GYRO_TOTAL_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MD1_GYRO_TOTAL_FAILURE", + ["mm"] = 0, + }, -- end of ["MD1_GYRO_TOTAL_FAILURE"] + ["VHF_FM_RADIO_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_FM_RADIO_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["VHF_FM_RADIO_FAILURE_TOTAL"] + ["RIGHT_MFCD_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RIGHT_MFCD_FAILURE", + ["mm"] = 0, + }, -- end of ["RIGHT_MFCD_FAILURE"] + ["F2_BOTTOM_CYLINDER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "F2_BOTTOM_CYLINDER", + ["mm"] = 0, + }, -- end of ["F2_BOTTOM_CYLINDER"] + ["LEFT_WING_TANK_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "LEFT_WING_TANK_LEAK", + ["mm"] = 0, + }, -- end of ["LEFT_WING_TANK_LEAK"] + ["CARBAIR_BREAK_LEADS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CARBAIR_BREAK_LEADS", + ["mm"] = 0, + }, -- end of ["CARBAIR_BREAK_LEADS"] + ["GUN_LEFT_IN_OPEN_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_IN_OPEN_CIRCUIT", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_IN_OPEN_CIRCUIT"] + ["EGI_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "EGI_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["EGI_FAILURE_TOTAL"] + ["UHF_RADIO_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "UHF_RADIO_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["UHF_RADIO_FAILURE_TOTAL"] + ["GUN_RIGHT_CENTER_AMMUN_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_CENTER_AMMUN_FAULT", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_CENTER_AMMUN_FAULT"] + ["LEFT_GUNNER_KILLED_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "LEFT_GUNNER_KILLED_FAILURE", + ["mm"] = 0, + }, -- end of ["LEFT_GUNNER_KILLED_FAILURE"] + ["VHF_VT207_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_VT207_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["VHF_VT207_DEFECTIVE"] + ["RightEngine_LowOilPressure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RightEngine_LowOilPressure", + ["mm"] = 0, + }, -- end of ["RightEngine_LowOilPressure"] + ["radar"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "radar", + ["mm"] = 0, + }, -- end of ["radar"] + ["RIGHT_TANK_PUMP_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RIGHT_TANK_PUMP_FAULT", + ["mm"] = 0, + }, -- end of ["RIGHT_TANK_PUMP_FAULT"] + ["COOLANT_UNPRES"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_UNPRES", + ["mm"] = 0, + }, -- end of ["COOLANT_UNPRES"] + ["ARN_82_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ARN_82_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["ARN_82_FAILURE_TOTAL"] + ["FLEX_S_NO_POWER_SUPPLY"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FLEX_S_NO_POWER_SUPPLY", + ["mm"] = 0, + }, -- end of ["FLEX_S_NO_POWER_SUPPLY"] + ["eos"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "eos", + ["mm"] = 0, + }, -- end of ["eos"] + ["HYDRO_LOW_AIR_PRESSURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "HYDRO_LOW_AIR_PRESSURE", + ["mm"] = 0, + }, -- end of ["HYDRO_LOW_AIR_PRESSURE"] + ["K14_MOTOR_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "K14_MOTOR_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["K14_MOTOR_DEFECTIVE"] + ["GENERATOR_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GENERATOR_FAULT", + ["mm"] = 0, + }, -- end of ["GENERATOR_FAULT"] + ["FUEL_PUMP_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FUEL_PUMP_FAILURE", + ["mm"] = 0, + }, -- end of ["FUEL_PUMP_FAILURE"] + ["RADAR_ALTIMETR_LEFT_ANT_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RADAR_ALTIMETR_LEFT_ANT_FAILURE", + ["mm"] = 0, + }, -- end of ["RADAR_ALTIMETR_LEFT_ANT_FAILURE"] + ["hydro"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hydro", + ["mm"] = 0, + }, -- end of ["hydro"] + ["BAT_SOLENOID_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BAT_SOLENOID_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["BAT_SOLENOID_DEFECTIVE"] + ["LeftEngine_Fire"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["mm"] = 0, + }, -- end of ["LeftEngine_Fire"] + ["SUPERCHARGER_LIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SUPERCHARGER_LIGHT", + ["mm"] = 0, + }, -- end of ["SUPERCHARGER_LIGHT"] + ["L_GEAR_UPL_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "L_GEAR_UPL_FAULT", + ["mm"] = 0, + }, -- end of ["L_GEAR_UPL_FAULT"] + ["fs_damage_right_cell_boost_pump"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "fs_damage_right_cell_boost_pump", + ["mm"] = 0, + }, -- end of ["fs_damage_right_cell_boost_pump"] + ["TACH_RESISTANCE_ADJ"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACH_RESISTANCE_ADJ", + ["mm"] = 0, + }, -- end of ["TACH_RESISTANCE_ADJ"] + ["MAGNETO_1"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MAGNETO_1", + ["mm"] = 0, + }, -- end of ["MAGNETO_1"] + ["BOMBS_NO_VOLATAGE_AT_RACK_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_NO_VOLATAGE_AT_RACK_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_NO_VOLATAGE_AT_RACK_RIGHT"] + ["GUN_RIGHT_OUT_MOUNT_LOOSE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_OUT_MOUNT_LOOSE", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_OUT_MOUNT_LOOSE"] + ["TailReductor_ShaveInOil"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TailReductor_ShaveInOil", + ["mm"] = 0, + }, -- end of ["TailReductor_ShaveInOil"] + ["R_GEAR_UPL_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "R_GEAR_UPL_FAULT", + ["mm"] = 0, + }, -- end of ["R_GEAR_UPL_FAULT"] + ["BOMBS_TRAIN_DEFECTIVE_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_TRAIN_DEFECTIVE_WIRING", + ["mm"] = 0, + }, -- end of ["BOMBS_TRAIN_DEFECTIVE_WIRING"] + ["autopilot"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "autopilot", + ["mm"] = 0, + }, -- end of ["autopilot"] + ["BOMBS_TRAIN_DEFECTIVE_SWITCH"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_TRAIN_DEFECTIVE_SWITCH", + ["mm"] = 0, + }, -- end of ["BOMBS_TRAIN_DEFECTIVE_SWITCH"] + ["CARBAIR_SHORT_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CARBAIR_SHORT_CIRCUIT", + ["mm"] = 0, + }, -- end of ["CARBAIR_SHORT_CIRCUIT"] + ["STARTER_RELAY"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "STARTER_RELAY", + ["mm"] = 0, + }, -- end of ["STARTER_RELAY"] + ["AN_ALE_40V_FAILURE_CONTAINER_RIGHT_WING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALE_40V_FAILURE_CONTAINER_RIGHT_WING", + ["mm"] = 0, + }, -- end of ["AN_ALE_40V_FAILURE_CONTAINER_RIGHT_WING"] + ["TACH_POOR_CONNECTION"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACH_POOR_CONNECTION", + ["mm"] = 0, + }, -- end of ["TACH_POOR_CONNECTION"] + ["GUN_RIGHT_IN_MOUNT_LOOSE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_IN_MOUNT_LOOSE", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_IN_MOUNT_LOOSE"] + ["LEFT_MFCD_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "LEFT_MFCD_FAILURE", + ["mm"] = 0, + }, -- end of ["LEFT_MFCD_FAILURE"] + ["sas_yaw_right"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "sas_yaw_right", + ["mm"] = 0, + }, -- end of ["sas_yaw_right"] + ["DOORS_TVC_BROKEN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "DOORS_TVC_BROKEN", + ["mm"] = 0, + }, -- end of ["DOORS_TVC_BROKEN"] + ["SADL_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SADL_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["SADL_FAILURE_TOTAL"] + ["fs_damage_left_cell_boost_pump"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "fs_damage_left_cell_boost_pump", + ["mm"] = 0, + }, -- end of ["fs_damage_left_cell_boost_pump"] + ["BOOST_REG"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOOST_REG", + ["mm"] = 0, + }, -- end of ["BOOST_REG"] + ["r_conv"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "r_conv", + ["mm"] = 0, + }, -- end of ["r_conv"] + ["ENGINE_JAM"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ENGINE_JAM", + ["mm"] = 0, + }, -- end of ["ENGINE_JAM"] + ["MAGNETO_2"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MAGNETO_2", + ["mm"] = 0, + }, -- end of ["MAGNETO_2"] + ["SAR_1_95"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SAR_1_95", + ["mm"] = 0, + }, -- end of ["SAR_1_95"] + ["BOMBS_SOLENOID_FAULT_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_SOLENOID_FAULT_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_SOLENOID_FAULT_RIGHT"] + ["CDU_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CDU_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["CDU_FAILURE_TOTAL"] + ["AN_ALR69V_FAILURE_SENSOR_NOSE_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALR69V_FAILURE_SENSOR_NOSE_RIGHT", + ["mm"] = 0, + }, -- end of ["AN_ALR69V_FAILURE_SENSOR_NOSE_RIGHT"] + ["TAIL_GEAR_C_CABLE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TAIL_GEAR_C_CABLE", + ["mm"] = 0, + }, -- end of ["TAIL_GEAR_C_CABLE"] + ["STARTER_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "STARTER_WIRING", + ["mm"] = 0, + }, -- end of ["STARTER_WIRING"] + ["engine_driveshaft_failure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "engine_driveshaft_failure", + ["mm"] = 0, + }, -- end of ["engine_driveshaft_failure"] + ["PUMP_RELIEF_VALVE_LEAKS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PUMP_RELIEF_VALVE_LEAKS", + ["mm"] = 0, + }, -- end of ["PUMP_RELIEF_VALVE_LEAKS"] + ["HUD_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "HUD_FAILURE", + ["mm"] = 0, + }, -- end of ["HUD_FAILURE"] + ["mfd"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "mfd", + ["mm"] = 0, + }, -- end of ["mfd"] + ["CARBAIR_GND_LEAD"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CARBAIR_GND_LEAD", + ["mm"] = 0, + }, -- end of ["CARBAIR_GND_LEAD"] + ["GMC_MAGN_COMP_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GMC_MAGN_COMP_FAILURE", + ["mm"] = 0, + }, -- end of ["GMC_MAGN_COMP_FAILURE"] + ["es_damage_GeneratorLeft"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_GeneratorLeft", + ["mm"] = 0, + }, -- end of ["es_damage_GeneratorLeft"] + ["ILS_FAILURE_ANT_GLIDESLOPE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ILS_FAILURE_ANT_GLIDESLOPE", + ["mm"] = 0, + }, -- end of ["ILS_FAILURE_ANT_GLIDESLOPE"] + ["engine_chip"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "engine_chip", + ["mm"] = 0, + }, -- end of ["engine_chip"] + ["ARN_83_TOTAL_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ARN_83_TOTAL_FAILURE", + ["mm"] = 0, + }, -- end of ["ARN_83_TOTAL_FAILURE"] + ["CADC_FAILURE_MACH"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_MACH", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_MACH"] + ["ROCKETS_DEFECTIVE_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ROCKETS_DEFECTIVE_WIRING", + ["mm"] = 0, + }, -- end of ["ROCKETS_DEFECTIVE_WIRING"] + ["COPILOT_GYRO_TOTAL_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COPILOT_GYRO_TOTAL_FAILURE", + ["mm"] = 0, + }, -- end of ["COPILOT_GYRO_TOTAL_FAILURE"] + ["RightEngine_ShaveInOil"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RightEngine_ShaveInOil", + ["mm"] = 0, + }, -- end of ["RightEngine_ShaveInOil"] + ["EEC_Failure_RightEngine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "EEC_Failure_RightEngine", + ["mm"] = 0, + }, -- end of ["EEC_Failure_RightEngine"] + ["laser_failure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "laser_failure", + ["mm"] = 0, + }, -- end of ["laser_failure"] + ["ARN_83_ADF_DAMAGE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ARN_83_ADF_DAMAGE", + ["mm"] = 0, + }, -- end of ["ARN_83_ADF_DAMAGE"] + ["BOMBS_NO_VOLATAGE_BOTH"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_NO_VOLATAGE_BOTH", + ["mm"] = 0, + }, -- end of ["BOMBS_NO_VOLATAGE_BOTH"] + ["es_damage_SpareInverter"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_SpareInverter", + ["mm"] = 0, + }, -- end of ["es_damage_SpareInverter"] + ["AAR_47_FAILURE_SENSOR_BOTTOM"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AAR_47_FAILURE_SENSOR_BOTTOM", + ["mm"] = 0, + }, -- end of ["AAR_47_FAILURE_SENSOR_BOTTOM"] + ["CARBAIR_SHORT_CIRCUIT_LEADS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CARBAIR_SHORT_CIRCUIT_LEADS", + ["mm"] = 0, + }, -- end of ["CARBAIR_SHORT_CIRCUIT_LEADS"] + ["sas_pitch_left"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "sas_pitch_left", + ["mm"] = 0, + }, -- end of ["sas_pitch_left"] + ["BATTERY_OVERHEAT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BATTERY_OVERHEAT", + ["mm"] = 0, + }, -- end of ["BATTERY_OVERHEAT"] + ["NOSE_AIRSPEED_INDICATOR_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "NOSE_AIRSPEED_INDICATOR_FAILURE", + ["mm"] = 0, + }, -- end of ["NOSE_AIRSPEED_INDICATOR_FAILURE"] + ["CADC_FAILURE_DYNAMIC"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_DYNAMIC", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_DYNAMIC"] + ["INSUF_FUEL_PRES"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "INSUF_FUEL_PRES", + ["mm"] = 0, + }, -- end of ["INSUF_FUEL_PRES"] + ["GUN_LEFT_CENTER_OPEN_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_CENTER_OPEN_CIRCUIT", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_CENTER_OPEN_CIRCUIT"] + ["AN_ALR69V_FAILURE_SENSOR_TAIL_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALR69V_FAILURE_SENSOR_TAIL_LEFT", + ["mm"] = 0, + }, -- end of ["AN_ALR69V_FAILURE_SENSOR_TAIL_LEFT"] + ["CADC_FAILURE_IAS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_IAS", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_IAS"] + ["GUN_LEFT_CENTER_AMMUN_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_CENTER_AMMUN_FAULT", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_CENTER_AMMUN_FAULT"] + ["GMC_TOTAL_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GMC_TOTAL_FAILURE", + ["mm"] = 0, + }, -- end of ["GMC_TOTAL_FAILURE"] + ["DEFECTIVE_MECHANISM"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "DEFECTIVE_MECHANISM", + ["mm"] = 0, + }, -- end of ["DEFECTIVE_MECHANISM"] + ["INT_HYDRO_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "INT_HYDRO_LEAK", + ["mm"] = 0, + }, -- end of ["INT_HYDRO_LEAK"] + ["TACH_BREAK_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACH_BREAK_CIRCUIT", + ["mm"] = 0, + }, -- end of ["TACH_BREAK_CIRCUIT"] + ["hydro_main_irreversible_valve"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hydro_main_irreversible_valve", + ["mm"] = 0, + }, -- end of ["hydro_main_irreversible_valve"] + ["COOLANT_DEFECTIVE_IND"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_DEFECTIVE_IND", + ["mm"] = 0, + }, -- end of ["COOLANT_DEFECTIVE_IND"] + ["hud"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hud", + ["mm"] = 0, + }, -- end of ["hud"] + ["STARTER_SOLENOID"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "STARTER_SOLENOID", + ["mm"] = 0, + }, -- end of ["STARTER_SOLENOID"] + ["hydro_left"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hydro_left", + ["mm"] = 0, + }, -- end of ["hydro_left"] + ["SAR_1_2_95"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SAR_1_2_95", + ["mm"] = 0, + }, -- end of ["SAR_1_2_95"] + ["fuel_sys_left_transfer_pump"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "fuel_sys_left_transfer_pump", + ["mm"] = 0, + }, -- end of ["fuel_sys_left_transfer_pump"] + ["LeftEngine_LowOilPressure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "LeftEngine_LowOilPressure", + ["mm"] = 0, + }, -- end of ["LeftEngine_LowOilPressure"] + ["BOMBS_ARMING_BROKEN_SOLENOID_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_BROKEN_SOLENOID_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_BROKEN_SOLENOID_LEFT"] + ["FAULTY_ROCKET_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FAULTY_ROCKET_LEFT", + ["mm"] = 0, + }, -- end of ["FAULTY_ROCKET_LEFT"] + ["l_conv"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "l_conv", + ["mm"] = 0, + }, -- end of ["l_conv"] + ["hydro_right"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hydro_right", + ["mm"] = 0, + }, -- end of ["hydro_right"] + ["es_damage_StarterGenerator"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_StarterGenerator", + ["mm"] = 0, + }, -- end of ["es_damage_StarterGenerator"] + ["es_damage_Battery"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_Battery", + ["mm"] = 0, + }, -- end of ["es_damage_Battery"] + ["ILS_FAILURE_ANT_MARKER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ILS_FAILURE_ANT_MARKER", + ["mm"] = 0, + }, -- end of ["ILS_FAILURE_ANT_MARKER"] + ["TGP_FAILURE_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TGP_FAILURE_LEFT", + ["mm"] = 0, + }, -- end of ["TGP_FAILURE_LEFT"] + ["VHF_CRYSTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_CRYSTAL", + ["mm"] = 0, + }, -- end of ["VHF_CRYSTAL"] + ["VHF_VT_BURNED_OUT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_VT_BURNED_OUT", + ["mm"] = 0, + }, -- end of ["VHF_VT_BURNED_OUT"] + ["sas_pitch_right"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "sas_pitch_right", + ["mm"] = 0, + }, -- end of ["sas_pitch_right"] + ["BOMBS_NO_VOLATAGE_AT_RACK_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_NO_VOLATAGE_AT_RACK_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_NO_VOLATAGE_AT_RACK_LEFT"] + ["TGP_FAILURE_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TGP_FAILURE_RIGHT", + ["mm"] = 0, + }, -- end of ["TGP_FAILURE_RIGHT"] + ["TACAN_FAILURE_RECEIVER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACAN_FAILURE_RECEIVER", + ["mm"] = 0, + }, -- end of ["TACAN_FAILURE_RECEIVER"] + ["VHF_AM_RADIO_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_AM_RADIO_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["VHF_AM_RADIO_FAILURE_TOTAL"] + ["main_reductor_chip"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "main_reductor_chip", + ["mm"] = 0, + }, -- end of ["main_reductor_chip"] + ["VHF_SQUELCH_RELAY"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "VHF_SQUELCH_RELAY", + ["mm"] = 0, + }, -- end of ["VHF_SQUELCH_RELAY"] + ["COOLANT_RADIATOR_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_RADIATOR_WIRING", + ["mm"] = 0, + }, -- end of ["COOLANT_RADIATOR_WIRING"] + ["RADAR_ALTIMETR_RIGHT_ANT_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RADAR_ALTIMETR_RIGHT_ANT_FAILURE", + ["mm"] = 0, + }, -- end of ["RADAR_ALTIMETR_RIGHT_ANT_FAILURE"] + ["F2_TOP_CYLINDER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "F2_TOP_CYLINDER", + ["mm"] = 0, + }, -- end of ["F2_TOP_CYLINDER"] + ["FLEX_S_MAIN_LAMP_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FLEX_S_MAIN_LAMP_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["FLEX_S_MAIN_LAMP_DEFECTIVE"] + ["MANIFOLD_LINE_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "MANIFOLD_LINE_LEAK", + ["mm"] = 0, + }, -- end of ["MANIFOLD_LINE_LEAK"] + ["engine_surge_failure"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "engine_surge_failure", + ["mm"] = 0, + }, -- end of ["engine_surge_failure"] + ["CADC_FAILURE_PRESSURE_ALT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_PRESSURE_ALT", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_PRESSURE_ALT"] + ["K14_NO_POWER_SUPPLY"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "K14_NO_POWER_SUPPLY", + ["mm"] = 0, + }, -- end of ["K14_NO_POWER_SUPPLY"] + ["PUMP_FAILS"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PUMP_FAILS", + ["mm"] = 0, + }, -- end of ["PUMP_FAILS"] + ["RIGHT_WING_TANK_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "RIGHT_WING_TANK_LEAK", + ["mm"] = 0, + }, -- end of ["RIGHT_WING_TANK_LEAK"] + ["BOMBS_DAMAGE_LINKAGE_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_DAMAGE_LINKAGE_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_DAMAGE_LINKAGE_RIGHT"] + ["fs_damage_engine_pump"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "fs_damage_engine_pump", + ["mm"] = 0, + }, -- end of ["fs_damage_engine_pump"] + ["ROOF_AIRSPEED_INDICATOR_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ROOF_AIRSPEED_INDICATOR_FAILURE", + ["mm"] = 0, + }, -- end of ["ROOF_AIRSPEED_INDICATOR_FAILURE"] + ["CADC_FAILURE_STATIC"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_STATIC", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_STATIC"] + ["CADC_FAILURE_BARO_ALT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CADC_FAILURE_BARO_ALT", + ["mm"] = 0, + }, -- end of ["CADC_FAILURE_BARO_ALT"] + ["GUN_RIGHT_CENTER_OPEN_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_CENTER_OPEN_CIRCUIT", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_CENTER_OPEN_CIRCUIT"] + ["IFFCC_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "IFFCC_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["IFFCC_FAILURE_TOTAL"] + ["GUN_FAIL_RIGHT_IN_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_FAIL_RIGHT_IN_GUN", + ["mm"] = 0, + }, -- end of ["GUN_FAIL_RIGHT_IN_GUN"] + ["BOMBS_ARMING_BROKEN_WIRING_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_BROKEN_WIRING_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_BROKEN_WIRING_LEFT"] + ["Failure_RightEngine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "Failure_RightEngine", + ["mm"] = 0, + }, -- end of ["Failure_RightEngine"] + ["ecf"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["mm"] = 0, + }, -- end of ["ecf"] + ["GUN_LEFT_OUT_BARREL_WORN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_OUT_BARREL_WORN", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_OUT_BARREL_WORN"] + ["EXT_HYDRO_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "EXT_HYDRO_LEAK", + ["mm"] = 0, + }, -- end of ["EXT_HYDRO_LEAK"] + ["BOMBS_ARMING_BROKEN_SOLENOID_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_BROKEN_SOLENOID_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_BROKEN_SOLENOID_RIGHT"] + ["DEFECTIVE_INSTRUMENT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "DEFECTIVE_INSTRUMENT", + ["mm"] = 0, + }, -- end of ["DEFECTIVE_INSTRUMENT"] + ["AN_ALR69V_FAILURE_SENSOR_NOSE_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALR69V_FAILURE_SENSOR_NOSE_LEFT", + ["mm"] = 0, + }, -- end of ["AN_ALR69V_FAILURE_SENSOR_NOSE_LEFT"] + ["mlws"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "mlws", + ["mm"] = 0, + }, -- end of ["mlws"] + ["BOMBS_ARMING_NO_VOLATAGE_BOTH"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_NO_VOLATAGE_BOTH", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_NO_VOLATAGE_BOTH"] + ["BAT_SOLENOID_WIRING"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BAT_SOLENOID_WIRING", + ["mm"] = 0, + }, -- end of ["BAT_SOLENOID_WIRING"] + ["STARTER_LOSE_CON"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "STARTER_LOSE_CON", + ["mm"] = 0, + }, -- end of ["STARTER_LOSE_CON"] + ["FUEL_VALVE_LEAK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FUEL_VALVE_LEAK", + ["mm"] = 0, + }, -- end of ["FUEL_VALVE_LEAK"] + ["FLEX_S_NO_GUN_SIGN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FLEX_S_NO_GUN_SIGN", + ["mm"] = 0, + }, -- end of ["FLEX_S_NO_GUN_SIGN"] + ["fuel_sys_right_transfer_pump"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "fuel_sys_right_transfer_pump", + ["mm"] = 0, + }, -- end of ["fuel_sys_right_transfer_pump"] + ["COOLANT_RADIATOR_MOTOR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_RADIATOR_MOTOR", + ["mm"] = 0, + }, -- end of ["COOLANT_RADIATOR_MOTOR"] + ["CARBAIR_OPEN_CIRCUIT_BLB"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CARBAIR_OPEN_CIRCUIT_BLB", + ["mm"] = 0, + }, -- end of ["CARBAIR_OPEN_CIRCUIT_BLB"] + ["AAR_47_FAILURE_SENSOR_TAIL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AAR_47_FAILURE_SENSOR_TAIL", + ["mm"] = 0, + }, -- end of ["AAR_47_FAILURE_SENSOR_TAIL"] + ["GUN_LEFT_OUT_OPEN_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_OUT_OPEN_CIRCUIT", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_OUT_OPEN_CIRCUIT"] + ["TACAN_FAILURE_TRANSMITTER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACAN_FAILURE_TRANSMITTER", + ["mm"] = 0, + }, -- end of ["TACAN_FAILURE_TRANSMITTER"] + ["BOMBS_ARMING_BROKEN_WIRING_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_BROKEN_WIRING_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_BROKEN_WIRING_RIGHT"] + ["l_gen"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "l_gen", + ["mm"] = 0, + }, -- end of ["l_gen"] + ["TURNIND_POINTER_VIBRATES"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_POINTER_VIBRATES", + ["mm"] = 0, + }, -- end of ["TURNIND_POINTER_VIBRATES"] + ["GUN_LEFT_IN_BARREL_WORN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_LEFT_IN_BARREL_WORN", + ["mm"] = 0, + }, -- end of ["GUN_LEFT_IN_BARREL_WORN"] + ["r_gen"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "r_gen", + ["mm"] = 0, + }, -- end of ["r_gen"] + ["COOLANT_RADIATOR_SENSOR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COOLANT_RADIATOR_SENSOR", + ["mm"] = 0, + }, -- end of ["COOLANT_RADIATOR_SENSOR"] + ["AAR_47_FAILURE_SENSOR_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AAR_47_FAILURE_SENSOR_RIGHT", + ["mm"] = 0, + }, -- end of ["AAR_47_FAILURE_SENSOR_RIGHT"] + ["ROCKETS_INTERVALOMETER_SEQ"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ROCKETS_INTERVALOMETER_SEQ", + ["mm"] = 0, + }, -- end of ["ROCKETS_INTERVALOMETER_SEQ"] + ["hydro_common"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "hydro_common", + ["mm"] = 0, + }, -- end of ["hydro_common"] + ["SAR_2_95"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SAR_2_95", + ["mm"] = 0, + }, -- end of ["SAR_2_95"] + ["SAR_2_101"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SAR_2_101", + ["mm"] = 0, + }, -- end of ["SAR_2_101"] + ["BOOSTER_COIL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOOSTER_COIL", + ["mm"] = 0, + }, -- end of ["BOOSTER_COIL"] + ["BOMBS_DAMAGE_ELINKAGE_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_DAMAGE_ELINKAGE_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_DAMAGE_ELINKAGE_RIGHT"] + ["FAULTY_ROCKET_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "FAULTY_ROCKET_RIGHT", + ["mm"] = 0, + }, -- end of ["FAULTY_ROCKET_RIGHT"] + ["GUN_RIGHT_IN_OPEN_CIRCUIT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_IN_OPEN_CIRCUIT", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_IN_OPEN_CIRCUIT"] + ["COMPASS_ERRATIC_INDIACATON"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COMPASS_ERRATIC_INDIACATON", + ["mm"] = 0, + }, -- end of ["COMPASS_ERRATIC_INDIACATON"] + ["OIL_DILUTION_SOLENOID"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "OIL_DILUTION_SOLENOID", + ["mm"] = 0, + }, -- end of ["OIL_DILUTION_SOLENOID"] + ["PUMP_SEPARATOR_CLOGGED"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "PUMP_SEPARATOR_CLOGGED", + ["mm"] = 0, + }, -- end of ["PUMP_SEPARATOR_CLOGGED"] + ["es_damage_MainGenerator"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_MainGenerator", + ["mm"] = 0, + }, -- end of ["es_damage_MainGenerator"] + ["BOMBS_RUST_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_RUST_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_RUST_RIGHT"] + ["CLOGGED_FUEL_STRAINER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "CLOGGED_FUEL_STRAINER", + ["mm"] = 0, + }, -- end of ["CLOGGED_FUEL_STRAINER"] + ["BOMBS_DAMAGE_ELINKAGE_LEFT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_DAMAGE_ELINKAGE_LEFT", + ["mm"] = 0, + }, -- end of ["BOMBS_DAMAGE_ELINKAGE_LEFT"] + ["r_engine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "r_engine", + ["mm"] = 0, + }, -- end of ["r_engine"] + ["TACH_BREAK_IN_INDICATOR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TACH_BREAK_IN_INDICATOR", + ["mm"] = 0, + }, -- end of ["TACH_BREAK_IN_INDICATOR"] + ["A11_CLOCK_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "A11_CLOCK_FAILURE", + ["mm"] = 0, + }, -- end of ["A11_CLOCK_FAILURE"] + ["DOORS_TV_JAMMED"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "DOORS_TV_JAMMED", + ["mm"] = 0, + }, -- end of ["DOORS_TV_JAMMED"] + ["D2_RIGHT_CYLINDER"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "D2_RIGHT_CYLINDER", + ["mm"] = 0, + }, -- end of ["D2_RIGHT_CYLINDER"] + ["ecm"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "ecm", + ["mm"] = 0, + }, -- end of ["ecm"] + ["AN_ALR69V_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALR69V_FAILURE_TOTAL", + ["mm"] = 0, + }, -- end of ["AN_ALR69V_FAILURE_TOTAL"] + ["es_damage_GeneratorRight"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "es_damage_GeneratorRight", + ["mm"] = 0, + }, -- end of ["es_damage_GeneratorRight"] + ["SUPERCHARGER_SOLENOID"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "SUPERCHARGER_SOLENOID", + ["mm"] = 0, + }, -- end of ["SUPERCHARGER_SOLENOID"] + ["GUN_RIGHT_OUT_AMMUN_FAULT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "GUN_RIGHT_OUT_AMMUN_FAULT", + ["mm"] = 0, + }, -- end of ["GUN_RIGHT_OUT_AMMUN_FAULT"] + ["l_engine"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "l_engine", + ["mm"] = 0, + }, -- end of ["l_engine"] + ["AN_ALE_40V_FAILURE_CONTAINER_RIGHT_GEAR"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "AN_ALE_40V_FAILURE_CONTAINER_RIGHT_GEAR", + ["mm"] = 0, + }, -- end of ["AN_ALE_40V_FAILURE_CONTAINER_RIGHT_GEAR"] + ["TransitionalReductor_ShaveInOil"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TransitionalReductor_ShaveInOil", + ["mm"] = 0, + }, -- end of ["TransitionalReductor_ShaveInOil"] + ["COPILOT_KILLED_FAILURE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "COPILOT_KILLED_FAILURE", + ["mm"] = 0, + }, -- end of ["COPILOT_KILLED_FAILURE"] + ["TAIL_GEAR_D_LOCK"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TAIL_GEAR_D_LOCK", + ["mm"] = 0, + }, -- end of ["TAIL_GEAR_D_LOCK"] + ["JADRO_1A_FAILURE_TOTAL"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["mm"] = 0, + }, -- end of ["JADRO_1A_FAILURE_TOTAL"] + ["BOMBS_ARMING_NO_VOLATAGE_RIGHT"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "BOMBS_ARMING_NO_VOLATAGE_RIGHT", + ["mm"] = 0, + }, -- end of ["BOMBS_ARMING_NO_VOLATAGE_RIGHT"] + ["IFFCC_FAILURE_GUN"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "IFFCC_FAILURE_GUN", + ["mm"] = 0, + }, -- end of ["IFFCC_FAILURE_GUN"] + ["APU_Fire"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["mm"] = 0, + }, -- end of ["APU_Fire"] + ["TURNIND_INCORRECT_SENS_DEFECTIVE"] = + { + ["hh"] = 0, + ["prob"] = 100, + ["enable"] = false, + ["mmint"] = 1, + ["id"] = "TURNIND_INCORRECT_SENS_DEFECTIVE", + ["mm"] = 0, + }, -- end of ["TURNIND_INCORRECT_SENS_DEFECTIVE"] + }, -- end of ["failures"] +} -- end of mission diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/options b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/options new file mode 100644 index 000000000..bf093522c --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/options @@ -0,0 +1,229 @@ +options = +{ + ["playerName"] = "Killer", + ["miscellaneous"] = + { + ["headmove"] = true, + ["TrackIR_external_views"] = true, + ["f5_nearest_ac"] = true, + ["f11_free_camera"] = true, + ["F2_view_effects"] = 2, + ["f10_awacs"] = true, + ["Coordinate_Display"] = "Lat Long", + ["accidental_failures"] = false, + ["force_feedback_enabled"] = true, + ["synchronize_controls"] = false, + ["show_pilot_body"] = true, + }, -- end of ["miscellaneous"] + ["difficulty"] = + { + ["padlock"] = true, + ["labels"] = false, + ["easyCommunication"] = true, + ["easyRadar"] = false, + ["fuel"] = false, + ["miniHUD"] = false, + ["tips"] = true, + ["birds"] = 0, + ["optionsView"] = "optview_all", + ["permitCrash"] = true, + ["immortal"] = false, + ["cockpitStatusBarAllowed"] = false, + ["cockpitVisualRM"] = true, + ["easyFlight"] = false, + ["reports"] = true, + ["hideStick"] = false, + ["radio"] = true, + ["externalViews"] = true, + ["units"] = "metric", + ["userMarks"] = true, + ["cockpitLanguage"] = "english", + ["spectatorExternalViews"] = true, + ["userSnapView"] = true, + ["avionicsLanguage"] = "native", + ["impostors"] = "medium", + ["iconsTheme"] = "nato", + ["map"] = true, + ["weapons"] = false, + ["setGlobal"] = true, + ["geffect"] = "realistic", + }, -- end of ["difficulty"] + ["VR"] = + { + ["use_mouse"] = false, + ["enable"] = true, + ["box_mouse_cursor"] = true, + ["pixel_density"] = 1, + }, -- end of ["VR"] + ["graphics"] = + { + ["OculusRift"] = false, + ["color"] = "32", + ["LensEffects"] = 3, + ["heatBlr"] = 2, + ["scenes"] = "high", + ["water"] = 2, + ["visibRange"] = "High", + ["treesVisibility"] = 25000, + ["aspect"] = 1.25, + ["lights"] = 2, + ["HDR"] = 1, + ["MSAA"] = 2, + ["civTraffic"] = "high", + ["clutterMaxDistance"] = 1500, + ["terrainTextures"] = "max", + ["multiMonitorSetup"] = "1camera", + ["shadowTree"] = true, + ["fullScreen"] = false, + ["disableAero"] = false, + ["DOF"] = 0, + ["clouds"] = 1, + ["flatTerrainShadows"] = 1, + ["cockpitShadows"] = true, + ["height"] = 1024, + ["width"] = 1280, + ["shadows"] = 4, + ["TranspSSAA"] = false, + ["sync"] = true, + ["preloadRadius"] = 73885, + ["anisotropy"] = 2, + ["haze"] = 1, + ["textures"] = 2, + ["effects"] = 3, + }, -- end of ["graphics"] + ["plugins"] = + { + ["CA"] = + { + ["kompass_options"] = 1, + ["ground_target_info"] = true, + ["ground_aim_helper"] = true, + ["ground_platform_shake"] = true, + ["ground_automatic"] = true, + }, -- end of ["CA"] + ["M-2000C"] = + { + ["UNI_NODRIFT"] = false, + ["TDC_"] = false, + ["CPLocalList"] = "default", + ["PPA_TOTPAR"] = false, + ["UNI_ALIGNED"] = false, + }, -- end of ["M-2000C"] + ["A-10C"] = + { + ["CPLocalList"] = "default", + }, -- end of ["A-10C"] + ["FC3"] = + { + ["CPLocalList_F-15C"] = "default", + ["CPLocalList_MiG-29S"] = "default", + ["CPLocalList_MiG-29A"] = "default", + ["CPLocalList_Su-25"] = "default", + ["CPLocalList_A-10A"] = "default", + ["CPLocalList_Su-27"] = "chinese", + ["CPLocalList_MiG-29G"] = "default", + ["CPLocalList_Su-33"] = "default", + }, -- end of ["FC3"] + ["Hawk"] = + { + ["CPLocalList"] = "high", + }, -- end of ["Hawk"] + ["P-51D"] = + { + ["assistance"] = 100, + ["CPLocalList"] = "default", + ["autoRudder"] = false, + }, -- end of ["P-51D"] + ["TF-51D"] = + { + ["assistance"] = 100, + ["CPLocalList"] = "default", + ["autoRudder"] = false, + }, -- end of ["TF-51D"] + ["MiG-21Bis"] = + { + ["Engine"] = false, + ["Shake"] = 100, + ["CustomCockpit"] = false, + ["Reticle"] = false, + ["Freeze"] = false, + }, -- end of ["MiG-21Bis"] + ["F-86F"] = + { + ["landSeatAdjustF86"] = true, + ["aiHelper"] = false, + ["CPLocalList"] = "default", + ["NoseWheelSteeringSimpleBehaviourF86"] = true, + ["gunCamera"] = 0, + }, -- end of ["F-86F"] + ["Su-25T"] = + { + ["CPLocalList"] = "default", + }, -- end of ["Su-25T"] + ["Mi-8MTV2"] = + { + ["Mi8TrimmingMethod"] = 0, + ["Mi8AutopilotAdjustment"] = false, + ["gunCamera"] = 0, + ["controlHelperMi8"] = false, + ["weapTooltipsMi8"] = true, + ["Mi8RudderTrimmer"] = false, + ["CPLocalList"] = "default", + ["altMi8TrimmingMethod"] = false, + ["Mi8FOV"] = 120, + }, -- end of ["Mi-8MTV2"] + ["MiG-15bis"] = + { + ["autoLeanToAimMiG15"] = true, + ["CPLocalList"] = "chinese", + ["gunCamera"] = 0, + ["aiHelper"] = false, + }, -- end of ["MiG-15bis"] + ["FW-190D9"] = + { + ["assistance"] = 100, + ["CPLocalList"] = "default", + ["autoRudder"] = false, + }, -- end of ["FW-190D9"] + ["UH-1H"] = + { + ["UHTrackIRAiming"] = true, + ["autoPilot"] = true, + ["UHTrimmingMethod"] = 0, + ["altUHTrimmingMethod"] = false, + ["CPLocalList"] = "default", + ["weapTooltips"] = true, + ["UHRudderTrimmer"] = false, + }, -- end of ["UH-1H"] + ["Ka-50"] = + { + ["altTrimmingMethod"] = false, + ["Ka50RudderTrimmer"] = false, + ["CPLocalList"] = "english", + }, -- end of ["Ka-50"] + }, -- end of ["plugins"] + ["format"] = 1, + ["sound"] = + { + ["hear_in_helmet"] = false, + ["headphones"] = 100, + ["cockpit"] = 100, + ["GBreathEffect"] = true, + ["gui"] = 100, + ["volume"] = 100, + ["radioSpeech"] = true, + ["music"] = 100, + ["subtitles"] = true, + ["world"] = 100, + }, -- end of ["sound"] + ["views"] = + { + ["cockpit"] = + { + ["mirrors"] = false, + ["reflections"] = false, + ["avionics"] = 3, + ["russianHud"] = false, + }, -- end of ["cockpit"] + }, -- end of ["views"] +} -- end of options diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/warehouses b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/warehouses new file mode 100644 index 000000000..52b43d127 --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-005 - Patrol AI and Randomize Zones/AIB-005 - Patrol AI and Randomize Zones/warehouses @@ -0,0 +1,807 @@ +warehouses = +{ + ["airports"] = + { + [12] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "RED", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [12] + [13] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "BLUE", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [13] + [14] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "RED", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [14] + [15] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "RED", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [15] + [16] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "BLUE", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [16] + [17] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [17] + [18] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [18] + [19] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [19] + [20] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [20] + [21] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [21] + [22] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [22] + [23] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [23] + [24] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [24] + [25] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [25] + [26] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [26] + [27] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [27] + [28] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [28] + [29] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [29] + [30] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [30] + [31] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [31] + [32] = + { + ["gasoline"] = + { + ["InitFuel"] = 100, + }, -- end of ["gasoline"] + ["unlimitedMunitions"] = true, + ["methanol_mixture"] = + { + ["InitFuel"] = 100, + }, -- end of ["methanol_mixture"] + ["OperatingLevel_Air"] = 10, + ["diesel"] = + { + ["InitFuel"] = 100, + }, -- end of ["diesel"] + ["speed"] = 16.666666, + ["size"] = 100, + ["periodicity"] = 30, + ["suppliers"] = + { + }, -- end of ["suppliers"] + ["coalition"] = "NEUTRAL", + ["jet_fuel"] = + { + ["InitFuel"] = 100, + }, -- end of ["jet_fuel"] + ["OperatingLevel_Eqp"] = 10, + ["unlimitedFuel"] = true, + ["aircrafts"] = + { + }, -- end of ["aircrafts"] + ["weapons"] = + { + }, -- end of ["weapons"] + ["OperatingLevel_Fuel"] = 10, + ["unlimitedAircrafts"] = true, + }, -- end of [32] + }, -- end of ["airports"] + ["warehouses"] = + { + }, -- end of ["warehouses"] +} -- end of warehouses diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.lua b/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.lua new file mode 100644 index 000000000..1b604a94f --- /dev/null +++ b/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.lua @@ -0,0 +1,43 @@ +-- Name: AIB-005 - Patrol AI and Randomize Zones +-- Author: FlightControl +-- Date Created: 10 Jan 2016 +-- +-- # Situation: +-- +-- For the red coalition, 2 client slots are foreseen. +-- For those players that have not joined the mission, red AI is spawned. +-- You'll notice a lot of AI is being spawned, as there are a lot of slots... +-- If the SPAWN API :InitCleanUp( secs ) is NOT used, you'll notice that the planes block each other on the runway. +-- After a short period of time, nothing will move anymore... +-- The :InitCleanUp( seconds ) API of the SPAWN class ensure that any AI that is parked longer than the +-- specified amount of seconds, is respawned back at the parking position. +-- This frees up the other planes departing, and the airbase is in this way decluttered... +-- +-- # Test cases: +-- +-- 1. Observe the de-cluttering of planes at Krymsk. +-- 2. Play with the InitCleanUp API of the SPAWN class, extende the amount of seconds to find the optimal setting. + +-- Define the SET of CLIENTs from the red coalition. This SET is filled during startup. +local RU_PlanesClientSet = SET_CLIENT:New():FilterCountries( "RUSSIA" ):FilterCategories( "plane" ) + +-- Define the SPAWN object for the red AI plane template. +-- We use InitCleanUp to check every 20 seconds, if there are no planes blocked at the airbase, waithing for take-off. +-- If a blocked plane exists, this red plane will be ReSpawned. +local RU_PlanesSpawn = SPAWN:New( "AI RU" ):InitCleanUp( 20 ) + +-- Start the AI_BALANCER, using the SET of red CLIENTs, and the SPAWN object as a parameter. +local RU_AI_Balancer = AI_BALANCER:New( RU_PlanesClientSet, RU_PlanesSpawn ) + +-- Create the first polygon zone ... +local PatrolZoneGroup1 = GROUP:FindByName( "PatrolZone1" ) +local PatrolZone1 = ZONE_POLYGON:New( "PatrolZone1", PatrolZoneGroup1 ) + +function RU_AI_Balancer:OnAfterSpawned( SetGroup, From, Event, To, AIGroup ) + + local Patrol = AI_PATROL_ZONE:New( PatrolZone1, 3000, 6000, 400, 600 ) + Patrol:ManageFuel( 0.2, 60 ) + Patrol:SetControllable( AIGroup ) + Patrol:__Start( 5 ) + +end diff --git a/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz b/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz new file mode 100644 index 000000000..13541bd70 Binary files /dev/null and b/Moose Test Missions/AIB - AI Balancing/AIB-006 - Declutter AI at Airbases/AIB-006 - Declutter AI at Airbases.miz differ diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.lua b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.lua new file mode 100644 index 000000000..92d27b1b2 --- /dev/null +++ b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.lua @@ -0,0 +1,18 @@ +-- Name: CAP-001 - Combat Air Patrol +-- Author: FlightControl +-- Date Created: 16 January 2017 +-- +-- # Situation: +-- +-- # Test cases: +-- + +local CapPlane = GROUP:FindByName( "Plane" ) + +local PatrolZone = ZONE:New( "Patrol Zone" ) + +local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 ) + +AICapZone:SetControllable( CapPlane ) + +AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone. diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.miz b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.miz new file mode 100644 index 000000000..dc4ceadc4 Binary files /dev/null and b/Moose Test Missions/CAP - Combat Air Patrol/CAP-001 - Combat Air Patrol/CAP-001 - Combat Air Patrol.miz differ diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.lua b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.lua new file mode 100644 index 000000000..283396d73 --- /dev/null +++ b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.lua @@ -0,0 +1,19 @@ +-- Name: CAP-001 - Combat Air Patrol +-- Author: FlightControl +-- Date Created: 16 January 2017 +-- +-- # Situation: +-- +-- # Test cases: +-- + +local CapPlane = GROUP:FindByName( "Plane" ) + +local PatrolZone = ZONE:New( "Patrol Zone" ) + +local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 ) + +AICapZone:SetControllable( CapPlane ) +AICapZone:SetEngageRange( 20000 ) -- Set the Engage Range to 20.000 meters. The AI won't engage when the enemy is beyond 20.000 meters. + +AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone. diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.miz b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.miz new file mode 100644 index 000000000..936a6cda6 Binary files /dev/null and b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Range/CAP-010 - CAP and Engage within Range.miz differ diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua new file mode 100644 index 000000000..5e911a096 --- /dev/null +++ b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.lua @@ -0,0 +1,23 @@ +-- Name: CAP-001 - Combat Air Patrol +-- Author: FlightControl +-- Date Created: 16 January 2017 +-- +-- # Situation: +-- +-- # Test cases: +-- + +local CapPlane = GROUP:FindByName( "Plane" ) + +local PatrolZone = ZONE:New( "Patrol Zone" ) + +local AICapZone = AI_CAP_ZONE:New( PatrolZone, 500, 1000, 500, 600 ) + +local EngageZoneGroup = GROUP:FindByName( "Engage Zone" ) + +local CapEngageZone = ZONE_POLYGON:New( "Engage Zone", EngageZoneGroup ) + +AICapZone:SetControllable( CapPlane ) +AICapZone:SetEngageZone( CapEngageZone ) -- Set the Engage Zone. The AI will only engage when the bogeys are within the CapEngageZone. + +AICapZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone. diff --git a/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.miz b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.miz new file mode 100644 index 000000000..705139400 Binary files /dev/null and b/Moose Test Missions/CAP - Combat Air Patrol/CAP-010 - CAP and Engage within Zone/CAP-010 - CAP and Engage within Zone.miz differ diff --git a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.lua b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.lua new file mode 100644 index 000000000..f5f267f69 --- /dev/null +++ b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.lua @@ -0,0 +1,59 @@ +-- Name: CAS in a ZONE +-- Author: FlightControl +-- Date Created: 13 January 2017 +-- +-- # Situation: +-- +-- # Test cases: +-- +-- Create a local variable (in this case called CASEngagementZone) and +-- using the ZONE function find the pre-defined zone called "Engagement Zone" +-- currently on the map and assign it to this variable +local CASEngagementZone = ZONE:New( "Engagement Zone" ) + +-- Create a local variable (in this case called CASPlane) and +-- using the GROUP function find the aircraft group called "Plane" and assign to this variable +local CASPlane = GROUP:FindByName( "Plane" ) + +-- Create a local Variable (in this cased called PatrolZone and +-- using the ZONE function find the pre-defined zone called "Patrol Zone" and assign it to this variable +local PatrolZone = ZONE:New( "Patrol Zone" ) + +-- Create and object (in this case called AICasZone) and +-- using the functions AI_CAS_ZONE assign the parameters that define this object +-- (in this case PatrolZone, 500, 1000, 500, 600, CASEngagementZone) +local AICasZone = AI_CAS_ZONE:New( PatrolZone, 500, 1000, 500, 600, CASEngagementZone ) + +-- Create an object (in this case called Targets) and +-- using the GROUP function find the group labeled "Targets" and assign it to this object +local Targets = GROUP:FindByName("Targets") + + +-- Tell the program to use the object (in this case called CASPlane) as the group to use in the CAS function +AICasZone:SetControllable( CASPlane ) + +-- Tell the group CASPlane to start the mission in 1 second. +AICasZone:__Start( 1 ) -- They should statup, and start patrolling in the PatrolZone. + +-- After 10 minutes, tell the group CASPlane to engage the targets located in the engagement zone called CASEngagement Zone. (600 is 600 seconds) +AICasZone:__Engage( 600 ) + +-- Check every 60 seconds whether the Targets have been eliminated. +-- When the trigger completed has been fired, the Plane will go back to the Patrol Zone. +Check, CheckScheduleID = SCHEDULER:New(nil, + function() + BASE:E( { "In Scheduler: ", Targets:GetSize() } ) + if Targets:IsAlive() and Targets:GetSize() > 5 then + BASE:E("Still alive") + else + BASE:E("Destroyed") + AICasZone:__Accomplish( 1 ) -- Now they should fly back to teh patrolzone and patrol. + Check:Stop(CheckScheduleID) + end + end, {}, 20, 60, 0.2 ) + + +-- When the targets in the zone are destroyed, (see scheduled function), the planes will return home ... +function AICasZone:OnAfterAccomplish( Controllable, From, Event, To ) + AICasZone:__RTB( 1 ) +end diff --git a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz new file mode 100644 index 000000000..b9a4b9a0a Binary files /dev/null and b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - CAS in a ZONE.miz differ diff --git a/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz new file mode 100644 index 000000000..a1f6b5ca8 Binary files /dev/null and b/Moose Test Missions/CAS - Close Air Support/CAS-001 - CAS in a ZONE/CAS-001 - Manual Test.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz b/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz index 703781aff..7f0505c7f 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-001 - Unit Boarding/CGO-001 - Unit Boarding.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz b/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz index 8c548daa4..304357caf 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-002 - Unit Unboarding/CGO-002 - Unit Unboarding.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.lua b/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.lua index b5eb57036..68d74a3dc 100644 --- a/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.lua +++ b/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.lua @@ -12,13 +12,14 @@ local CargoCarrierTo = UNIT:FindByName( "CarrierTo" ) InfantryCargo:Board( CargoCarrierFrom ) -- Once the Cargo has been loaded into the Carrier, drive to a point and unload the Cargo. -function InfantryCargo:OnAfterLoaded() +function InfantryCargo:OnEnterLoaded() self:__UnBoard( 1 ) - self.OnAfterLoaded = nil + self.OnEnterLoaded = nil end -- Once the Cargo has been unloaded from the Carrier (the Cargo has arrived to the unload gathering point), OnBoard the Cargo in the other Carrier. -function InfantryCargo:OnAfterUnLoaded() +function InfantryCargo:OnEnterUnLoaded() self:__Board( 1, CargoCarrierTo ) - self.OnAfterUnLoaded = nil + self.OnEnterUnLoaded = nil end + diff --git a/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz b/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz index d7bae593c..4ef50a887 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz and b/Moose Test Missions/CGO - Cargo/CGO-003 - Unit Transferring/CGO-003 - Unit Transferring.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz b/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz index 6dfbf3998..f81573419 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-101 - Group Boarding/CGO-101 - Group Boarding.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz b/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz index 4ad60d11d..91bcabb31 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-102 - Group Unboarding/CGO-102 - Group Unboarding.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.lua b/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.lua index 06968a6da..4b1d85f18 100644 --- a/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.lua +++ b/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.lua @@ -17,13 +17,13 @@ local CargoCarrierTo = UNIT:FindByName( "CarrierTo" ) InfantryCargo:Board( CargoCarrierFrom ) -- Once the Cargo has been loaded into the Carrier, drive to a point and unload the Cargo. -function InfantryCargo:OnAfterLoaded() +function InfantryCargo:OnEnterLoaded() self:__UnBoard( 1 ) - self.OnAfterLoaded = nil + self.OnEnterLoaded = nil end -- Once the Cargo has been unloaded from the Carrier (the Cargo has arrived to the unload gathering point), OnBoard the Cargo in the other Carrier. -function InfantryCargo:OnAfterUnLoaded() +function InfantryCargo:OnEnterUnLoaded() self:__Board( 1, CargoCarrierTo ) - self.OnAfterUnLoaded = nil + self.OnEnterUnLoaded = nil end diff --git a/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz b/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz index b3d831071..3ca7000e7 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz and b/Moose Test Missions/CGO - Cargo/CGO-103 - Group Transferring/CGO-103 - Group Transferring.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz b/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz index ab9da98db..b6d70f09d 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-201 - Package Boarding/CGO-201 - Package Boarding.miz differ diff --git a/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz b/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz index 9cb466c70..2c3a99429 100644 Binary files a/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz and b/Moose Test Missions/CGO - Cargo/CGO-202 - Package Unboarding/CGO-202 - Package Unboarding.miz differ diff --git a/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz b/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz index dc58789bf..1b32d1b58 100644 Binary files a/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz and b/Moose Test Missions/DET - Detection/DET-001 - Detection Areas/DET-001 - Detection Areas.miz differ diff --git a/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz b/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz index ab1c7b2ee..d445f5128 100644 Binary files a/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz and b/Moose Test Missions/DET - Detection/DET-101 - Detection Reporting/DET-101 - Detection Reporting.miz differ diff --git a/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz b/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz index 6e77213f5..23d06b8c9 100644 Binary files a/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz and b/Moose Test Missions/ESC - Escorting/ESC-001 - Escorting Helicopters/ESC-001 - Escorting Helicopters.miz differ diff --git a/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz b/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz index 12e14f675..7c69b1ae9 100644 Binary files a/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz and b/Moose Test Missions/FSM - Finite State Machine/FSM-100 - Transition Explanation/FSM-100 - Transition Explanation.miz differ diff --git a/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz b/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz index 6dc8223a9..abe076c97 100644 Binary files a/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz and b/Moose Test Missions/GRP - Group Commands/GRP-200 - Follow Group/GRP-200 - Follow Group.miz differ diff --git a/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz b/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz index da1651bbc..2a7df90f6 100644 Binary files a/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz and b/Moose Test Missions/GRP - Group Commands/GRP-300 - Switch WayPoints/GRP-300 - Switch WayPoints.miz differ diff --git a/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz b/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz index 910d4155e..c8430de80 100644 Binary files a/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz and b/Moose Test Missions/GRP - Group Commands/Moose_Test_WRAPPER.miz differ diff --git a/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz b/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz index 49f40a33f..5a7c87f98 100644 Binary files a/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz and b/Moose Test Missions/MEN - Menu Options/MEN-001 - Menu Client/MEN-001 - Menu Client.miz differ diff --git a/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz b/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz index b915c3d37..a428c9c86 100644 Binary files a/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz and b/Moose Test Missions/MEN - Menu Options/MEN-002 - Menu Coalition/MEN-002 - Menu Coalition.miz differ diff --git a/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz b/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz index 78d351a39..8322e8f62 100644 Binary files a/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz and b/Moose Test Missions/MEN - Menu Options/MEN-003 - Menu Group/MEN-003 - Menu Group.miz differ diff --git a/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz b/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz index 47e71638b..592dd05da 100644 Binary files a/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz and b/Moose Test Missions/MIT - Missile Trainer/MIT-001 - Missile Trainer/MIT-001 - Missile Trainer.miz differ diff --git a/Moose Test Missions/MOOSE_Test_Template.miz b/Moose Test Missions/MOOSE_Test_Template.miz index f5d3c1b27..31b824c41 100644 Binary files a/Moose Test Missions/MOOSE_Test_Template.miz and b/Moose Test Missions/MOOSE_Test_Template.miz differ diff --git a/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.lua b/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.lua index 2c35574c8..0cbc54bdc 100644 --- a/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.lua +++ b/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.lua @@ -1,6 +1,6 @@ --- This test mission models the behaviour of the AI_PATROLZONE class. +-- This test mission models the behaviour of the AI_PATROL_ZONE class. -- --- It creates a 2 AI_PATROLZONE objects with the name Patrol1 and Patrol2. +-- It creates a 2 AI_PATROL_ZONE objects with the name Patrol1 and Patrol2. -- Patrol1 will govern a GROUP object to patrol the zone defined by PatrolZone1, within 3000 meters and 6000 meters, within a speed of 400 and 600 km/h. -- When the GROUP object that is assigned to Patrol has fuel below 20%, the GROUP object will orbit for 60 secondes, before returning to base. -- @@ -23,24 +23,24 @@ local PatrolZone2 = ZONE_POLYGON:New( "Patrol Zone 2", PatrolZoneGroup2 ) local PatrolSpawn = SPAWN:New( "Patrol Group" ) local PatrolGroup = PatrolSpawn:Spawn() -local Patrol1 = AI_PATROLZONE:New( PatrolZone1, 3000, 6000, 400, 600 ) +local Patrol1 = AI_PATROL_ZONE:New( PatrolZone1, 3000, 6000, 400, 600 ) Patrol1:ManageFuel( 0.2, 60 ) Patrol1:SetControllable( PatrolGroup ) Patrol1:__Start( 5 ) -local Patrol2 = AI_PATROLZONE:New( PatrolZone2, 600, 1000, 300, 400 ) +local Patrol2 = AI_PATROL_ZONE:New( PatrolZone2, 600, 1000, 300, 400 ) Patrol2:ManageFuel( 0.2, 0 ) --- State transition function for the PROCESS\_PATROLZONE **Patrol1** object --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @param Wrapper.Group#GROUP AIGroup -- @return #boolean If false is returned, then the OnAfter state transition function will not be called. -function Patrol1:OnBeforeRTB( AIGroup ) +function Patrol1:OnLeaveRTB( AIGroup ) AIGroup:MessageToRed( "Returning to base", 20 ) end --- State transition function for the PROCESS\_PATROLZONE **Patrol1** object --- @param Process_PatrolCore.Zone#AI_PATROLZONE self +-- @param Process_PatrolCore.Zone#AI_PATROL_ZONE self -- @param Wrapper.Group#GROUP AIGroup function Patrol1:OnAfterRTB( AIGroup ) local NewGroup = PatrolSpawn:Spawn() @@ -49,32 +49,32 @@ function Patrol1:OnAfterRTB( AIGroup ) end --- State transition function for the PROCESS\_PATROLZONE **Patrol1** object --- @param Process_PatrolCore.Zone#AI_PATROLZONE self +-- @param Process_PatrolCore.Zone#AI_PATROL_ZONE self -- @param Wrapper.Group#GROUP AIGroup -function Patrol1:OnAfterPatrol( AIGroup ) +function Patrol1:OnEnterPatrol( AIGroup ) AIGroup:MessageToRed( "Patrolling in zone " .. PatrolZone1:GetName() , 20 ) end --- State transition function for the PROCESS\_PATROLZONE **Patrol2** object --- @param #AI_PATROLZONE self +-- @param #AI_PATROL_ZONE self -- @param Wrapper.Group#GROUP AIGroup --- @return #boolean If false is returned, then the OnAfter state transition function will not be called. +-- @return #boolean If false is returned, then the OnEnter state transition function will not be called. function Patrol2:OnBeforeRTB( AIGroup ) AIGroup:MessageToRed( "Returning to base", 20 ) end --- State transition function for the PROCESS\_PATROLZONE **Patrol2** object --- @param Process_PatrolCore.Zone#AI_PATROLZONE self +-- @param Process_PatrolCore.Zone#AI_PATROL_ZONE self -- @param Wrapper.Group#GROUP AIGroup -function Patrol2:OnAfterRTB( AIGroup ) +function Patrol2:OnEnterRTB( AIGroup ) local NewGroup = PatrolSpawn:Spawn() Patrol1:SetControllable( NewGroup ) Patrol1:__Start( 1 ) end --- State transition function for the PROCESS\_PATROLZONE **Patrol2** object --- @param Process_PatrolCore.Zone#AI_PATROLZONE self +-- @param Process_PatrolCore.Zone#AI_PATROL_ZONE self -- @param Wrapper.Group#GROUP AIGroup -function Patrol2:OnAfterPatrol( AIGroup ) +function Patrol2:OnEnterPatrol( AIGroup ) AIGroup:MessageToRed( "Patrolling in zone " .. PatrolZone2:GetName() , 20 ) end diff --git a/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz b/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz index eb6ab97be..7ce81baab 100644 Binary files a/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz and b/Moose Test Missions/PAT - Patrolling/PAT-001 - Switching Patrol Zones/PAT-001 - Switching Patrol Zones.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz index f70f33e03..3ad072a39 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-000 - Simple Scheduling/SCH-000 - Simple Scheduling.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz index b0da5157b..c0d7d9922 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-001 - Simple Object Scheduling/SCH-001 - Simple Object Scheduling.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz index ad4d02030..08f643cb9 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-100 - Simple Repeat Scheduling/SCH-100 - Simple Repeat Scheduling.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz index f25018759..34db8ea48 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-110 - Object Repeat Scheduling/SCH-110 - Object Repeat Scheduling.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz b/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz index c6d5e8106..1db4a1df9 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz and b/Moose Test Missions/SCH - Scheduler/SCH-200 - Simple Repeat Scheduling Stop and Start/SCH-200 - Simple Repeat Scheduling Stop and Start.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz index 021de303b..a3236fccc 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-300 - GC Simple Object Scheduling/SCH-300 - GC Simple Object Scheduling.miz differ diff --git a/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz b/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz index 5cab31918..3bb2eaee7 100644 Binary files a/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz and b/Moose Test Missions/SCH - Scheduler/SCH-310 - GC Object Repeat Scheduling/SCH-310 - GC Object Repeat Scheduling.miz differ diff --git a/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz b/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz index b32cce74e..f4f865d13 100644 Binary files a/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz and b/Moose Test Missions/SET - Data Sets/SET-001 - Airbase Sets/SET-001 - Airbase Sets.miz differ diff --git a/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz b/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz index 7005fd8c2..aa98512c0 100644 Binary files a/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz and b/Moose Test Missions/SET - Data Sets/SET-101 - Group Sets/SET-101 - Group Sets.miz differ diff --git a/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz b/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz index 54ecbecd7..5b70c77fd 100644 Binary files a/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz and b/Moose Test Missions/SET - Data Sets/SET-201 - Client Sets/SET-201 - Client Sets.miz differ diff --git a/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz b/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz index df92d4792..3a5c951bb 100644 Binary files a/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz and b/Moose Test Missions/SEV - SEAD Evasion/SEV-001 - SEAD Evasion/SEV-001 - SEAD Evasion.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz b/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz index dc401ec98..f1a2bed6c 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz and b/Moose Test Missions/SPA - Spawning/SPA-010 - Spawn Demo/SPA-010 - Spawn Demo.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.lua b/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.lua new file mode 100644 index 000000000..4272c98f0 --- /dev/null +++ b/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.lua @@ -0,0 +1,22 @@ +-- Name: SPA-011 - Ground Ops - Simple Spawning +-- Author: FlightControl +-- Date Created: 10 Jan 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn a ground vehicle. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicle is spawned. + + + +-- Tests Gudauta +-- ------------- +-- Spawn a gound vehicle... +Spawn_Vehicle_1 = SPAWN:New( "Spawn Vehicle 1" ) +Spawn_Group_1 = Spawn_Vehicle_1:Spawn() + + + diff --git a/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz b/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz new file mode 100644 index 000000000..77d59f731 Binary files /dev/null and b/Moose Test Missions/SPA - Spawning/SPA-011 - Ground Ops - Simple Spawning/SPA-011 - Ground Ops - Simple Spawning.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.lua b/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.lua new file mode 100644 index 000000000..36ce824e3 --- /dev/null +++ b/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.lua @@ -0,0 +1,26 @@ +-- Name: SPA-012 - Ground Ops - Multiple Spawns +-- Author: FlightControl +-- Date Created: 10 Jan 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn multiple ground vehicles. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicles are spawned at the position declared within the mission editor. + + + +-- Tests Gudauta +-- ------------- +-- Spawn a gound vehicle... +Spawn_Vehicle_1 = SPAWN:New( "Spawn Vehicle 1" ) +Spawn_Group_1 = Spawn_Vehicle_1:Spawn() +Spawn_Group_2 = Spawn_Vehicle_1:Spawn() +Spawn_Group_3 = Spawn_Vehicle_1:Spawn() +Spawn_Group_4 = Spawn_Vehicle_1:Spawn() +Spawn_Group_5 = Spawn_Vehicle_1:Spawn() + + + diff --git a/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz b/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz new file mode 100644 index 000000000..110dceb8f Binary files /dev/null and b/Moose Test Missions/SPA - Spawning/SPA-012 - Ground Ops - Multiple Spawns/SPA-012 - Ground Ops - Multiple Spawns.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.lua b/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.lua new file mode 100644 index 000000000..3549c9a4e --- /dev/null +++ b/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.lua @@ -0,0 +1,22 @@ +-- Name: SPA-013 - Ground Ops - Scheduled Spawns +-- Author: FlightControl +-- Date Created: 10 Jan 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn multiple ground vehicles, in a scheduled fashion. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicles are spawned at the position declared within the mission editor. +-- 2. The vehicles should spawn according the scheduler parameters. + + + +-- Tests Gudauta +-- ------------- +Spawn_Vehicle_1 = SPAWN:New( "Spawn Vehicle 1" ):SpawnScheduled( 10, 0.5 ) + + + + diff --git a/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz b/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz new file mode 100644 index 000000000..cf3bc2187 Binary files /dev/null and b/Moose Test Missions/SPA - Spawning/SPA-013 - Ground Ops - Scheduled Spawns/SPA-013 - Ground Ops - Scheduled Spawns.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.lua b/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.lua new file mode 100644 index 000000000..2f8ccdc9f --- /dev/null +++ b/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.lua @@ -0,0 +1,21 @@ +-- Name: SPA-014 - Ground Ops - Scheduled Spawns Limited +-- Author: FlightControl +-- Date Created: 10 Jan 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn multiple ground vehicles, in a scheduled fashion. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicles are spawned at the position declared within the mission editor. +-- 2. The vehicles should spawn according the scheduler parameters. +-- 3. There should not be more than 5 groups spawned. + + + +-- Tests Gudauta +-- ------------- +Spawn_Vehicle_1 = SPAWN:New( "Spawn Vehicle 1" ):InitLimit( 5, 10 ):SpawnScheduled( 5, .5 ) + + diff --git a/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz b/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz new file mode 100644 index 000000000..3f5f562b9 Binary files /dev/null and b/Moose Test Missions/SPA - Spawning/SPA-014 - Ground Ops - Scheduled Spawns Limited/SPA-014 - Ground Ops - Scheduled Spawns Limited.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.lua b/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.lua new file mode 100644 index 000000000..c6c88f56a --- /dev/null +++ b/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.lua @@ -0,0 +1,27 @@ +-- Name: SPA-015 - Ground Ops - Randomize Route +-- Author: FlightControl +-- Date Created: 10 Jan 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn multiple ground vehicles, in a scheduled fashion. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicles are spawned at the position declared within the mission editor. +-- 2. The vehicles should spawn according the scheduler parameters. +-- 3. There should not be more than 5 groups spawned. +-- 4. Observe that the route that the vehicles follow is randomized starting from point 1 till point 3. + + + +-- Tests Gudauta +-- ------------- +Spawn_Vehicle_1 = SPAWN:New( "Spawn Vehicle 1" ) + :InitLimit( 10, 10 ) + :InitRandomizeRoute( 1, 1, 200 ) -- Randomize route starting from point 1 till point 3, with a radius of 200 meters around each point. + :SpawnScheduled( 5, .5 ) + + + + diff --git a/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz b/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz new file mode 100644 index 000000000..2c4fe1adb Binary files /dev/null and b/Moose Test Missions/SPA - Spawning/SPA-015 - Ground Ops - Randomize Route/SPA-015 - Ground Ops - Randomize Route.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.lua b/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.lua new file mode 100644 index 000000000..3bf1f8bfb --- /dev/null +++ b/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.lua @@ -0,0 +1,29 @@ +-- Name: SPA-016 - Ground Ops - Randomize Zones +-- Author: FlightControl +-- Date Created: 10 Jan 2017 +-- +-- # Situation: +-- +-- At Gudauta spawn multiple ground vehicles, in a scheduled fashion. +-- +-- # Test cases: +-- +-- 1. Observe that the ground vehicles are spawned at the position declared within the mission editor. +-- 2. The vehicles should spawn according the scheduler parameters. +-- 3. There should not be more than 5 groups spawned. +-- 4. Observe that the route that the vehicles follow is randomized starting from point 1 till point 3. +-- 5. Observe that the position where the units are spawned, is randomized according the zones. + + + +-- Tests Gudauta +-- ------------- +-- Create a zone table of the 2 zones. +ZoneTable = { ZONE:New( "Zone1" ), ZONE:New( "Zone2" ) } + +Spawn_Vehicle_1 = SPAWN:New( "Spawn Vehicle 1" ) + :InitLimit( 10, 10 ) + :InitRandomizeRoute( 1, 1, 200 ) + :InitRandomizeZones( ZoneTable ) + :SpawnScheduled( 5, .5 ) + diff --git a/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz b/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz new file mode 100644 index 000000000..37f984464 Binary files /dev/null and b/Moose Test Missions/SPA - Spawning/SPA-016 - Ground Ops - Randomize Zones/SPA-016 - Ground Ops - Randomize Zones.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz b/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz index db96ec5c8..14b5c1234 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz and b/Moose Test Missions/SPA - Spawning/SPA-100 - CleanUp Inactive Units/SPA-100 - CleanUp Inactive Units.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz b/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz index 7dec6f673..7ab9d16f5 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz and b/Moose Test Missions/SPA - Spawning/SPA-110 - Limit Spawning/SPA-110 - Limit Spawning.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz b/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz index 5c6107869..bc6fcb145 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz and b/Moose Test Missions/SPA - Spawning/SPA-120 - Repeat Spawning/SPA-120 - Repeat Spawning.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz b/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz index dfac695a6..6e5d59d14 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz and b/Moose Test Missions/SPA - Spawning/SPA-200 - Randomize Unit Types/SPA-200 - Randomize Unit Types.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz b/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz index 092d81d69..62e0518c5 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz and b/Moose Test Missions/SPA - Spawning/SPA-220 - Randomize Zones/SPA-220 - Randomize Zones.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz b/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz index 868b23385..16b472608 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz and b/Moose Test Missions/SPA - Spawning/SPA-310 - Spawn at Static position/SPA-310 - Spawn at Static position.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz b/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz index 2b4440766..b30e871b9 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz and b/Moose Test Missions/SPA - Spawning/SPA-320 - Spawn at Unit position/SPA-320 - Spawn at Unit position.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz b/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz index 1af97b8bf..a25aa52cc 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz and b/Moose Test Missions/SPA - Spawning/SPA-330 - Spawn at Vec2 position/SPA-330 - Spawn at Vec2 position.miz differ diff --git a/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz b/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz index 1dff8f823..de64be70e 100644 Binary files a/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz and b/Moose Test Missions/SPA - Spawning/SPA-340 - Spawn at Vec3 position/SPA-340 - Spawn at Vec3 position.miz differ diff --git a/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz b/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz index 9d49df0e8..91669ff65 100644 Binary files a/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz and b/Moose Test Missions/TAD - Task Dispatching/TAD-010 - Task Dispatching Demo/TAD-010 - Task Dispatching Demo.miz differ diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua index 17526a9c1..520e32cec 100644 --- a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua +++ b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.lua @@ -506,7 +506,7 @@ SEADProcess:AddScoreProcess( "Updated", "Account", "Failed", "failed to destroy SEADProcess:AddScore( "Success", "Destroyed all target radars", 250 ) SEADProcess:AddScore( "Failed", "Failed to destroy all target radars", -100 ) -function SEADProcess:OnEnterUpdated(Controllable,From,Event,To) +function SEADProcess:OnEnterUpdated( Controllable, From, Event, To ) self:E( { self } ) self:Account() self:Smoke() @@ -517,7 +517,7 @@ end -- we check if the SEADTask has still AlivePlayers assigned to the Task. -- If not, the Task will Abort. -- And it will be Replanned within 30 seconds. -function SEADTask:OnAfterPlayerCrashed( PlayerUnit, PlayerName ) +function SEADTask:OnEnterPlayerCrashed( PlayerUnit, PlayerName ) if not SEADTask:HasAliveUnits() then SEADTask:__Abort() SEADTask:__Replan( 30 ) diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz index aa3d43398..1b3d36c4a 100644 Binary files a/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz and b/Moose Test Missions/TSK - Task Modelling/TSK-010 - Task Modelling - SEAD/TSK-010 - Task Modelling - SEAD.miz differ diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz b/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz index f6d0adc6e..7a8b7692d 100644 Binary files a/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz and b/Moose Test Missions/TSK - Task Modelling/TSK-020 - Task Modelling - Pickup/TSK-020 - Task Modelling - Pickup.miz differ diff --git a/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz b/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz index 6deec88ca..e1e737483 100644 Binary files a/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-100 - Normal Zone/ZON-100 - Normal Zone.miz differ diff --git a/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz b/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz index 4925e1a7d..ee13b09d3 100644 Binary files a/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-200 - Group Zone/ZON-200 - Group Zone.miz differ diff --git a/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz b/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz index 396b71f4e..92133f436 100644 Binary files a/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-300 - Unit Zone/ZON-300 - Unit Zone.miz differ diff --git a/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz b/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz index 9cb111f0c..614c1b017 100644 Binary files a/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-400 - Radius Zone/ZON-400 - Radius Zone.miz differ diff --git a/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz b/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz index ac7801ef1..ff9359079 100644 Binary files a/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz and b/Moose Test Missions/ZON - Zones/ZON-500 - Polygon Zone/ZON-500 - Polygon Zone.miz differ diff --git a/docs/Documentation/AI_Balancer.html b/docs/Documentation/AI_Balancer.html index 15d059e29..02a4952eb 100644 --- a/docs/Documentation/AI_Balancer.html +++ b/docs/Documentation/AI_Balancer.html @@ -18,6 +18,9 @@
  • AI_Balancer
  • +
  • AI_Cap
  • +
  • AI_Cas
  • +
  • AI_Patrol
  • Account
  • Airbase
  • AirbasePolice
  • @@ -41,7 +44,6 @@
  • MissileTrainer
  • Mission
  • Object
  • -
  • Patrol
  • Point
  • Positionable
  • Process_JTAC
  • @@ -68,42 +70,81 @@

    Module AI_Balancer

    -

    This module contains the AI_BALANCER class.

    +

    Single-Player:No / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions +non-occupied human slots with AI groups, in order to provide an engaging simulation environment, +even when there are hardly any players in the mission.

    + +

    Banner Image

    -

    1) AI.AIBalancer#AIBALANCER class, extends Core.Fsm#FSM_SET

    -

    The AI.AIBalancer#AIBALANCER class monitors and manages as many AI GROUPS as there are -CLIENTS in a SETCLIENT collection not occupied by players. -The AIBALANCER class manages internally a collection of AI management objects, which govern the behaviour -of the underlying AI GROUPS.

    -

    The parent class Core.Fsm#FSM_SET manages the functionality to control the Finite State Machine (FSM) -and calls for each event the state transition methods providing the internal Core.Fsm#FSM_SET.Set object containing the -SET_GROUP and additional event parameters provided during the event.

    +

    The AI.AIBalancer#AIBALANCER class monitors and manages as many replacement AI groups as there are +CLIENTS in a SET_CLIENT collection, which are not occupied by human players.

    -

    1.1) AI_BALANCER construction method

    -

    Create a new AI_BALANCER object with the AI_BALANCER.New method:

    + +

    In other words, use AI_BALANCER to simulate human behaviour by spawning in replacement AI in multi player missions.

    + +

    The parent class Core.Fsm#FSM_SET manages the functionality to control the Finite State Machine (FSM). +The mission designer can tailor the behaviour of the AI_BALANCER, by defining event and state transition methods. +An explanation about state and event transition methods can be found in the FSM module documentation.

    + +

    The mission designer can tailor the AI_BALANCER behaviour, by implementing a state or event handling method for the following:

    -

    1.2)

    -

    * Add - * Remove

    +

    1.1) AI_BALANCER construction

    -

    1.2) AI_BALANCER returns AI to Airbases

    -

    You can configure to have the AI to return to:

    +

    Create a new AI_BALANCER object with the AI_BALANCER.New() method:

    + +

    1.2) AI_BALANCER is a FSM

    + +

    Process

    + +

    1.2.1) AI_BALANCER States

      -
    • AI_BALANCER.ReturnToHomeAirbase: Returns the AI to the home Wrapper.Airbase#AIRBASE.
    • -
    • AI_BALANCER.ReturnToNearestAirbases: Returns the AI to the nearest friendly Wrapper.Airbase#AIRBASE. - --
    • +
    • Monitoring ( Set ): Monitoring the Set if all AI is spawned for the Clients.
    • +
    • Spawning ( Set, ClientName ): There is a new AI group spawned with ClientName as the name of reference.
    • +
    • Spawned ( Set, AIGroup ): A new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes.
    • +
    • Destroying ( Set, AIGroup ): The AI is being destroyed.
    • +
    • Returning ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods. Handle this state to customize the return behaviour of the AI, if any.
    +

    1.2.2) AI_BALANCER Events

    + +
      +
    • Monitor ( Set ): Every 10 seconds, the Monitor event is triggered to monitor the Set.
    • +
    • Spawn ( Set, ClientName ): Triggers when there is a new AI group to be spawned with ClientName as the name of reference.
    • +
    • Spawned ( Set, AIGroup ): Triggers when a new AI has been spawned. You can handle this event to customize the AI behaviour with other AI FSMs or own processes.
    • +
    • Destroy ( Set, AIGroup ): The AI is being destroyed.
    • +
    • Return ( Set, AIGroup ): The AI is returning to the airbase specified by the ReturnToAirbase methods.
    • +
    + +

    1.3) AI_BALANCER spawn interval for replacement AI

    + +

    Use the method AI_BALANCER.InitSpawnInterval() to set the earliest and latest interval in seconds that is waited until a new replacement AI is spawned.

    + +

    1.4) AI_BALANCER returns AI to Airbases

    + +

    By default, When a human player joins a slot that is AI_BALANCED, the AI group will be destroyed by default. +However, there are 2 additional options that you can use to customize the destroy behaviour. +When a human player joins a slot, you can configure to let the AI return to:

    + + + +

    Note that when AI returns to an airbase, the AIBALANCER will trigger the Return event and the AI will return, +otherwise the AIBALANCER will trigger a Destroy event, and the AI will be destroyed.

    + +
    +

    API CHANGE HISTORY

    The underlying change log documents the API changes. Please read this carefully. The following notation is used:

    @@ -115,32 +156,25 @@ SET_GROUP and additional event parameters provided during the event.

    Hereby the change log:

    -

    2016-08-17: SPAWN:InitCleanUp( SpawnCleanUpInterval ) replaces SPAWN:CleanUp( SpawnCleanUpInterval )

    +

    2017-01-17: There is still a problem with AI being destroyed, but not respawned. Need to check further upon that.

    -
      -
    • Want to ensure that the methods starting with Init are the first called methods before any Spawn method is called!
    • -
    • This notation makes it now more clear which methods are initialization methods and which methods are Spawn enablement methods.
    • -
    +

    2017-01-08: AI_BALANCER:InitSpawnInterval( Earliest, Latest ) added.


    -

    AUTHORS and CONTRIBUTIONS

    +

    AUTHORS and CONTRIBUTIONS

    Contributions:

      -
    • Dutch_Baron (James): Who you can search on the Eagle Dynamics Forums.
      - Working together with James has resulted in the creation of the AI_BALANCER class.
      - James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)

    • -
    • SNAFU: - Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. - None of the script code has been used however within the new AI_BALANCER moose class.

    • +
    • Dutch_Baron: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)
    • +
    • SNAFU: Had a couple of mails with the guys to validate, if the same concept in the GCI/CAP script could be reworked within MOOSE. None of the script code has been used however within the new AI_BALANCER moose class.

    Authors:

      -
    • FlightControl: Framework Design & Programming
    • +
    • FlightControl: Framework Design & Programming and Documentation.
    @@ -165,6 +199,24 @@ SET_GROUP and additional event parameters provided during the event.

    AI_BALANCER.ClassName + + + + AI_BALANCER.Earliest + + + + + + AI_BALANCER:InitSpawnInterval(Earliest, Latest) + +

    Sets the earliest to the latest interval in seconds how long AI_BALANCER will wait to spawn a new AI.

    + + + + AI_BALANCER.Latest + + @@ -207,6 +259,18 @@ SET_GROUP and additional event parameters provided during the event.

    AI_BALANCER.SetClient + + + + AI_BALANCER.SpawnAI + + + + + + AI_BALANCER.Test + + @@ -222,7 +286,7 @@ SET_GROUP and additional event parameters provided during the event.

    - AI_BALANCER:onenterDestroying(SetGroup, AIGroup, From, Event, To) + AI_BALANCER:onenterDestroying(SetGroup, AIGroup, From, Event, To, ClientName) @@ -295,6 +359,70 @@ SET_GROUP and additional event parameters provided during the event.

    + + +
    +
    + + + +AI_BALANCER.Earliest + +
    +
    + + + +
    +
    +
    +
    + + +AI_BALANCER:InitSpawnInterval(Earliest, Latest) + +
    +
    + +

    Sets the earliest to the latest interval in seconds how long AI_BALANCER will wait to spawn a new AI.

    + + +

    Provide 2 identical seconds if the interval should be a fixed amount of seconds.

    + +

    Parameters

    +
      +
    • + +

      #number Earliest : +The earliest a new AI can be spawned in seconds.

      + +
    • +
    • + +

      #number Latest : +The latest a new AI can be spawned in seconds.

      + +
    • +
    +

    Return value

    + + +

    self

    + +
    +
    +
    +
    + + + +AI_BALANCER.Latest + +
    +
    + + +
    @@ -328,9 +456,6 @@ The default Spawn object to spawn new AI Groups when needed.

    #AI_BALANCER:

    -

    Usage:

    -
    -- Define a new AI_BALANCER Object.
    -
    @@ -437,6 +562,34 @@ The SET of Core.Set#SET_AIRBASEs to e + +
    +
    +
    + + Functional.Spawn#SPAWN + +AI_BALANCER.SpawnAI + +
    +
    + + + +
    +
    +
    +
    + + Wrapper.Group#GROUP + +AI_BALANCER.Test + +
    +
    + + +
    @@ -471,7 +624,7 @@ The SET of Core.Set#SET_AIRBASEs to e
    -AI_BALANCER:onenterDestroying(SetGroup, AIGroup, From, Event, To) +AI_BALANCER:onenterDestroying(SetGroup, AIGroup, From, Event, To, ClientName)
    @@ -504,6 +657,11 @@ The SET of Core.Set#SET_AIRBASEs to e

    To :

    + +
  • + +

    ClientName :

    +
diff --git a/docs/Documentation/AI_Cap.html b/docs/Documentation/AI_Cap.html new file mode 100644 index 000000000..a2f0778d5 --- /dev/null +++ b/docs/Documentation/AI_Cap.html @@ -0,0 +1,1673 @@ + + + + + + +
+
+ +
+
+
+
+ +
+

Module AI_Cap

+ +

Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Execute Combat Air Patrol (CAP).

+ +

Banner Image

+ + +
+ +

1) #AICAPZONE class, extends AI.AICap#AIPATROL_ZONE

+ +

The #AICAPZONE class implements the core functions to patrol a Zone by an AI Controllable or Group +and automatically engage any airborne enemies that are within a certain range or within a certain zone.

+ + + +

Process

+ +

The AICAPZONE is assigned a @(Group) and this must be done before the AICAPZONE process can be started using the Start event.

+ +

Process

+ +

The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.

+ +

Process

+ +

This cycle will continue.

+ +

Process

+ +

During the patrol, the AI will detect enemy targets, which are reported through the Detected event.

+ +

Process

+ +

When enemies are detected, the AI will automatically engage the enemy.

+ +

Process

+ +

Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. +When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.

+ +

Process

+ +

1.1) AICAPZONE constructor

+ + + +

1.2) AICAPZONE is a FSM

+ +

Process

+ +

1.2.1) AICAPZONE States

+ +
    +
  • None ( Group ): The process is not started yet.
  • +
  • Patrolling ( Group ): The AI is patrolling the Patrol Zone.
  • +
  • Engaging ( Group ): The AI is engaging the bogeys.
  • +
  • Returning ( Group ): The AI is returning to Base..
  • +
+ +

1.2.2) AICAPZONE Events

+ +
    +
  • Start ( Group ): Start the process.
  • +
  • Route ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
  • +
  • Engage ( Group ): Let the AI engage the bogeys.
  • +
  • RTB ( Group ): Route the AI to the home base.
  • +
  • Detect ( Group ): The AI is detecting targets.
  • +
  • Detected ( Group ): The AI has detected new targets.
  • +
  • Status ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
  • +
+ +

1.3) Set the Range of Engagement

+ +

Range

+ +

An optional range can be set in meters, +that will define when the AI will engage with the detected airborne enemy targets. +The range can be beyond or smaller than the range of the Patrol Zone. +The range is applied at the position of the AI. +Use the method AI.AICap#AICAP_ZONE.SetEngageRange() to define that range.

+ +

1.4) Set the Zone of Engagement

+ +

Zone

+ +

An optional Zone can be set, +that will define when the AI will engage with the detected airborne enemy targets. +Use the method AI.AICap#AICAP_ZONE.SetEngageZone() to define that Zone.

+ +
+ +

API CHANGE HISTORY

+ +

The underlying change log documents the API changes. Please read this carefully. The following notation is used:

+ +
    +
  • Added parts are expressed in bold type face.
  • +
  • Removed parts are expressed in italic type face.
  • +
+ +

Hereby the change log:

+ +

2017-01-15: Initial class and API.

+ +
+ +

AUTHORS and CONTRIBUTIONS

+ +

Contributions:

+ +
    +
  • Quax: Concept, Advice & Testing.
  • +
  • Pikey: Concept, Advice & Testing.
  • +
  • Gunterlund: Test case revision.
  • +
+ +

Authors:

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

Global(s)

+ + + + + + + + + +
AI_CAP_ZONE + +
_NewEngageCapRoute(AIControllable) + +
+

Type AI_CAP_ZONE

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AI_CAP_ZONE.AIControllable +

The Controllable patrolling.

+
AI_CAP_ZONE:Abort() +

Synchronous Event Trigger for Event Abort.

+
AI_CAP_ZONE:Accomplish() +

Synchronous Event Trigger for Event Accomplish.

+
AI_CAP_ZONE.Accomplished + +
AI_CAP_ZONE.ClassName + +
AI_CAP_ZONE:Destroy() +

Synchronous Event Trigger for Event Destroy.

+
AI_CAP_ZONE.DetectUnits + +
AI_CAP_ZONE:Engage() +

Synchronous Event Trigger for Event Engage.

+
AI_CAP_ZONE.EngageRange + +
AI_CAP_ZONE.EngageZone + +
AI_CAP_ZONE.Engaging + +
AI_CAP_ZONE:Fired() +

Synchronous Event Trigger for Event Fired.

+
AI_CAP_ZONE:New(PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed) +

Creates a new AICAPZONE object

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

OnAfter Transition Handler for Event Abort.

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

OnAfter Transition Handler for Event Accomplish.

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

OnAfter Transition Handler for Event Destroy.

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

OnAfter Transition Handler for Event Engage.

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

OnAfter Transition Handler for Event Fired.

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

OnBefore Transition Handler for Event Abort.

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

OnBefore Transition Handler for Event Accomplish.

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

OnBefore Transition Handler for Event Destroy.

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

OnBefore Transition Handler for Event Engage.

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

OnBefore Transition Handler for Event Fired.

+
AI_CAP_ZONE:OnDead(EventData) + +
AI_CAP_ZONE:OnEnterEngaging(Controllable, From, Event, To) +

OnEnter Transition Handler for State Engaging.

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

OnLeave Transition Handler for State Engaging.

+
AI_CAP_ZONE:SetEngageRange(EngageRange) +

Set the Engage Range when the AI will engage with airborne enemies.

+
AI_CAP_ZONE:SetEngageZone(EngageZone) +

Set the Engage Zone which defines where the AI will engage bogies.

+
AI_CAP_ZONE.TargetZone +

The Zone where the patrol needs to be executed.

+
AI_CAP_ZONE:__Abort(Delay) +

Asynchronous Event Trigger for Event Abort.

+
AI_CAP_ZONE:__Accomplish(Delay) +

Asynchronous Event Trigger for Event Accomplish.

+
AI_CAP_ZONE:__Destroy(Delay) +

Asynchronous Event Trigger for Event Destroy.

+
AI_CAP_ZONE:__Engage(Delay) +

Asynchronous Event Trigger for Event Engage.

+
AI_CAP_ZONE:__Fired(Delay) +

Asynchronous Event Trigger for Event Fired.

+
AI_CAP_ZONE:onafterAccomplish(Controllable, From, Event, To) + +
AI_CAP_ZONE:onafterDestroy(Controllable, From, Event, To, EventData) + +
AI_CAP_ZONE:onafterDetected(Controllable, From, Event, To) + +
AI_CAP_ZONE:onafterEngage(Controllable, From, Event, To) + +
AI_CAP_ZONE:onafterStart(Controllable, From, Event, To) +

onafter State Transition for Event Start.

+
AI_CAP_ZONE:onbeforeEngage(Controllable, From, Event, To) + +
+ +

Global(s)

+
+
+ + #AI_CAP_ZONE + +AI_CAP_ZONE + +
+
+ + + +
+
+
+
+ + +_NewEngageCapRoute(AIControllable) + +
+
+ + + +

Parameter

+ +
+
+

Type AI_Cap

+ +

Type AI_CAP_ZONE

+ +

AICAPZONE class

+ +

Field(s)

+
+
+ + Wrapper.Controllable#CONTROLLABLE + +AI_CAP_ZONE.AIControllable + +
+
+ +

The Controllable patrolling.

+ +
+
+
+
+ + +AI_CAP_ZONE:Abort() + +
+
+ +

Synchronous Event Trigger for Event Abort.

+ +
+
+
+
+ + +AI_CAP_ZONE:Accomplish() + +
+
+ +

Synchronous Event Trigger for Event Accomplish.

+ +
+
+
+
+ + #boolean + +AI_CAP_ZONE.Accomplished + +
+
+ + + +
+
+
+
+ + #string + +AI_CAP_ZONE.ClassName + +
+
+ + + +
+
+
+
+ + +AI_CAP_ZONE:Destroy() + +
+
+ +

Synchronous Event Trigger for Event Destroy.

+ +
+
+
+
+ + #boolean + +AI_CAP_ZONE.DetectUnits + +
+
+ + + +
+
+
+
+ + +AI_CAP_ZONE:Engage() + +
+
+ +

Synchronous Event Trigger for Event Engage.

+ +
+
+
+
+ + + +AI_CAP_ZONE.EngageRange + +
+
+ + + +
+
+
+
+ + + +AI_CAP_ZONE.EngageZone + +
+
+ + + +
+
+
+
+ + #boolean + +AI_CAP_ZONE.Engaging + +
+
+ + + +
+
+
+
+ + +AI_CAP_ZONE:Fired() + +
+
+ +

Synchronous Event Trigger for Event Fired.

+ +
+
+
+
+ + +AI_CAP_ZONE:New(PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed) + +
+
+ +

Creates a new AICAPZONE object

+ +

Parameters

+ +

Return value

+ +

#AICAPZONE: +self

+ +
+
+
+
+ + +AI_CAP_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_CAP_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_CAP_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_CAP_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_CAP_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_CAP_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_CAP_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_CAP_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_CAP_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.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_CAP_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_CAP_ZONE:OnDead(EventData) + +
+
+ + + +

Parameter

+ +
+
+
+
+ + +AI_CAP_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_CAP_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_CAP_ZONE:SetEngageRange(EngageRange) + +
+
+ +

Set the Engage Range when the AI will engage with airborne enemies.

+ +

Parameter

+
    +
  • + +

    #number EngageRange : +The Engage Range.

    + +
  • +
+

Return value

+ +

#AICAPZONE: +self

+ +
+
+
+
+ + +AI_CAP_ZONE:SetEngageZone(EngageZone) + +
+
+ +

Set the Engage Zone which defines where the AI will engage bogies.

+ +

Parameter

+
    +
  • + +

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

    + +
  • +
+

Return value

+ +

#AICAPZONE: +self

+ +
+
+
+
+ + Core.Zone#ZONE_BASE + +AI_CAP_ZONE.TargetZone + +
+
+ +

The Zone where the patrol needs to be executed.

+ +
+
+
+
+ + +AI_CAP_ZONE:__Abort(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Abort.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAP_ZONE:__Accomplish(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Accomplish.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAP_ZONE:__Destroy(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Destroy.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAP_ZONE:__Engage(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Engage.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAP_ZONE:__Fired(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Fired.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAP_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_CAP_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_CAP_ZONE:onafterDetected(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_CAP_ZONE:onafterEngage(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_CAP_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_CAP_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_Cas.html b/docs/Documentation/AI_Cas.html new file mode 100644 index 000000000..7bf994b13 --- /dev/null +++ b/docs/Documentation/AI_Cas.html @@ -0,0 +1,1571 @@ + + + + + + +
+
+ +
+
+
+
+ +
+

Module AI_Cas

+ +

Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Provide Close Air Support to friendly ground troops.

+ +

Banner Image

+ + +
+ +

1) #AICASZONE class, extends AI.AIPatrol#AIPATROL_ZONE

+ +

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

+ + +

+The #AICASZONE class implements the core functions to provide Close Air Support in an Engage Zone by an AIR Controllable or Group. +The AICASZONE 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 AICASZONE is assigned a @(Group) and this must be done before the AICASZONE 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 Close Air Support (through the event Engage), the AI will fly towards the Engage Zone. +Any target that is detected in the Engage Zone will be reported and will be destroyed by the AI.

+ +

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 CAS, 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 CAS Zone. +It can be notified to go RTB through the RTB event.

+ +

When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.

+ +

Engage Event

+ +

1.1) AICASZONE constructor

+ + + +

1.2) AICASZONE is a FSM

+ +

Process

+ +

1.2.1) AICASZONE States

+ +
    +
  • None ( Group ): The process is not started yet.
  • +
  • Patrolling ( Group ): The AI is patrolling the Patrol Zone.
  • +
  • Engaging ( Group ): The AI is engaging the targets in the Engage Zone, executing CAS.
  • +
  • Returning ( Group ): The AI is returning to Base..
  • +
+ +

1.2.2) AICASZONE Events

+ +
    +
  • Start ( Group ): Start the process.
  • +
  • Route ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
  • +
  • Engage ( Group ): Engage the AI to provide CAS in the Engage Zone, destroying any target it finds.
  • +
  • RTB ( Group ): Route the AI to the home base.
  • +
  • Detect ( Group ): The AI is detecting targets.
  • +
  • Detected ( Group ): The AI has detected new targets.
  • +
  • Status ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
  • +
+ +
+ +

API CHANGE HISTORY

+ +

The underlying change log documents the API changes. Please read this carefully. The following notation is used:

+ +
    +
  • Added parts are expressed in bold type face.
  • +
  • Removed parts are expressed in italic type face.
  • +
+ +

Hereby the change log:

+ +

2017-01-15: Initial class and API.

+ +
+ +

AUTHORS and CONTRIBUTIONS

+ +

Contributions:

+ +
    +
  • Quax: Concept, Advice & Testing.
  • +
  • Pikey: Concept, Advice & Testing.
  • +
  • Gunterlund: Test case revision.
  • +
+ +

Authors:

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

Global(s)

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

Type AI_CAS_ZONE

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AI_CAS_ZONE.AIControllable +

The Controllable patrolling.

+
AI_CAS_ZONE:Abort() +

Synchronous Event Trigger for Event Abort.

+
AI_CAS_ZONE:Accomplish() +

Synchronous Event Trigger for Event Accomplish.

+
AI_CAS_ZONE.Accomplished + +
AI_CAS_ZONE.ClassName + +
AI_CAS_ZONE:Destroy() +

Synchronous Event Trigger for Event Destroy.

+
AI_CAS_ZONE.DetectUnits + +
AI_CAS_ZONE:Engage() +

Synchronous Event Trigger for Event Engage.

+
AI_CAS_ZONE.EngageZone + +
AI_CAS_ZONE:Fired() +

Synchronous Event Trigger for Event Fired.

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

Creates a new AICASZONE object

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

OnAfter Transition Handler for Event Abort.

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

OnAfter Transition Handler for Event Accomplish.

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

OnAfter Transition Handler for Event Destroy.

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

OnAfter Transition Handler for Event Engage.

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

OnAfter Transition Handler for Event Fired.

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

OnBefore Transition Handler for Event Abort.

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

OnBefore Transition Handler for Event Accomplish.

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

OnBefore Transition Handler for Event Destroy.

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

OnBefore Transition Handler for Event Engage.

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

OnBefore Transition Handler for Event Fired.

+
AI_CAS_ZONE:OnDead(EventData) + +
AI_CAS_ZONE:OnEnterEngaging(Controllable, From, Event, To) +

OnEnter Transition Handler for State Engaging.

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

OnLeave Transition Handler for State Engaging.

+
AI_CAS_ZONE:SetEngageZone(EngageZone) +

Set the Engage Zone where the AI is performing CAS.

+
AI_CAS_ZONE.TargetZone +

The Zone where the patrol needs to be executed.

+
AI_CAS_ZONE:__Abort(Delay) +

Asynchronous Event Trigger for Event Abort.

+
AI_CAS_ZONE:__Accomplish(Delay) +

Asynchronous Event Trigger for Event Accomplish.

+
AI_CAS_ZONE:__Destroy(Delay) +

Asynchronous Event Trigger for Event Destroy.

+
AI_CAS_ZONE:__Engage(Delay) +

Asynchronous Event Trigger for Event Engage.

+
AI_CAS_ZONE:__Fired(Delay) +

Asynchronous Event Trigger for Event Fired.

+
AI_CAS_ZONE:onafterAccomplish(Controllable, From, Event, To) + +
AI_CAS_ZONE:onafterDestroy(Controllable, From, Event, To, EventData) + +
AI_CAS_ZONE:onafterEngage(Controllable, From, Event, To) + +
AI_CAS_ZONE:onafterStart(Controllable, From, Event, To) +

onafter State Transition for Event Start.

+
AI_CAS_ZONE:onbeforeEngage(Controllable, From, Event, To) + +
+ +

Global(s)

+
+
+ + #AI_CAS_ZONE + +AI_CAS_ZONE + +
+
+ + + +
+
+
+
+ + +_NewEngageRoute(AIControllable) + +
+
+ + + +

Parameter

+ +
+
+

Type AI_Cas

+ +

Type AI_CAS_ZONE

+ +

AICASZONE class

+ +

Field(s)

+
+
+ + Wrapper.Controllable#CONTROLLABLE + +AI_CAS_ZONE.AIControllable + +
+
+ +

The Controllable patrolling.

+ +
+
+
+
+ + +AI_CAS_ZONE:Abort() + +
+
+ +

Synchronous Event Trigger for Event Abort.

+ +
+
+
+
+ + +AI_CAS_ZONE:Accomplish() + +
+
+ +

Synchronous Event Trigger for Event Accomplish.

+ +
+
+
+
+ + #boolean + +AI_CAS_ZONE.Accomplished + +
+
+ + + +
+
+
+
+ + #string + +AI_CAS_ZONE.ClassName + +
+
+ + + +
+
+
+
+ + +AI_CAS_ZONE:Destroy() + +
+
+ +

Synchronous Event Trigger for Event Destroy.

+ +
+
+
+
+ + #boolean + +AI_CAS_ZONE.DetectUnits + +
+
+ + + +
+
+
+
+ + +AI_CAS_ZONE:Engage() + +
+
+ +

Synchronous Event Trigger for Event Engage.

+ +
+
+
+
+ + + +AI_CAS_ZONE.EngageZone + +
+
+ + + +
+
+
+
+ + +AI_CAS_ZONE:Fired() + +
+
+ +

Synchronous Event Trigger for Event Fired.

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

Creates a new AICASZONE object

+ +

Parameters

+ +

Return value

+ +

#AICASZONE: +self

+ +
+
+
+
+ + +AI_CAS_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_CAS_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_CAS_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_CAS_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_CAS_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_CAS_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_CAS_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_CAS_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_CAS_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.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_CAS_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_CAS_ZONE:OnDead(EventData) + +
+
+ + + +

Parameter

+ +
+
+
+
+ + +AI_CAS_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_CAS_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_CAS_ZONE:SetEngageZone(EngageZone) + +
+
+ +

Set the Engage Zone where the AI is performing CAS.

+ + +

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 CAS.

    + +
  • +
+

Return value

+ +

#AICASZONE: +self

+ +
+
+
+
+ + Core.Zone#ZONE_BASE + +AI_CAS_ZONE.TargetZone + +
+
+ +

The Zone where the patrol needs to be executed.

+ +
+
+
+
+ + +AI_CAS_ZONE:__Abort(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Abort.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAS_ZONE:__Accomplish(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Accomplish.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAS_ZONE:__Destroy(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Destroy.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAS_ZONE:__Engage(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Engage.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAS_ZONE:__Fired(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Fired.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_CAS_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_CAS_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_CAS_ZONE:onafterEngage(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_CAS_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_CAS_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_Patrol.html b/docs/Documentation/AI_Patrol.html new file mode 100644 index 000000000..78927fa78 --- /dev/null +++ b/docs/Documentation/AI_Patrol.html @@ -0,0 +1,2353 @@ + + + + + + +
+
+ +
+
+
+
+ +
+

Module AI_Patrol

+ +

Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Air Patrolling or Staging.

+ +

Banner Image

+ + +
+ +

1) #AIPATROLZONE class, extends Core.Fsm#FSM_CONTROLLABLE

+ +

The #AIPATROLZONE class implements the core functions to patrol a Zone by an AI Controllable or Group.

+ + + +

Process

+ +

The AIPATROLZONE is assigned a @(Group) and this must be done before the AIPATROLZONE process can be started using the Start event.

+ +

Process

+ +

The AI will fly towards the random 3D point within the patrol zone, using a random speed within the given altitude and speed limits. +Upon arrival at the 3D point, a new random 3D point will be selected within the patrol zone using the given limits.

+ +

Process

+ +

This cycle will continue.

+ +

Process

+ +

During the patrol, the AI will detect enemy targets, which are reported through the Detected event.

+ +

Process

+ +

-- Note that the enemy is not engaged! To model enemy engagement, either tailor the Detected event, or +use derived AI_ classes to model AI offensive or defensive behaviour.

+ +

Process

+ +

Until a fuel or damage treshold has been reached by the AI, or when the AI is commanded to RTB. +When the fuel treshold has been reached, the airplane will fly towards the nearest friendly airbase and will land.

+ +

Process

+ +

1.1) AIPATROLZONE constructor

+ + + +

1.2) AIPATROLZONE is a FSM

+ +

Process

+ +

1.2.1) AIPATROLZONE States

+ +
    +
  • None ( Group ): The process is not started yet.
  • +
  • Patrolling ( Group ): The AI is patrolling the Patrol Zone.
  • +
  • Returning ( Group ): The AI is returning to Base..
  • +
+ +

1.2.2) AIPATROLZONE Events

+ +
    +
  • Start ( Group ): Start the process.
  • +
  • Route ( Group ): Route the AI to a new random 3D point within the Patrol Zone.
  • +
  • RTB ( Group ): Route the AI to the home base.
  • +
  • Detect ( Group ): The AI is detecting targets.
  • +
  • Detected ( Group ): The AI has detected new targets.
  • +
  • Status ( Group ): The AI is checking status (fuel and damage). When the tresholds have been reached, the AI will RTB.
  • +
+ +

1.3) Set or Get the AI controllable

+ + + +

1.4) Set the Speed and Altitude boundaries of the AI controllable

+ + + +

1.5) Manage the detection process of the AI controllable

+ +

The detection process of the AI controllable can be manipulated. +Detection requires an amount of CPU power, which has an impact on your mission performance. +Only put detection on when absolutely necessary, and the frequency of the detection can also be set.

+ + + +

The detection frequency can be set with AIPATROLZONE.SetDetectionInterval( seconds ), where the amount of seconds specify how much seconds will be waited before the next detection. +Use the method AIPATROLZONE.GetDetectedUnits() to obtain a list of the Units detected by the AI.

+ +

The detection can be filtered to potential targets in a specific zone. +Use the method AIPATROLZONE.SetDetectionZone() to set the zone where targets need to be detected. +Note that when the zone is too far away, or the AI is not heading towards the zone, or the AI is too high, no targets may be detected +according the weather conditions.

+ +

1.6) Manage the "out of fuel" in the AIPATROLZONE

+ +

When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base. +Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. +When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, +while a new AI is targetted to the AIPATROLZONE. +Once the time is finished, the old AI will return to the base. +Use the method AIPATROLZONE.ManageFuel() to have this proces in place.

+ +

1.7) Manage "damage" behaviour of the AI in the AIPATROLZONE

+ +

When the AI is damaged, it is required that a new AIControllable is started. However, damage cannon be foreseen early on. +Therefore, when the damage treshold is reached, the AI will return immediately to the home base (RTB). +Use the method AIPATROLZONE.ManageDamage() to have this proces in place.

+ +
+ +

OPEN ISSUES

+ +

2017-01-17: When Spawned AI is located at an airbase, it will be routed first back to the airbase after take-off.

+ +

2016-01-17: + -- Fixed problem with AI returning to base too early and unexpected. + -- ReSpawning of AI will reset the AI_PATROL and derived classes. + -- Checked the correct workings of SCHEDULER, and it DOES work correctly.

+ +
+ +

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-17: Rename of class: AI_PATROL_ZONE is the new name for the old AI_PATROLZONE.

+ +

2017-01-15: Complete revision. AIPATROLZONE is the base class for other AI_PATROL like classes.

+ +

2016-09-01: Initial class and API.

+ +
+ +

AUTHORS and CONTRIBUTIONS

+ +

Contributions:

+ +
    +
  • Dutch_Baron: Working together with James has resulted in the creation of the AI_BALANCER class. James has shared his ideas on balancing AI with air units, and together we made a first design which you can use now :-)
  • +
  • Pikey: Testing and API concept review.
  • +
+ +

Authors:

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

Global(s)

+ + + + + +
AI_PATROL_ZONE + +
+

Type AI_PATROL_ZONE

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AI_PATROL_ZONE.AIControllable +

The Controllable patrolling.

+
AI_PATROL_ZONE.CheckStatus + +
AI_PATROL_ZONE.ClassName + +
AI_PATROL_ZONE.CoordTest + +
AI_PATROL_ZONE:Detect() +

Synchronous Event Trigger for Event Detect.

+
AI_PATROL_ZONE.DetectInterval + +
AI_PATROL_ZONE.DetectUnits + +
AI_PATROL_ZONE.DetectZone + +
AI_PATROL_ZONE:Detected() +

Synchronous Event Trigger for Event Detected.

+
AI_PATROL_ZONE.DetectedUnits + +
AI_PATROL_ZONE:GetDetectedUnits() +

Gets a list of Wrapper.Unit#UNITs that were detected by the AI.

+
AI_PATROL_ZONE:ManageDamage(PatrolDamageTreshold) +

When the AI is damaged beyond a certain treshold, it is required that the AI returns to the home base.

+
AI_PATROL_ZONE:ManageFuel(PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime) +

When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base.

+
AI_PATROL_ZONE:New(PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed) +

Creates a new AIPATROLZONE object

+
AI_PATROL_ZONE:OnAfterDetect(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Detect.

+
AI_PATROL_ZONE:OnAfterDetected(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Detected.

+
AI_PATROL_ZONE:OnAfterRTB(Controllable, From, Event, To) +

OnAfter Transition Handler for Event RTB.

+
AI_PATROL_ZONE:OnAfterRoute(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Route.

+
AI_PATROL_ZONE:OnAfterStart(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Start.

+
AI_PATROL_ZONE:OnAfterStatus(Controllable, From, Event, To) +

OnAfter Transition Handler for Event Status.

+
AI_PATROL_ZONE:OnBeforeDetect(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Detect.

+
AI_PATROL_ZONE:OnBeforeDetected(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Detected.

+
AI_PATROL_ZONE:OnBeforeRTB(Controllable, From, Event, To) +

OnBefore Transition Handler for Event RTB.

+
AI_PATROL_ZONE:OnBeforeRoute(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Route.

+
AI_PATROL_ZONE:OnBeforeStart(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Start.

+
AI_PATROL_ZONE:OnBeforeStatus(Controllable, From, Event, To) +

OnBefore Transition Handler for Event Status.

+
AI_PATROL_ZONE:OnEnterPatrolling(Controllable, From, Event, To) +

OnEnter Transition Handler for State Patrolling.

+
AI_PATROL_ZONE:OnEnterReturning(Controllable, From, Event, To) +

OnEnter Transition Handler for State Returning.

+
AI_PATROL_ZONE:OnLeavePatrolling(Controllable, From, Event, To) +

OnLeave Transition Handler for State Patrolling.

+
AI_PATROL_ZONE:OnLeaveReturning(Controllable, From, Event, To) +

OnLeave Transition Handler for State Returning.

+
AI_PATROL_ZONE.PatrolCeilingAltitude +

The highest altitude in meters where to execute the patrol.

+
AI_PATROL_ZONE.PatrolDamageTreshold + +
AI_PATROL_ZONE.PatrolFloorAltitude +

The lowest altitude in meters where to execute the patrol.

+
AI_PATROL_ZONE.PatrolFuelTresholdPercentage + +
AI_PATROL_ZONE.PatrolManageDamage + +
AI_PATROL_ZONE.PatrolManageFuel + +
AI_PATROL_ZONE.PatrolMaxSpeed +

The maximum speed of the Controllable in km/h.

+
AI_PATROL_ZONE.PatrolMinSpeed +

The minimum speed of the Controllable in km/h.

+
AI_PATROL_ZONE.PatrolOutOfFuelOrbitTime + +
AI_PATROL_ZONE.PatrolZone +

The Zone where the patrol needs to be executed.

+
AI_PATROL_ZONE:RTB() +

Synchronous Event Trigger for Event RTB.

+
AI_PATROL_ZONE:Route() +

Synchronous Event Trigger for Event Route.

+
AI_PATROL_ZONE:SetAltitude(PatrolFloorAltitude, PatrolCeilingAltitude) +

Sets the floor and ceiling altitude of the patrol.

+
AI_PATROL_ZONE:SetDetectionInterval(Seconds) +

Set the interval in seconds between each detection executed by the AI.

+
AI_PATROL_ZONE:SetDetectionOff() +

Set the detection off.

+
AI_PATROL_ZONE:SetDetectionOn() +

Set the detection on.

+
AI_PATROL_ZONE:SetDetectionZone(DetectionZone) +

Set the detection zone where the AI is detecting targets.

+
AI_PATROL_ZONE:SetSpeed(PatrolMinSpeed, PatrolMaxSpeed) +

Sets (modifies) the minimum and maximum speed of the patrol.

+
AI_PATROL_ZONE:Start() +

Synchronous Event Trigger for Event Start.

+
AI_PATROL_ZONE:Status() +

Synchronous Event Trigger for Event Status.

+
AI_PATROL_ZONE._NewPatrolRoute(AIControllable, self) + +
AI_PATROL_ZONE:__Detect(Delay) +

Asynchronous Event Trigger for Event Detect.

+
AI_PATROL_ZONE:__Detected(Delay) +

Asynchronous Event Trigger for Event Detected.

+
AI_PATROL_ZONE:__RTB(Delay) +

Asynchronous Event Trigger for Event RTB.

+
AI_PATROL_ZONE:__Route(Delay) +

Asynchronous Event Trigger for Event Route.

+
AI_PATROL_ZONE:__Start(Delay) +

Asynchronous Event Trigger for Event Start.

+
AI_PATROL_ZONE:__Status(Delay) +

Asynchronous Event Trigger for Event Status.

+
AI_PATROL_ZONE:onafterDetect(Controllable, From, Event, To) + +
AI_PATROL_ZONE:onafterRTB() + +
AI_PATROL_ZONE:onafterRoute(Controllable, From, Event, To) +

Defines a new patrol route using the Process_PatrolZone parameters and settings.

+
AI_PATROL_ZONE:onafterStart(Controllable, From, Event, To) +

Defines a new patrol route using the Process_PatrolZone parameters and settings.

+
AI_PATROL_ZONE:onafterStatus() + +
AI_PATROL_ZONE:onbeforeDetect(Controllable, From, Event, To) + +
AI_PATROL_ZONE:onbeforeStatus() + +
+ +

Global(s)

+
+
+ + #AI_PATROL_ZONE + +AI_PATROL_ZONE + +
+
+ + + +
+
+

Type AI_Patrol

+ +

Type AI_PATROL_ZONE

+ +

AIPATROLZONE class

+ +

Field(s)

+
+
+ + Wrapper.Controllable#CONTROLLABLE + +AI_PATROL_ZONE.AIControllable + +
+
+ +

The Controllable patrolling.

+ +
+
+
+
+ + #boolean + +AI_PATROL_ZONE.CheckStatus + +
+
+ + + +
+
+
+
+ + #string + +AI_PATROL_ZONE.ClassName + +
+
+ + + +
+
+
+
+ + Functional.Spawn#SPAWN + +AI_PATROL_ZONE.CoordTest + +
+
+ + + +
+
+
+
+ + +AI_PATROL_ZONE:Detect() + +
+
+ +

Synchronous Event Trigger for Event Detect.

+ +
+
+
+
+ + + +AI_PATROL_ZONE.DetectInterval + +
+
+ + + +
+
+
+
+ + #boolean + +AI_PATROL_ZONE.DetectUnits + +
+
+ + + +
+
+
+
+ + + +AI_PATROL_ZONE.DetectZone + +
+
+ + + +
+
+
+
+ + +AI_PATROL_ZONE:Detected() + +
+
+ +

Synchronous Event Trigger for Event Detected.

+ +
+
+
+
+ + + +AI_PATROL_ZONE.DetectedUnits + +
+
+ + + + +

This table contains the targets detected during patrol.

+ +
+
+
+
+ + +AI_PATROL_ZONE:GetDetectedUnits() + +
+
+ +

Gets a list of Wrapper.Unit#UNITs that were detected by the AI.

+ + +

No filtering is applied, so, ANY detected UNIT can be in this list. +It is up to the mission designer to use the Unit class and methods to filter the targets.

+ +

Return value

+ +

#table: +The list of Wrapper.Unit#UNITs

+ +
+
+
+
+ + +AI_PATROL_ZONE:ManageDamage(PatrolDamageTreshold) + +
+
+ +

When the AI is damaged beyond a certain treshold, it is required that the AI returns to the home base.

+ + +

However, damage cannot be foreseen early on. +Therefore, when the damage treshold is reached, +the AI will return immediately to the home base (RTB). +Note that for groups, the average damage of the complete group will be calculated. +So, in a group of 4 airplanes, 2 lost and 2 with damage 0.2, the damage treshold will be 0.25.

+ +

Parameter

+
    +
  • + +

    #number PatrolDamageTreshold : +The treshold in percentage (between 0 and 1) when the AI is considered to be damaged.

    + +
  • +
+

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:ManageFuel(PatrolFuelTresholdPercentage, PatrolOutOfFuelOrbitTime) + +
+
+ +

When the AI is out of fuel, it is required that a new AI is started, before the old AI can return to the home base.

+ + +

Therefore, with a parameter and a calculation of the distance to the home base, the fuel treshold is calculated. +When the fuel treshold is reached, the AI will continue for a given time its patrol task in orbit, while a new AIControllable is targetted to the AIPATROLZONE. +Once the time is finished, the old AI will return to the base.

+ +

Parameters

+
    +
  • + +

    #number PatrolFuelTresholdPercentage : +The treshold in percentage (between 0 and 1) when the AIControllable is considered to get out of fuel.

    + +
  • +
  • + +

    #number PatrolOutOfFuelOrbitTime : +The amount of seconds the out of fuel AIControllable will orbit before returning to the base.

    + +
  • +
+

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:New(PatrolZone, PatrolFloorAltitude, PatrolCeilingAltitude, PatrolMinSpeed, PatrolMaxSpeed) + +
+
+ +

Creates a new AIPATROLZONE object

+ +

Parameters

+ +

Return value

+ +

#AIPATROLZONE: +self

+ +

Usage:

+
-- Define a new AI_PATROL_ZONE Object. This PatrolArea will patrol an AIControllable within PatrolZone between 3000 and 6000 meters, with a variying speed between 600 and 900 km/h.
+PatrolZone = ZONE:New( 'PatrolZone' )
+PatrolSpawn = SPAWN:New( 'Patrol Group' )
+PatrolArea = AI_PATROL_ZONE:New( PatrolZone, 3000, 6000, 600, 900 )
+ +
+
+
+
+ + +AI_PATROL_ZONE:OnAfterDetect(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Detect.

+ +

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_PATROL_ZONE:OnAfterDetected(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Detected.

+ +

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_PATROL_ZONE:OnAfterRTB(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event RTB.

+ +

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_PATROL_ZONE:OnAfterRoute(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Route.

+ +

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_PATROL_ZONE:OnAfterStart(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler 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_PATROL_ZONE:OnAfterStatus(Controllable, From, Event, To) + +
+
+ +

OnAfter Transition Handler for Event Status.

+ +

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_PATROL_ZONE:OnBeforeDetect(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Detect.

+ +

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_PATROL_ZONE:OnBeforeDetected(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Detected.

+ +

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_PATROL_ZONE:OnBeforeRTB(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event RTB.

+ +

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_PATROL_ZONE:OnBeforeRoute(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Route.

+ +

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_PATROL_ZONE:OnBeforeStart(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler 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.

    + +
  • +
+

Return value

+ +

#boolean: +Return false to cancel Transition.

+ +
+
+
+
+ + +AI_PATROL_ZONE:OnBeforeStatus(Controllable, From, Event, To) + +
+
+ +

OnBefore Transition Handler for Event Status.

+ +

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_PATROL_ZONE:OnEnterPatrolling(Controllable, From, Event, To) + +
+
+ +

OnEnter Transition Handler for State Patrolling.

+ +

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_PATROL_ZONE:OnEnterReturning(Controllable, From, Event, To) + +
+
+ +

OnEnter Transition Handler for State Returning.

+ +

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_PATROL_ZONE:OnLeavePatrolling(Controllable, From, Event, To) + +
+
+ +

OnLeave Transition Handler for State Patrolling.

+ +

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_PATROL_ZONE:OnLeaveReturning(Controllable, From, Event, To) + +
+
+ +

OnLeave Transition Handler for State Returning.

+ +

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.

+ +
+
+
+
+ + Dcs.DCSTypes#Altitude + +AI_PATROL_ZONE.PatrolCeilingAltitude + +
+
+ +

The highest altitude in meters where to execute the patrol.

+ +
+
+
+
+ + + +AI_PATROL_ZONE.PatrolDamageTreshold + +
+
+ + + +
+
+
+
+ + Dcs.DCSTypes#Altitude + +AI_PATROL_ZONE.PatrolFloorAltitude + +
+
+ +

The lowest altitude in meters where to execute the patrol.

+ +
+
+
+
+ + + +AI_PATROL_ZONE.PatrolFuelTresholdPercentage + +
+
+ + + +
+
+
+
+ + #boolean + +AI_PATROL_ZONE.PatrolManageDamage + +
+
+ + + +
+
+
+
+ + #boolean + +AI_PATROL_ZONE.PatrolManageFuel + +
+
+ + + +
+
+
+
+ + Dcs.DCSTypes#Speed + +AI_PATROL_ZONE.PatrolMaxSpeed + +
+
+ +

The maximum speed of the Controllable in km/h.

+ +
+
+
+
+ + Dcs.DCSTypes#Speed + +AI_PATROL_ZONE.PatrolMinSpeed + +
+
+ +

The minimum speed of the Controllable in km/h.

+ +
+
+
+
+ + + +AI_PATROL_ZONE.PatrolOutOfFuelOrbitTime + +
+
+ + + +
+
+
+
+ + Core.Zone#ZONE_BASE + +AI_PATROL_ZONE.PatrolZone + +
+
+ +

The Zone where the patrol needs to be executed.

+ +
+
+
+
+ + +AI_PATROL_ZONE:RTB() + +
+
+ +

Synchronous Event Trigger for Event RTB.

+ +
+
+
+
+ + +AI_PATROL_ZONE:Route() + +
+
+ +

Synchronous Event Trigger for Event Route.

+ +
+
+
+
+ + +AI_PATROL_ZONE:SetAltitude(PatrolFloorAltitude, PatrolCeilingAltitude) + +
+
+ +

Sets the floor and ceiling altitude of the patrol.

+ +

Parameters

+
    +
  • + +

    Dcs.DCSTypes#Altitude PatrolFloorAltitude : +The lowest altitude in meters where to execute the patrol.

    + +
  • +
  • + +

    Dcs.DCSTypes#Altitude PatrolCeilingAltitude : +The highest altitude in meters where to execute the patrol.

    + +
  • +
+

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:SetDetectionInterval(Seconds) + +
+
+ +

Set the interval in seconds between each detection executed by the AI.

+ + +

The list of already detected targets will be kept and updated. +Newly detected targets will be added, but already detected targets that were +not detected in this cycle, will NOT be removed! +The default interval is 30 seconds.

+ +

Parameter

+
    +
  • + +

    #number Seconds : +The interval in seconds.

    + +
  • +
+

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:SetDetectionOff() + +
+
+ +

Set the detection off.

+ + +

The AI will NOT detect for targets. +However, the list of already detected targets will be kept and can be enquired!

+ +

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:SetDetectionOn() + +
+
+ +

Set the detection on.

+ + +

The AI will detect for targets.

+ +

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:SetDetectionZone(DetectionZone) + +
+
+ +

Set the detection zone where the AI is detecting targets.

+ +

Parameter

+
    +
  • + +

    Core.Zone#ZONE DetectionZone : +The zone where to detect targets.

    + +
  • +
+

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:SetSpeed(PatrolMinSpeed, PatrolMaxSpeed) + +
+
+ +

Sets (modifies) the minimum and maximum speed of the patrol.

+ +

Parameters

+ +

Return value

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:Start() + +
+
+ +

Synchronous Event Trigger for Event Start.

+ +
+
+
+
+ + +AI_PATROL_ZONE:Status() + +
+
+ +

Synchronous Event Trigger for Event Status.

+ +
+
+
+
+ + +AI_PATROL_ZONE._NewPatrolRoute(AIControllable, self) + +
+
+ + + +

Parameters

+
    +
  • + +

    Wrapper.Controllable#CONTROLLABLE AIControllable : +This statis method is called from the route path within the last task at the last waaypoint of the Controllable. +Note that this method is required, as triggers the next route when patrolling for the Controllable.

    + +
  • +
  • + +

    self :

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:__Detect(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Detect.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:__Detected(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Detected.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:__RTB(Delay) + +
+
+ +

Asynchronous Event Trigger for Event RTB.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:__Route(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Route.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:__Start(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Start.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:__Status(Delay) + +
+
+ +

Asynchronous Event Trigger for Event Status.

+ +

Parameter

+
    +
  • + +

    #number Delay : +The delay in seconds.

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:onafterDetect(Controllable, From, Event, To) + +
+
+ + + +

Parameters

+
    +
  • + +

    Controllable :

    + +
  • +
  • + +

    From :

    + +
  • +
  • + +

    Event :

    + +
  • +
  • + +

    To :

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:onafterRTB() + +
+
+ + + +
+
+
+
+ + +AI_PATROL_ZONE:onafterRoute(Controllable, From, Event, To) + +
+
+ +

Defines a new patrol route using the Process_PatrolZone parameters and settings.

+ +

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_PATROL_ZONE:onafterStart(Controllable, From, Event, To) + +
+
+ +

Defines a new patrol route using the Process_PatrolZone parameters and settings.

+ +

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

+ +

#AIPATROLZONE: +self

+ +
+
+
+
+ + +AI_PATROL_ZONE:onafterStatus() + +
+
+ + + +
+
+
+
+ + +AI_PATROL_ZONE:onbeforeDetect(Controllable, From, Event, To) + +
+
+ + + +

Parameters

+
    +
  • + +

    Controllable :

    + +
  • +
  • + +

    From :

    + +
  • +
  • + +

    Event :

    + +
  • +
  • + +

    To :

    + +
  • +
+
+
+
+
+ + +AI_PATROL_ZONE:onbeforeStatus() + +
+
+ + + +
+
+ +
+ +
+ + diff --git a/docs/Documentation/Account.html b/docs/Documentation/Account.html index 8505a004e..51eb80f32 100644 --- a/docs/Documentation/Account.html +++ b/docs/Documentation/Account.html @@ -18,6 +18,9 @@
diff --git a/docs/Documentation/Database.html b/docs/Documentation/Database.html index 1f2bacb64..cd538dd3f 100644 --- a/docs/Documentation/Database.html +++ b/docs/Documentation/Database.html @@ -18,6 +18,9 @@ + + +
+
+ + + +FSM.CallScheduler + +
+
+ + +
@@ -1115,6 +1191,20 @@ The To state.

+ +
+
+
+ + + +FSM.Events + +
+
+ + +
@@ -1315,6 +1405,20 @@ A string containing the start state.

#FSM:

+ +
+
+
+ + + +FSM.Scores + +
+
+ + +
@@ -1343,6 +1447,48 @@ A string defining the start state.

+ +FSM._EndStates + +
+
+ + + +
+
+
+
+ + + +FSM._Processes + +
+
+ + + +
+
+
+
+ + + +FSM._Scores + +
+
+ + + +
+
+
+
+ + #string FSM._StartState @@ -1351,6 +1497,20 @@ A string defining the start state.

+ +
+
+
+ + + +FSM._Transitions + +
+
+ + +
@@ -1622,7 +1782,6 @@ A string defining the start state.

- FSM.current @@ -1631,6 +1790,20 @@ A string defining the start state.

+ +
+
+
+ + + +FSM.endstates + +
+
+ + +
@@ -1652,6 +1825,33 @@ A string defining the start state.

+ +
+
+
+ + +FSM.options + +
+
+ + + +
+
+
+
+ + + +FSM.subs + +
+
+ + +
diff --git a/docs/Documentation/Group.html b/docs/Documentation/Group.html index 6dcce1c17..bc2c97e39 100644 --- a/docs/Documentation/Group.html +++ b/docs/Documentation/Group.html @@ -18,6 +18,9 @@
  • AI_Balancer
  • +
  • AI_Cap
  • +
  • AI_Cas
  • +
  • AI_Patrol
  • Account
  • Airbase
  • AirbasePolice
  • @@ -41,7 +44,6 @@
  • MissileTrainer
  • Mission
  • Object
  • -
  • Patrol
  • Point
  • Positionable
  • Process_JTAC
  • @@ -541,6 +543,12 @@ In order to keep the credibility of the the author, I want to emphasize that the

    Type POINT_VEC3.RoutePointAction

    + + + +
    POINT_VEC3.RoutePointAction.FromParkingArea +

    "From Parking Area"

    +
    POINT_VEC3.RoutePointAction.TurningPoint

    "Turning Point"

    @@ -561,6 +569,12 @@ In order to keep the credibility of the the author, I want to emphasize that the

    Type POINT_VEC3.RoutePointType

    + + + + + + + + @@ -425,6 +433,34 @@ The POSITIONABLE is not existing or alive.

    + +POSITIONABLE:GetPointVec3() + +
    +
    + +

    Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission.

    + +

    Return values

    +
      +
    1. + +

      Core.Point#POINT_VEC3: +The 3D point vector of the POSITIONABLE.

      + +
    2. +
    3. + +

      #nil: +The POSITIONABLE is not existing or alive.

      + +
    4. +
    +
    +
    +
    +
    + POSITIONABLE:GetPositionVec3() @@ -609,6 +645,9 @@ The POSITIONABLE is not existing or alive.

    Returns true if the POSITIONABLE is in the air.

    + +

    Polymorphic, is overridden in GROUP and UNIT.

    +

    Return values

    1. diff --git a/docs/Documentation/Process_JTAC.html b/docs/Documentation/Process_JTAC.html index b838cdfb0..194cee4de 100644 --- a/docs/Documentation/Process_JTAC.html +++ b/docs/Documentation/Process_JTAC.html @@ -18,6 +18,9 @@
    + + + + @@ -1600,6 +1608,20 @@ The added BASE Object.

    Core.Base#BASE: The added BASE Object.

    + + +
    +
    + + Core.Scheduler#SCHEDULER + +SET_BASE.CallScheduler + +
    +
    + + +
    diff --git a/docs/Documentation/Smoke.html b/docs/Documentation/Smoke.html index b66891f51..5816894a1 100644 --- a/docs/Documentation/Smoke.html +++ b/docs/Documentation/Smoke.html @@ -18,6 +18,9 @@
    diff --git a/docs/Documentation/Static.html b/docs/Documentation/Static.html index a59aa4a26..4be12f0c8 100644 --- a/docs/Documentation/Static.html +++ b/docs/Documentation/Static.html @@ -18,6 +18,9 @@
    + + + + @@ -292,6 +300,12 @@ If you want to obtain the complete 3D position including ori� + + + + @@ -996,6 +1010,24 @@ The DCS Unit is not existing or alive.

    + +UNIT:GetUnits() + +
    +
    + +

    Returns the UNIT in a UNIT list of one element.

    + +

    Return value

    + +

    #list: +Wrapper.Unit#UNIT> The UNITs wrappers.

    + +
    +
    +
    +
    + UNIT:HasSEAD() @@ -1060,6 +1092,34 @@ The DCS Unit is not existing or alive.

    + +UNIT:InAir() + +
    +
    + +

    Returns true if the UNIT is in the air.

    + +

    Return values

    +
      +
    1. + +

      #boolean: +true if in the air.

      + +
    2. +
    3. + +

      #nil: +The UNIT is not existing or alive.

      + +
    4. +
    +
    +
    +
    +
    + UNIT:IsActive() @@ -1505,6 +1565,8 @@ The name of the DCS unit.

    +

    Type list

    + diff --git a/docs/Documentation/Utils.html b/docs/Documentation/Utils.html index 257221207..e0be30322 100644 --- a/docs/Documentation/Utils.html +++ b/docs/Documentation/Utils.html @@ -18,6 +18,9 @@
    + + + + + + + + + + + + @@ -107,7 +167,7 @@ @@ -210,12 +270,6 @@ - - - - diff --git a/docs/Documentation/routines.html b/docs/Documentation/routines.html index 01e4bbccc..f59f1eb4f 100644 --- a/docs/Documentation/routines.html +++ b/docs/Documentation/routines.html @@ -18,6 +18,9 @@
    • AI_Balancer
    • +
    • AI_Cap
    • +
    • AI_Cas
    • +
    • AI_Patrol
    • Account
    • Airbase
    • AirbasePolice
    • @@ -41,7 +44,6 @@
    • MissileTrainer
    • Mission
    • Object
    • -
    • Patrol
    • Point
    • Positionable
    • Process_JTAC
    • diff --git a/docs/Presentations/AI_BALANCER.pptx b/docs/Presentations/AI_BALANCER.pptx new file mode 100644 index 000000000..39ba7e6a5 Binary files /dev/null and b/docs/Presentations/AI_BALANCER.pptx differ diff --git a/docs/Presentations/AI_BALANCER/Dia10.JPG b/docs/Presentations/AI_BALANCER/Dia10.JPG new file mode 100644 index 000000000..e713661c4 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia10.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia11.JPG b/docs/Presentations/AI_BALANCER/Dia11.JPG new file mode 100644 index 000000000..1167fb811 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia11.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia12.JPG b/docs/Presentations/AI_BALANCER/Dia12.JPG new file mode 100644 index 000000000..f91a2fcbb Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia12.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia13.JPG b/docs/Presentations/AI_BALANCER/Dia13.JPG new file mode 100644 index 000000000..6b9350c1e Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia13.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia14.JPG b/docs/Presentations/AI_BALANCER/Dia14.JPG new file mode 100644 index 000000000..e90ad1b0e Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia14.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia15.JPG b/docs/Presentations/AI_BALANCER/Dia15.JPG new file mode 100644 index 000000000..fa5e59f92 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia15.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia16.JPG b/docs/Presentations/AI_BALANCER/Dia16.JPG new file mode 100644 index 000000000..ed220b049 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia16.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia17.JPG b/docs/Presentations/AI_BALANCER/Dia17.JPG new file mode 100644 index 000000000..13a4b8d0c Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia17.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia18.JPG b/docs/Presentations/AI_BALANCER/Dia18.JPG new file mode 100644 index 000000000..e3db039e2 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia18.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia3.JPG b/docs/Presentations/AI_BALANCER/Dia3.JPG new file mode 100644 index 000000000..f17322dd9 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia3.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia4.JPG b/docs/Presentations/AI_BALANCER/Dia4.JPG new file mode 100644 index 000000000..fe3378f0f Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia4.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia5.JPG b/docs/Presentations/AI_BALANCER/Dia5.JPG new file mode 100644 index 000000000..cf520aead Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia5.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia6.JPG b/docs/Presentations/AI_BALANCER/Dia6.JPG new file mode 100644 index 000000000..768fe1f2b Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia6.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia7.JPG b/docs/Presentations/AI_BALANCER/Dia7.JPG new file mode 100644 index 000000000..513786720 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia7.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia8.JPG b/docs/Presentations/AI_BALANCER/Dia8.JPG new file mode 100644 index 000000000..c49de1bf7 Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia8.JPG differ diff --git a/docs/Presentations/AI_BALANCER/Dia9.JPG b/docs/Presentations/AI_BALANCER/Dia9.JPG new file mode 100644 index 000000000..6eaaeb98b Binary files /dev/null and b/docs/Presentations/AI_BALANCER/Dia9.JPG differ diff --git a/docs/Presentations/AI_Balancer/Dia1.JPG b/docs/Presentations/AI_Balancer/Dia1.JPG new file mode 100644 index 000000000..eca62afff Binary files /dev/null and b/docs/Presentations/AI_Balancer/Dia1.JPG differ diff --git a/docs/Presentations/AI_Balancer/Dia2.JPG b/docs/Presentations/AI_Balancer/Dia2.JPG new file mode 100644 index 000000000..5f439e6b4 Binary files /dev/null and b/docs/Presentations/AI_Balancer/Dia2.JPG differ diff --git a/docs/Presentations/AI_CAP.pptx b/docs/Presentations/AI_CAP.pptx new file mode 100644 index 000000000..17395cd37 Binary files /dev/null and b/docs/Presentations/AI_CAP.pptx differ diff --git a/docs/Presentations/AI_CAP/Dia1.JPG b/docs/Presentations/AI_CAP/Dia1.JPG new file mode 100644 index 000000000..7b1c0d8dc Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia1.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia10.JPG b/docs/Presentations/AI_CAP/Dia10.JPG new file mode 100644 index 000000000..c49f26545 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia10.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia11.JPG b/docs/Presentations/AI_CAP/Dia11.JPG new file mode 100644 index 000000000..0e7e53142 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia11.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia12.JPG b/docs/Presentations/AI_CAP/Dia12.JPG new file mode 100644 index 000000000..b9c42741b Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia12.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia13.JPG b/docs/Presentations/AI_CAP/Dia13.JPG new file mode 100644 index 000000000..efedca7b0 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia13.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia14.JPG b/docs/Presentations/AI_CAP/Dia14.JPG new file mode 100644 index 000000000..2913091b7 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia14.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia2.JPG b/docs/Presentations/AI_CAP/Dia2.JPG new file mode 100644 index 000000000..1b1492d6c Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia2.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia3.JPG b/docs/Presentations/AI_CAP/Dia3.JPG new file mode 100644 index 000000000..f32e036c0 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia3.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia4.JPG b/docs/Presentations/AI_CAP/Dia4.JPG new file mode 100644 index 000000000..f3015fbeb Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia4.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia5.JPG b/docs/Presentations/AI_CAP/Dia5.JPG new file mode 100644 index 000000000..1fd33de78 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia5.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia6.JPG b/docs/Presentations/AI_CAP/Dia6.JPG new file mode 100644 index 000000000..c5024ddbf Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia6.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia7.JPG b/docs/Presentations/AI_CAP/Dia7.JPG new file mode 100644 index 000000000..fbf9987ad Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia7.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia8.JPG b/docs/Presentations/AI_CAP/Dia8.JPG new file mode 100644 index 000000000..ee0b36aba Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia8.JPG differ diff --git a/docs/Presentations/AI_CAP/Dia9.JPG b/docs/Presentations/AI_CAP/Dia9.JPG new file mode 100644 index 000000000..0c4760538 Binary files /dev/null and b/docs/Presentations/AI_CAP/Dia9.JPG differ diff --git a/docs/Presentations/AI_CAS.pptx b/docs/Presentations/AI_CAS.pptx new file mode 100644 index 000000000..07e718c00 Binary files /dev/null and b/docs/Presentations/AI_CAS.pptx differ diff --git a/docs/Presentations/AI_CAS/Dia1.JPG b/docs/Presentations/AI_CAS/Dia1.JPG new file mode 100644 index 000000000..0bf4c1e92 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia1.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia10.JPG b/docs/Presentations/AI_CAS/Dia10.JPG new file mode 100644 index 000000000..6e5096863 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia10.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia11.JPG b/docs/Presentations/AI_CAS/Dia11.JPG new file mode 100644 index 000000000..a236d65e2 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia11.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia12.JPG b/docs/Presentations/AI_CAS/Dia12.JPG new file mode 100644 index 000000000..bcf6d85ff Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia12.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia13.JPG b/docs/Presentations/AI_CAS/Dia13.JPG new file mode 100644 index 000000000..797dcbaf8 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia13.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia2.JPG b/docs/Presentations/AI_CAS/Dia2.JPG new file mode 100644 index 000000000..574ed5b9b Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia2.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia3.JPG b/docs/Presentations/AI_CAS/Dia3.JPG new file mode 100644 index 000000000..9bcc78a57 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia3.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia4.JPG b/docs/Presentations/AI_CAS/Dia4.JPG new file mode 100644 index 000000000..2cd22e14a Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia4.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia5.JPG b/docs/Presentations/AI_CAS/Dia5.JPG new file mode 100644 index 000000000..22f923f5c Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia5.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia6.JPG b/docs/Presentations/AI_CAS/Dia6.JPG new file mode 100644 index 000000000..668413e95 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia6.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia7.JPG b/docs/Presentations/AI_CAS/Dia7.JPG new file mode 100644 index 000000000..04d4abd9a Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia7.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia8.JPG b/docs/Presentations/AI_CAS/Dia8.JPG new file mode 100644 index 000000000..c1aebf592 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia8.JPG differ diff --git a/docs/Presentations/AI_CAS/Dia9.JPG b/docs/Presentations/AI_CAS/Dia9.JPG new file mode 100644 index 000000000..47845f382 Binary files /dev/null and b/docs/Presentations/AI_CAS/Dia9.JPG differ diff --git a/docs/Presentations/AI_PATROL.pptx b/docs/Presentations/AI_PATROL.pptx new file mode 100644 index 000000000..bf425bd57 Binary files /dev/null and b/docs/Presentations/AI_PATROL.pptx differ diff --git a/docs/Presentations/AI_PATROL/Dia1.JPG b/docs/Presentations/AI_PATROL/Dia1.JPG new file mode 100644 index 000000000..26bc14fe0 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia1.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia10.JPG b/docs/Presentations/AI_PATROL/Dia10.JPG new file mode 100644 index 000000000..63cee3a04 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia10.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia11.JPG b/docs/Presentations/AI_PATROL/Dia11.JPG new file mode 100644 index 000000000..cae7f2722 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia11.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia12.JPG b/docs/Presentations/AI_PATROL/Dia12.JPG new file mode 100644 index 000000000..851e5f161 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia12.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia2.JPG b/docs/Presentations/AI_PATROL/Dia2.JPG new file mode 100644 index 000000000..0227de5ed Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia2.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia3.JPG b/docs/Presentations/AI_PATROL/Dia3.JPG new file mode 100644 index 000000000..f32e036c0 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia3.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia4.JPG b/docs/Presentations/AI_PATROL/Dia4.JPG new file mode 100644 index 000000000..f3015fbeb Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia4.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia5.JPG b/docs/Presentations/AI_PATROL/Dia5.JPG new file mode 100644 index 000000000..1fd33de78 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia5.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia6.JPG b/docs/Presentations/AI_PATROL/Dia6.JPG new file mode 100644 index 000000000..a41920d1c Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia6.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia7.JPG b/docs/Presentations/AI_PATROL/Dia7.JPG new file mode 100644 index 000000000..55ee1a64b Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia7.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia8.JPG b/docs/Presentations/AI_PATROL/Dia8.JPG new file mode 100644 index 000000000..8c9155db4 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia8.JPG differ diff --git a/docs/Presentations/AI_PATROL/Dia9.JPG b/docs/Presentations/AI_PATROL/Dia9.JPG new file mode 100644 index 000000000..0c4760538 Binary files /dev/null and b/docs/Presentations/AI_PATROL/Dia9.JPG differ diff --git a/docs/Presentations/CARGO.pptx b/docs/Presentations/CARGO.pptx new file mode 100644 index 000000000..617704b83 Binary files /dev/null and b/docs/Presentations/CARGO.pptx differ diff --git a/docs/Presentations/CARGO/Dia1.JPG b/docs/Presentations/CARGO/Dia1.JPG new file mode 100644 index 000000000..c38ff1e02 Binary files /dev/null and b/docs/Presentations/CARGO/Dia1.JPG differ diff --git a/docs/Presentations/CARGO/Dia2.JPG b/docs/Presentations/CARGO/Dia2.JPG new file mode 100644 index 000000000..626f6a55b Binary files /dev/null and b/docs/Presentations/CARGO/Dia2.JPG differ diff --git a/docs/Presentations/CARGO/Dia3.JPG b/docs/Presentations/CARGO/Dia3.JPG new file mode 100644 index 000000000..75e5d78b3 Binary files /dev/null and b/docs/Presentations/CARGO/Dia3.JPG differ diff --git a/docs/Presentations/CARGO/Dia4.JPG b/docs/Presentations/CARGO/Dia4.JPG new file mode 100644 index 000000000..93dad1a32 Binary files /dev/null and b/docs/Presentations/CARGO/Dia4.JPG differ diff --git a/docs/Presentations/CARGO/Dia5.JPG b/docs/Presentations/CARGO/Dia5.JPG new file mode 100644 index 000000000..dfd0a3877 Binary files /dev/null and b/docs/Presentations/CARGO/Dia5.JPG differ diff --git a/docs/Presentations/CARGO/Dia6.JPG b/docs/Presentations/CARGO/Dia6.JPG new file mode 100644 index 000000000..a7e01cdce Binary files /dev/null and b/docs/Presentations/CARGO/Dia6.JPG differ diff --git a/docs/Presentations/CARGO/Dia7.JPG b/docs/Presentations/CARGO/Dia7.JPG new file mode 100644 index 000000000..4ed46bfd8 Binary files /dev/null and b/docs/Presentations/CARGO/Dia7.JPG differ diff --git a/docs/Presentations/CARGO/Dia8.JPG b/docs/Presentations/CARGO/Dia8.JPG new file mode 100644 index 000000000..87b45f85c Binary files /dev/null and b/docs/Presentations/CARGO/Dia8.JPG differ diff --git a/docs/Presentations/CARGO/Dia9.JPG b/docs/Presentations/CARGO/Dia9.JPG new file mode 100644 index 000000000..0f2a2e707 Binary files /dev/null and b/docs/Presentations/CARGO/Dia9.JPG differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts.pptx b/docs/Presentations/FSM.pptx similarity index 99% rename from docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts.pptx rename to docs/Presentations/FSM.pptx index a35d71fa0..65f5eaded 100644 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts.pptx and b/docs/Presentations/FSM.pptx differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia1.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia1.JPG deleted file mode 100644 index 61217a2e1..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia1.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia2.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia2.JPG deleted file mode 100644 index b1063f0d3..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia2.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia3.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia3.JPG deleted file mode 100644 index 8af08a1de..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia3.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia4.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia4.JPG deleted file mode 100644 index 059694846..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia4.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia5.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia5.JPG deleted file mode 100644 index 3d2a79c64..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia5.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia6.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia6.JPG deleted file mode 100644 index afbd35fb2..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia6.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia7.JPG b/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia7.JPG deleted file mode 100644 index 5eadc2a1b..000000000 Binary files a/docs/Presentations/FSM/DOC.MOOSE - FSM - 1. Concepts/Dia7.JPG and /dev/null differ diff --git a/docs/Presentations/FSM/Dia1.JPG b/docs/Presentations/FSM/Dia1.JPG index 61217a2e1..a2979700e 100644 Binary files a/docs/Presentations/FSM/Dia1.JPG and b/docs/Presentations/FSM/Dia1.JPG differ diff --git a/docs/Presentations/FSM/Dia2.JPG b/docs/Presentations/FSM/Dia2.JPG index b1063f0d3..4ccd1b2c7 100644 Binary files a/docs/Presentations/FSM/Dia2.JPG and b/docs/Presentations/FSM/Dia2.JPG differ diff --git a/docs/Presentations/FSM/Dia3.JPG b/docs/Presentations/FSM/Dia3.JPG index 8af08a1de..ef0dbc6af 100644 Binary files a/docs/Presentations/FSM/Dia3.JPG and b/docs/Presentations/FSM/Dia3.JPG differ diff --git a/docs/Presentations/FSM/Dia4.JPG b/docs/Presentations/FSM/Dia4.JPG index 059694846..258000d73 100644 Binary files a/docs/Presentations/FSM/Dia4.JPG and b/docs/Presentations/FSM/Dia4.JPG differ diff --git a/docs/Presentations/FSM/Dia5.JPG b/docs/Presentations/FSM/Dia5.JPG index 3d2a79c64..64345fabc 100644 Binary files a/docs/Presentations/FSM/Dia5.JPG and b/docs/Presentations/FSM/Dia5.JPG differ diff --git a/docs/Presentations/FSM/Dia6.JPG b/docs/Presentations/FSM/Dia6.JPG index afbd35fb2..fd8e91c67 100644 Binary files a/docs/Presentations/FSM/Dia6.JPG and b/docs/Presentations/FSM/Dia6.JPG differ diff --git a/docs/Presentations/FSM/Dia7.JPG b/docs/Presentations/FSM/Dia7.JPG index 5eadc2a1b..b0297c65c 100644 Binary files a/docs/Presentations/FSM/Dia7.JPG and b/docs/Presentations/FSM/Dia7.JPG differ diff --git a/docs/Presentations/MOOSE.pptx b/docs/Presentations/MOOSE.pptx new file mode 100644 index 000000000..b9c40c706 Binary files /dev/null and b/docs/Presentations/MOOSE.pptx differ diff --git a/docs/Presentations/MOOSE/Dia1.JPG b/docs/Presentations/MOOSE/Dia1.JPG new file mode 100644 index 000000000..e9541c1aa Binary files /dev/null and b/docs/Presentations/MOOSE/Dia1.JPG differ diff --git a/docs/Presentations/MOOSE/Dia2.JPG b/docs/Presentations/MOOSE/Dia2.JPG new file mode 100644 index 000000000..90f7d21e9 Binary files /dev/null and b/docs/Presentations/MOOSE/Dia2.JPG differ diff --git a/docs/Presentations/SPAWN.pptx b/docs/Presentations/SPAWN.pptx new file mode 100644 index 000000000..060aeabea Binary files /dev/null and b/docs/Presentations/SPAWN.pptx differ diff --git a/docs/Presentations/SPAWN/Dia1.JPG b/docs/Presentations/SPAWN/Dia1.JPG new file mode 100644 index 000000000..c38ff1e02 Binary files /dev/null and b/docs/Presentations/SPAWN/Dia1.JPG differ diff --git a/docs/Presentations/SPAWN/Dia2.JPG b/docs/Presentations/SPAWN/Dia2.JPG new file mode 100644 index 000000000..626f6a55b Binary files /dev/null and b/docs/Presentations/SPAWN/Dia2.JPG differ diff --git a/docs/Presentations/SPAWN/Dia3.JPG b/docs/Presentations/SPAWN/Dia3.JPG new file mode 100644 index 000000000..75e5d78b3 Binary files /dev/null and b/docs/Presentations/SPAWN/Dia3.JPG differ diff --git a/docs/Presentations/SPAWN/Dia4.JPG b/docs/Presentations/SPAWN/Dia4.JPG new file mode 100644 index 000000000..93dad1a32 Binary files /dev/null and b/docs/Presentations/SPAWN/Dia4.JPG differ diff --git a/docs/Presentations/SPAWN/Dia5.JPG b/docs/Presentations/SPAWN/Dia5.JPG new file mode 100644 index 000000000..dfd0a3877 Binary files /dev/null and b/docs/Presentations/SPAWN/Dia5.JPG differ diff --git a/docs/Presentations/SPAWN/Dia6.JPG b/docs/Presentations/SPAWN/Dia6.JPG new file mode 100644 index 000000000..a7e01cdce Binary files /dev/null and b/docs/Presentations/SPAWN/Dia6.JPG differ diff --git a/docs/Presentations/SPAWN/Dia7.JPG b/docs/Presentations/SPAWN/Dia7.JPG new file mode 100644 index 000000000..4ed46bfd8 Binary files /dev/null and b/docs/Presentations/SPAWN/Dia7.JPG differ diff --git a/docs/Presentations/SPAWN/Dia8.JPG b/docs/Presentations/SPAWN/Dia8.JPG new file mode 100644 index 000000000..87b45f85c Binary files /dev/null and b/docs/Presentations/SPAWN/Dia8.JPG differ diff --git a/docs/Presentations/SPAWN/Dia9.JPG b/docs/Presentations/SPAWN/Dia9.JPG new file mode 100644 index 000000000..0f2a2e707 Binary files /dev/null and b/docs/Presentations/SPAWN/Dia9.JPG differ diff --git a/docs/README.md b/docs/README.md index 5f67ae907..965f165f0 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,19 +3,54 @@ MOOSE is a **M**ission **O**bject **O**riented **S**cripting **E**nvironment, and is meant for mission designers and mission hosters. It allows to quickly setup complex missions using pre-scripted scenarios using the available classes within the MOOSE Framework. -MOOSE is currently still in alpha version, but will evolve over time. Right now, it has been updated to work with DCS world 1.5. and 2.0. +MOOSE is designed to work with DCS world 1.5. and 2.0. -You can find the source of MOOSE here on GITHUB. It is free for download: -https://github.com/FlightControl-Master/MOOSE/ - -Note: MOOSE is complementary to [MIST](https://github.com/mrSkortch/MissionScriptingTools/releases), so if you use MIST in parallel with MOOSE objects, this should work. +![Banner](Presentations\MOOSE\Dia1.JPG) # Goals The goal of MOOSE is to allow mission designers to enhance their scripting with mission orchestration objects, which can be instantiated from defined classes within the framework. This will allow to write mission scripts with minimal code embedded. Of course, the richness of the framework will determine the richness of the misson scenarios. We can expect that MOOSE will evolve over time, as more missions will be designed within the framework. +## GitHub Repository + +You can find the source of [MOOSE on GITHUB](https://github.com/FlightControl-Master/MOOSE/). It is free for download. + +## YouTube Broadcast Channel + +MOOSE has a [broadcast channel](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg/playlists) on youtube. +These videos are grouped into playlists, which explain specific MOOSE capabilities, +and gradually build up the "understanding" and "what is possible" to do with the MOOSE framework. +I really, really encourage all to watch the explanation videos. + +Some mandatory videos to watch are: + + * [MOOSE Introduction](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1JEtVcyf9sazUV5_fGICz4) + + * [MOOSE Setup](https://www.youtube.com/watch?v=-Hxae3mTCE8&t=159s&index=1&list=PL7ZUrU4zZUl0riB9ULVh-bZvFlw1_Wym2) + * [MOOSE Spawning](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl1jirWIo4t4YxqN-HxjqRkL) + * [MOOSE Tasking](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3CgxN2iAViiGLTPpQ-Ajdg) + * [MOOSE Task Dispatching](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3I6ieFM-cjey-rncF1ktNI) + +## MOOSE community + +There is a MOOSE community at various places out there. The main community can be found at slack.com. +Various channels and people are helping each other out using the framework. +If you would like to join, please contact me on skype: FlightControl_Skype. + + +## Test Missions + +The framework comes with [Test Missions](https://github.com/FlightControl-Master/MOOSE/tree/master/Moose%20Test%20Missions), that you can try out and helps you to code. +You can copy/paste code the code snippets into your missions, as it accellerates your mission developments. + +These exact test missions are demonstrated at the demo videos in the YouTube channel. + +Note: MOOSE is complementary to [MIST](https://github.com/mrSkortch/MissionScriptingTools/releases), so if you use MIST in parallel with MOOSE objects, this should work. + # MOOSE Directory Structure +As you can see at the GitHub site, the MOOSE framework is devided into a couple of directories: + * Moose Development: Contains the collection of lua files that define the MOOSE classes. You can use this directory to build the dynamic luadoc documentation intellisense in your eclipse development environment. * Moose Mission Setup: Contains the Moose.lua file to be included in your scripts when using MOOSE classes (see below the point Mission Design with Moose). * Moose Test Missions: Contains a directory structure with Moose Test Missions and examples. In each directory, you will find a miz file and a lua file containing the main mission script. @@ -38,11 +73,12 @@ IMPORTANT NOTE: When a new version of MOOSE is released, you'll have to UPDATE t This can be a tedious task, and for this purpose, a tool has been developed that will update the Moose.lua files automatically within your missions. Refer to the tool at [Moose Mission Setup\Moose Mission Update](https://github.com/FlightControl-Master/MOOSE/tree/master/Moose%20Mission%20Setup/Moose%20Mission%20Update) directory for further information included in the [READ.ME]() file. - # MOOSE Classes The following classes are currently embedded within MOOSE and can be included within your mission scripts: +![Classes](Presentations\MOOSE\Dia2.JPG) + ## MOOSE Core Classes These classes define the base building blocks of the MOOSE framework. These classes are heavily used within the MOOSE framework.
    POINT_VEC3.RoutePointType.TakeOffParking +

    "TakeOffParking"

    +
    POINT_VEC3.RoutePointType.TurningPoint

    "Turning Point"

    @@ -2097,6 +2111,19 @@ The new calculated POINT_VEC3.

    + +POINT_VEC3.RoutePointAction.FromParkingArea + +
    +
    + +

    "From Parking Area"

    + +
    +
    +
    +
    + POINT_VEC3.RoutePointAction.TurningPoint @@ -2135,6 +2162,19 @@ The new calculated POINT_VEC3.

    + +POINT_VEC3.RoutePointType.TakeOffParking + +
    +
    + +

    "TakeOffParking"

    + +
    +
    +
    +
    + POINT_VEC3.RoutePointType.TurningPoint diff --git a/docs/Documentation/Positionable.html b/docs/Documentation/Positionable.html index 64e64762c..a45df76af 100644 --- a/docs/Documentation/Positionable.html +++ b/docs/Documentation/Positionable.html @@ -18,6 +18,9 @@
    POSITIONABLE:GetPointVec2()

    Returns a POINT_VEC2 object indicating the point in 2D of the POSITIONABLE within the mission.

    +
    POSITIONABLE:GetPointVec3() +

    Returns a POINT_VEC3 object indicating the point in 3D of the POSITIONABLE within the mission.

    SET_BASE:AddObject(Object)

    Adds a Core.Base#BASE object in the Core.Set#SET_BASE, using the Object Name as the index.

    +
    SET_BASE.CallScheduler +
    UNIT:GetThreatLevel()

    Returns the Unit's A2G threat level on a scale from 1 to 10 ...

    +
    UNIT:GetUnits() +

    Returns the UNIT in a UNIT list of one element.

    UNIT:HasSensors(...)

    Returns if the unit has sensors of a certain type.

    +
    UNIT:InAir() +

    Returns true if the UNIT is in the air.

    AI_Balancer -

    This module contains the AI_BALANCER class.

    +

    Single-Player:No / Mulit-Player:Yes / AI:Yes / Human:No / Types:All -- AI Balancing will replace in multi player missions +non-occupied human slots with AI groups, in order to provide an engaging simulation environment, +even when there are hardly any players in the mission.

    + +

    Banner Image

    + + +
    + +

    1) AI.AIBalancer#AIBALANCER class, extends Core.Fsm#FSM_SET

    + +

    The AI.AIBalancer#AIBALANCER class monitors and manages as many replacement AI groups as there are +CLIENTS in a SET_CLIENT collection, which are not occupied by human players.

    +
    AI_Cap +

    Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Execute Combat Air Patrol (CAP).

    + +

    Banner Image

    + + +
    + +

    1) #AICAPZONE class, extends AI.AICap#AIPATROL_ZONE

    + +

    The #AICAPZONE class implements the core functions to patrol a Zone by an AI Controllable or Group +and automatically engage any airborne enemies that are within a certain range or within a certain zone.

    +
    AI_Cas +

    Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Provide Close Air Support to friendly ground troops.

    + +

    Banner Image

    + + +
    + +

    1) #AICASZONE class, extends AI.AIPatrol#AIPATROL_ZONE

    + +

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

    +
    AI_Patrol +

    Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Air -- Air Patrolling or Staging.

    + +

    Banner Image

    + + +
    + +

    1) #AIPATROLZONE class, extends Core.Fsm#FSM_CONTROLLABLE

    + +

    The #AIPATROLZONE class implements the core functions to patrol a Zone by an AI Controllable or Group.

    Cargo -

    Management of logical cargo objects, that can be transported from and to transportation carriers.

    +

    Single-Player:Yes / Mulit-Player:Yes / AI:Yes / Human:No / Types:Ground -- Management of logical cargo objects, that can be transported from and to transportation carriers.

    Object

    This module contains the OBJECT class.

    -
    Patrol -

    (AI) (FSM) Make AI patrol routes or zones.