diff --git a/Moose Development/Dcs/DCSTask.lua b/Moose Development/Dcs/DCSTask.lua index 344f52a25..4b4cd277a 100644 --- a/Moose Development/Dcs/DCSTask.lua +++ b/Moose Development/Dcs/DCSTask.lua @@ -1,10 +1,15 @@ --- @module DCSTask ---- @type Task +--- A task descriptor (internal structure for DCS World) +-- @type Task -- @field #string id -- @field #Task.param param --- @type Task.param +--- List of @{#Task} +-- @type TaskArray +-- @list <#Task> + env.info( "Task defined" ) diff --git a/Moose Development/Dcs/DCSTypes.lua b/Moose Development/Dcs/DCSTypes.lua index b11d4a87b..176725302 100644 --- a/Moose Development/Dcs/DCSTypes.lua +++ b/Moose Development/Dcs/DCSTypes.lua @@ -60,6 +60,16 @@ -- @type TypeName -- @extends #string +--- AttributeName = string +-- Each object type may have attributes. +-- Attributes are enlisted in ./Scripts/Database/db_attributes.Lua. +-- To know what attributes the object type has, look for the unit type script in sub-directories planes/, helicopter/s, vehicles, navy/ of ./Scripts/Database/ directory. +-- @type AttributeName +-- @extends #string + +--- List of @{#AttributeName} +-- @type AttributeNameArray +-- @list <#AttributeName> --- @type AI -- @field #AI.Skill Skill diff --git a/Moose Development/Dcs/Moose_Test_WRAPPER.lua b/Moose Development/Dcs/Moose_Test_WRAPPER.lua deleted file mode 100644 index bed5f303a..000000000 --- a/Moose Development/Dcs/Moose_Test_WRAPPER.lua +++ /dev/null @@ -1,8 +0,0 @@ - -Include.File( "Group" ) -Include.File( "Unit" ) - -local UnitAirPlaneAI = _DATABASE:FindUnit( "Airplane AI" ) - -UnitAirPlaneAI:FlareRed() - diff --git a/Moose Development/Moose/Airbase.lua b/Moose Development/Moose/Airbase.lua new file mode 100644 index 000000000..970e8ddfa --- /dev/null +++ b/Moose Development/Moose/Airbase.lua @@ -0,0 +1,290 @@ +--- AIRBASE Class +-- +-- @{AIRBASE} class +-- ============== +-- The @{AIRBASE} class is a wrapper class to handle the DCS Airbase objects: +-- +-- * Support all DCS Airbase APIs. +-- * Enhance with Airbase specific APIs not in the DCS Airbase API set. +-- +-- +-- AIRBASE reference methods +-- ====================== +-- For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the _@{DATABASE} object. +-- This is done at the beginning of the mission (when the mission starts). +-- +-- The AIRBASE class **does not contain a :New()** method, rather it provides **:Find()** methods to retrieve the object reference +-- using the DCS Airbase or the DCS AirbaseName. +-- +-- Another thing to know is that AIRBASE objects do not "contain" the DCS Airbase object. +-- The AIRBASE methods will reference the DCS Airbase object by name when it is needed during API execution. +-- If the DCS Airbase object does not exist or is nil, the AIRBASE methods will return nil and log an exception in the DCS.log file. +-- +-- The AIRBASE class provides the following functions to retrieve quickly the relevant AIRBASE instance: +-- +-- * @{#AIRBASE.Find}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase object. +-- * @{#AIRBASE.FindByName}(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase name. +-- +-- IMPORTANT: ONE SHOULD NEVER SANATIZE these AIRBASE OBJECT REFERENCES! (make the AIRBASE object references nil). +-- +-- DCS AIRBASE APIs +-- ============= +-- The DCS Airbase APIs are used extensively within MOOSE. The AIRBASE class has for each DCS Airbase API a corresponding method. +-- To be able to distinguish easily in your code the difference between a AIRBASE API call and a DCS Airbase API call, +-- the first letter of the method is also capitalized. So, by example, the DCS Airbase method @{DCSAirbase#Airbase.getName}() +-- is implemented in the AIRBASE class as @{#AIRBASE.GetName}(). +-- +-- More functions will be added +-- ---------------------------- +-- During the MOOSE development, more functions will be added. +-- +-- @module Airbase +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Message" ) + +--- The AIRBASE class +-- @type AIRBASE +-- @extends Base#BASE +AIRBASE = { + ClassName="AIRBASE", + CategoryName = { + [Airbase.Category.AIRDROME] = "Airdrome", + [Airbase.Category.HELIPAD] = "Helipad", + [Airbase.Category.SHIP] = "Ship", + }, + } + +-- Registration. + +--- Create a new AIRBASE from DCSAirbase. +-- @param #AIRBASE self +-- @param DCSAirbase#Airbase DCSAirbase +-- @param Database#DATABASE Database +-- @return Airbase#AIRBASE +function AIRBASE:Register( AirbaseName ) + + local self = BASE:Inherit( self, BASE:New() ) + self:F2( AirbaseName ) + self.AirbaseName = AirbaseName + return self +end + +-- Reference methods. + +--- Finds a AIRBASE from the _DATABASE using a DCSAirbase object. +-- @param #AIRBASE self +-- @param DCSAirbase#Airbase DCSAirbase An existing DCS Airbase object reference. +-- @return Airbase#AIRBASE self +function AIRBASE:Find( DCSAirbase ) + + local AirbaseName = DCSAirbase:getName() + local AirbaseFound = _DATABASE:FindAirbase( AirbaseName ) + return AirbaseFound +end + +--- Find a AIRBASE in the _DATABASE using the name of an existing DCS Airbase. +-- @param #AIRBASE self +-- @param #string AirbaseName The Airbase Name. +-- @return Airbase#AIRBASE self +function AIRBASE:FindByName( AirbaseName ) + + local AirbaseFound = _DATABASE:FindAirbase( AirbaseName ) + return AirbaseFound +end + +function AIRBASE:GetDCSAirbase() + local DCSAirbase = Airbase.getByName( self.AirbaseName ) + + if DCSAirbase then + return DCSAirbase + end + + return nil +end + +--- Returns coalition of the Airbase. +-- @param Airbase#AIRBASE self +-- @return DCSCoalitionObject#coalition.side The side of the coalition. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetCoalition() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseCoalition = DCSAirbase:getCoalition() + self:T3( AirbaseCoalition ) + return AirbaseCoalition + end + + return nil +end + +--- Returns country of the Airbase. +-- @param Airbase#AIRBASE self +-- @return DCScountry#country.id The country identifier. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetCountry() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseCountry = DCSAirbase:getCountry() + self:T3( AirbaseCountry ) + return AirbaseCountry + end + + return nil +end + + +--- Returns DCS Airbase object name. +-- The function provides access to non-activated units too. +-- @param Airbase#AIRBASE self +-- @return #string The name of the DCS Airbase. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetName() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseName = self.AirbaseName + return AirbaseName + end + + return nil +end + + +--- Returns if the airbase is alive. +-- @param Airbase#AIRBASE self +-- @return #boolean true if Airbase is alive. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:IsAlive() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseIsAlive = DCSAirbase:isExist() + return AirbaseIsAlive + end + + return false +end + +--- Returns the unit's unique identifier. +-- @param Airbase#AIRBASE self +-- @return DCSAirbase#Airbase.ID Airbase ID +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetID() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseID = DCSAirbase:getID() + return AirbaseID + end + + return nil +end + +--- Returns the Airbase's callsign - the localized string. +-- @param Airbase#AIRBASE self +-- @return #string The Callsign of the Airbase. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetCallSign() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseCallSign = DCSAirbase:getCallsign() + return AirbaseCallSign + end + + return nil +end + + + +--- Returns unit descriptor. Descriptor type depends on unit category. +-- @param Airbase#AIRBASE self +-- @return DCSAirbase#Airbase.Desc The Airbase descriptor. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetDesc() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseDesc = DCSAirbase:getDesc() + return AirbaseDesc + end + + return nil +end + + +--- Returns the type name of the DCS Airbase. +-- @param Airbase#AIRBASE self +-- @return #string The type name of the DCS Airbase. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetTypeName() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseTypeName = DCSAirbase:getTypeName() + self:T3( AirbaseTypeName ) + return AirbaseTypeName + end + + return nil +end + + +--- Returns the @{DCSTypes#Vec2} vector indicating the point in 2D of the DCS Airbase within the mission. +-- @param Airbase#AIRBASE self +-- @return DCSTypes#Vec2 The 2D point vector of the DCS Airbase. +-- @return #nil The DCS Airbase is not existing or alive. +function AIRBASE:GetPointVec2() + self:F2( self.AirbaseName ) + + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbasePointVec3 = DCSAirbase:getPosition().p + + local AirbasePointVec2 = {} + AirbasePointVec2.x = AirbasePointVec3.x + AirbasePointVec2.y = AirbasePointVec3.z + + self:T3( AirbasePointVec2 ) + return AirbasePointVec2 + end + + return nil +end + +--- Returns the DCS Airbase category name as defined within the DCS Airbase Descriptor. +-- @param Airbase#AIRBASE self +-- @return #string The DCS Airbase Category Name +function AIRBASE:GetCategoryName() + local DCSAirbase = self:GetDCSAirbase() + + if DCSAirbase then + local AirbaseCategoryName = self.CategoryName[ self:GetDesc().category ] + return AirbaseCategoryName + end + + return nil +end + diff --git a/Moose Development/Moose/Base.lua b/Moose Development/Moose/Base.lua index 3586673d1..10f5cf4dc 100644 --- a/Moose Development/Moose/Base.lua +++ b/Moose Development/Moose/Base.lua @@ -380,12 +380,12 @@ end --- Trace a function call. Must be at the beginning of the function logic. -- @param #BASE self -- @param Arguments A #table or any field. -function BASE:F( Arguments ) +function BASE:F( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if _TraceOn and ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) then - local DebugInfoCurrent = debug.getinfo( 2, "nl" ) - local DebugInfoFrom = debug.getinfo( 3, "l" ) + local DebugInfoCurrent = DebugInfoCurrentParam and DebugInfoCurrentParam or debug.getinfo( 2, "nl" ) + local DebugInfoFrom = DebugInfoFromParam and DebugInfoFromParam or debug.getinfo( 3, "l" ) local Function = "function" if DebugInfoCurrent.name then @@ -408,8 +408,11 @@ end -- @param Arguments A #table or any field. function BASE:F2( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 2 then - self:F( Arguments ) + self:F( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -419,8 +422,11 @@ end -- @param Arguments A #table or any field. function BASE:F3( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 3 then - self:F( Arguments ) + self:F( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -428,12 +434,12 @@ end --- Trace a function logic. Can be anywhere within the function logic. -- @param #BASE self -- @param Arguments A #table or any field. -function BASE:T( Arguments ) +function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if _TraceOn and ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) then - local DebugInfoCurrent = debug.getinfo( 2, "nl" ) - local DebugInfoFrom = debug.getinfo( 3, "l" ) + local DebugInfoCurrent = DebugInfoCurrentParam and DebugInfoCurrentParam or debug.getinfo( 2, "nl" ) + local DebugInfoFrom = DebugInfoFromParam and DebugInfoFromParam or debug.getinfo( 3, "l" ) local Function = "function" if DebugInfoCurrent.name then @@ -456,8 +462,11 @@ end -- @param Arguments A #table or any field. function BASE:T2( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 2 then - self:T( Arguments ) + self:T( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -467,8 +476,11 @@ end -- @param Arguments A #table or any field. function BASE:T3( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 3 then - self:T( Arguments ) + self:T( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end diff --git a/Moose Development/Moose/Client.lua b/Moose Development/Moose/Client.lua index 75e1ebd16..4326d11cf 100644 --- a/Moose Development/Moose/Client.lua +++ b/Moose Development/Moose/Client.lua @@ -1,10 +1,10 @@ ---- The CLIENT models client units in multi player missions. +--- This module contains the CLIENT class. -- --- @{#CLIENT} class --- ================ +-- 1) @{Client#CLIENT} class, extends @{Unit#UNIT} +-- =============================================== -- Clients are those **Units** defined within the Mission Editor that have the skillset defined as __Client__ or __Player__. -- Note that clients are NOT the same as Units, they are NOT necessarily alive. --- The @{CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__: +-- The @{Client#CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__: -- -- * Wraps the DCS Unit objects with skill level set to Player or Client. -- * Support all DCS Unit APIs. @@ -15,8 +15,8 @@ -- -- Clients are being used by the @{MISSION} class to follow players and register their successes. -- --- CLIENT reference methods --- ======================= +-- 1.1) CLIENT reference methods +-- ----------------------------- -- For each DCS Unit having skill level Player or Client, a CLIENT wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts). -- diff --git a/Moose Development/Moose/Database.lua b/Moose Development/Moose/Database.lua index 66febcae9..656df9bf0 100644 --- a/Moose Development/Moose/Database.lua +++ b/Moose Development/Moose/Database.lua @@ -36,9 +36,11 @@ Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Menu" ) Include.File( "Group" ) +Include.File( "Static" ) Include.File( "Unit" ) Include.File( "Event" ) Include.File( "Client" ) +Include.File( "Scheduler" ) --- DATABASE class @@ -54,7 +56,9 @@ DATABASE = { }, DCSUnits = {}, DCSGroups = {}, + DCSStatics = {}, UNITS = {}, + STATICS = {}, GROUPS = {}, PLAYERS = {}, PLAYERSALIVE = {}, @@ -100,7 +104,8 @@ function DATABASE:New() _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventOnPlayerLeaveUnit, self ) self:_RegisterTemplates() - self:_RegisterDatabase() + self:_RegisterGroupsAndUnits() + self:_RegisterStatics() self:_RegisterPlayers() return self @@ -133,6 +138,32 @@ function DATABASE:DeleteUnit( DCSUnitName ) self.DCSUnits[DCSUnitName] = nil end +--- Adds a Static based on the Static Name in the DATABASE. +-- @param #DATABASE self +function DATABASE:AddStatic( DCSStatic, DCSStaticName ) + + self.DCSStatics[DCSStaticName] = DCSStatic + self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName ) +end + + +--- Deletes a Static from the DATABASE based on the Static Name. +-- @param #DATABASE self +function DATABASE:DeleteStatic( DCSStaticName ) + + self.DCSStatics[DCSStaticName] = nil +end + +--- Finds a STATIC based on the StaticName. +-- @param #DATABASE self +-- @param #string StaticName +-- @return Static#STATIC The found STATIC. +function DATABASE:FindStatic( StaticName ) + + local StaticFound = self.STATICS[StaticName] + return StaticFound +end + --- Finds a CLIENT based on the ClientName. -- @param #DATABASE self @@ -220,6 +251,8 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.SpawnCategoryID = nil self:_RegisterTemplate( SpawnTemplate ) + + self:T3( SpawnTemplate ) coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate ) -- Restore @@ -227,7 +260,6 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.SpawnCountryID = SpawnCountryID SpawnTemplate.SpawnCategoryID = SpawnCategoryID - local SpawnGroup = GROUP:Register( SpawnTemplate.name ) return SpawnGroup end @@ -320,10 +352,10 @@ function DATABASE:_RegisterPlayers() end ---- Private method that registers all datapoints within in the mission. +--- Private method that registers all Groups and Units within in the mission. -- @param #DATABASE self -- @return #DATABASE self -function DATABASE:_RegisterDatabase() +function DATABASE:_RegisterGroupsAndUnits() local CoalitionsData = { GroupsRed = coalition.getGroups( coalition.side.RED ), GroupsBlue = coalition.getGroups( coalition.side.BLUE ) } for CoalitionId, CoalitionData in pairs( CoalitionsData ) do @@ -356,6 +388,27 @@ function DATABASE:_RegisterDatabase() return self end +function DATABASE:_RegisterStatics() + + local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) } + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do + for DCSStaticId, DCSStatic in pairs( CoalitionData ) do + + if DCSStatic:isExist() then + local DCSStaticName = DCSStatic:getName() + + self:E( { "Register Static:", DCSStatic, DCSStaticName } ) + self:AddStatic( DCSStatic, DCSStaticName ) + else + self:E( { "Static does not exist: ", DCSStatic } ) + end + end + end + + return self +end + + --- Events --- Handles the OnBirth event for the alive units set. diff --git a/Moose Development/Moose/Group.lua b/Moose Development/Moose/Group.lua index 27e972843..a63d742a5 100644 --- a/Moose Development/Moose/Group.lua +++ b/Moose Development/Moose/Group.lua @@ -1,33 +1,148 @@ ---- GROUP class. --- --- @{GROUP} class --- ============== --- The @{GROUP} class is a wrapper class to handle the DCS Group objects: +--- This module contains the GROUP class. -- +-- 1) @{Group#GROUP} class, extends @{Base#BASE} +-- ============================================= +-- The @{Group#GROUP} class is a wrapper class to handle the DCS Group objects: +-- -- * Support all DCS Group APIs. -- * Enhance with Group specific APIs not in the DCS Group API set. -- * Handle local Group Controller. -- * Manage the "state" of the DCS Group. --- --- --- GROUP reference methods --- ======================= +-- +-- **IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** +-- +-- 1.1) GROUP reference methods +-- ----------------------- -- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{SPAWN} class). --- +-- -- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the DCS Group or the DCS GroupName. --- --- Another thing to know is that GROUP objects do not "contain" the DCS Group object. +-- +-- Another thing to know is that GROUP objects do not "contain" the DCS Group object. -- The GROUP methods will reference the DCS Group object by name when it is needed during API execution. -- If the DCS Group object does not exist or is nil, the GROUP methods will return nil and log an exception in the DCS.log file. --- +-- -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: --- +-- -- * @{#GROUP.Find}(): Find a GROUP instance from the _DATABASE object using a DCS Group object. -- * @{#GROUP.FindByName}(): Find a GROUP instance from the _DATABASE object using a DCS Group name. --- --- IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil). +-- +-- 1.2) GROUP task methods +-- ----------------------- +-- Several group task methods are available that help you to prepare tasks. +-- These methods return a string consisting of the task description, which can then be given to either a @{Group#GROUP.PushTask} or @{Group#SetTask} method to assign the task to the GROUP. +-- Tasks are specific for the category of the GROUP, more specific, for AIR, GROUND or AIR and GROUND. +-- Each task description where applicable indicates for which group category the task is valid. +-- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks. +-- +-- ### 1.2.1) Assigned task methods +-- +-- Assigned task methods make the group execute the task where the location of the (possible) targets of the task are known before being detected. +-- This is different from the EnRoute tasks, where the targets of the task need to be detected before the task can be executed. +-- +-- Find below a list of the **assigned task** methods: +-- +-- * @{#GROUP.TaskAttackGroup}: (AIR) Attack a Group. +-- * @{#GROUP.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c). +-- * @{#GROUP.TaskAttackUnit}: (AIR) Attack the Unit. +-- * @{#GROUP.TaskBombing}: (AIR) Delivering weapon at the point on the ground. +-- * @{#GROUP.TaskBombingRunway}: (AIR) Delivering weapon on the runway. +-- * @{#GROUP.TaskEmbarking}: (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group. +-- * @{#GROUP.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location. +-- * @{#GROUP.TaskEscort}: (AIR) Escort another airborne group. +-- * @{#GROUP.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction. +-- * @{#GROUP.TaskFireAtPoint}: (GROUND) Fire at a VEC2 point until ammunition is finished. +-- * @{#GROUP.TaskFollow}: (AIR) Following another airborne group. +-- * @{#GROUP.TaskHold}: (GROUND) Hold ground group from moving. +-- * @{#GROUP.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the group. +-- * @{#GROUP.TaskLand}: (AIR HELICOPTER) Landing at the ground. For helicopters only. +-- * @{#GROUP.TaskLandAtZone}: (AIR) Land the group at a @{Zone#ZONE_RADIUS). +-- * @{#GROUP.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the group at a specified alititude. +-- * @{#GROUP.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. +-- * @{#GROUP.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters. +-- * @{#GROUP.TaskRoute}: (AIR + GROUND) Return a Misson task to follow a given route defined by Points. +-- * @{#GROUP.TaskRouteToVec2}: (AIR + GROUND) Make the Group move to a given point. +-- * @{#GROUP.TaskRouteToVec3}: (AIR + GROUND) Make the Group move to a given point. +-- * @{#GROUP.TaskRouteToZone}: (AIR + GROUND) Route the group to a given zone. +-- +-- ### 1.2.2) EnRoute task methods +-- +-- EnRoute tasks require the targets of the task need to be detected by the group (using its sensors) before the task can be executed: +-- +-- * @{#GROUP.EnRouteTaskAWACS}: (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters. +-- * @{#GROUP.EnRouteTaskEngageGroup}: (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskEngageTargets}: (AIR) Engaging targets of defined types. +-- * @{#GROUP.EnRouteTaskEWR}: (AIR) Attack the Unit. +-- * @{#GROUP.EnRouteTaskFAC}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskFAC_EngageGroup}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskTanker}: (AIR) Aircraft will act as a tanker for friendly units. No parameters. +-- +-- ### 1.2.3) Preparation task methods +-- +-- There are certain task methods that allow to tailor the task behaviour: +-- +-- * @{#GROUP.TaskWrappedAction}: Return a WrappedAction Task taking a Command. +-- * @{#GROUP.TaskCombo}: Return a Combo Task taking an array of Tasks. +-- * @{#GROUP.TaskCondition}: Return a condition section for a controlled task. +-- * @{#GROUP.TaskControlled}: Return a Controlled Task taking a Task and a TaskCondition. +-- +-- ### 1.2.4) Obtain the mission from group templates +-- +-- Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another: +-- +-- * @{#GROUP.TaskMission}: (AIR + GROUND) Return a mission task from a mission template. +-- +-- 1.3) GROUP Command methods +-- -------------------------- +-- Group **command methods** prepare the execution of commands using the @{#GROUP.SetCommand} method: +-- +-- * @{#GROUP.CommandDoScript}: Do Script command. +-- * @{#GROUP.CommandSwitchWayPoint}: Perform a switch waypoint command. +-- +-- 1.4) GROUP Option methods +-- ------------------------- +-- Group **Option methods** change the behaviour of the Group while being alive. +-- +-- ### 1.4.1) Rule of Engagement: +-- +-- * @{#GROUP.OptionROEWeaponFree} +-- * @{#GROUP.OptionROEOpenFire} +-- * @{#GROUP.OptionROEReturnFire} +-- * @{#GROUP.OptionROEEvadeFire} +-- +-- To check whether an ROE option is valid for a specific group, use: +-- +-- * @{#GROUP.OptionROEWeaponFreePossible} +-- * @{#GROUP.OptionROEOpenFirePossible} +-- * @{#GROUP.OptionROEReturnFirePossible} +-- * @{#GROUP.OptionROEEvadeFirePossible} +-- +-- ### 1.4.2) Rule on thread: +-- +-- * @{#GROUP.OptionROTNoReaction} +-- * @{#GROUP.OptionROTPassiveDefense} +-- * @{#GROUP.OptionROTEvadeFire} +-- * @{#GROUP.OptionROTVertical} +-- +-- To test whether an ROT option is valid for a specific group, use: +-- +-- * @{#GROUP.OptionROTNoReactionPossible} +-- * @{#GROUP.OptionROTPassiveDefensePossible} +-- * @{#GROUP.OptionROTEvadeFirePossible} +-- * @{#GROUP.OptionROTVerticalPossible} +-- +-- 1.5) GROUP Zone validation methods +-- ---------------------------------- +-- The group can be validated whether it is completely, partly or not within a @{Zone}. +-- Use the following Zone validation methods on the group: +-- +-- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Zone}. +-- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Zone}. +-- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Zone}. +-- +-- The zone can be of any @{Zone} class derived from @{Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. +-- -- @module Group -- @author FlightControl @@ -42,14 +157,14 @@ Include.File( "Unit" ) -- @field DCSGroup#Group DCSGroup The DCS group class. -- @field #string GroupName The name of the group. GROUP = { - ClassName = "GROUP", - GroupName = "", - GroupID = 0, - Controller = nil, - DCSGroup = nil, - WayPointFunctions = {}, - } - + ClassName = "GROUP", + GroupName = "", + GroupID = 0, + Controller = nil, + DCSGroup = nil, + WayPointFunctions = {}, +} + --- A DCSGroup -- @type DCSGroup -- @field id_ The ID of the group in DCS @@ -59,10 +174,10 @@ GROUP = { -- @param DCSGroup#Group GroupName The DCS Group name -- @return #GROUP self function GROUP:Register( GroupName ) - local self = BASE:Inherit( self, BASE:New() ) - self:F2( GroupName ) - self.GroupName = GroupName - return self + local self = BASE:Inherit( self, BASE:New() ) + self:F2( GroupName ) + self.GroupName = GroupName + return self end -- Reference methods. @@ -95,11 +210,11 @@ end -- @return DCSGroup#Group The DCS Group. function GROUP:GetDCSGroup() local DCSGroup = Group.getByName( self.GroupName ) - + if DCSGroup then return DCSGroup end - + return nil end @@ -110,27 +225,27 @@ end -- @return #boolean true if the DCS Group is alive. function GROUP:IsAlive() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupIsAlive = DCSGroup:isExist() self:T3( GroupIsAlive ) return GroupIsAlive end - + return nil end ---- Destroys the DCS Group and all of its DCS Units. +--- Destroys the DCS Group and all of its DCS Units. -- Note that this destroy method also raises a destroy event at run-time. -- So all event listeners will catch the destroy event of this DCS Group. -- @param #GROUP self function GROUP:Destroy() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then for Index, UnitData in pairs( DCSGroup:getUnits() ) do self:CreateEventCrash( timer.getTime(), UnitData ) @@ -138,11 +253,11 @@ function GROUP:Destroy() DCSGroup:destroy() DCSGroup = nil end - + return nil end ---- Returns category of the DCS Group. +--- Returns category of the DCS Group. -- @param #GROUP self -- @return DCSGroup#Group.Category The category ID function GROUP:GetCategory() @@ -154,7 +269,7 @@ function GROUP:GetCategory() self:T3( GroupCategory ) return GroupCategory end - + return nil end @@ -170,14 +285,14 @@ function GROUP:GetCategoryName() [Group.Category.AIRPLANE] = "Airplane", [Group.Category.HELICOPTER] = "Helicopter", [Group.Category.GROUND] = "Ground Unit", - [Group.Category.SHIP] = "Ship", + [Group.Category.SHIP] = "Ship", } local GroupCategory = DCSGroup:getCategory() self:T3( GroupCategory ) - + return CategoryNames[GroupCategory] end - + return nil end @@ -194,14 +309,14 @@ function GROUP:GetCoalition() self:T3( GroupCoalition ) return GroupCoalition end - + return nil end --- Returns the country of the DCS Group. -- @param #GROUP self -- @return DCScountry#country.id The country identifier. --- @return #nil The DCS Group is not existing or alive. +-- @return #nil The DCS Group is not existing or alive. function GROUP:GetCountry() self:F2( self.GroupName ) @@ -211,7 +326,7 @@ function GROUP:GetCountry() self:T3( GroupCountry ) return GroupCountry end - + return nil end @@ -222,13 +337,13 @@ function GROUP:GetName() self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupName = DCSGroup:getName() self:T3( GroupName ) return GroupName end - + return nil end @@ -237,19 +352,19 @@ end -- @return #number The identifier of the DCS Group. function GROUP:GetID() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupID = DCSGroup:getID() self:T3( GroupID ) return GroupID end - + return nil end ---- Returns the UNIT wrapper class with number UnitNumber. +--- Returns the UNIT wrapper class with number UnitNumber. -- If the underlying DCS Unit does not exist, the method will return nil. . -- @param #GROUP self -- @param #number UnitNumber The number of the UNIT wrapper class to be returned. @@ -258,7 +373,7 @@ function GROUP:GetUnit( UnitNumber ) self:F2( { self.GroupName, UnitNumber } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) ) self:T3( UnitFound.UnitName ) @@ -269,7 +384,7 @@ function GROUP:GetUnit( UnitNumber ) return nil end ---- Returns the DCS Unit with number UnitNumber. +--- Returns the DCS Unit with number UnitNumber. -- If the underlying DCS Unit does not exist, the method will return nil. . -- @param #GROUP self -- @param #number UnitNumber The number of the DCS Unit to be returned. @@ -278,7 +393,7 @@ function GROUP:GetDCSUnit( UnitNumber ) self:F2( { self.GroupName, UnitNumber } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnitFound = DCSGroup:getUnit( UnitNumber ) self:T3( DCSUnitFound ) @@ -288,14 +403,14 @@ function GROUP:GetDCSUnit( UnitNumber ) return nil end ---- Returns current size of the DCS Group. --- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed. +--- Returns current size of the DCS Group. +-- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed. -- @param #GROUP self -- @return #number The DCS Group size. function GROUP:GetSize() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupSize = DCSGroup:getSize() self:T3( GroupSize ) @@ -305,15 +420,15 @@ function GROUP:GetSize() return nil end ---- ---- Returns the initial size of the DCS Group. --- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged. +--- +--- Returns the initial size of the DCS Group. +-- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged. -- @param #GROUP self -- @return #number The DCS Group initial size. function GROUP:GetInitialSize() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupInitialSize = DCSGroup:getInitialSize() self:T3( GroupInitialSize ) @@ -329,7 +444,7 @@ end function GROUP:GetUnits() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnits = DCSGroup:getUnits() local Units = {} @@ -350,7 +465,7 @@ end function GROUP:GetDCSUnits() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnits = DCSGroup:getUnits() self:T3( DCSUnits ) @@ -366,7 +481,7 @@ end function GROUP:_GetController() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupController = DCSGroup:getController() self:T3( GroupController ) @@ -386,7 +501,7 @@ end function GROUP:WayPointInitialize() self.WayPoints = self:GetTaskRoute() - + return self end @@ -399,7 +514,7 @@ end -- @return #GROUP function GROUP:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) self:F2( { WayPoint, WayPointIndex, WayPointFunction } ) - + table.insert( self.WayPoints[WayPoint].task.params.tasks, WayPointIndex ) self.WayPoints[WayPoint].task.params.tasks[WayPointIndex] = self:TaskFunction( WayPoint, WayPointIndex, WayPointFunction, arg ) return self @@ -409,7 +524,7 @@ end function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionArguments ) local DCSTask - + local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionGroup = GROUP:Find( ... ) " @@ -417,16 +532,16 @@ function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionAr DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" else DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )" - end - - DCSTask = self:TaskWrappedAction( + end + + DCSTask = self:TaskWrappedAction( self:CommandDoScript( table.concat( DCSScript ) ), WayPointIndex ) - + self:T3( DCSTask ) - + return DCSTask end @@ -438,21 +553,21 @@ end -- Note that when the WayPoint parameter is used, the new start mission waypoint of the group will be 1! -- @param #GROUP self -- @param #number WayPoint The WayPoint from where to execute the mission. --- @param #WaitTime The amount seconds to wait before initiating the mission. +-- @param #number WaitTime The amount seconds to wait before initiating the mission. -- @return #GROUP function GROUP:WayPointExecute( WayPoint, WaitTime ) if not WayPoint then WayPoint = 1 end - + -- When starting the mission from a certain point, the TaskPoints need to be deleted before the given WayPoint. for TaskPointID = 1, WayPoint - 1 do table.remove( self.WayPoints, 1 ) end self:T3( self.WayPoints ) - + self:SetTask( self:TaskRoute( self.WayPoints ), WaitTime ) return self @@ -462,9 +577,9 @@ end --- Activates a GROUP. -- @param #GROUP self function GROUP:Activate() - self:F2( { self.GroupName } ) - trigger.action.activateGroup( self:GetDCSGroup() ) - return self:GetDCSGroup() + self:F2( { self.GroupName } ) + trigger.action.activateGroup( self:GetDCSGroup() ) + return self:GetDCSGroup() end @@ -475,13 +590,13 @@ function GROUP:GetTypeName() self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupTypeName = DCSGroup:getUnit(1):getTypeName() self:T3( GroupTypeName ) return( GroupTypeName ) end - + return nil end @@ -490,33 +605,33 @@ end -- @return #string The CallSign of the first DCS Unit of the DCS Group. function GROUP:GetCallsign() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCallSign = DCSGroup:getUnit(1):getCallsign() self:T3( GroupCallSign ) return GroupCallSign end - + return nil end --- Returns the current point (Vec2 vector) of the first DCS Unit in the DCS Group. -- @return DCSTypes#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group. function GROUP:GetPointVec2() - self:F2( self.GroupName ) - - local GroupPointVec2 = self:GetUnit(1):GetPointVec2() - self:T3( GroupPointVec2 ) - return GroupPointVec2 + self:F2( self.GroupName ) + + local GroupPointVec2 = self:GetUnit(1):GetPointVec2() + self:T3( GroupPointVec2 ) + return GroupPointVec2 end --- Returns the current point (Vec3 vector) of the first DCS Unit in the DCS Group. -- @return DCSTypes#Vec3 Current Vec3 point of the first DCS Unit of the DCS Group. function GROUP:GetPointVec3() - self:F2( self.GroupName ) - + self:F2( self.GroupName ) + local GroupPointVec3 = self:GetUnit(1):GetPointVec3() self:T3( GroupPointVec3 ) return GroupPointVec3 @@ -524,23 +639,75 @@ end --- Is Functions +-- Is Zone Functions + +--- Returns true if all units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsCompletelyInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + else + return false + end + end + + return true +end + +--- Returns true if some units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsPartlyInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + return true + end + end + + return false +end + +--- Returns true if none of the group units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsNotInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + return false + end + end + + return true +end --- Returns if the group is of an air category. -- If the group is a helicopter or a plane, then this method will return true, otherwise false. -- @param #GROUP self -- @return #boolean Air category evaluation result. function GROUP:IsAir() - self:F2( self.GroupName ) + self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER - self:T3( IsAirResult ) - return IsAirResult + local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER + self:T3( IsAirResult ) + return IsAirResult end - + return nil end @@ -549,15 +716,15 @@ end -- @return #boolean true if DCS Group contains Helicopters. function GROUP:IsHelicopter() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.HELICOPTER end - + return nil end @@ -566,15 +733,15 @@ end -- @return #boolean true if DCS Group contains AirPlanes. function GROUP:IsAirPlane() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.AIRPLANE end - + return nil end @@ -583,15 +750,15 @@ end -- @return #boolean true if DCS Group contains Ground troops. function GROUP:IsGround() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.GROUND end - + return nil end @@ -600,15 +767,15 @@ end -- @return #boolean true if DCS Group contains Ships. function GROUP:IsShip() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.SHIP end - + return nil end @@ -617,23 +784,23 @@ end -- @param #GROUP self -- @return #boolean All units on the ground result. function GROUP:AllOnGround() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local AllOnGroundResult = true - - for Index, UnitData in pairs( DCSGroup:getUnits() ) do - if UnitData:inAir() then - AllOnGroundResult = false - end - end - - self:T3( AllOnGroundResult ) - return AllOnGroundResult + local AllOnGroundResult = true + + for Index, UnitData in pairs( DCSGroup:getUnits() ) do + if UnitData:inAir() then + AllOnGroundResult = false + end + end + + self:T3( AllOnGroundResult ) + return AllOnGroundResult end - + return nil end @@ -642,26 +809,26 @@ end -- @param #GROUP self -- @return #number Maximum velocity found. function GROUP:GetMaxVelocity() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local MaxVelocity = 0 - - for Index, UnitData in pairs( DCSGroup:getUnits() ) do - - local Velocity = UnitData:getVelocity() - local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z ) - - if VelocityTotal < MaxVelocity then - MaxVelocity = VelocityTotal - end - end - - return MaxVelocity + local MaxVelocity = 0 + + for Index, UnitData in pairs( DCSGroup:getUnits() ) do + + local Velocity = UnitData:getVelocity() + local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z ) + + if VelocityTotal < MaxVelocity then + MaxVelocity = VelocityTotal + end + end + + return MaxVelocity end - + return nil end @@ -670,7 +837,7 @@ end -- @param #GROUP self -- @return #number Minimum height found. function GROUP:GetMinHeight() - self:F2() + self:F2() end @@ -679,7 +846,7 @@ end -- @param #GROUP self -- @return #number Maximum height found. function GROUP:GetMaxHeight() - self:F2() + self:F2() end @@ -689,16 +856,16 @@ end -- @param #GROUP self -- @return Group#GROUP self function GROUP:PopCurrentTask() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() Controller:popTask() return self end - + return nil end @@ -706,27 +873,27 @@ end -- @param #GROUP self -- @return Group#GROUP self function GROUP:PushTask( DCSTask, WaitTime ) - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() - + -- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Group. -- Controller:pushTask( DCSTask ) - + if WaitTime then --routines.scheduleFunction( Controller.pushTask, { Controller, DCSTask }, timer.getTime() + WaitTime ) SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime ) else Controller:pushTask( DCSTask ) end - + return self end - + return nil end @@ -737,40 +904,40 @@ function GROUP:SetTask( DCSTask, WaitTime ) self:F2( { DCSTask } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - + local Controller = self:_GetController() - + -- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Group. -- Controller.setTask( Controller, DCSTask ) - + if not WaitTime then WaitTime = 1 end --routines.scheduleFunction( Controller.setTask, { Controller, DCSTask }, timer.getTime() + WaitTime ) SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime ) - + return self end - + return nil end ---- Return a condition section for a controlled task +--- Return a condition section for a controlled task. -- @param #GROUP self -- @param DCSTime#Time time --- @param #string userFlag --- @param #boolean userFlagValue +-- @param #string userFlag +-- @param #boolean userFlagValue -- @param #string condition --- @param DCSTime#Time duration --- @param #number lastWayPoint +-- @param DCSTime#Time duration +-- @param #number lastWayPoint -- return DCSTask#Task function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration, lastWayPoint ) - self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) - + self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) + local DCSStopCondition = {} DCSStopCondition.time = time DCSStopCondition.userFlag = userFlag @@ -778,54 +945,54 @@ function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration DCSStopCondition.condition = condition DCSStopCondition.duration = duration DCSStopCondition.lastWayPoint = lastWayPoint - + self:T3( { DCSStopCondition } ) - return DCSStopCondition + return DCSStopCondition end ---- Return a Controlled Task taking a Task and a TaskCondition +--- Return a Controlled Task taking a Task and a TaskCondition. -- @param #GROUP self -- @param DCSTask#Task DCSTask -- @param #DCSStopCondition DCSStopCondition -- @return DCSTask#Task function GROUP:TaskControlled( DCSTask, DCSStopCondition ) - self:F2( { DCSTask, DCSStopCondition } ) + self:F2( { DCSTask, DCSStopCondition } ) local DCSTaskControlled - - DCSTaskControlled = { - id = 'ControlledTask', - params = { - task = DCSTask, - stopCondition = DCSStopCondition - } + + DCSTaskControlled = { + id = 'ControlledTask', + params = { + task = DCSTask, + stopCondition = DCSStopCondition + } } - + self:T3( { DCSTaskControlled } ) return DCSTaskControlled end ---- Return a Combo Task taking an array of Tasks +--- Return a Combo Task taking an array of Tasks. -- @param #GROUP self --- @param #list DCSTasks +-- @param DCSTask#TaskArray DCSTasks Array of @{DCSTask#Task} -- @return DCSTask#Task function GROUP:TaskCombo( DCSTasks ) self:F2( { DCSTasks } ) local DCSTaskCombo - - DCSTaskCombo = { - id = 'ComboTask', - params = { + + DCSTaskCombo = { + id = 'ComboTask', + params = { tasks = DCSTasks - } + } } - + self:T3( { DCSTaskCombo } ) return DCSTaskCombo end ---- Return a WrappedAction Task taking a Command +--- Return a WrappedAction Task taking a Command. -- @param #GROUP self -- @param DCSCommand#Command DCSCommand -- @return DCSTask#Task @@ -833,8 +1000,8 @@ function GROUP:TaskWrappedAction( DCSCommand, Index ) self:F2( { DCSCommand } ) local DCSTaskWrappedAction - - DCSTaskWrappedAction = { + + DCSTaskWrappedAction = { id = "WrappedAction", enabled = true, number = Index, @@ -854,15 +1021,15 @@ end -- @return #GROUP self function GROUP:SetCommand( DCSCommand ) self:F2( DCSCommand ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() Controller:setCommand( DCSCommand ) return self end - + return nil end @@ -873,117 +1040,387 @@ end -- @return DCSTask#Task function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index ) self:F2( { FromWayPoint, ToWayPoint, Index } ) - + local CommandSwitchWayPoint = { - id = 'SwitchWaypoint', - params = { - fromWaypointIndex = FromWayPoint, - goToWaypointIndex = ToWayPoint, + id = 'SwitchWaypoint', + params = { + fromWaypointIndex = FromWayPoint, + goToWaypointIndex = ToWayPoint, }, } - + self:T3( { CommandSwitchWayPoint } ) return CommandSwitchWayPoint end - ---- Orbit at a specified position at a specified alititude during a specified duration with a specified speed. + +-- TASKS FOR AIR GROUPS + + +--- (AIR) Attack a Group. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) + self:F2( { self.GroupName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) + + -- AttackGroup = { + -- id = 'AttackGroup', + -- params = { + -- groupId = Group.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend, + -- attackQty = number, + -- directionEnabled = boolean, + -- direction = Azimuth, + -- altitudeEnabled = boolean, + -- altitude = Distance, + -- attackQtyLimit = boolean, + -- } + -- } + + local DirectionEnabled = nil + if Direction then + DirectionEnabled = true + end + + local AltitudeEnabled = nil + if Altitude then + AltitudeEnabled = true + end + + local DCSTask + DCSTask = { id = 'AttackGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + directionEnabled = DirectionEnabled, + direction = Direction, + altitudeEnabled = AltitudeEnabled, + altitude = Altitude, + attackQtyLimit = AttackQtyLimit, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Attack the Unit. +-- @param #GROUP self +-- @param Unit#UNIT AttackUnit The unit. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack ) + self:F2( { self.GroupName, AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack } ) + + -- AttackUnit = { + -- id = 'AttackUnit', + -- params = { + -- unitId = Unit.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend + -- attackQty = number, + -- direction = Azimuth, + -- attackQtyLimit = boolean, + -- groupAttack = boolean, + -- } + -- } + + local DCSTask + DCSTask = { id = 'AttackUnit', + params = { + unitId = AttackUnit:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + attackQtyLimit = AttackQtyLimit, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Delivering weapon at the point on the ground. +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the point to deliver weapon at. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskBombing( PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- Bombing = { +-- id = 'Bombing', +-- params = { +-- point = Vec2, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'Bombing', + params = { + point = PointVec2, + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point to hold the position. -- @param #number Altitude The altitude to hold the position. -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed ) - self:F2( { self.GroupName, Point, Altitude, Speed } ) + self:F2( { self.GroupName, Point, Altitude, Speed } ) + + -- pattern = enum AI.Task.OribtPattern, + -- point = Vec2, + -- point2 = Vec2, + -- speed = Distance, + -- altitude = Distance --- pattern = enum AI.Task.OribtPattern, --- point = Vec2, --- point2 = Vec2, --- speed = Distance, --- altitude = Distance - local LandHeight = land.getHeight( Point ) - + self:T3( { LandHeight } ) - local DCSTask = { id = 'Orbit', - params = { pattern = AI.Task.OrbitPattern.CIRCLE, - point = Point, - speed = Speed, - altitude = Altitude + LandHeight - } - } + local DCSTask = { id = 'Orbit', + params = { pattern = AI.Task.OrbitPattern.CIRCLE, + point = Point, + speed = Speed, + altitude = Altitude + LandHeight + } + } + + + -- local AITask = { id = 'ControlledTask', + -- params = { task = { id = 'Orbit', + -- params = { pattern = AI.Task.OrbitPattern.CIRCLE, + -- point = Point, + -- speed = Speed, + -- altitude = Altitude + LandHeight + -- } + -- }, + -- stopCondition = { duration = Duration + -- } + -- } + -- } + -- ) - --- local AITask = { id = 'ControlledTask', --- params = { task = { id = 'Orbit', --- params = { pattern = AI.Task.OrbitPattern.CIRCLE, --- point = Point, --- speed = Speed, --- altitude = Altitude + LandHeight --- } --- }, --- stopCondition = { duration = Duration --- } --- } --- } --- ) - return DCSTask end ---- Orbit at the current position of the first unit of the group at a specified alititude +--- (AIR) Orbit at the current position of the first unit of the group at a specified alititude. -- @param #GROUP self -- @param #number Altitude The altitude to hold the position. -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircle( Altitude, Speed ) - self:F2( { self.GroupName, Altitude, Speed } ) + self:F2( { self.GroupName, Altitude, Speed } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupPoint = self:GetPointVec2() return self:TaskOrbitCircleAtVec2( GroupPoint, Altitude, Speed ) end - + return nil end ---- Hold position at the current position of the first unit of the group. +--- (AIR) Hold position at the current position of the first unit of the group. -- @param #GROUP self -- @param #number Duration The maximum duration in seconds to hold the position. -- @return #GROUP self function GROUP:TaskHoldPosition() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) return self:TaskOrbitCircle( 30, 10 ) end ---- Land the group at a Vec2Point. + + +--- (AIR) Attacking the map object (building, structure, e.t.c). +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackMapObject( PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- AttackMapObject = { +-- id = 'AttackMapObject', +-- params = { +-- point = Vec2, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'AttackMapObject', + params = { + point = PointVec2, + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Delivering weapon on the runway. +-- @param #GROUP self +-- @param Airbase#AIRBASE Airbase Airbase to attack. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskBombingRunway( Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- BombingRunway = { +-- id = 'BombingRunway', +-- params = { +-- runwayId = AirdromeId, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'BombingRunway', + params = { + point = Airbase:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Refueling from the nearest tanker. No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskRefueling() + self:F2( { self.GroupName } ) + +-- Refueling = { +-- id = 'Refueling', +-- params = {} +-- } + + local DCSTask + DCSTask = { id = 'Refueling', + params = { + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR HELICOPTER) Landing at the ground. For helicopters only. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to land. -- @param #number Duration The duration in seconds to stay on the ground. -- @return #GROUP self function GROUP:TaskLandAtVec2( Point, Duration ) - self:F2( { self.GroupName, Point, Duration } ) + self:F2( { self.GroupName, Point, Duration } ) +-- Land = { +-- id= 'Land', +-- params = { +-- point = Vec2, +-- durationFlag = boolean, +-- duration = Time +-- } +-- } + local DCSTask - - if Duration and Duration > 0 then - DCSTask = { id = 'Land', params = { point = Point, durationFlag = true, duration = Duration } } - else - DCSTask = { id = 'Land', params = { point = Point, durationFlag = false } } - end + if Duration and Duration > 0 then + DCSTask = { id = 'Land', + params = { + point = Point, + durationFlag = true, + duration = Duration, + }, + } + else + DCSTask = { id = 'Land', + params = { + point = Point, + durationFlag = false, + }, + } + end self:T3( DCSTask ) - return DCSTask + return DCSTask end ---- Land the group at a @{Zone#ZONE). +--- (AIR) Land the group at a @{Zone#ZONE_RADIUS). -- @param #GROUP self -- @param Zone#ZONE Zone The zone where to land. -- @param #number Duration The duration in seconds to stay on the ground. @@ -997,7 +1434,7 @@ function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint ) else Point = Zone:GetPointVec2() end - + local DCSTask = self:TaskLandAtVec2( Point, Duration ) self:T3( DCSTask ) @@ -1005,155 +1442,570 @@ function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint ) end ---- Attack the Unit. --- @param #GROUP self --- @param Unit#UNIT The unit. --- @return DCSTask#Task The DCS task structure. -function GROUP:TaskAttackUnit( AttackUnit ) - self:F2( { self.GroupName, AttackUnit } ) --- AttackUnit = { --- id = 'AttackUnit', --- params = { --- unitId = Unit.ID, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend --- attackQty = number, --- direction = Azimuth, --- attackQtyLimit = boolean, --- groupAttack = boolean, --- } +--- (AIR) Following another airborne group. +-- The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +-- If another group is on land the unit / group will orbit around. +-- @param #GROUP self +-- @param Group#GROUP FollowGroup The group to be followed. +-- @param DCSTypes#Vec3 PointVec3 Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around. +-- @param #number LastWaypointIndex Detach waypoint of another group. Once reached the unit / group Follow task is finished. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskFollow( FollowGroup, PointVec3, LastWaypointIndex ) + self:F2( { self.GroupName, FollowGroup, PointVec3, LastWaypointIndex } ) + +-- Follow = { +-- id = 'Follow', +-- params = { +-- groupId = Group.ID, +-- pos = Vec3, +-- lastWptIndexFlag = boolean, +-- lastWptIndex = number +-- } -- } + + local LastWaypointIndexFlag = nil + if LastWaypointIndex then + LastWaypointIndexFlag = true + end - local DCSTask - DCSTask = { id = 'AttackUnit', - params = { unitId = AttackUnit:GetID(), - expend = AI.Task.WeaponExpend.TWO, - groupAttack = true, - }, - }, - + local DCSTask + DCSTask = { id = 'Follow', + params = { + groupId = FollowGroup:GetID(), + pos = PointVec3, + lastWptIndexFlag = LastWaypointIndexFlag, + lastWptIndex = LastWaypointIndex, + }, + }, + self:T3( { DCSTask } ) return DCSTask end ---- Attack a Group. + +--- (AIR) Escort another airborne group. +-- The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +-- The unit / group will also protect that group from threats of specified types. -- @param #GROUP self --- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param Group#GROUP EscortGroup The group to be escorted. +-- @param DCSTypes#Vec3 PointVec3 Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around. +-- @param #number LastWaypointIndex Detach waypoint of another group. Once reached the unit / group Follow task is finished. +-- @param #number EngagementDistanceMax Maximal distance from escorted group to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. -- @return DCSTask#Task The DCS task structure. -function GROUP:TaskAttackGroup( AttackGroup ) - self:F2( { self.GroupName, AttackGroup } ) +function GROUP:TaskEscort( FollowGroup, PointVec3, LastWaypointIndex, EngagementDistance, TargetTypes ) + self:F2( { self.GroupName, FollowGroup, PointVec3, LastWaypointIndex, EngagementDistance, TargetTypes } ) --- AttackGroup = { --- id = 'AttackGroup', --- params = { --- groupId = Group.ID, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend, --- attackQty = number, --- directionEnabled = boolean, --- direction = Azimuth, --- altitudeEnabled = boolean, --- altitude = Distance, --- attackQtyLimit = boolean, --- } --- } +-- Escort = { +-- id = 'Escort', +-- params = { +-- groupId = Group.ID, +-- pos = Vec3, +-- lastWptIndexFlag = boolean, +-- lastWptIndex = number, +-- engagementDistMax = Distance, +-- targetTypes = array of AttributeName, +-- } +-- } - local DCSTask - DCSTask = { id = 'AttackGroup', - params = { groupId = AttackGroup:GetID(), - expend = AI.Task.WeaponExpend.TWO, - }, - }, + local LastWaypointIndexFlag = nil + if LastWaypointIndex then + LastWaypointIndexFlag = true + end + local DCSTask + DCSTask = { id = 'Follow', + params = { + groupId = FollowGroup:GetID(), + pos = PointVec3, + lastWptIndexFlag = LastWaypointIndexFlag, + lastWptIndex = LastWaypointIndex, + engagementDistMax = EngagementDistance, + targetTypes = TargetTypes, + }, + }, + self:T3( { DCSTask } ) return DCSTask end ---- Fires at a VEC2 point. + +-- GROUND TASKS + +--- (GROUND) Fire at a VEC2 point until ammunition is finished. -- @param #GROUP self --- @param DCSTypes#Vec2 The point to fire at. +-- @param DCSTypes#Vec2 PointVec2 The point to fire at. -- @param DCSTypes#Distance Radius The radius of the zone to deploy the fire at. -- @return DCSTask#Task The DCS task structure. function GROUP:TaskFireAtPoint( PointVec2, Radius ) self:F2( { self.GroupName, PointVec2, Radius } ) --- FireAtPoint = { --- id = 'FireAtPoint', --- params = { --- point = Vec2, --- radius = Distance, --- } --- } - - local DCSTask - DCSTask = { id = 'FireAtPoint', - params = { point = PointVec2, - radius = Radius, - } - } - + -- FireAtPoint = { + -- id = 'FireAtPoint', + -- params = { + -- point = Vec2, + -- radius = Distance, + -- } + -- } + + local DCSTask + DCSTask = { id = 'FireAtPoint', + params = { + point = PointVec2, + radius = Radius, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (GROUND) Hold ground group from moving. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskHold() + self:F2( { self.GroupName } ) + +-- Hold = { +-- id = 'Hold', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'Hold', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- TASKS FOR AIRBORNE AND GROUND UNITS/GROUPS + +--- (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup Target GROUP. +-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type. +-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink ) + self:F2( { self.GroupName, AttackGroup, WeaponType, Designation, Datalink } ) + +-- FAC_AttackGroup = { +-- id = 'FAC_AttackGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- designation = enum AI.Task.Designation, +-- datalink = boolean +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC_AttackGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + designation = Designation, + datalink = Datalink, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + +-- EN-ROUTE TASKS FOR AIRBORNE GROUPS + +--- (AIR) Engaging targets of defined types. +-- @param #GROUP self +-- @param DCSTypes#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage. +-- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority ) + self:F2( { self.GroupName, Distance, TargetTypes, Priority } ) + +-- EngageTargets ={ +-- id = 'EngageTargets', +-- params = { +-- maxDist = Distance, +-- targetTypes = array of AttributeName, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'EngageTargets', + params = { + maxDist = Distance, + targetTypes = TargetTypes, + priority = Priority + } + } + self:T3( { DCSTask } ) return DCSTask end ---- Move the group to a Vec2 Point, wait for a defined duration and embark a group. +--- (AIR) Engaging a targets of defined types at circle-shaped zone. +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the zone. +-- @param DCSTypes#Distance Radius Radius of the zone. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageTargets( PointVec2, Radius, TargetTypes, Priority ) + self:F2( { self.GroupName, PointVec2, Radius, TargetTypes, Priority } ) + +-- EngageTargetsInZone = { +-- id = 'EngageTargetsInZone', +-- params = { +-- point = Vec2, +-- zoneRadius = Distance, +-- targetTypes = array of AttributeName, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'EngageTargetsInZone', + params = { + point = PointVec2, + zoneRadius = Radius, + targetTypes = TargetTypes, + priority = Priority + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) + self:F2( { self.GroupName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) + + -- EngageGroup = { + -- id = 'EngageGroup ', + -- params = { + -- groupId = Group.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend, + -- attackQty = number, + -- directionEnabled = boolean, + -- direction = Azimuth, + -- altitudeEnabled = boolean, + -- altitude = Distance, + -- attackQtyLimit = boolean, + -- priority = number, + -- } + -- } + + local DirectionEnabled = nil + if Direction then + DirectionEnabled = true + end + + local AltitudeEnabled = nil + if Altitude then + AltitudeEnabled = true + end + + local DCSTask + DCSTask = { id = 'EngageGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + directionEnabled = DirectionEnabled, + direction = Direction, + altitudeEnabled = AltitudeEnabled, + altitude = Altitude, + attackQtyLimit = AttackQtyLimit, + priority = Priority, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Attack the Unit. +-- @param #GROUP self +-- @param Unit#UNIT AttackUnit The UNIT. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageUnit( AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack ) + self:F2( { self.GroupName, AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack } ) + + -- EngageUnit = { + -- id = 'EngageUnit', + -- params = { + -- unitId = Unit.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend + -- attackQty = number, + -- direction = Azimuth, + -- attackQtyLimit = boolean, + -- groupAttack = boolean, + -- priority = number, + -- } + -- } + + local DCSTask + DCSTask = { id = 'EngageUnit', + params = { + unitId = AttackUnit:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + attackQtyLimit = AttackQtyLimit, + groupAttack = GroupAttack, + priority = Priority, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + + +--- (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskAWACS( ) + self:F2( { self.GroupName } ) + +-- AWACS = { +-- id = 'AWACS', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'AWACS', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Aircraft will act as a tanker for friendly units. No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskTanker( ) + self:F2( { self.GroupName } ) + +-- Tanker = { +-- id = 'Tanker', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'Tanker', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- En-route tasks for ground units/groups + +--- (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts). No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEWR( ) + self:F2( { self.GroupName } ) + +-- EWR = { +-- id = 'EWR', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'EWR', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- En-route tasks for airborne and ground units/groups + +--- (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup Target GROUP. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type. +-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink ) + self:F2( { self.GroupName, AttackGroup, WeaponType, Priority, Designation, Datalink } ) + +-- FAC_EngageGroup = { +-- id = 'FAC_EngageGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- designation = enum AI.Task.Designation, +-- datalink = boolean, +-- priority = number, +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC_EngageGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + designation = Designation, + datalink = Datalink, + priority = Priority, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param DCSTypes#Distance Radius The maximal distance from the FAC to a target. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskFAC( Radius, Priority ) + self:F2( { self.GroupName, Radius, Priority } ) + +-- FAC = { +-- id = 'FAC', +-- params = { +-- radius = Distance, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC', + params = { + radius = Radius, + priority = Priority + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + + + +--- (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to wait. -- @param #number Duration The duration in seconds to wait. -- @param #GROUP EmbarkingGroup The group to be embarked. -- @return DCSTask#Task The DCS task structure -function GROUP:TaskEmbarkingAtVec2( Point, Duration, EmbarkingGroup ) - self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } ) +function GROUP:TaskEmbarking( Point, Duration, EmbarkingGroup ) + self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } ) - local DCSTask - DCSTask = { id = 'Embarking', - params = { x = Point.x, - y = Point.y, - duration = Duration, - groupsForEmbarking = { EmbarkingGroup.GroupID }, - durationFlag = true, - distributionFlag = false, - distribution = {}, - } - } - - self:T3( { DCSTask } ) - return DCSTask + local DCSTask + DCSTask = { id = 'Embarking', + params = { x = Point.x, + y = Point.y, + duration = Duration, + groupsForEmbarking = { EmbarkingGroup.GroupID }, + durationFlag = true, + distributionFlag = false, + distribution = {}, + } + } + + self:T3( { DCSTask } ) + return DCSTask end +--- (GROUND) Embark to a Transport landed at a location. + --- Move to a defined Vec2 Point, and embark to a group when arrived within a defined Radius. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to wait. -- @param #number Radius The radius of the embarking zone around the Point. -- @return DCSTask#Task The DCS task structure. -function GROUP:TaskEmbarkToTransportAtVec2( Point, Radius ) - self:F2( { self.GroupName, Point, Radius } ) +function GROUP:TaskEmbarkToTransport( Point, Radius ) + self:F2( { self.GroupName, Point, Radius } ) local DCSTask --DCSTask#Task - DCSTask = { id = 'EmbarkToTransport', - params = { x = Point.x, - y = Point.y, - zoneRadius = Radius, - } - } + DCSTask = { id = 'EmbarkToTransport', + params = { x = Point.x, + y = Point.y, + zoneRadius = Radius, + } + } self:T3( { DCSTask } ) - return DCSTask + return DCSTask end ---- Return a Misson task from a mission template. + + +--- (AIR + GROUND) Return a mission task from a mission template. -- @param #GROUP self -- @param #table TaskMission A table containing the mission task. --- @return DCSTask#Task +-- @return DCSTask#Task function GROUP:TaskMission( TaskMission ) - self:F2( Points ) - + self:F2( Points ) + local DCSTask DCSTask = { id = 'Mission', params = { TaskMission, }, } - + self:T3( { DCSTask } ) return DCSTask end @@ -1161,18 +2013,18 @@ end --- Return a Misson task to follow a given route defined by Points. -- @param #GROUP self -- @param #table Points A table of route points. --- @return DCSTask#Task +-- @return DCSTask#Task function GROUP:TaskRoute( Points ) self:F2( Points ) - + local DCSTask DCSTask = { id = 'Mission', params = { route = { points = Points, }, }, } - + self:T3( { DCSTask } ) return DCSTask end ---- Make the DCS Group to fly to a given point and hover. +--- (AIR + GROUND) Make the Group move to fly to a given point. -- @param #GROUP self -- @param DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param #number Speed The speed to travel. @@ -1181,22 +2033,22 @@ function GROUP:TaskRouteToVec2( Point, Speed ) self:F2( { Point, Speed } ) local GroupPoint = self:GetUnit( 1 ):GetPointVec2() - + local PointFrom = {} PointFrom.x = GroupPoint.x PointFrom.y = GroupPoint.y PointFrom.type = "Turning Point" PointFrom.action = "Turning Point" - PointFrom.speed = Speed + PointFrom.speed = Speed PointFrom.speed_locked = true PointFrom.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local PointTo = {} PointTo.x = Point.x @@ -1206,24 +2058,24 @@ function GROUP:TaskRouteToVec2( Point, Speed ) PointTo.speed = Speed PointTo.speed_locked = true PointTo.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local Points = { PointFrom, PointTo } - + self:T3( Points ) - + self:Route( Points ) return self end ---- Make the DCS Group to fly to a given point and hover. +--- (AIR + GROUND) Make the Group move to a given point. -- @param #GROUP self -- @param DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param #number Speed The speed to travel. @@ -1232,7 +2084,7 @@ function GROUP:TaskRouteToVec3( Point, Speed ) self:F2( { Point, Speed } ) local GroupPoint = self:GetUnit( 1 ):GetPointVec3() - + local PointFrom = {} PointFrom.x = GroupPoint.x PointFrom.y = GroupPoint.z @@ -1240,39 +2092,39 @@ function GROUP:TaskRouteToVec3( Point, Speed ) PointFrom.alt_type = "BARO" PointFrom.type = "Turning Point" PointFrom.action = "Turning Point" - PointFrom.speed = Speed + PointFrom.speed = Speed PointFrom.speed_locked = true PointFrom.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local PointTo = {} PointTo.x = Point.x PointTo.y = Point.z - PointTo.alt = Point.y + PointTo.alt = Point.y PointTo.alt_type = "BARO" PointTo.type = "Turning Point" PointTo.action = "Fly Over Point" PointTo.speed = Speed PointTo.speed_locked = true PointTo.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local Points = { PointFrom, PointTo } - + self:T3( Points ) - + self:Route( Points ) return self @@ -1283,28 +2135,28 @@ end --- Make the group to follow a given route. -- @param #GROUP self -- @param #table GoPoints A table of Route Points. --- @return #GROUP self +-- @return #GROUP self function GROUP:Route( GoPoints ) - self:F2( GoPoints ) + self:F2( GoPoints ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local Points = routines.utils.deepCopy( GoPoints ) - local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } - local Controller = self:_GetController() + local Points = routines.utils.deepCopy( GoPoints ) + local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } + local Controller = self:_GetController() --Controller.setTask( Controller, MissionTask ) - --routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 ) + --routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 ) SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 ) - return self + return self end - + return nil end ---- Route the group to a given zone. +--- (AIR + GROUND) Route the group to a given zone. -- The group final destination point can be randomized. -- A speed can be given in km/h. -- A given formation can be given. @@ -1314,56 +2166,56 @@ end -- @param #number Speed The speed. -- @param Base#FORMATION Formation The formation string. function GROUP:TaskRouteToZone( Zone, Randomize, Speed, Formation ) - self:F2( Zone ) + self:F2( Zone ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - - local GroupPoint = self:GetPointVec2() - - local PointFrom = {} - PointFrom.x = GroupPoint.x - PointFrom.y = GroupPoint.y - PointFrom.type = "Turning Point" - PointFrom.action = "Cone" - PointFrom.speed = 20 / 1.6 - - - local PointTo = {} - local ZonePoint - - if Randomize then - ZonePoint = Zone:GetRandomPointVec2() - else - ZonePoint = Zone:GetPointVec2() - end - - PointTo.x = ZonePoint.x - PointTo.y = ZonePoint.y - PointTo.type = "Turning Point" - - if Formation then - PointTo.action = Formation - else - PointTo.action = "Cone" - end - - if Speed then - PointTo.speed = Speed - else - PointTo.speed = 20 / 1.6 - end - - local Points = { PointFrom, PointTo } - - self:T3( Points ) - - self:Route( Points ) - - return self + + local GroupPoint = self:GetPointVec2() + + local PointFrom = {} + PointFrom.x = GroupPoint.x + PointFrom.y = GroupPoint.y + PointFrom.type = "Turning Point" + PointFrom.action = "Cone" + PointFrom.speed = 20 / 1.6 + + + local PointTo = {} + local ZonePoint + + if Randomize then + ZonePoint = Zone:GetRandomPointVec2() + else + ZonePoint = Zone:GetPointVec2() + end + + PointTo.x = ZonePoint.x + PointTo.y = ZonePoint.y + PointTo.type = "Turning Point" + + if Formation then + PointTo.action = Formation + else + PointTo.action = "Cone" + end + + if Speed then + PointTo.speed = Speed + else + PointTo.speed = 20 / 1.6 + end + + local Points = { PointFrom, PointTo } + + self:T3( Points ) + + self:Route( Points ) + + return self end - + return nil end @@ -1410,48 +2262,48 @@ end -- @param #number Begin The route point from where the copy will start. The base route point is 0. -- @param #number End The route point where the copy will end. The End point is the last point - the End point. The last point has base 0. -- @param #boolean Randomize Randomization of the route, when true. --- @param #number Radius When randomization is on, the randomization is within the radius. +-- @param #number Radius When randomization is on, the randomization is within the radius. function GROUP:CopyRoute( Begin, End, Randomize, Radius ) - self:F2( { Begin, End } ) + self:F2( { Begin, End } ) - local Points = {} - - -- Could be a Spawned Group - local GroupName = string.match( self:GetName(), ".*#" ) - if GroupName then - GroupName = GroupName:sub( 1, -2 ) - else - GroupName = self:GetName() - end - - self:T3( { GroupName } ) - - local Template = _DATABASE.Templates.Groups[GroupName].Template - - if Template then - if not Begin then - Begin = 0 - end - if not End then - End = 0 - end - - for TPointID = Begin + 1, #Template.route.points - End do - if Template.route.points[TPointID] then - Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] ) - if Randomize then - if not Radius then - Radius = 500 - end - Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius ) - Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius ) - end - end - end - return Points - end - - return nil + local Points = {} + + -- Could be a Spawned Group + local GroupName = string.match( self:GetName(), ".*#" ) + if GroupName then + GroupName = GroupName:sub( 1, -2 ) + else + GroupName = self:GetName() + end + + self:T3( { GroupName } ) + + local Template = _DATABASE.Templates.Groups[GroupName].Template + + if Template then + if not Begin then + Begin = 0 + end + if not End then + End = 0 + end + + for TPointID = Begin + 1, #Template.route.points - End do + if Template.route.points[TPointID] then + Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] ) + if Randomize then + if not Radius then + Radius = 500 + end + Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius ) + Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius ) + end + end + end + return Points + end + + return nil end @@ -1462,28 +2314,28 @@ function GROUP:GetDetectedTargets() if DCSGroup then return self:_GetController():getDetectedTargets() end - + return nil end function GROUP:IsTargetDetected( DCSObject ) self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then - + local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity - = self:_GetController().isTargetDetected( self:_GetController(), DCSObject, - Controller.Detection.VISUAL, - Controller.Detection.OPTIC, - Controller.Detection.RADAR, - Controller.Detection.IRST, - Controller.Detection.RWR, - Controller.Detection.DLINK - ) + = self:_GetController().isTargetDetected( self:_GetController(), DCSObject, + Controller.Detection.VISUAL, + Controller.Detection.OPTIC, + Controller.Detection.RADAR, + Controller.Detection.IRST, + Controller.Detection.RWR, + Controller.Detection.DLINK + ) return TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity end - + return nil end @@ -1494,16 +2346,16 @@ end -- @return #boolean function GROUP:OptionROEHoldFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -1511,12 +2363,12 @@ end -- @param Group#GROUP self -- @return Group#GROUP self function GROUP:OptionROEHoldFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_HOLD ) elseif self:IsGround() then @@ -1524,10 +2376,10 @@ function GROUP:OptionROEHoldFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.WEAPON_HOLD ) end - + return self end - + return nil end @@ -1536,16 +2388,16 @@ end -- @return #boolean function GROUP:OptionROEReturnFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -1553,12 +2405,12 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEReturnFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.RETURN_FIRE ) elseif self:IsGround() then @@ -1566,10 +2418,10 @@ function GROUP:OptionROEReturnFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.RETURN_FIRE ) end - + return self end - + return nil end @@ -1584,10 +2436,10 @@ function GROUP:OptionROEOpenFirePossible() if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -1595,12 +2447,12 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEOpenFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.OPEN_FIRE ) elseif self:IsGround() then @@ -1608,10 +2460,10 @@ function GROUP:OptionROEOpenFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.OPEN_FIRE ) end - + return self end - + return nil end @@ -1620,16 +2472,16 @@ end -- @return #boolean function GROUP:OptionROEWeaponFreePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -1637,19 +2489,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEWeaponFree() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_FREE ) end - + return self end - + return nil end @@ -1658,16 +2510,16 @@ end -- @return #boolean function GROUP:OptionROTNoReactionPossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -1676,19 +2528,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTNoReaction() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.NO_REACTION ) end - + return self end - + return nil end @@ -1703,10 +2555,10 @@ function GROUP:OptionROTPassiveDefensePossible() if self:IsAir() then return true end - + return false end - + return nil end @@ -1714,19 +2566,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTPassiveDefense() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.PASSIVE_DEFENCE ) end - + return self end - + return nil end @@ -1735,16 +2587,16 @@ end -- @return #boolean function GROUP:OptionROTEvadeFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -1753,19 +2605,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTEvadeFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.EVADE_FIRE ) end - + return self end - + return nil end @@ -1774,16 +2626,16 @@ end -- @return #boolean function GROUP:OptionROTVerticalPossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -1792,19 +2644,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTVertical() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.BYPASS_AND_ESCAPE ) end - + return self end - + return nil end @@ -1813,16 +2665,16 @@ end --- Returns a message for a coalition or a client. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. -- @return Message#MESSAGE function GROUP:Message( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then return MESSAGE:New( Message, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")", Duration, self:GetClassNameAndID() ) end - + return nil end @@ -1830,15 +2682,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. function GROUP:MessageToAll( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToAll() end - + return nil end @@ -1846,15 +2698,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTYpes#Duration Duration The duration of the message. function GROUP:MessageToRed( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToRed() end - + return nil end @@ -1862,15 +2714,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. function GROUP:MessageToBlue( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToBlue() end - + return nil end @@ -1878,15 +2730,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. -- @param Client#CLIENT Client The client object receiving the message. function GROUP:MessageToClient( Message, Duration, Client ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToClient( Client ) end - + return nil end diff --git a/Moose Development/Moose/GroupSet.lua b/Moose Development/Moose/GroupSet.lua index f3aea95fc..6ef3e8488 100644 --- a/Moose Development/Moose/GroupSet.lua +++ b/Moose Development/Moose/GroupSet.lua @@ -57,7 +57,6 @@ Include.File( "Set" ) -- @extends Set#SET GROUPSET = { ClassName = "GROUPSET", - Units = {}, Filter = { Coalitions = nil, Categories = nil, @@ -100,7 +99,7 @@ end -- @param #GROUPSET self -- @param #string GroupName -- @return Group#GROUP The found Group. -function GROUPSET:FindUnit( GroupName ) +function GROUPSET:FindGroup( GroupName ) local GroupFound = self.Set[GroupName] return GroupFound @@ -228,7 +227,7 @@ end -- @param #GROUPSET self -- @param #function IteratorFunction The function that will be called when there is an alive GROUP in the GROUPSET. The function needs to accept a GROUP parameter. -- @return #GROUPSET self -function GROUPSET:ForEachUnit( IteratorFunction, ... ) +function GROUPSET:ForEachGroup( IteratorFunction, ... ) self:F2( arg ) self:ForEach( IteratorFunction, arg, self.Set ) diff --git a/Moose Development/Moose/Point.lua b/Moose Development/Moose/Point.lua new file mode 100644 index 000000000..e0dfa6cdb --- /dev/null +++ b/Moose Development/Moose/Point.lua @@ -0,0 +1,195 @@ +--- This module contains the POINT classes. +-- +-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE} +-- =============================================== +-- The @{Point#POINT_VEC3} class defines a 3D point in the simulator. +-- +-- 1.1) POINT_VEC3 constructor +-- --------------------------- +-- +-- A new POINT instance can be created with: +-- +-- * @{#POINT_VEC3.New}(): a 3D point. +-- +-- 2) @{Point#POINT_VEC2} class, extends @{Point#POINT_VEC3} +-- ========================================================= +-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified. +-- +-- 2.1) POINT_VEC2 constructor +-- --------------------------- +-- +-- A new POINT instance can be created with: +-- +-- * @{#POINT_VEC2.New}(): a 2D point. +-- +-- @module Point +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Point" ) + +--- The POINT_VEC3 class +-- @type POINT_VEC3 +-- @extends Base#BASE +-- @field #POINT_VEC3.SmokeColor SmokeColor +-- @field #POINT_VEC3.FlareColor FlareColor +POINT_VEC3 = { + ClassName = "POINT_VEC3", + SmokeColor = { + Green = trigger.smokeColor.Green, + Red = trigger.smokeColor.Red, + White = trigger.smokeColor.White, + Orange = trigger.smokeColor.Orange, + Blue = trigger.smokeColor.Blue + }, + FlareColor = { + Green = trigger.flareColor.Green, + Red = trigger.flareColor.Red, + White = trigger.flareColor.White, + Yellow = trigger.flareColor.Yellow + }, + } + +--- SmokeColor +-- @type POINT_VEC3.SmokeColor +-- @field Green +-- @field Red +-- @field White +-- @field Orange +-- @field Blue + +--- FlareColor +-- @type POINT_VEC3.FlareColor +-- @field Green +-- @field Red +-- @field White +-- @field Yellow + +-- Constructor. + +--- Create a new POINT_VEC3 object. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. +-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing Upwards. +-- @param DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right. +-- @return Point#POINT_VEC3 +function POINT_VEC3:New( x, y, z ) + + local self = BASE:Inherit( self, BASE:New() ) + self:F2( { x, y, z } ) + self.PointVec3 = { x = x, y = y, z = z } + return self +end + +--- Smokes the point in a color. +-- @param #POINT_VEC3 self +-- @param Point#POINT_VEC3.SmokeColor SmokeColor +function POINT_VEC3:Smoke( SmokeColor ) + self:F2( { SmokeColor, self.PointVec3 } ) + trigger.action.smoke( self.PointVec3, SmokeColor ) +end + +--- Smoke the POINT_VEC3 Green. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeGreen() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Green ) +end + +--- Smoke the POINT_VEC3 Red. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeRed() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Red ) +end + +--- Smoke the POINT_VEC3 White. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeWhite() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.White ) +end + +--- Smoke the POINT_VEC3 Orange. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeOrange() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Orange ) +end + +--- Smoke the POINT_VEC3 Blue. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeBlue() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Blue ) +end + +--- Flares the point in a color. +-- @param #POINT_VEC3 self +-- @param Point#POINT_VEC3.FlareColor +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:Flare( FlareColor, Azimuth ) + self:F2( { FlareColor, self.PointVec3 } ) + trigger.action.signalFlare( self.PointVec3, FlareColor, Azimuth and Azimuth or 0 ) +end + +--- Flare the POINT_VEC3 White. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareWhite( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.White, Azimuth ) +end + +--- Flare the POINT_VEC3 Yellow. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareYellow( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Yellow, Azimuth ) +end + +--- Flare the POINT_VEC3 Green. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareGreen( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Green, Azimuth ) +end + +--- Flare the POINT_VEC3 Red. +-- @param #POINT_VEC3 self +function POINT_VEC3:FlareRed( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Red, Azimuth ) +end + + +--- The POINT_VEC2 class +-- @type POINT_VEC2 +-- @extends Point#POINT_VEC3 +POINT_VEC2 = { + ClassName = "POINT_VEC2", + } + +--- Create a new POINT_VEC2 object. +-- @param #POINT_VEC2 self +-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. +-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right. +-- @param DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height. +-- @return Point#POINT_VEC2 +function POINT_VEC2:New( x, y, LandHeightAdd ) + + local LandHeight = land.getHeight( { ["x"] = x, ["y"] = y } ) + if LandHeightAdd then + LandHeight = LandHeight + LandHeightAdd + end + + local self = BASE:Inherit( self, POINT_VEC3:New( x, LandHeight, y ) ) + self:F2( { x, y, LandHeightAdd } ) + + return self +end + + diff --git a/Moose Development/Moose/Scheduler.lua b/Moose Development/Moose/Scheduler.lua index a45b85135..a9bfddb62 100644 --- a/Moose Development/Moose/Scheduler.lua +++ b/Moose Development/Moose/Scheduler.lua @@ -121,7 +121,7 @@ function SCHEDULER:_Scheduler() self:T( { Status, Result } ) - if Status and Status == true and Result and Result == true then + if Status and ( ( not Result ) or ( Result and Result ~= false ) ) then if self.Repeat and ( not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) ) then timer.scheduleFunction( self._Scheduler, diff --git a/Moose Development/Moose/Spawn.lua b/Moose Development/Moose/Spawn.lua index afe13cae3..8c63ae23c 100644 --- a/Moose Development/Moose/Spawn.lua +++ b/Moose Development/Moose/Spawn.lua @@ -1,7 +1,7 @@ ---- Dynamic spawning of groups (and units). +--- This module contains the SPAWN class. -- --- @{#SPAWN} class --- =============== +-- 1) @{Spawn#SPAWN} class, extends @{Base#BASE} +-- ============================================= -- The @{#SPAWN} class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned. -- For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the *"Spawn Template"* of the SPAWN object. -- A reference to this Spawn Template needs to be provided when constructing the SPAWN object, by indicating the name of the group within the mission editor in the constructor methods. @@ -24,8 +24,8 @@ -- * It is important to defined BEFORE you spawn new groups, a proper initialization of the SPAWN instance is done with the options you want to use. -- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn Template(s), or the SPAWN module logic won't work anymore. -- --- SPAWN construction methods: --- =========================== +-- 1.1) SPAWN construction methods +-- ------------------------------- -- Create a new SPAWN object with the @{#SPAWN.New} or the @{#SPAWN.NewWithAlias} methods: -- -- * @{#SPAWN.New}: Creates a new SPAWN object taking the name of the group that functions as the Template. @@ -34,8 +34,8 @@ -- The initialization functions will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons. -- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient. -- --- SPAWN initialization methods: --- ============================= +-- 1.2) SPAWN initialization methods +-- --------------------------------- -- A spawn object will behave differently based on the usage of initialization methods: -- -- * @{#SPAWN.Limit}: Limits the amount of groups that can be alive at the same time and that can be dynamically spawned. @@ -45,8 +45,8 @@ -- * @{#SPAWN.Array}: Make groups visible before they are actually activated, and order these groups like a batallion in an array. -- * @{#SPAWN.InitRepeat}: Re-spawn groups when they land at the home base. Similar functions are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}. -- --- SPAWN spawning methods: --- ======================= +-- 1.3) SPAWN spawning methods +-- --------------------------- -- Groups can be spawned at different times and methods: -- -- * @{#SPAWN.Spawn}: Spawn one new group based on the last spawned index. @@ -58,8 +58,8 @@ -- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object. -- You can use the @{GROUP} object to do further actions with the DCSGroup. -- --- SPAWN object cleaning: --- ========================= +-- 1.4) SPAWN object cleaning +-- -------------------------- -- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive. -- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't, -- and it may occur that no new groups are or can be spawned as limits are reached. @@ -70,7 +70,7 @@ -- This models AI that has succesfully returned to their airbase, to restart their combat activities. -- Check the @{#SPAWN.CleanUp} for further info. -- --- ==== +-- -- @module Spawn -- @author FlightControl @@ -473,6 +473,12 @@ function SPAWN:SpawnWithIndex( SpawnIndex ) end self.SpawnGroups[self.SpawnIndex].Spawned = true + + local SpawnGroup = self.SpawnGroups[self.SpawnIndex].Group -- Group#GROUP + local Route = SpawnGroup:GetTaskRoute() + SpawnGroup:Route(Route) + + return self.SpawnGroups[self.SpawnIndex].Group else --self:E( { self.SpawnTemplatePrefix, "No more Groups to Spawn:", SpawnIndex, self.SpawnMaxGroups } ) @@ -980,11 +986,12 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) SpawnTemplate.name = self:SpawnGroupName( SpawnIndex ) SpawnTemplate.groupId = nil - SpawnTemplate.lateActivation = false + --SpawnTemplate.lateActivation = false + SpawnTemplate.lateActivation = false -- TODO BUGFIX if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then self:T( "For ground units, visible needs to be false..." ) - SpawnTemplate.visible = false + SpawnTemplate.visible = false -- TODO BUGFIX end if SpawnTemplate.SpawnCategoryID == Group.Category.HELICOPTER or SpawnTemplate.SpawnCategoryID == Group.Category.AIRPLANE then @@ -1032,7 +1039,7 @@ end -- @param #number SpawnIndex -- @return #SPAWN self function SPAWN:_RandomizeTemplate( SpawnIndex ) - self:F( { self.SpawnTemplatePrefix, SpawnIndex } ) + self:F( { self.SpawnTemplatePrefix, SpawnIndex, self.SpawnRandomizeTemplate } ) if self.SpawnRandomizeTemplate then self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefixTable[ math.random( 1, #self.SpawnTemplatePrefixTable ) ] diff --git a/Moose Development/Moose/Static.lua b/Moose Development/Moose/Static.lua new file mode 100644 index 000000000..ba6467023 --- /dev/null +++ b/Moose Development/Moose/Static.lua @@ -0,0 +1,81 @@ +--- This module contains the STATIC class. +-- +-- 1) @{Static#STATIC} class, extends @{Unit#UNIT} +-- =============================================== +-- Statics are **Static Units** defined within the Mission Editor. +-- Note that Statics are almost the same as Units, but they don't have a controller. +-- The @{Static#STATIC} class is a wrapper class to handle the DCS Static objects: +-- +-- * Wraps the DCS Static objects. +-- * Support all DCS Static APIs. +-- * Enhance with Static specific APIs not in the DCS API set. +-- +-- 1.1) STATIC reference methods +-- ----------------------------- +-- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object. +-- This is done at the beginning of the mission (when the mission starts). +-- +-- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference +-- using the Static Name. +-- +-- Another thing to know is that STATIC objects do not "contain" the DCS Static object. +-- The STATIc methods will reference the DCS Static object by name when it is needed during API execution. +-- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file. +-- +-- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance: +-- +-- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name. +-- +-- IMPORTANT: ONE SHOULD NEVER SANATIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil). +-- +-- @module Static +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Message" ) + + +--- The STATIC class +-- @type STATIC +-- @extends Unit#UNIT +STATIC = { + ClassName = "STATIC", +} + + +--- Finds a STATIC from the _DATABASE using the relevant Static Name. +-- As an optional parameter, a briefing text can be given also. +-- @param #STATIC self +-- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor. +-- @return #STATIC +function STATIC:FindByName( StaticName ) + local StaticFound = _DATABASE:FindStatic( StaticName ) + + if StaticFound then + StaticFound:F( { StaticName } ) + + return StaticFound + end + + error( "STATIC not found for: " .. StaticName ) +end + +function STATIC:Register( StaticName ) + local self = BASE:Inherit( self, UNIT:Register( StaticName ) ) + + self:F( StaticName ) + + return self +end + + +function STATIC:GetDCSUnit() + local DCSStatic = StaticObject.getByName( self.UnitName ) + + if DCSStatic then + return DCSStatic + end + + return nil +end diff --git a/Moose Development/Moose/Unit.lua b/Moose Development/Moose/Unit.lua index 5df82eeec..cdb8a43f8 100644 --- a/Moose Development/Moose/Unit.lua +++ b/Moose Development/Moose/Unit.lua @@ -1,8 +1,8 @@ ---- UNIT Class +--- This module contains the UNIT class. -- --- @{UNIT} class --- ============== --- The @{UNIT} class is a wrapper class to handle the DCS Unit objects: +-- 1) @{Unit#UNIT} class, extends @{Base#BASE} +-- =========================================== +-- The @{Unit#UNIT} class is a wrapper class to handle the DCS Unit objects: -- -- * Support all DCS Unit APIs. -- * Enhance with Unit specific APIs not in the DCS Unit API set. @@ -10,8 +10,8 @@ -- * Manage the "state" of the DCS Unit. -- -- --- UNIT reference methods --- ====================== +-- 1.1) UNIT reference methods +-- ---------------------- -- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Unit objects are spawned (using the @{SPAWN} class). -- @@ -29,19 +29,15 @@ -- -- IMPORTANT: ONE SHOULD NEVER SANATIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil). -- --- DCS UNIT APIs --- ============= +-- 1.2) DCS UNIT APIs +-- ------------------ -- The DCS Unit APIs are used extensively within MOOSE. The UNIT class has for each DCS Unit API a corresponding method. -- To be able to distinguish easily in your code the difference between a UNIT API call and a DCS Unit API call, -- the first letter of the method is also capitalized. So, by example, the DCS Unit method @{DCSUnit#Unit.getName}() -- is implemented in the UNIT class as @{#UNIT.GetName}(). -- --- Additional UNIT APIs --- ==================== --- The UNIT class comes with additional methods. Find below a summary. --- --- Smoke, Flare Units --- ------------------ +-- 1.3) Smoke, Flare Units +-- ----------------------- -- The UNIT class provides methods to smoke or flare units easily. -- The @{#UNIT.SmokeBlue}(), @{#UNIT.SmokeGreen}(),@{#UNIT.SmokeOrange}(), @{#UNIT.SmokeRed}(), @{#UNIT.SmokeRed}() methods -- will smoke the unit in the corresponding color. Note that smoking a unit is done at the current position of the DCS Unit. @@ -49,26 +45,25 @@ -- The @{#UNIT.FlareGreen}(), @{#UNIT.FlareRed}(), @{#UNIT.FlareWhite}(), @{#UNIT.FlareYellow}() -- methods will fire off a flare in the air with the corresponding color. Note that a flare is a one-off shot and its effect is of very short duration. -- --- Position, Point --- --------------- +-- 1.4) Location Position, Point +-- ----------------------------- -- The UNIT class provides methods to obtain the current point or position of the DCS Unit. --- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetPointVec3}() will obtain the current location of the DCS Unit in a Vec2 (2D) or a Vec3 (3D) vector respectively. --- If you want to obtain the complete 3D position including oriëntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively. +-- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetPointVec3}() will obtain the current **location** of the DCS Unit in a Vec2 (2D) or a **point** in a Vec3 (3D) vector respectively. +-- If you want to obtain the complete **3D position** including oriëntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively. -- --- Alive --- ----- +-- 1.5) Test if alive +-- ------------------ -- The @{#UNIT.IsAlive}(), @{#UNIT.IsActive}() methods determines if the DCS Unit is alive, meaning, it is existing and active. -- --- Test for other units in radius --- ------------------------------ --- One can test if another DCS Unit is within a given radius of the current DCS Unit, by using the @{#UNIT.OtherUnitInRadius}() method. --- --- More functions will be added --- ---------------------------- --- During the MOOSE development, more functions will be added. A complete list of the current functions is below. --- +-- 1.6) Test for proximity +-- ----------------------- +-- The UNIT class contains methods to test the location or proximity against zones or other objects. -- +-- ### 1.6.1) Zones +-- To test whether the Unit is within a **zone**, use the @{#UNIT.IsInZone}() or the @{#UNIT.IsNotInZone}() methods. Any zone can be tested on, but the zone must be derived from @{Zone#ZONE_BASE}. -- +-- ### 1.6.2) Units +-- Test if another DCS Unit is within a given radius of the current DCS Unit, use the @{#UNIT.OtherUnitInRadius}() method. -- -- @module Unit -- @author FlightControl @@ -540,7 +535,7 @@ function UNIT:GetPointVec2() UnitPointVec2.x = UnitPointVec3.x UnitPointVec2.y = UnitPointVec3.z - self:T3( UnitPointVec2 ) + self:T2( UnitPointVec2 ) return UnitPointVec2 end @@ -601,7 +596,35 @@ function UNIT:GetVelocity() return nil end - + +-- Is functions + +--- Returns true if the unit is within a @{Zone}. +-- @param #UNIT self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the unit is within the @{Zone#ZONE_BASE} +function UNIT:IsInZone( Zone ) + self:F2( { self.UnitName, Zone } ) + + local IsInZone = Zone:IsPointVec3InZone( self:GetPointVec3() ) + + self:T( { IsInZone } ) + return IsInZone +end + +--- Returns true if the unit is not within a @{Zone}. +-- @param #UNIT self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the unit is not within the @{Zone#ZONE_BASE} +function UNIT:IsNotInZone( Zone ) + self:F2( { self.UnitName, Zone } ) + + local IsInZone = not Zone:IsPointVec3InZone( self:GetPointVec3() ) + + self:T( { IsInZone } ) + return IsInZone +end + --- Returns true if the DCS Unit is in the air. -- @param Unit#UNIT self -- @return #boolean true if in the air. diff --git a/Moose Development/Moose/Zone.lua b/Moose Development/Moose/Zone.lua index c85cae774..a27c3f1df 100644 --- a/Moose Development/Moose/Zone.lua +++ b/Moose Development/Moose/Zone.lua @@ -1,79 +1,479 @@ ---- ZONE Classes +--- This module contains the ZONE classes, inherited from @{Zone#ZONE_BASE}. +-- There are essentially two core functions that zones accomodate: +-- +-- * Test if an object is within the zone boundaries. +-- * Provide the zone behaviour. Some zones are static, while others are moveable. +-- +-- The object classes are using the zone classes to test the zone boundaries, which can take various forms: +-- +-- * Test if completely within the zone. +-- * Test if partly within the zone (for @{Group#GROUP} objects). +-- * Test if not in the zone. +-- * Distance to the nearest intersecting point of the zone. +-- * Distance to the center of the zone. +-- * ... +-- +-- Each of these ZONE classes have a zone name, and specific parameters defining the zone type: +-- +-- * @{Zone#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes. +-- * @{Zone#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius. +-- * @{Zone#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor. +-- * @{Zone#ZONE_UNIT}: The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- * @{Zone#ZONE_POLYGON}: The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- +-- Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}: +-- +-- * @{#ZONE_BASE.IsPointVec2InZone}: Returns if a location is within the zone. +-- * @{#ZONE_BASE.IsPointVec3InZone}: Returns if a point is within the zone. +-- +-- === +-- +-- 1) @{Zone#ZONE_BASE} class, extends @{Base#BASE} +-- ================================================ +-- The ZONE_BASE class defining the base for all other zone classes. +-- +-- === +-- +-- 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE} +-- ======================================================= +-- The ZONE_RADIUS class defined by a zone name, a location and a radius. +-- +-- === +-- +-- 3) @{Zone#ZONE} class, extends @{Zone#ZONE_RADIUS} +-- ========================================== +-- The ZONE class, defined by the zone name as defined within the Mission Editor. +-- +-- === +-- +-- 4) @{Zone#ZONE_UNIT} class, extends @{Zone#ZONE_RADIUS} +-- ======================================================= +-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- +-- === +-- +-- 5) @{Zone#ZONE_POLYGON} class, extends @{Zone#ZONE_BASE} +-- ======================================================== +-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- +-- === +-- -- @module Zone +-- @author FlightControl + Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Message" ) +Include.File( "Point" ) ---- The ZONE class --- @type ZONE --- @Extends Base#BASE -ZONE = { - ClassName="ZONE", + + +--- The ZONE_BASE class +-- @type ZONE_BASE +-- @extends Base#BASE +ZONE_BASE = { + ClassName = "ZONE_BASE", + } + +--- ZONE_BASE constructor +-- @param #ZONE_BASE self +-- @param #string ZoneName Name of the zone. +-- @return #ZONE_BASE self +function ZONE_BASE:New( ZoneName ) + local self = BASE:Inherit( self, BASE:New() ) + self:F( ZoneName ) + + self.ZoneName = ZoneName + + return self +end + +--- Returns if a location is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_BASE:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + return false +end + +--- Returns if a point is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec3 PointVec3 The point to test. +-- @return #boolean true if the point is within the zone. +function ZONE_BASE:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( { x = PointVec3.x, y = PointVec3.z } ) + + return InZone +end + +--- Smokes the zone boundaries in a color. +-- @param #ZONE_BASE self +-- @param SmokeColor The smoke color. +function ZONE_BASE:SmokeZone( SmokeColor ) + self:F2( SmokeColor ) + +end + + +--- The ZONE_RADIUS class, defined by a zone name, a location and a radius. +-- @type ZONE_RADIUS +-- @field DCSTypes#Vec2 PointVec2 The current location of the zone. +-- @field DCSTypes#Distance Radius The radius of the zone. +-- @extends Zone#ZONE_BASE +ZONE_RADIUS = { + ClassName="ZONE_RADIUS", } - -function ZONE:New( ZoneName ) - local self = BASE:Inherit( self, BASE:New() ) - self:F( ZoneName ) - local Zone = trigger.misc.getZone( ZoneName ) - - if not Zone then - error( "Zone " .. ZoneName .. " does not exist." ) - return nil - end - - self.Zone = Zone - self.ZoneName = ZoneName +--- Constructor of ZONE_RADIUS, taking the zone name, the zone location and a radius. +-- @param #ZONE_RADIUS self +-- @param #string ZoneName Name of the zone. +-- @param DCSTypes#Vec2 PointVec2 The location of the zone. +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:New( ZoneName, PointVec2, Radius ) + local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) + self:F( { ZoneName, PointVec2, Radius } ) + + self.Radius = Radius + self.PointVec2 = PointVec2 return self end -function ZONE:GetPointVec2() - self:F( self.ZoneName ) +--- Smokes the zone boundaries in a color. +-- @param #ZONE_RADIUS self +-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color. +-- @param #number Points (optional) The amount of points in the circle. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:SmokeZone( SmokeColor, Points ) + self:F2( SmokeColor ) - local Zone = trigger.misc.getZone( self.ZoneName ) - local Point = { x = Zone.point.x, y = Zone.point.z } + local Point = {} + local PointVec2 = self:GetPointVec2() - self:T( { Zone, Point } ) - - return Point -end + Points = Points and Points or 360 -function ZONE:GetPointVec3( Height ) - self:F( self.ZoneName ) - - local Zone = trigger.misc.getZone( self.ZoneName ) - local Point = { x = Zone.point.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = Zone.point.z } - - self:T( { Zone, Point } ) + local Angle + local RadialBase = math.pi*2 - return Point + for Angle = 0, 360, 360 / Points do + local Radial = Angle * RadialBase / 360 + Point.x = PointVec2.x + math.cos( Radial ) * self:GetRadius() + Point.y = PointVec2.y + math.sin( Radial ) * self:GetRadius() + POINT_VEC2:New( Point.x, Point.y ):Smoke( SmokeColor ) + end + + return self end -function ZONE:GetRandomPointVec2() + +--- Flares the zone boundaries in a color. +-- @param #ZONE_RADIUS self +-- @param #POINT_VEC3.FlareColor FlareColor The flare color. +-- @param #number Points (optional) The amount of points in the circle. +-- @param DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth ) + self:F2( { FlareColor, Azimuth } ) + + local Point = {} + local PointVec2 = self:GetPointVec2() + + Points = Points and Points or 360 + + local Angle + local RadialBase = math.pi*2 + + for Angle = 0, 360, 360 / Points do + local Radial = Angle * RadialBase / 360 + Point.x = PointVec2.x + math.cos( Radial ) * self:GetRadius() + Point.y = PointVec2.y + math.sin( Radial ) * self:GetRadius() + POINT_VEC2:New( Point.x, Point.y ):Flare( FlareColor, Azimuth ) + end + + return self +end + +--- Returns the radius of the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Distance The radius of the zone. +function ZONE_RADIUS:GetRadius() + self:F2( self.ZoneName ) + + self:T2( { self.Radius } ) + + return self.Radius +end + +--- Sets the radius of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return DCSTypes#Distance The radius of the zone. +function ZONE_RADIUS:SetRadius( Radius ) + self:F2( self.ZoneName ) + + self.Radius = Radius + self:T2( { self.Radius } ) + + return self.Radius +end + +--- Returns the location of the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Vec2 The location of the zone. +function ZONE_RADIUS:GetPointVec2() + self:F2( self.ZoneName ) + + self:T2( { self.PointVec2 } ) + + return self.PointVec2 +end + +--- Sets the location of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The new location of the zone. +-- @return DCSTypes#Vec2 The new location of the zone. +function ZONE_RADIUS:SetPointVec2( PointVec2 ) + self:F2( self.ZoneName ) + + self.PointVec2 = PointVec2 + + self:T2( { self.PointVec2 } ) + + return self.PointVec2 +end + +--- Returns the point of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. +-- @return DCSTypes#Vec3 The point of the zone. +function ZONE_RADIUS:GetPointVec3( Height ) + self:F2( self.ZoneName ) + + local PointVec2 = self:GetPointVec2() + + local PointVec3 = { x = PointVec2.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = PointVec2.y } + + self:T2( { PointVec3 } ) + + return PointVec3 +end + + +--- Returns if a location is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_RADIUS:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local ZonePointVec2 = self:GetPointVec2() + + if (( PointVec2.x - ZonePointVec2.x )^2 + ( PointVec2.y - ZonePointVec2.y ) ^2 ) ^ 0.5 <= self:GetRadius() then + return true + end + + return false +end + +--- Returns if a point is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec3 PointVec3 The point to test. +-- @return #boolean true if the point is within the zone. +function ZONE_RADIUS:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( { x = PointVec3.x, y = PointVec3.z } ) + + return InZone +end + +--- Returns a random location within the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Vec2 The random location within the zone. +function ZONE_RADIUS:GetRandomPointVec2() self:F( self.ZoneName ) local Point = {} + local PointVec2 = self:GetPointVec2() - local Zone = trigger.misc.getZone( self.ZoneName ) - local angle = math.random() * math.pi*2; - Point.x = Zone.point.x + math.cos( angle ) * math.random() * Zone.radius; - Point.y = Zone.point.z + math.sin( angle ) * math.random() * Zone.radius; + Point.x = PointVec2.x + math.cos( angle ) * math.random() * self:GetRadius(); + Point.y = PointVec2.y + math.sin( angle ) * math.random() * self:GetRadius(); - self:T( { Zone, Point } ) + self:T( { Point } ) return Point end -function ZONE:GetRadius() - self:F( self.ZoneName ) - local Zone = trigger.misc.getZone( self.ZoneName ) - self:T( { Zone } ) +--- The ZONE class, defined by the zone name as defined within the Mission Editor. The location and the radius are automatically collected from the mission settings. +-- @type ZONE +-- @extends Zone#ZONE_RADIUS +ZONE = { + ClassName="ZONE", + } - return Zone.radius + +--- Constructor of ZONE, taking the zone name. +-- @param #ZONE self +-- @param #string ZoneName The name of the zone as defined within the mission editor. +-- @return #ZONE +function ZONE:New( ZoneName ) + + local Zone = trigger.misc.getZone( ZoneName ) + + if not Zone then + error( "Zone " .. ZoneName .. " does not exist." ) + return nil + end + + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, { x = Zone.point.x, y = Zone.point.z }, Zone.radius ) ) + self:F( ZoneName ) + + self.Zone = Zone + + return self +end + + +--- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- @type ZONE_UNIT +-- @field Unit#UNIT ZoneUNIT +-- @extends Zone#ZONE_RADIUS +ZONE_UNIT = { + ClassName="ZONE_UNIT", + } + +--- Constructor to create a ZONE_UNIT instance, taking the zone name, a zone unit and a radius. +-- @param #ZONE_UNIT self +-- @param #string ZoneName Name of the zone. +-- @param Unit#UNIT ZoneUNIT The unit as the center of the zone. +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return #ZONE_UNIT self +function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetPointVec2(), Radius ) ) + self:F( { ZoneName, ZoneUNIT:GetPointVec2(), Radius } ) + + self.ZoneUNIT = ZoneUNIT + + return self +end + + +--- Returns the current location of the @{Unit#UNIT}. +-- @param #ZONE_UNIT self +-- @return DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location. +function ZONE_UNIT:GetPointVec2() + self:F( self.ZoneName ) + + local ZonePointVec2 = self.ZoneUNIT:GetPointVec2() + + self:T( { ZonePointVec2 } ) + + return ZonePointVec2 +end + + +--- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- @type ZONE_POLYGON +-- @extends Zone#ZONE_BASE +ZONE_POLYGON = { + ClassName="ZONE_POLYGON", + } + +--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the name of the @{Group#GROUP} defined within the Mission Editor. +-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON. +-- @param #ZONE_POLYGON self +-- @param #string ZoneName Name of the zone. +-- @param Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:New( ZoneName, ZoneGroup ) + local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) + self:F( { ZoneName, ZoneGroup } ) + + local GroupPoints = ZoneGroup:GetTaskRoute() + local i = 0 + + self.Polygon = {} + + for i = 1, #GroupPoints do + self.Polygon[i] = {} + self.Polygon[i].x = GroupPoints[i].x + self.Polygon[i].y = GroupPoints[i].y + end + + return self +end + +--- Smokes the zone boundaries in a color. +-- @param #ZONE_POLYGON self +-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:SmokeZone( SmokeColor ) + self:F2( SmokeColor ) + + local i + local j + local Segments = 10 + + i = 1 + j = #self.Polygon + + while i <= #self.Polygon do + self:T( { i, j, self.Polygon[i], self.Polygon[j] } ) + + local DeltaX = self.Polygon[j].x - self.Polygon[i].x + local DeltaY = self.Polygon[j].y - self.Polygon[i].y + + for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line. + local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments ) + local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments ) + POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor ) + end + j = i + i = i + 1 + end + + return self +end + + + + +--- Returns if a location is within the zone. +-- @param #ZONE_POLYGON self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_POLYGON:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local i + local j + local c = false + + i = 1 + j = #self.Polygon + + while i < #self.Polygon do + j = i + i = i + 1 + self:T( { i, j, self.Polygon[i], self.Polygon[j] } ) + if ( ( ( self.Polygon[i].y > PointVec2.y ) ~= ( self.Polygon[j].y > PointVec2.y ) ) and + ( PointVec2.x < ( self.Polygon[j].x - self.Polygon[i].x ) * ( PointVec2.y - self.Polygon[i].y ) / ( self.Polygon[j].y - self.Polygon[i].y ) + self.Polygon[i].x ) + ) then + c = not c + end + self:T2( { "c = ", c } ) + end + + self:T( { "c = ", c } ) + return c end 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 a555b44df..92334c9b8 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: 20160527_1352' ) +env.info( 'Moose Generation Timestamp: 20160606_1516' ) local base = _G env.info("Loading MOOSE " .. base.timer.getAbsTime() ) @@ -2930,12 +2930,12 @@ end --- Trace a function call. Must be at the beginning of the function logic. -- @param #BASE self -- @param Arguments A #table or any field. -function BASE:F( Arguments ) +function BASE:F( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if _TraceOn and ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) then - local DebugInfoCurrent = debug.getinfo( 2, "nl" ) - local DebugInfoFrom = debug.getinfo( 3, "l" ) + local DebugInfoCurrent = DebugInfoCurrentParam and DebugInfoCurrentParam or debug.getinfo( 2, "nl" ) + local DebugInfoFrom = DebugInfoFromParam and DebugInfoFromParam or debug.getinfo( 3, "l" ) local Function = "function" if DebugInfoCurrent.name then @@ -2958,8 +2958,11 @@ end -- @param Arguments A #table or any field. function BASE:F2( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 2 then - self:F( Arguments ) + self:F( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -2969,8 +2972,11 @@ end -- @param Arguments A #table or any field. function BASE:F3( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 3 then - self:F( Arguments ) + self:F( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -2978,12 +2984,12 @@ end --- Trace a function logic. Can be anywhere within the function logic. -- @param #BASE self -- @param Arguments A #table or any field. -function BASE:T( Arguments ) +function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if _TraceOn and ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) then - local DebugInfoCurrent = debug.getinfo( 2, "nl" ) - local DebugInfoFrom = debug.getinfo( 3, "l" ) + local DebugInfoCurrent = DebugInfoCurrentParam and DebugInfoCurrentParam or debug.getinfo( 2, "nl" ) + local DebugInfoFrom = DebugInfoFromParam and DebugInfoFromParam or debug.getinfo( 3, "l" ) local Function = "function" if DebugInfoCurrent.name then @@ -3006,8 +3012,11 @@ end -- @param Arguments A #table or any field. function BASE:T2( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 2 then - self:T( Arguments ) + self:T( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -3017,8 +3026,11 @@ end -- @param Arguments A #table or any field. function BASE:T3( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 3 then - self:T( Arguments ) + self:T( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -3170,7 +3182,7 @@ function SCHEDULER:_Scheduler() self:T( { Status, Result } ) - if Status and Status == true and Result and Result == true then + if Status and ( ( not Result ) or ( Result and Result ~= false ) ) then if self.Repeat and ( not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) ) then timer.scheduleFunction( self._Scheduler, @@ -4071,36 +4083,151 @@ function MENU_COALITION_COMMAND:Remove() self.ParentMenu.Menus[self.MenuPath] = nil return nil end ---- GROUP class. --- --- @{GROUP} class --- ============== --- The @{GROUP} class is a wrapper class to handle the DCS Group objects: +--- This module contains the GROUP class. -- +-- 1) @{Group#GROUP} class, extends @{Base#BASE} +-- ============================================= +-- The @{Group#GROUP} class is a wrapper class to handle the DCS Group objects: +-- -- * Support all DCS Group APIs. -- * Enhance with Group specific APIs not in the DCS Group API set. -- * Handle local Group Controller. -- * Manage the "state" of the DCS Group. --- --- --- GROUP reference methods --- ======================= +-- +-- **IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** +-- +-- 1.1) GROUP reference methods +-- ----------------------- -- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{SPAWN} class). --- +-- -- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the DCS Group or the DCS GroupName. --- --- Another thing to know is that GROUP objects do not "contain" the DCS Group object. +-- +-- Another thing to know is that GROUP objects do not "contain" the DCS Group object. -- The GROUP methods will reference the DCS Group object by name when it is needed during API execution. -- If the DCS Group object does not exist or is nil, the GROUP methods will return nil and log an exception in the DCS.log file. --- +-- -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: --- +-- -- * @{#GROUP.Find}(): Find a GROUP instance from the _DATABASE object using a DCS Group object. -- * @{#GROUP.FindByName}(): Find a GROUP instance from the _DATABASE object using a DCS Group name. --- --- IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil). +-- +-- 1.2) GROUP task methods +-- ----------------------- +-- Several group task methods are available that help you to prepare tasks. +-- These methods return a string consisting of the task description, which can then be given to either a @{Group#GROUP.PushTask} or @{Group#SetTask} method to assign the task to the GROUP. +-- Tasks are specific for the category of the GROUP, more specific, for AIR, GROUND or AIR and GROUND. +-- Each task description where applicable indicates for which group category the task is valid. +-- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks. +-- +-- ### 1.2.1) Assigned task methods +-- +-- Assigned task methods make the group execute the task where the location of the (possible) targets of the task are known before being detected. +-- This is different from the EnRoute tasks, where the targets of the task need to be detected before the task can be executed. +-- +-- Find below a list of the **assigned task** methods: +-- +-- * @{#GROUP.TaskAttackGroup}: (AIR) Attack a Group. +-- * @{#GROUP.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c). +-- * @{#GROUP.TaskAttackUnit}: (AIR) Attack the Unit. +-- * @{#GROUP.TaskBombing}: (AIR) Delivering weapon at the point on the ground. +-- * @{#GROUP.TaskBombingRunway}: (AIR) Delivering weapon on the runway. +-- * @{#GROUP.TaskEmbarking}: (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group. +-- * @{#GROUP.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location. +-- * @{#GROUP.TaskEscort}: (AIR) Escort another airborne group. +-- * @{#GROUP.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction. +-- * @{#GROUP.TaskFireAtPoint}: (GROUND) Fire at a VEC2 point until ammunition is finished. +-- * @{#GROUP.TaskFollow}: (AIR) Following another airborne group. +-- * @{#GROUP.TaskHold}: (GROUND) Hold ground group from moving. +-- * @{#GROUP.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the group. +-- * @{#GROUP.TaskLand}: (AIR HELICOPTER) Landing at the ground. For helicopters only. +-- * @{#GROUP.TaskLandAtZone}: (AIR) Land the group at a @{Zone#ZONE_RADIUS). +-- * @{#GROUP.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the group at a specified alititude. +-- * @{#GROUP.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. +-- * @{#GROUP.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters. +-- * @{#GROUP.TaskRoute}: (AIR + GROUND) Return a Misson task to follow a given route defined by Points. +-- * @{#GROUP.TaskRouteToVec2}: (AIR + GROUND) Make the Group move to a given point. +-- * @{#GROUP.TaskRouteToVec3}: (AIR + GROUND) Make the Group move to a given point. +-- * @{#GROUP.TaskRouteToZone}: (AIR + GROUND) Route the group to a given zone. +-- +-- ### 1.2.2) EnRoute task methods +-- +-- EnRoute tasks require the targets of the task need to be detected by the group (using its sensors) before the task can be executed: +-- +-- * @{#GROUP.EnRouteTaskAWACS}: (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters. +-- * @{#GROUP.EnRouteTaskEngageGroup}: (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskEngageTargets}: (AIR) Engaging targets of defined types. +-- * @{#GROUP.EnRouteTaskEWR}: (AIR) Attack the Unit. +-- * @{#GROUP.EnRouteTaskFAC}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskFAC_EngageGroup}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskTanker}: (AIR) Aircraft will act as a tanker for friendly units. No parameters. +-- +-- ### 1.2.3) Preparation task methods +-- +-- There are certain task methods that allow to tailor the task behaviour: +-- +-- * @{#GROUP.TaskWrappedAction}: Return a WrappedAction Task taking a Command. +-- * @{#GROUP.TaskCombo}: Return a Combo Task taking an array of Tasks. +-- * @{#GROUP.TaskCondition}: Return a condition section for a controlled task. +-- * @{#GROUP.TaskControlled}: Return a Controlled Task taking a Task and a TaskCondition. +-- +-- ### 1.2.4) Obtain the mission from group templates +-- +-- Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another: +-- +-- * @{#GROUP.TaskMission}: (AIR + GROUND) Return a mission task from a mission template. +-- +-- 1.3) GROUP Command methods +-- -------------------------- +-- Group **command methods** prepare the execution of commands using the @{#GROUP.SetCommand} method: +-- +-- * @{#GROUP.CommandDoScript}: Do Script command. +-- * @{#GROUP.CommandSwitchWayPoint}: Perform a switch waypoint command. +-- +-- 1.4) GROUP Option methods +-- ------------------------- +-- Group **Option methods** change the behaviour of the Group while being alive. +-- +-- ### 1.4.1) Rule of Engagement: +-- +-- * @{#GROUP.OptionROEWeaponFree} +-- * @{#GROUP.OptionROEOpenFire} +-- * @{#GROUP.OptionROEReturnFire} +-- * @{#GROUP.OptionROEEvadeFire} +-- +-- To check whether an ROE option is valid for a specific group, use: +-- +-- * @{#GROUP.OptionROEWeaponFreePossible} +-- * @{#GROUP.OptionROEOpenFirePossible} +-- * @{#GROUP.OptionROEReturnFirePossible} +-- * @{#GROUP.OptionROEEvadeFirePossible} +-- +-- ### 1.4.2) Rule on thread: +-- +-- * @{#GROUP.OptionROTNoReaction} +-- * @{#GROUP.OptionROTPassiveDefense} +-- * @{#GROUP.OptionROTEvadeFire} +-- * @{#GROUP.OptionROTVertical} +-- +-- To test whether an ROT option is valid for a specific group, use: +-- +-- * @{#GROUP.OptionROTNoReactionPossible} +-- * @{#GROUP.OptionROTPassiveDefensePossible} +-- * @{#GROUP.OptionROTEvadeFirePossible} +-- * @{#GROUP.OptionROTVerticalPossible} +-- +-- 1.5) GROUP Zone validation methods +-- ---------------------------------- +-- The group can be validated whether it is completely, partly or not within a @{Zone}. +-- Use the following Zone validation methods on the group: +-- +-- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Zone}. +-- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Zone}. +-- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Zone}. +-- +-- The zone can be of any @{Zone} class derived from @{Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. +-- -- @module Group -- @author FlightControl @@ -4115,14 +4242,14 @@ Include.File( "Unit" ) -- @field DCSGroup#Group DCSGroup The DCS group class. -- @field #string GroupName The name of the group. GROUP = { - ClassName = "GROUP", - GroupName = "", - GroupID = 0, - Controller = nil, - DCSGroup = nil, - WayPointFunctions = {}, - } - + ClassName = "GROUP", + GroupName = "", + GroupID = 0, + Controller = nil, + DCSGroup = nil, + WayPointFunctions = {}, +} + --- A DCSGroup -- @type DCSGroup -- @field id_ The ID of the group in DCS @@ -4132,10 +4259,10 @@ GROUP = { -- @param DCSGroup#Group GroupName The DCS Group name -- @return #GROUP self function GROUP:Register( GroupName ) - local self = BASE:Inherit( self, BASE:New() ) - self:F2( GroupName ) - self.GroupName = GroupName - return self + local self = BASE:Inherit( self, BASE:New() ) + self:F2( GroupName ) + self.GroupName = GroupName + return self end -- Reference methods. @@ -4168,11 +4295,11 @@ end -- @return DCSGroup#Group The DCS Group. function GROUP:GetDCSGroup() local DCSGroup = Group.getByName( self.GroupName ) - + if DCSGroup then return DCSGroup end - + return nil end @@ -4183,27 +4310,27 @@ end -- @return #boolean true if the DCS Group is alive. function GROUP:IsAlive() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupIsAlive = DCSGroup:isExist() self:T3( GroupIsAlive ) return GroupIsAlive end - + return nil end ---- Destroys the DCS Group and all of its DCS Units. +--- Destroys the DCS Group and all of its DCS Units. -- Note that this destroy method also raises a destroy event at run-time. -- So all event listeners will catch the destroy event of this DCS Group. -- @param #GROUP self function GROUP:Destroy() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then for Index, UnitData in pairs( DCSGroup:getUnits() ) do self:CreateEventCrash( timer.getTime(), UnitData ) @@ -4211,11 +4338,11 @@ function GROUP:Destroy() DCSGroup:destroy() DCSGroup = nil end - + return nil end ---- Returns category of the DCS Group. +--- Returns category of the DCS Group. -- @param #GROUP self -- @return DCSGroup#Group.Category The category ID function GROUP:GetCategory() @@ -4227,7 +4354,7 @@ function GROUP:GetCategory() self:T3( GroupCategory ) return GroupCategory end - + return nil end @@ -4243,14 +4370,14 @@ function GROUP:GetCategoryName() [Group.Category.AIRPLANE] = "Airplane", [Group.Category.HELICOPTER] = "Helicopter", [Group.Category.GROUND] = "Ground Unit", - [Group.Category.SHIP] = "Ship", + [Group.Category.SHIP] = "Ship", } local GroupCategory = DCSGroup:getCategory() self:T3( GroupCategory ) - + return CategoryNames[GroupCategory] end - + return nil end @@ -4267,14 +4394,14 @@ function GROUP:GetCoalition() self:T3( GroupCoalition ) return GroupCoalition end - + return nil end --- Returns the country of the DCS Group. -- @param #GROUP self -- @return DCScountry#country.id The country identifier. --- @return #nil The DCS Group is not existing or alive. +-- @return #nil The DCS Group is not existing or alive. function GROUP:GetCountry() self:F2( self.GroupName ) @@ -4284,7 +4411,7 @@ function GROUP:GetCountry() self:T3( GroupCountry ) return GroupCountry end - + return nil end @@ -4295,13 +4422,13 @@ function GROUP:GetName() self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupName = DCSGroup:getName() self:T3( GroupName ) return GroupName end - + return nil end @@ -4310,19 +4437,19 @@ end -- @return #number The identifier of the DCS Group. function GROUP:GetID() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupID = DCSGroup:getID() self:T3( GroupID ) return GroupID end - + return nil end ---- Returns the UNIT wrapper class with number UnitNumber. +--- Returns the UNIT wrapper class with number UnitNumber. -- If the underlying DCS Unit does not exist, the method will return nil. . -- @param #GROUP self -- @param #number UnitNumber The number of the UNIT wrapper class to be returned. @@ -4331,7 +4458,7 @@ function GROUP:GetUnit( UnitNumber ) self:F2( { self.GroupName, UnitNumber } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) ) self:T3( UnitFound.UnitName ) @@ -4342,7 +4469,7 @@ function GROUP:GetUnit( UnitNumber ) return nil end ---- Returns the DCS Unit with number UnitNumber. +--- Returns the DCS Unit with number UnitNumber. -- If the underlying DCS Unit does not exist, the method will return nil. . -- @param #GROUP self -- @param #number UnitNumber The number of the DCS Unit to be returned. @@ -4351,7 +4478,7 @@ function GROUP:GetDCSUnit( UnitNumber ) self:F2( { self.GroupName, UnitNumber } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnitFound = DCSGroup:getUnit( UnitNumber ) self:T3( DCSUnitFound ) @@ -4361,14 +4488,14 @@ function GROUP:GetDCSUnit( UnitNumber ) return nil end ---- Returns current size of the DCS Group. --- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed. +--- Returns current size of the DCS Group. +-- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed. -- @param #GROUP self -- @return #number The DCS Group size. function GROUP:GetSize() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupSize = DCSGroup:getSize() self:T3( GroupSize ) @@ -4378,15 +4505,15 @@ function GROUP:GetSize() return nil end ---- ---- Returns the initial size of the DCS Group. --- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged. +--- +--- Returns the initial size of the DCS Group. +-- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged. -- @param #GROUP self -- @return #number The DCS Group initial size. function GROUP:GetInitialSize() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupInitialSize = DCSGroup:getInitialSize() self:T3( GroupInitialSize ) @@ -4402,7 +4529,7 @@ end function GROUP:GetUnits() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnits = DCSGroup:getUnits() local Units = {} @@ -4423,7 +4550,7 @@ end function GROUP:GetDCSUnits() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnits = DCSGroup:getUnits() self:T3( DCSUnits ) @@ -4439,7 +4566,7 @@ end function GROUP:_GetController() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupController = DCSGroup:getController() self:T3( GroupController ) @@ -4459,7 +4586,7 @@ end function GROUP:WayPointInitialize() self.WayPoints = self:GetTaskRoute() - + return self end @@ -4472,7 +4599,7 @@ end -- @return #GROUP function GROUP:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) self:F2( { WayPoint, WayPointIndex, WayPointFunction } ) - + table.insert( self.WayPoints[WayPoint].task.params.tasks, WayPointIndex ) self.WayPoints[WayPoint].task.params.tasks[WayPointIndex] = self:TaskFunction( WayPoint, WayPointIndex, WayPointFunction, arg ) return self @@ -4482,7 +4609,7 @@ end function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionArguments ) local DCSTask - + local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionGroup = GROUP:Find( ... ) " @@ -4490,16 +4617,16 @@ function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionAr DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" else DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )" - end - - DCSTask = self:TaskWrappedAction( + end + + DCSTask = self:TaskWrappedAction( self:CommandDoScript( table.concat( DCSScript ) ), WayPointIndex ) - + self:T3( DCSTask ) - + return DCSTask end @@ -4511,21 +4638,21 @@ end -- Note that when the WayPoint parameter is used, the new start mission waypoint of the group will be 1! -- @param #GROUP self -- @param #number WayPoint The WayPoint from where to execute the mission. --- @param #WaitTime The amount seconds to wait before initiating the mission. +-- @param #number WaitTime The amount seconds to wait before initiating the mission. -- @return #GROUP function GROUP:WayPointExecute( WayPoint, WaitTime ) if not WayPoint then WayPoint = 1 end - + -- When starting the mission from a certain point, the TaskPoints need to be deleted before the given WayPoint. for TaskPointID = 1, WayPoint - 1 do table.remove( self.WayPoints, 1 ) end self:T3( self.WayPoints ) - + self:SetTask( self:TaskRoute( self.WayPoints ), WaitTime ) return self @@ -4535,9 +4662,9 @@ end --- Activates a GROUP. -- @param #GROUP self function GROUP:Activate() - self:F2( { self.GroupName } ) - trigger.action.activateGroup( self:GetDCSGroup() ) - return self:GetDCSGroup() + self:F2( { self.GroupName } ) + trigger.action.activateGroup( self:GetDCSGroup() ) + return self:GetDCSGroup() end @@ -4548,13 +4675,13 @@ function GROUP:GetTypeName() self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupTypeName = DCSGroup:getUnit(1):getTypeName() self:T3( GroupTypeName ) return( GroupTypeName ) end - + return nil end @@ -4563,33 +4690,33 @@ end -- @return #string The CallSign of the first DCS Unit of the DCS Group. function GROUP:GetCallsign() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCallSign = DCSGroup:getUnit(1):getCallsign() self:T3( GroupCallSign ) return GroupCallSign end - + return nil end --- Returns the current point (Vec2 vector) of the first DCS Unit in the DCS Group. -- @return DCSTypes#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group. function GROUP:GetPointVec2() - self:F2( self.GroupName ) - - local GroupPointVec2 = self:GetUnit(1):GetPointVec2() - self:T3( GroupPointVec2 ) - return GroupPointVec2 + self:F2( self.GroupName ) + + local GroupPointVec2 = self:GetUnit(1):GetPointVec2() + self:T3( GroupPointVec2 ) + return GroupPointVec2 end --- Returns the current point (Vec3 vector) of the first DCS Unit in the DCS Group. -- @return DCSTypes#Vec3 Current Vec3 point of the first DCS Unit of the DCS Group. function GROUP:GetPointVec3() - self:F2( self.GroupName ) - + self:F2( self.GroupName ) + local GroupPointVec3 = self:GetUnit(1):GetPointVec3() self:T3( GroupPointVec3 ) return GroupPointVec3 @@ -4597,23 +4724,75 @@ end --- Is Functions +-- Is Zone Functions + +--- Returns true if all units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsCompletelyInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + else + return false + end + end + + return true +end + +--- Returns true if some units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsPartlyInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + return true + end + end + + return false +end + +--- Returns true if none of the group units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsNotInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + return false + end + end + + return true +end --- Returns if the group is of an air category. -- If the group is a helicopter or a plane, then this method will return true, otherwise false. -- @param #GROUP self -- @return #boolean Air category evaluation result. function GROUP:IsAir() - self:F2( self.GroupName ) + self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER - self:T3( IsAirResult ) - return IsAirResult + local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER + self:T3( IsAirResult ) + return IsAirResult end - + return nil end @@ -4622,15 +4801,15 @@ end -- @return #boolean true if DCS Group contains Helicopters. function GROUP:IsHelicopter() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.HELICOPTER end - + return nil end @@ -4639,15 +4818,15 @@ end -- @return #boolean true if DCS Group contains AirPlanes. function GROUP:IsAirPlane() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.AIRPLANE end - + return nil end @@ -4656,15 +4835,15 @@ end -- @return #boolean true if DCS Group contains Ground troops. function GROUP:IsGround() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.GROUND end - + return nil end @@ -4673,15 +4852,15 @@ end -- @return #boolean true if DCS Group contains Ships. function GROUP:IsShip() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.SHIP end - + return nil end @@ -4690,23 +4869,23 @@ end -- @param #GROUP self -- @return #boolean All units on the ground result. function GROUP:AllOnGround() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local AllOnGroundResult = true - - for Index, UnitData in pairs( DCSGroup:getUnits() ) do - if UnitData:inAir() then - AllOnGroundResult = false - end - end - - self:T3( AllOnGroundResult ) - return AllOnGroundResult + local AllOnGroundResult = true + + for Index, UnitData in pairs( DCSGroup:getUnits() ) do + if UnitData:inAir() then + AllOnGroundResult = false + end + end + + self:T3( AllOnGroundResult ) + return AllOnGroundResult end - + return nil end @@ -4715,26 +4894,26 @@ end -- @param #GROUP self -- @return #number Maximum velocity found. function GROUP:GetMaxVelocity() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local MaxVelocity = 0 - - for Index, UnitData in pairs( DCSGroup:getUnits() ) do - - local Velocity = UnitData:getVelocity() - local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z ) - - if VelocityTotal < MaxVelocity then - MaxVelocity = VelocityTotal - end - end - - return MaxVelocity + local MaxVelocity = 0 + + for Index, UnitData in pairs( DCSGroup:getUnits() ) do + + local Velocity = UnitData:getVelocity() + local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z ) + + if VelocityTotal < MaxVelocity then + MaxVelocity = VelocityTotal + end + end + + return MaxVelocity end - + return nil end @@ -4743,7 +4922,7 @@ end -- @param #GROUP self -- @return #number Minimum height found. function GROUP:GetMinHeight() - self:F2() + self:F2() end @@ -4752,7 +4931,7 @@ end -- @param #GROUP self -- @return #number Maximum height found. function GROUP:GetMaxHeight() - self:F2() + self:F2() end @@ -4762,16 +4941,16 @@ end -- @param #GROUP self -- @return Group#GROUP self function GROUP:PopCurrentTask() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() Controller:popTask() return self end - + return nil end @@ -4779,27 +4958,27 @@ end -- @param #GROUP self -- @return Group#GROUP self function GROUP:PushTask( DCSTask, WaitTime ) - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() - + -- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Group. -- Controller:pushTask( DCSTask ) - + if WaitTime then --routines.scheduleFunction( Controller.pushTask, { Controller, DCSTask }, timer.getTime() + WaitTime ) SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime ) else Controller:pushTask( DCSTask ) end - + return self end - + return nil end @@ -4810,40 +4989,40 @@ function GROUP:SetTask( DCSTask, WaitTime ) self:F2( { DCSTask } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - + local Controller = self:_GetController() - + -- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Group. -- Controller.setTask( Controller, DCSTask ) - + if not WaitTime then WaitTime = 1 end --routines.scheduleFunction( Controller.setTask, { Controller, DCSTask }, timer.getTime() + WaitTime ) SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime ) - + return self end - + return nil end ---- Return a condition section for a controlled task +--- Return a condition section for a controlled task. -- @param #GROUP self -- @param DCSTime#Time time --- @param #string userFlag --- @param #boolean userFlagValue +-- @param #string userFlag +-- @param #boolean userFlagValue -- @param #string condition --- @param DCSTime#Time duration --- @param #number lastWayPoint +-- @param DCSTime#Time duration +-- @param #number lastWayPoint -- return DCSTask#Task function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration, lastWayPoint ) - self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) - + self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) + local DCSStopCondition = {} DCSStopCondition.time = time DCSStopCondition.userFlag = userFlag @@ -4851,54 +5030,54 @@ function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration DCSStopCondition.condition = condition DCSStopCondition.duration = duration DCSStopCondition.lastWayPoint = lastWayPoint - + self:T3( { DCSStopCondition } ) - return DCSStopCondition + return DCSStopCondition end ---- Return a Controlled Task taking a Task and a TaskCondition +--- Return a Controlled Task taking a Task and a TaskCondition. -- @param #GROUP self -- @param DCSTask#Task DCSTask -- @param #DCSStopCondition DCSStopCondition -- @return DCSTask#Task function GROUP:TaskControlled( DCSTask, DCSStopCondition ) - self:F2( { DCSTask, DCSStopCondition } ) + self:F2( { DCSTask, DCSStopCondition } ) local DCSTaskControlled - - DCSTaskControlled = { - id = 'ControlledTask', - params = { - task = DCSTask, - stopCondition = DCSStopCondition - } + + DCSTaskControlled = { + id = 'ControlledTask', + params = { + task = DCSTask, + stopCondition = DCSStopCondition + } } - + self:T3( { DCSTaskControlled } ) return DCSTaskControlled end ---- Return a Combo Task taking an array of Tasks +--- Return a Combo Task taking an array of Tasks. -- @param #GROUP self --- @param #list DCSTasks +-- @param DCSTask#TaskArray DCSTasks Array of @{DCSTask#Task} -- @return DCSTask#Task function GROUP:TaskCombo( DCSTasks ) self:F2( { DCSTasks } ) local DCSTaskCombo - - DCSTaskCombo = { - id = 'ComboTask', - params = { + + DCSTaskCombo = { + id = 'ComboTask', + params = { tasks = DCSTasks - } + } } - + self:T3( { DCSTaskCombo } ) return DCSTaskCombo end ---- Return a WrappedAction Task taking a Command +--- Return a WrappedAction Task taking a Command. -- @param #GROUP self -- @param DCSCommand#Command DCSCommand -- @return DCSTask#Task @@ -4906,8 +5085,8 @@ function GROUP:TaskWrappedAction( DCSCommand, Index ) self:F2( { DCSCommand } ) local DCSTaskWrappedAction - - DCSTaskWrappedAction = { + + DCSTaskWrappedAction = { id = "WrappedAction", enabled = true, number = Index, @@ -4927,15 +5106,15 @@ end -- @return #GROUP self function GROUP:SetCommand( DCSCommand ) self:F2( DCSCommand ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() Controller:setCommand( DCSCommand ) return self end - + return nil end @@ -4946,117 +5125,387 @@ end -- @return DCSTask#Task function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index ) self:F2( { FromWayPoint, ToWayPoint, Index } ) - + local CommandSwitchWayPoint = { - id = 'SwitchWaypoint', - params = { - fromWaypointIndex = FromWayPoint, - goToWaypointIndex = ToWayPoint, + id = 'SwitchWaypoint', + params = { + fromWaypointIndex = FromWayPoint, + goToWaypointIndex = ToWayPoint, }, } - + self:T3( { CommandSwitchWayPoint } ) return CommandSwitchWayPoint end - ---- Orbit at a specified position at a specified alititude during a specified duration with a specified speed. + +-- TASKS FOR AIR GROUPS + + +--- (AIR) Attack a Group. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) + self:F2( { self.GroupName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) + + -- AttackGroup = { + -- id = 'AttackGroup', + -- params = { + -- groupId = Group.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend, + -- attackQty = number, + -- directionEnabled = boolean, + -- direction = Azimuth, + -- altitudeEnabled = boolean, + -- altitude = Distance, + -- attackQtyLimit = boolean, + -- } + -- } + + local DirectionEnabled = nil + if Direction then + DirectionEnabled = true + end + + local AltitudeEnabled = nil + if Altitude then + AltitudeEnabled = true + end + + local DCSTask + DCSTask = { id = 'AttackGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + directionEnabled = DirectionEnabled, + direction = Direction, + altitudeEnabled = AltitudeEnabled, + altitude = Altitude, + attackQtyLimit = AttackQtyLimit, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Attack the Unit. +-- @param #GROUP self +-- @param Unit#UNIT AttackUnit The unit. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack ) + self:F2( { self.GroupName, AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack } ) + + -- AttackUnit = { + -- id = 'AttackUnit', + -- params = { + -- unitId = Unit.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend + -- attackQty = number, + -- direction = Azimuth, + -- attackQtyLimit = boolean, + -- groupAttack = boolean, + -- } + -- } + + local DCSTask + DCSTask = { id = 'AttackUnit', + params = { + unitId = AttackUnit:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + attackQtyLimit = AttackQtyLimit, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Delivering weapon at the point on the ground. +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the point to deliver weapon at. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskBombing( PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- Bombing = { +-- id = 'Bombing', +-- params = { +-- point = Vec2, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'Bombing', + params = { + point = PointVec2, + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point to hold the position. -- @param #number Altitude The altitude to hold the position. -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed ) - self:F2( { self.GroupName, Point, Altitude, Speed } ) + self:F2( { self.GroupName, Point, Altitude, Speed } ) + + -- pattern = enum AI.Task.OribtPattern, + -- point = Vec2, + -- point2 = Vec2, + -- speed = Distance, + -- altitude = Distance --- pattern = enum AI.Task.OribtPattern, --- point = Vec2, --- point2 = Vec2, --- speed = Distance, --- altitude = Distance - local LandHeight = land.getHeight( Point ) - + self:T3( { LandHeight } ) - local DCSTask = { id = 'Orbit', - params = { pattern = AI.Task.OrbitPattern.CIRCLE, - point = Point, - speed = Speed, - altitude = Altitude + LandHeight - } - } + local DCSTask = { id = 'Orbit', + params = { pattern = AI.Task.OrbitPattern.CIRCLE, + point = Point, + speed = Speed, + altitude = Altitude + LandHeight + } + } + + + -- local AITask = { id = 'ControlledTask', + -- params = { task = { id = 'Orbit', + -- params = { pattern = AI.Task.OrbitPattern.CIRCLE, + -- point = Point, + -- speed = Speed, + -- altitude = Altitude + LandHeight + -- } + -- }, + -- stopCondition = { duration = Duration + -- } + -- } + -- } + -- ) - --- local AITask = { id = 'ControlledTask', --- params = { task = { id = 'Orbit', --- params = { pattern = AI.Task.OrbitPattern.CIRCLE, --- point = Point, --- speed = Speed, --- altitude = Altitude + LandHeight --- } --- }, --- stopCondition = { duration = Duration --- } --- } --- } --- ) - return DCSTask end ---- Orbit at the current position of the first unit of the group at a specified alititude +--- (AIR) Orbit at the current position of the first unit of the group at a specified alititude. -- @param #GROUP self -- @param #number Altitude The altitude to hold the position. -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircle( Altitude, Speed ) - self:F2( { self.GroupName, Altitude, Speed } ) + self:F2( { self.GroupName, Altitude, Speed } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupPoint = self:GetPointVec2() return self:TaskOrbitCircleAtVec2( GroupPoint, Altitude, Speed ) end - + return nil end ---- Hold position at the current position of the first unit of the group. +--- (AIR) Hold position at the current position of the first unit of the group. -- @param #GROUP self -- @param #number Duration The maximum duration in seconds to hold the position. -- @return #GROUP self function GROUP:TaskHoldPosition() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) return self:TaskOrbitCircle( 30, 10 ) end ---- Land the group at a Vec2Point. + + +--- (AIR) Attacking the map object (building, structure, e.t.c). +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackMapObject( PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- AttackMapObject = { +-- id = 'AttackMapObject', +-- params = { +-- point = Vec2, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'AttackMapObject', + params = { + point = PointVec2, + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Delivering weapon on the runway. +-- @param #GROUP self +-- @param Airbase#AIRBASE Airbase Airbase to attack. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskBombingRunway( Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- BombingRunway = { +-- id = 'BombingRunway', +-- params = { +-- runwayId = AirdromeId, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'BombingRunway', + params = { + point = Airbase:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Refueling from the nearest tanker. No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskRefueling() + self:F2( { self.GroupName } ) + +-- Refueling = { +-- id = 'Refueling', +-- params = {} +-- } + + local DCSTask + DCSTask = { id = 'Refueling', + params = { + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR HELICOPTER) Landing at the ground. For helicopters only. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to land. -- @param #number Duration The duration in seconds to stay on the ground. -- @return #GROUP self function GROUP:TaskLandAtVec2( Point, Duration ) - self:F2( { self.GroupName, Point, Duration } ) + self:F2( { self.GroupName, Point, Duration } ) +-- Land = { +-- id= 'Land', +-- params = { +-- point = Vec2, +-- durationFlag = boolean, +-- duration = Time +-- } +-- } + local DCSTask - - if Duration and Duration > 0 then - DCSTask = { id = 'Land', params = { point = Point, durationFlag = true, duration = Duration } } - else - DCSTask = { id = 'Land', params = { point = Point, durationFlag = false } } - end + if Duration and Duration > 0 then + DCSTask = { id = 'Land', + params = { + point = Point, + durationFlag = true, + duration = Duration, + }, + } + else + DCSTask = { id = 'Land', + params = { + point = Point, + durationFlag = false, + }, + } + end self:T3( DCSTask ) - return DCSTask + return DCSTask end ---- Land the group at a @{Zone#ZONE). +--- (AIR) Land the group at a @{Zone#ZONE_RADIUS). -- @param #GROUP self -- @param Zone#ZONE Zone The zone where to land. -- @param #number Duration The duration in seconds to stay on the ground. @@ -5070,7 +5519,7 @@ function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint ) else Point = Zone:GetPointVec2() end - + local DCSTask = self:TaskLandAtVec2( Point, Duration ) self:T3( DCSTask ) @@ -5078,155 +5527,570 @@ function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint ) end ---- Attack the Unit. --- @param #GROUP self --- @param Unit#UNIT The unit. --- @return DCSTask#Task The DCS task structure. -function GROUP:TaskAttackUnit( AttackUnit ) - self:F2( { self.GroupName, AttackUnit } ) --- AttackUnit = { --- id = 'AttackUnit', --- params = { --- unitId = Unit.ID, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend --- attackQty = number, --- direction = Azimuth, --- attackQtyLimit = boolean, --- groupAttack = boolean, --- } +--- (AIR) Following another airborne group. +-- The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +-- If another group is on land the unit / group will orbit around. +-- @param #GROUP self +-- @param Group#GROUP FollowGroup The group to be followed. +-- @param DCSTypes#Vec3 PointVec3 Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around. +-- @param #number LastWaypointIndex Detach waypoint of another group. Once reached the unit / group Follow task is finished. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskFollow( FollowGroup, PointVec3, LastWaypointIndex ) + self:F2( { self.GroupName, FollowGroup, PointVec3, LastWaypointIndex } ) + +-- Follow = { +-- id = 'Follow', +-- params = { +-- groupId = Group.ID, +-- pos = Vec3, +-- lastWptIndexFlag = boolean, +-- lastWptIndex = number +-- } -- } + + local LastWaypointIndexFlag = nil + if LastWaypointIndex then + LastWaypointIndexFlag = true + end - local DCSTask - DCSTask = { id = 'AttackUnit', - params = { unitId = AttackUnit:GetID(), - expend = AI.Task.WeaponExpend.TWO, - groupAttack = true, - }, - }, - + local DCSTask + DCSTask = { id = 'Follow', + params = { + groupId = FollowGroup:GetID(), + pos = PointVec3, + lastWptIndexFlag = LastWaypointIndexFlag, + lastWptIndex = LastWaypointIndex, + }, + }, + self:T3( { DCSTask } ) return DCSTask end ---- Attack a Group. + +--- (AIR) Escort another airborne group. +-- The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +-- The unit / group will also protect that group from threats of specified types. -- @param #GROUP self --- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param Group#GROUP EscortGroup The group to be escorted. +-- @param DCSTypes#Vec3 PointVec3 Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around. +-- @param #number LastWaypointIndex Detach waypoint of another group. Once reached the unit / group Follow task is finished. +-- @param #number EngagementDistanceMax Maximal distance from escorted group to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. -- @return DCSTask#Task The DCS task structure. -function GROUP:TaskAttackGroup( AttackGroup ) - self:F2( { self.GroupName, AttackGroup } ) +function GROUP:TaskEscort( FollowGroup, PointVec3, LastWaypointIndex, EngagementDistance, TargetTypes ) + self:F2( { self.GroupName, FollowGroup, PointVec3, LastWaypointIndex, EngagementDistance, TargetTypes } ) --- AttackGroup = { --- id = 'AttackGroup', --- params = { --- groupId = Group.ID, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend, --- attackQty = number, --- directionEnabled = boolean, --- direction = Azimuth, --- altitudeEnabled = boolean, --- altitude = Distance, --- attackQtyLimit = boolean, --- } --- } +-- Escort = { +-- id = 'Escort', +-- params = { +-- groupId = Group.ID, +-- pos = Vec3, +-- lastWptIndexFlag = boolean, +-- lastWptIndex = number, +-- engagementDistMax = Distance, +-- targetTypes = array of AttributeName, +-- } +-- } - local DCSTask - DCSTask = { id = 'AttackGroup', - params = { groupId = AttackGroup:GetID(), - expend = AI.Task.WeaponExpend.TWO, - }, - }, + local LastWaypointIndexFlag = nil + if LastWaypointIndex then + LastWaypointIndexFlag = true + end + local DCSTask + DCSTask = { id = 'Follow', + params = { + groupId = FollowGroup:GetID(), + pos = PointVec3, + lastWptIndexFlag = LastWaypointIndexFlag, + lastWptIndex = LastWaypointIndex, + engagementDistMax = EngagementDistance, + targetTypes = TargetTypes, + }, + }, + self:T3( { DCSTask } ) return DCSTask end ---- Fires at a VEC2 point. + +-- GROUND TASKS + +--- (GROUND) Fire at a VEC2 point until ammunition is finished. -- @param #GROUP self --- @param DCSTypes#Vec2 The point to fire at. +-- @param DCSTypes#Vec2 PointVec2 The point to fire at. -- @param DCSTypes#Distance Radius The radius of the zone to deploy the fire at. -- @return DCSTask#Task The DCS task structure. function GROUP:TaskFireAtPoint( PointVec2, Radius ) self:F2( { self.GroupName, PointVec2, Radius } ) --- FireAtPoint = { --- id = 'FireAtPoint', --- params = { --- point = Vec2, --- radius = Distance, --- } --- } - - local DCSTask - DCSTask = { id = 'FireAtPoint', - params = { point = PointVec2, - radius = Radius, - } - } - + -- FireAtPoint = { + -- id = 'FireAtPoint', + -- params = { + -- point = Vec2, + -- radius = Distance, + -- } + -- } + + local DCSTask + DCSTask = { id = 'FireAtPoint', + params = { + point = PointVec2, + radius = Radius, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (GROUND) Hold ground group from moving. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskHold() + self:F2( { self.GroupName } ) + +-- Hold = { +-- id = 'Hold', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'Hold', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- TASKS FOR AIRBORNE AND GROUND UNITS/GROUPS + +--- (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup Target GROUP. +-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type. +-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink ) + self:F2( { self.GroupName, AttackGroup, WeaponType, Designation, Datalink } ) + +-- FAC_AttackGroup = { +-- id = 'FAC_AttackGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- designation = enum AI.Task.Designation, +-- datalink = boolean +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC_AttackGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + designation = Designation, + datalink = Datalink, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + +-- EN-ROUTE TASKS FOR AIRBORNE GROUPS + +--- (AIR) Engaging targets of defined types. +-- @param #GROUP self +-- @param DCSTypes#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage. +-- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority ) + self:F2( { self.GroupName, Distance, TargetTypes, Priority } ) + +-- EngageTargets ={ +-- id = 'EngageTargets', +-- params = { +-- maxDist = Distance, +-- targetTypes = array of AttributeName, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'EngageTargets', + params = { + maxDist = Distance, + targetTypes = TargetTypes, + priority = Priority + } + } + self:T3( { DCSTask } ) return DCSTask end ---- Move the group to a Vec2 Point, wait for a defined duration and embark a group. +--- (AIR) Engaging a targets of defined types at circle-shaped zone. +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the zone. +-- @param DCSTypes#Distance Radius Radius of the zone. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageTargets( PointVec2, Radius, TargetTypes, Priority ) + self:F2( { self.GroupName, PointVec2, Radius, TargetTypes, Priority } ) + +-- EngageTargetsInZone = { +-- id = 'EngageTargetsInZone', +-- params = { +-- point = Vec2, +-- zoneRadius = Distance, +-- targetTypes = array of AttributeName, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'EngageTargetsInZone', + params = { + point = PointVec2, + zoneRadius = Radius, + targetTypes = TargetTypes, + priority = Priority + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) + self:F2( { self.GroupName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) + + -- EngageGroup = { + -- id = 'EngageGroup ', + -- params = { + -- groupId = Group.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend, + -- attackQty = number, + -- directionEnabled = boolean, + -- direction = Azimuth, + -- altitudeEnabled = boolean, + -- altitude = Distance, + -- attackQtyLimit = boolean, + -- priority = number, + -- } + -- } + + local DirectionEnabled = nil + if Direction then + DirectionEnabled = true + end + + local AltitudeEnabled = nil + if Altitude then + AltitudeEnabled = true + end + + local DCSTask + DCSTask = { id = 'EngageGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + directionEnabled = DirectionEnabled, + direction = Direction, + altitudeEnabled = AltitudeEnabled, + altitude = Altitude, + attackQtyLimit = AttackQtyLimit, + priority = Priority, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Attack the Unit. +-- @param #GROUP self +-- @param Unit#UNIT AttackUnit The UNIT. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageUnit( AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack ) + self:F2( { self.GroupName, AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack } ) + + -- EngageUnit = { + -- id = 'EngageUnit', + -- params = { + -- unitId = Unit.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend + -- attackQty = number, + -- direction = Azimuth, + -- attackQtyLimit = boolean, + -- groupAttack = boolean, + -- priority = number, + -- } + -- } + + local DCSTask + DCSTask = { id = 'EngageUnit', + params = { + unitId = AttackUnit:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + attackQtyLimit = AttackQtyLimit, + groupAttack = GroupAttack, + priority = Priority, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + + +--- (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskAWACS( ) + self:F2( { self.GroupName } ) + +-- AWACS = { +-- id = 'AWACS', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'AWACS', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Aircraft will act as a tanker for friendly units. No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskTanker( ) + self:F2( { self.GroupName } ) + +-- Tanker = { +-- id = 'Tanker', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'Tanker', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- En-route tasks for ground units/groups + +--- (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts). No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEWR( ) + self:F2( { self.GroupName } ) + +-- EWR = { +-- id = 'EWR', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'EWR', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- En-route tasks for airborne and ground units/groups + +--- (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup Target GROUP. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type. +-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink ) + self:F2( { self.GroupName, AttackGroup, WeaponType, Priority, Designation, Datalink } ) + +-- FAC_EngageGroup = { +-- id = 'FAC_EngageGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- designation = enum AI.Task.Designation, +-- datalink = boolean, +-- priority = number, +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC_EngageGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + designation = Designation, + datalink = Datalink, + priority = Priority, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param DCSTypes#Distance Radius The maximal distance from the FAC to a target. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskFAC( Radius, Priority ) + self:F2( { self.GroupName, Radius, Priority } ) + +-- FAC = { +-- id = 'FAC', +-- params = { +-- radius = Distance, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC', + params = { + radius = Radius, + priority = Priority + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + + + +--- (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to wait. -- @param #number Duration The duration in seconds to wait. -- @param #GROUP EmbarkingGroup The group to be embarked. -- @return DCSTask#Task The DCS task structure -function GROUP:TaskEmbarkingAtVec2( Point, Duration, EmbarkingGroup ) - self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } ) +function GROUP:TaskEmbarking( Point, Duration, EmbarkingGroup ) + self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } ) - local DCSTask - DCSTask = { id = 'Embarking', - params = { x = Point.x, - y = Point.y, - duration = Duration, - groupsForEmbarking = { EmbarkingGroup.GroupID }, - durationFlag = true, - distributionFlag = false, - distribution = {}, - } - } - - self:T3( { DCSTask } ) - return DCSTask + local DCSTask + DCSTask = { id = 'Embarking', + params = { x = Point.x, + y = Point.y, + duration = Duration, + groupsForEmbarking = { EmbarkingGroup.GroupID }, + durationFlag = true, + distributionFlag = false, + distribution = {}, + } + } + + self:T3( { DCSTask } ) + return DCSTask end +--- (GROUND) Embark to a Transport landed at a location. + --- Move to a defined Vec2 Point, and embark to a group when arrived within a defined Radius. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to wait. -- @param #number Radius The radius of the embarking zone around the Point. -- @return DCSTask#Task The DCS task structure. -function GROUP:TaskEmbarkToTransportAtVec2( Point, Radius ) - self:F2( { self.GroupName, Point, Radius } ) +function GROUP:TaskEmbarkToTransport( Point, Radius ) + self:F2( { self.GroupName, Point, Radius } ) local DCSTask --DCSTask#Task - DCSTask = { id = 'EmbarkToTransport', - params = { x = Point.x, - y = Point.y, - zoneRadius = Radius, - } - } + DCSTask = { id = 'EmbarkToTransport', + params = { x = Point.x, + y = Point.y, + zoneRadius = Radius, + } + } self:T3( { DCSTask } ) - return DCSTask + return DCSTask end ---- Return a Misson task from a mission template. + + +--- (AIR + GROUND) Return a mission task from a mission template. -- @param #GROUP self -- @param #table TaskMission A table containing the mission task. --- @return DCSTask#Task +-- @return DCSTask#Task function GROUP:TaskMission( TaskMission ) - self:F2( Points ) - + self:F2( Points ) + local DCSTask DCSTask = { id = 'Mission', params = { TaskMission, }, } - + self:T3( { DCSTask } ) return DCSTask end @@ -5234,18 +6098,18 @@ end --- Return a Misson task to follow a given route defined by Points. -- @param #GROUP self -- @param #table Points A table of route points. --- @return DCSTask#Task +-- @return DCSTask#Task function GROUP:TaskRoute( Points ) self:F2( Points ) - + local DCSTask DCSTask = { id = 'Mission', params = { route = { points = Points, }, }, } - + self:T3( { DCSTask } ) return DCSTask end ---- Make the DCS Group to fly to a given point and hover. +--- (AIR + GROUND) Make the Group move to fly to a given point. -- @param #GROUP self -- @param DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param #number Speed The speed to travel. @@ -5254,22 +6118,22 @@ function GROUP:TaskRouteToVec2( Point, Speed ) self:F2( { Point, Speed } ) local GroupPoint = self:GetUnit( 1 ):GetPointVec2() - + local PointFrom = {} PointFrom.x = GroupPoint.x PointFrom.y = GroupPoint.y PointFrom.type = "Turning Point" PointFrom.action = "Turning Point" - PointFrom.speed = Speed + PointFrom.speed = Speed PointFrom.speed_locked = true PointFrom.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local PointTo = {} PointTo.x = Point.x @@ -5279,24 +6143,24 @@ function GROUP:TaskRouteToVec2( Point, Speed ) PointTo.speed = Speed PointTo.speed_locked = true PointTo.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local Points = { PointFrom, PointTo } - + self:T3( Points ) - + self:Route( Points ) return self end ---- Make the DCS Group to fly to a given point and hover. +--- (AIR + GROUND) Make the Group move to a given point. -- @param #GROUP self -- @param DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param #number Speed The speed to travel. @@ -5305,7 +6169,7 @@ function GROUP:TaskRouteToVec3( Point, Speed ) self:F2( { Point, Speed } ) local GroupPoint = self:GetUnit( 1 ):GetPointVec3() - + local PointFrom = {} PointFrom.x = GroupPoint.x PointFrom.y = GroupPoint.z @@ -5313,39 +6177,39 @@ function GROUP:TaskRouteToVec3( Point, Speed ) PointFrom.alt_type = "BARO" PointFrom.type = "Turning Point" PointFrom.action = "Turning Point" - PointFrom.speed = Speed + PointFrom.speed = Speed PointFrom.speed_locked = true PointFrom.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local PointTo = {} PointTo.x = Point.x PointTo.y = Point.z - PointTo.alt = Point.y + PointTo.alt = Point.y PointTo.alt_type = "BARO" PointTo.type = "Turning Point" PointTo.action = "Fly Over Point" PointTo.speed = Speed PointTo.speed_locked = true PointTo.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local Points = { PointFrom, PointTo } - + self:T3( Points ) - + self:Route( Points ) return self @@ -5356,28 +6220,28 @@ end --- Make the group to follow a given route. -- @param #GROUP self -- @param #table GoPoints A table of Route Points. --- @return #GROUP self +-- @return #GROUP self function GROUP:Route( GoPoints ) - self:F2( GoPoints ) + self:F2( GoPoints ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local Points = routines.utils.deepCopy( GoPoints ) - local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } - local Controller = self:_GetController() + local Points = routines.utils.deepCopy( GoPoints ) + local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } + local Controller = self:_GetController() --Controller.setTask( Controller, MissionTask ) - --routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 ) + --routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 ) SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 ) - return self + return self end - + return nil end ---- Route the group to a given zone. +--- (AIR + GROUND) Route the group to a given zone. -- The group final destination point can be randomized. -- A speed can be given in km/h. -- A given formation can be given. @@ -5387,56 +6251,56 @@ end -- @param #number Speed The speed. -- @param Base#FORMATION Formation The formation string. function GROUP:TaskRouteToZone( Zone, Randomize, Speed, Formation ) - self:F2( Zone ) + self:F2( Zone ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - - local GroupPoint = self:GetPointVec2() - - local PointFrom = {} - PointFrom.x = GroupPoint.x - PointFrom.y = GroupPoint.y - PointFrom.type = "Turning Point" - PointFrom.action = "Cone" - PointFrom.speed = 20 / 1.6 - - - local PointTo = {} - local ZonePoint - - if Randomize then - ZonePoint = Zone:GetRandomPointVec2() - else - ZonePoint = Zone:GetPointVec2() - end - - PointTo.x = ZonePoint.x - PointTo.y = ZonePoint.y - PointTo.type = "Turning Point" - - if Formation then - PointTo.action = Formation - else - PointTo.action = "Cone" - end - - if Speed then - PointTo.speed = Speed - else - PointTo.speed = 20 / 1.6 - end - - local Points = { PointFrom, PointTo } - - self:T3( Points ) - - self:Route( Points ) - - return self + + local GroupPoint = self:GetPointVec2() + + local PointFrom = {} + PointFrom.x = GroupPoint.x + PointFrom.y = GroupPoint.y + PointFrom.type = "Turning Point" + PointFrom.action = "Cone" + PointFrom.speed = 20 / 1.6 + + + local PointTo = {} + local ZonePoint + + if Randomize then + ZonePoint = Zone:GetRandomPointVec2() + else + ZonePoint = Zone:GetPointVec2() + end + + PointTo.x = ZonePoint.x + PointTo.y = ZonePoint.y + PointTo.type = "Turning Point" + + if Formation then + PointTo.action = Formation + else + PointTo.action = "Cone" + end + + if Speed then + PointTo.speed = Speed + else + PointTo.speed = 20 / 1.6 + end + + local Points = { PointFrom, PointTo } + + self:T3( Points ) + + self:Route( Points ) + + return self end - + return nil end @@ -5483,48 +6347,48 @@ end -- @param #number Begin The route point from where the copy will start. The base route point is 0. -- @param #number End The route point where the copy will end. The End point is the last point - the End point. The last point has base 0. -- @param #boolean Randomize Randomization of the route, when true. --- @param #number Radius When randomization is on, the randomization is within the radius. +-- @param #number Radius When randomization is on, the randomization is within the radius. function GROUP:CopyRoute( Begin, End, Randomize, Radius ) - self:F2( { Begin, End } ) + self:F2( { Begin, End } ) - local Points = {} - - -- Could be a Spawned Group - local GroupName = string.match( self:GetName(), ".*#" ) - if GroupName then - GroupName = GroupName:sub( 1, -2 ) - else - GroupName = self:GetName() - end - - self:T3( { GroupName } ) - - local Template = _DATABASE.Templates.Groups[GroupName].Template - - if Template then - if not Begin then - Begin = 0 - end - if not End then - End = 0 - end - - for TPointID = Begin + 1, #Template.route.points - End do - if Template.route.points[TPointID] then - Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] ) - if Randomize then - if not Radius then - Radius = 500 - end - Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius ) - Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius ) - end - end - end - return Points - end - - return nil + local Points = {} + + -- Could be a Spawned Group + local GroupName = string.match( self:GetName(), ".*#" ) + if GroupName then + GroupName = GroupName:sub( 1, -2 ) + else + GroupName = self:GetName() + end + + self:T3( { GroupName } ) + + local Template = _DATABASE.Templates.Groups[GroupName].Template + + if Template then + if not Begin then + Begin = 0 + end + if not End then + End = 0 + end + + for TPointID = Begin + 1, #Template.route.points - End do + if Template.route.points[TPointID] then + Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] ) + if Randomize then + if not Radius then + Radius = 500 + end + Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius ) + Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius ) + end + end + end + return Points + end + + return nil end @@ -5535,28 +6399,28 @@ function GROUP:GetDetectedTargets() if DCSGroup then return self:_GetController():getDetectedTargets() end - + return nil end function GROUP:IsTargetDetected( DCSObject ) self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then - + local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity - = self:_GetController().isTargetDetected( self:_GetController(), DCSObject, - Controller.Detection.VISUAL, - Controller.Detection.OPTIC, - Controller.Detection.RADAR, - Controller.Detection.IRST, - Controller.Detection.RWR, - Controller.Detection.DLINK - ) + = self:_GetController().isTargetDetected( self:_GetController(), DCSObject, + Controller.Detection.VISUAL, + Controller.Detection.OPTIC, + Controller.Detection.RADAR, + Controller.Detection.IRST, + Controller.Detection.RWR, + Controller.Detection.DLINK + ) return TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity end - + return nil end @@ -5567,16 +6431,16 @@ end -- @return #boolean function GROUP:OptionROEHoldFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -5584,12 +6448,12 @@ end -- @param Group#GROUP self -- @return Group#GROUP self function GROUP:OptionROEHoldFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_HOLD ) elseif self:IsGround() then @@ -5597,10 +6461,10 @@ function GROUP:OptionROEHoldFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.WEAPON_HOLD ) end - + return self end - + return nil end @@ -5609,16 +6473,16 @@ end -- @return #boolean function GROUP:OptionROEReturnFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -5626,12 +6490,12 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEReturnFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.RETURN_FIRE ) elseif self:IsGround() then @@ -5639,10 +6503,10 @@ function GROUP:OptionROEReturnFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.RETURN_FIRE ) end - + return self end - + return nil end @@ -5657,10 +6521,10 @@ function GROUP:OptionROEOpenFirePossible() if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -5668,12 +6532,12 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEOpenFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.OPEN_FIRE ) elseif self:IsGround() then @@ -5681,10 +6545,10 @@ function GROUP:OptionROEOpenFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.OPEN_FIRE ) end - + return self end - + return nil end @@ -5693,16 +6557,16 @@ end -- @return #boolean function GROUP:OptionROEWeaponFreePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5710,19 +6574,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEWeaponFree() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_FREE ) end - + return self end - + return nil end @@ -5731,16 +6595,16 @@ end -- @return #boolean function GROUP:OptionROTNoReactionPossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5749,19 +6613,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTNoReaction() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.NO_REACTION ) end - + return self end - + return nil end @@ -5776,10 +6640,10 @@ function GROUP:OptionROTPassiveDefensePossible() if self:IsAir() then return true end - + return false end - + return nil end @@ -5787,19 +6651,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTPassiveDefense() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.PASSIVE_DEFENCE ) end - + return self end - + return nil end @@ -5808,16 +6672,16 @@ end -- @return #boolean function GROUP:OptionROTEvadeFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5826,19 +6690,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTEvadeFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.EVADE_FIRE ) end - + return self end - + return nil end @@ -5847,16 +6711,16 @@ end -- @return #boolean function GROUP:OptionROTVerticalPossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5865,19 +6729,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTVertical() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.BYPASS_AND_ESCAPE ) end - + return self end - + return nil end @@ -5886,16 +6750,16 @@ end --- Returns a message for a coalition or a client. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. -- @return Message#MESSAGE function GROUP:Message( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then return MESSAGE:New( Message, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")", Duration, self:GetClassNameAndID() ) end - + return nil end @@ -5903,15 +6767,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. function GROUP:MessageToAll( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToAll() end - + return nil end @@ -5919,15 +6783,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTYpes#Duration Duration The duration of the message. function GROUP:MessageToRed( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToRed() end - + return nil end @@ -5935,15 +6799,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. function GROUP:MessageToBlue( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToBlue() end - + return nil end @@ -5951,23 +6815,23 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. -- @param Client#CLIENT Client The client object receiving the message. function GROUP:MessageToClient( Message, Duration, Client ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToClient( Client ) end - + return nil end ---- UNIT Class +--- This module contains the UNIT class. -- --- @{UNIT} class --- ============== --- The @{UNIT} class is a wrapper class to handle the DCS Unit objects: +-- 1) @{Unit#UNIT} class, extends @{Base#BASE} +-- =========================================== +-- The @{Unit#UNIT} class is a wrapper class to handle the DCS Unit objects: -- -- * Support all DCS Unit APIs. -- * Enhance with Unit specific APIs not in the DCS Unit API set. @@ -5975,8 +6839,8 @@ end -- * Manage the "state" of the DCS Unit. -- -- --- UNIT reference methods --- ====================== +-- 1.1) UNIT reference methods +-- ---------------------- -- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Unit objects are spawned (using the @{SPAWN} class). -- @@ -5994,19 +6858,15 @@ end -- -- IMPORTANT: ONE SHOULD NEVER SANATIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil). -- --- DCS UNIT APIs --- ============= +-- 1.2) DCS UNIT APIs +-- ------------------ -- The DCS Unit APIs are used extensively within MOOSE. The UNIT class has for each DCS Unit API a corresponding method. -- To be able to distinguish easily in your code the difference between a UNIT API call and a DCS Unit API call, -- the first letter of the method is also capitalized. So, by example, the DCS Unit method @{DCSUnit#Unit.getName}() -- is implemented in the UNIT class as @{#UNIT.GetName}(). -- --- Additional UNIT APIs --- ==================== --- The UNIT class comes with additional methods. Find below a summary. --- --- Smoke, Flare Units --- ------------------ +-- 1.3) Smoke, Flare Units +-- ----------------------- -- The UNIT class provides methods to smoke or flare units easily. -- The @{#UNIT.SmokeBlue}(), @{#UNIT.SmokeGreen}(),@{#UNIT.SmokeOrange}(), @{#UNIT.SmokeRed}(), @{#UNIT.SmokeRed}() methods -- will smoke the unit in the corresponding color. Note that smoking a unit is done at the current position of the DCS Unit. @@ -6014,26 +6874,25 @@ end -- The @{#UNIT.FlareGreen}(), @{#UNIT.FlareRed}(), @{#UNIT.FlareWhite}(), @{#UNIT.FlareYellow}() -- methods will fire off a flare in the air with the corresponding color. Note that a flare is a one-off shot and its effect is of very short duration. -- --- Position, Point --- --------------- +-- 1.4) Location Position, Point +-- ----------------------------- -- The UNIT class provides methods to obtain the current point or position of the DCS Unit. --- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetPointVec3}() will obtain the current location of the DCS Unit in a Vec2 (2D) or a Vec3 (3D) vector respectively. --- If you want to obtain the complete 3D position including oriëntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively. +-- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetPointVec3}() will obtain the current **location** of the DCS Unit in a Vec2 (2D) or a **point** in a Vec3 (3D) vector respectively. +-- If you want to obtain the complete **3D position** including oriëntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively. -- --- Alive --- ----- +-- 1.5) Test if alive +-- ------------------ -- The @{#UNIT.IsAlive}(), @{#UNIT.IsActive}() methods determines if the DCS Unit is alive, meaning, it is existing and active. -- --- Test for other units in radius --- ------------------------------ --- One can test if another DCS Unit is within a given radius of the current DCS Unit, by using the @{#UNIT.OtherUnitInRadius}() method. --- --- More functions will be added --- ---------------------------- --- During the MOOSE development, more functions will be added. A complete list of the current functions is below. --- +-- 1.6) Test for proximity +-- ----------------------- +-- The UNIT class contains methods to test the location or proximity against zones or other objects. -- +-- ### 1.6.1) Zones +-- To test whether the Unit is within a **zone**, use the @{#UNIT.IsInZone}() or the @{#UNIT.IsNotInZone}() methods. Any zone can be tested on, but the zone must be derived from @{Zone#ZONE_BASE}. -- +-- ### 1.6.2) Units +-- Test if another DCS Unit is within a given radius of the current DCS Unit, use the @{#UNIT.OtherUnitInRadius}() method. -- -- @module Unit -- @author FlightControl @@ -6505,7 +7364,7 @@ function UNIT:GetPointVec2() UnitPointVec2.x = UnitPointVec3.x UnitPointVec2.y = UnitPointVec3.z - self:T3( UnitPointVec2 ) + self:T2( UnitPointVec2 ) return UnitPointVec2 end @@ -6566,7 +7425,35 @@ function UNIT:GetVelocity() return nil end - + +-- Is functions + +--- Returns true if the unit is within a @{Zone}. +-- @param #UNIT self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the unit is within the @{Zone#ZONE_BASE} +function UNIT:IsInZone( Zone ) + self:F2( { self.UnitName, Zone } ) + + local IsInZone = Zone:IsPointVec3InZone( self:GetPointVec3() ) + + self:T( { IsInZone } ) + return IsInZone +end + +--- Returns true if the unit is not within a @{Zone}. +-- @param #UNIT self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the unit is not within the @{Zone#ZONE_BASE} +function UNIT:IsNotInZone( Zone ) + self:F2( { self.UnitName, Zone } ) + + local IsInZone = not Zone:IsPointVec3InZone( self:GetPointVec3() ) + + self:T( { IsInZone } ) + return IsInZone +end + --- Returns true if the DCS Unit is in the air. -- @param Unit#UNIT self -- @return #boolean true if in the air. @@ -6738,92 +7625,492 @@ function UNIT:IsAir() return IsAirResult end ---- ZONE Classes +--- This module contains the ZONE classes, inherited from @{Zone#ZONE_BASE}. +-- There are essentially two core functions that zones accomodate: +-- +-- * Test if an object is within the zone boundaries. +-- * Provide the zone behaviour. Some zones are static, while others are moveable. +-- +-- The object classes are using the zone classes to test the zone boundaries, which can take various forms: +-- +-- * Test if completely within the zone. +-- * Test if partly within the zone (for @{Group#GROUP} objects). +-- * Test if not in the zone. +-- * Distance to the nearest intersecting point of the zone. +-- * Distance to the center of the zone. +-- * ... +-- +-- Each of these ZONE classes have a zone name, and specific parameters defining the zone type: +-- +-- * @{Zone#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes. +-- * @{Zone#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius. +-- * @{Zone#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor. +-- * @{Zone#ZONE_UNIT}: The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- * @{Zone#ZONE_POLYGON}: The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- +-- Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}: +-- +-- * @{#ZONE_BASE.IsPointVec2InZone}: Returns if a location is within the zone. +-- * @{#ZONE_BASE.IsPointVec3InZone}: Returns if a point is within the zone. +-- +-- === +-- +-- 1) @{Zone#ZONE_BASE} class, extends @{Base#BASE} +-- ================================================ +-- The ZONE_BASE class defining the base for all other zone classes. +-- +-- === +-- +-- 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE} +-- ======================================================= +-- The ZONE_RADIUS class defined by a zone name, a location and a radius. +-- +-- === +-- +-- 3) @{Zone#ZONE} class, extends @{Zone#ZONE_RADIUS} +-- ========================================== +-- The ZONE class, defined by the zone name as defined within the Mission Editor. +-- +-- === +-- +-- 4) @{Zone#ZONE_UNIT} class, extends @{Zone#ZONE_RADIUS} +-- ======================================================= +-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- +-- === +-- +-- 5) @{Zone#ZONE_POLYGON} class, extends @{Zone#ZONE_BASE} +-- ======================================================== +-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- +-- === +-- -- @module Zone +-- @author FlightControl + Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Message" ) +Include.File( "Point" ) ---- The ZONE class --- @type ZONE --- @Extends Base#BASE -ZONE = { - ClassName="ZONE", + + +--- The ZONE_BASE class +-- @type ZONE_BASE +-- @extends Base#BASE +ZONE_BASE = { + ClassName = "ZONE_BASE", + } + +--- ZONE_BASE constructor +-- @param #ZONE_BASE self +-- @param #string ZoneName Name of the zone. +-- @return #ZONE_BASE self +function ZONE_BASE:New( ZoneName ) + local self = BASE:Inherit( self, BASE:New() ) + self:F( ZoneName ) + + self.ZoneName = ZoneName + + return self +end + +--- Returns if a location is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_BASE:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + return false +end + +--- Returns if a point is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec3 PointVec3 The point to test. +-- @return #boolean true if the point is within the zone. +function ZONE_BASE:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( { x = PointVec3.x, y = PointVec3.z } ) + + return InZone +end + +--- Smokes the zone boundaries in a color. +-- @param #ZONE_BASE self +-- @param SmokeColor The smoke color. +function ZONE_BASE:SmokeZone( SmokeColor ) + self:F2( SmokeColor ) + +end + + +--- The ZONE_RADIUS class, defined by a zone name, a location and a radius. +-- @type ZONE_RADIUS +-- @field DCSTypes#Vec2 PointVec2 The current location of the zone. +-- @field DCSTypes#Distance Radius The radius of the zone. +-- @extends Zone#ZONE_BASE +ZONE_RADIUS = { + ClassName="ZONE_RADIUS", } - -function ZONE:New( ZoneName ) - local self = BASE:Inherit( self, BASE:New() ) - self:F( ZoneName ) - local Zone = trigger.misc.getZone( ZoneName ) - - if not Zone then - error( "Zone " .. ZoneName .. " does not exist." ) - return nil - end - - self.Zone = Zone - self.ZoneName = ZoneName +--- Constructor of ZONE_RADIUS, taking the zone name, the zone location and a radius. +-- @param #ZONE_RADIUS self +-- @param #string ZoneName Name of the zone. +-- @param DCSTypes#Vec2 PointVec2 The location of the zone. +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:New( ZoneName, PointVec2, Radius ) + local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) + self:F( { ZoneName, PointVec2, Radius } ) + + self.Radius = Radius + self.PointVec2 = PointVec2 return self end -function ZONE:GetPointVec2() - self:F( self.ZoneName ) +--- Smokes the zone boundaries in a color. +-- @param #ZONE_RADIUS self +-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color. +-- @param #number Points (optional) The amount of points in the circle. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:SmokeZone( SmokeColor, Points ) + self:F2( SmokeColor ) - local Zone = trigger.misc.getZone( self.ZoneName ) - local Point = { x = Zone.point.x, y = Zone.point.z } + local Point = {} + local PointVec2 = self:GetPointVec2() - self:T( { Zone, Point } ) - - return Point -end + Points = Points and Points or 360 -function ZONE:GetPointVec3( Height ) - self:F( self.ZoneName ) - - local Zone = trigger.misc.getZone( self.ZoneName ) - local Point = { x = Zone.point.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = Zone.point.z } - - self:T( { Zone, Point } ) + local Angle + local RadialBase = math.pi*2 - return Point + for Angle = 0, 360, 360 / Points do + local Radial = Angle * RadialBase / 360 + Point.x = PointVec2.x + math.cos( Radial ) * self:GetRadius() + Point.y = PointVec2.y + math.sin( Radial ) * self:GetRadius() + POINT_VEC2:New( Point.x, Point.y ):Smoke( SmokeColor ) + end + + return self end -function ZONE:GetRandomPointVec2() + +--- Flares the zone boundaries in a color. +-- @param #ZONE_RADIUS self +-- @param #POINT_VEC3.FlareColor FlareColor The flare color. +-- @param #number Points (optional) The amount of points in the circle. +-- @param DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth ) + self:F2( { FlareColor, Azimuth } ) + + local Point = {} + local PointVec2 = self:GetPointVec2() + + Points = Points and Points or 360 + + local Angle + local RadialBase = math.pi*2 + + for Angle = 0, 360, 360 / Points do + local Radial = Angle * RadialBase / 360 + Point.x = PointVec2.x + math.cos( Radial ) * self:GetRadius() + Point.y = PointVec2.y + math.sin( Radial ) * self:GetRadius() + POINT_VEC2:New( Point.x, Point.y ):Flare( FlareColor, Azimuth ) + end + + return self +end + +--- Returns the radius of the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Distance The radius of the zone. +function ZONE_RADIUS:GetRadius() + self:F2( self.ZoneName ) + + self:T2( { self.Radius } ) + + return self.Radius +end + +--- Sets the radius of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return DCSTypes#Distance The radius of the zone. +function ZONE_RADIUS:SetRadius( Radius ) + self:F2( self.ZoneName ) + + self.Radius = Radius + self:T2( { self.Radius } ) + + return self.Radius +end + +--- Returns the location of the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Vec2 The location of the zone. +function ZONE_RADIUS:GetPointVec2() + self:F2( self.ZoneName ) + + self:T2( { self.PointVec2 } ) + + return self.PointVec2 +end + +--- Sets the location of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The new location of the zone. +-- @return DCSTypes#Vec2 The new location of the zone. +function ZONE_RADIUS:SetPointVec2( PointVec2 ) + self:F2( self.ZoneName ) + + self.PointVec2 = PointVec2 + + self:T2( { self.PointVec2 } ) + + return self.PointVec2 +end + +--- Returns the point of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. +-- @return DCSTypes#Vec3 The point of the zone. +function ZONE_RADIUS:GetPointVec3( Height ) + self:F2( self.ZoneName ) + + local PointVec2 = self:GetPointVec2() + + local PointVec3 = { x = PointVec2.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = PointVec2.y } + + self:T2( { PointVec3 } ) + + return PointVec3 +end + + +--- Returns if a location is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_RADIUS:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local ZonePointVec2 = self:GetPointVec2() + + if (( PointVec2.x - ZonePointVec2.x )^2 + ( PointVec2.y - ZonePointVec2.y ) ^2 ) ^ 0.5 <= self:GetRadius() then + return true + end + + return false +end + +--- Returns if a point is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec3 PointVec3 The point to test. +-- @return #boolean true if the point is within the zone. +function ZONE_RADIUS:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( { x = PointVec3.x, y = PointVec3.z } ) + + return InZone +end + +--- Returns a random location within the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Vec2 The random location within the zone. +function ZONE_RADIUS:GetRandomPointVec2() self:F( self.ZoneName ) local Point = {} + local PointVec2 = self:GetPointVec2() - local Zone = trigger.misc.getZone( self.ZoneName ) - local angle = math.random() * math.pi*2; - Point.x = Zone.point.x + math.cos( angle ) * math.random() * Zone.radius; - Point.y = Zone.point.z + math.sin( angle ) * math.random() * Zone.radius; + Point.x = PointVec2.x + math.cos( angle ) * math.random() * self:GetRadius(); + Point.y = PointVec2.y + math.sin( angle ) * math.random() * self:GetRadius(); - self:T( { Zone, Point } ) + self:T( { Point } ) return Point end -function ZONE:GetRadius() - self:F( self.ZoneName ) - local Zone = trigger.misc.getZone( self.ZoneName ) - self:T( { Zone } ) +--- The ZONE class, defined by the zone name as defined within the Mission Editor. The location and the radius are automatically collected from the mission settings. +-- @type ZONE +-- @extends Zone#ZONE_RADIUS +ZONE = { + ClassName="ZONE", + } - return Zone.radius + +--- Constructor of ZONE, taking the zone name. +-- @param #ZONE self +-- @param #string ZoneName The name of the zone as defined within the mission editor. +-- @return #ZONE +function ZONE:New( ZoneName ) + + local Zone = trigger.misc.getZone( ZoneName ) + + if not Zone then + error( "Zone " .. ZoneName .. " does not exist." ) + return nil + end + + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, { x = Zone.point.x, y = Zone.point.z }, Zone.radius ) ) + self:F( ZoneName ) + + self.Zone = Zone + + return self end ---- The CLIENT models client units in multi player missions. + +--- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- @type ZONE_UNIT +-- @field Unit#UNIT ZoneUNIT +-- @extends Zone#ZONE_RADIUS +ZONE_UNIT = { + ClassName="ZONE_UNIT", + } + +--- Constructor to create a ZONE_UNIT instance, taking the zone name, a zone unit and a radius. +-- @param #ZONE_UNIT self +-- @param #string ZoneName Name of the zone. +-- @param Unit#UNIT ZoneUNIT The unit as the center of the zone. +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return #ZONE_UNIT self +function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetPointVec2(), Radius ) ) + self:F( { ZoneName, ZoneUNIT:GetPointVec2(), Radius } ) + + self.ZoneUNIT = ZoneUNIT + + return self +end + + +--- Returns the current location of the @{Unit#UNIT}. +-- @param #ZONE_UNIT self +-- @return DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location. +function ZONE_UNIT:GetPointVec2() + self:F( self.ZoneName ) + + local ZonePointVec2 = self.ZoneUNIT:GetPointVec2() + + self:T( { ZonePointVec2 } ) + + return ZonePointVec2 +end + + +--- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- @type ZONE_POLYGON +-- @extends Zone#ZONE_BASE +ZONE_POLYGON = { + ClassName="ZONE_POLYGON", + } + +--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the name of the @{Group#GROUP} defined within the Mission Editor. +-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON. +-- @param #ZONE_POLYGON self +-- @param #string ZoneName Name of the zone. +-- @param Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:New( ZoneName, ZoneGroup ) + local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) + self:F( { ZoneName, ZoneGroup } ) + + local GroupPoints = ZoneGroup:GetTaskRoute() + local i = 0 + + self.Polygon = {} + + for i = 1, #GroupPoints do + self.Polygon[i] = {} + self.Polygon[i].x = GroupPoints[i].x + self.Polygon[i].y = GroupPoints[i].y + end + + return self +end + +--- Smokes the zone boundaries in a color. +-- @param #ZONE_POLYGON self +-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:SmokeZone( SmokeColor ) + self:F2( SmokeColor ) + + local i + local j + local Segments = 10 + + i = 1 + j = #self.Polygon + + while i <= #self.Polygon do + self:T( { i, j, self.Polygon[i], self.Polygon[j] } ) + + local DeltaX = self.Polygon[j].x - self.Polygon[i].x + local DeltaY = self.Polygon[j].y - self.Polygon[i].y + + for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line. + local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments ) + local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments ) + POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor ) + end + j = i + i = i + 1 + end + + return self +end + + + + +--- Returns if a location is within the zone. +-- @param #ZONE_POLYGON self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_POLYGON:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local i + local j + local c = false + + i = 1 + j = #self.Polygon + + while i < #self.Polygon do + j = i + i = i + 1 + self:T( { i, j, self.Polygon[i], self.Polygon[j] } ) + if ( ( ( self.Polygon[i].y > PointVec2.y ) ~= ( self.Polygon[j].y > PointVec2.y ) ) and + ( PointVec2.x < ( self.Polygon[j].x - self.Polygon[i].x ) * ( PointVec2.y - self.Polygon[i].y ) / ( self.Polygon[j].y - self.Polygon[i].y ) + self.Polygon[i].x ) + ) then + c = not c + end + self:T2( { "c = ", c } ) + end + + self:T( { "c = ", c } ) + return c +end + +--- This module contains the CLIENT class. -- --- @{#CLIENT} class --- ================ +-- 1) @{Client#CLIENT} class, extends @{Unit#UNIT} +-- =============================================== -- Clients are those **Units** defined within the Mission Editor that have the skillset defined as __Client__ or __Player__. -- Note that clients are NOT the same as Units, they are NOT necessarily alive. --- The @{CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__: +-- The @{Client#CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__: -- -- * Wraps the DCS Unit objects with skill level set to Player or Client. -- * Support all DCS Unit APIs. @@ -6834,8 +8121,8 @@ end -- -- Clients are being used by the @{MISSION} class to follow players and register their successes. -- --- CLIENT reference methods --- ======================= +-- 1.1) CLIENT reference methods +-- ----------------------------- -- For each DCS Unit having skill level Player or Client, a CLIENT wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts). -- @@ -7297,6 +8584,87 @@ function CLIENT:Message( Message, MessageDuration, MessageId, MessageCategory, M end end end +--- This module contains the STATIC class. +-- +-- 1) @{Static#STATIC} class, extends @{Unit#UNIT} +-- =============================================== +-- Statics are **Static Units** defined within the Mission Editor. +-- Note that Statics are almost the same as Units, but they don't have a controller. +-- The @{Static#STATIC} class is a wrapper class to handle the DCS Static objects: +-- +-- * Wraps the DCS Static objects. +-- * Support all DCS Static APIs. +-- * Enhance with Static specific APIs not in the DCS API set. +-- +-- 1.1) STATIC reference methods +-- ----------------------------- +-- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object. +-- This is done at the beginning of the mission (when the mission starts). +-- +-- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference +-- using the Static Name. +-- +-- Another thing to know is that STATIC objects do not "contain" the DCS Static object. +-- The STATIc methods will reference the DCS Static object by name when it is needed during API execution. +-- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file. +-- +-- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance: +-- +-- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name. +-- +-- IMPORTANT: ONE SHOULD NEVER SANATIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil). +-- +-- @module Static +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Message" ) + + +--- The STATIC class +-- @type STATIC +-- @extends Unit#UNIT +STATIC = { + ClassName = "STATIC", +} + + +--- Finds a STATIC from the _DATABASE using the relevant Static Name. +-- As an optional parameter, a briefing text can be given also. +-- @param #STATIC self +-- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor. +-- @return #STATIC +function STATIC:FindByName( StaticName ) + local StaticFound = _DATABASE:FindStatic( StaticName ) + + if StaticFound then + StaticFound:F( { StaticName } ) + + return StaticFound + end + + error( "STATIC not found for: " .. StaticName ) +end + +function STATIC:Register( StaticName ) + local self = BASE:Inherit( self, UNIT:Register( StaticName ) ) + + self:F( StaticName ) + + return self +end + + +function STATIC:GetDCSUnit() + local DCSStatic = StaticObject.getByName( self.UnitName ) + + if DCSStatic then + return DCSStatic + end + + return nil +end --- Manage the mission database. -- -- @{#DATABASE} class @@ -7335,9 +8703,11 @@ Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Menu" ) Include.File( "Group" ) +Include.File( "Static" ) Include.File( "Unit" ) Include.File( "Event" ) Include.File( "Client" ) +Include.File( "Scheduler" ) --- DATABASE class @@ -7353,7 +8723,9 @@ DATABASE = { }, DCSUnits = {}, DCSGroups = {}, + DCSStatics = {}, UNITS = {}, + STATICS = {}, GROUPS = {}, PLAYERS = {}, PLAYERSALIVE = {}, @@ -7399,7 +8771,8 @@ function DATABASE:New() _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventOnPlayerLeaveUnit, self ) self:_RegisterTemplates() - self:_RegisterDatabase() + self:_RegisterGroupsAndUnits() + self:_RegisterStatics() self:_RegisterPlayers() return self @@ -7432,6 +8805,32 @@ function DATABASE:DeleteUnit( DCSUnitName ) self.DCSUnits[DCSUnitName] = nil end +--- Adds a Static based on the Static Name in the DATABASE. +-- @param #DATABASE self +function DATABASE:AddStatic( DCSStatic, DCSStaticName ) + + self.DCSStatics[DCSStaticName] = DCSStatic + self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName ) +end + + +--- Deletes a Static from the DATABASE based on the Static Name. +-- @param #DATABASE self +function DATABASE:DeleteStatic( DCSStaticName ) + + self.DCSStatics[DCSStaticName] = nil +end + +--- Finds a STATIC based on the StaticName. +-- @param #DATABASE self +-- @param #string StaticName +-- @return Static#STATIC The found STATIC. +function DATABASE:FindStatic( StaticName ) + + local StaticFound = self.STATICS[StaticName] + return StaticFound +end + --- Finds a CLIENT based on the ClientName. -- @param #DATABASE self @@ -7519,6 +8918,8 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.SpawnCategoryID = nil self:_RegisterTemplate( SpawnTemplate ) + + self:T3( SpawnTemplate ) coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate ) -- Restore @@ -7526,7 +8927,6 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.SpawnCountryID = SpawnCountryID SpawnTemplate.SpawnCategoryID = SpawnCategoryID - local SpawnGroup = GROUP:Register( SpawnTemplate.name ) return SpawnGroup end @@ -7619,10 +9019,10 @@ function DATABASE:_RegisterPlayers() end ---- Private method that registers all datapoints within in the mission. +--- Private method that registers all Groups and Units within in the mission. -- @param #DATABASE self -- @return #DATABASE self -function DATABASE:_RegisterDatabase() +function DATABASE:_RegisterGroupsAndUnits() local CoalitionsData = { GroupsRed = coalition.getGroups( coalition.side.RED ), GroupsBlue = coalition.getGroups( coalition.side.BLUE ) } for CoalitionId, CoalitionData in pairs( CoalitionsData ) do @@ -7655,6 +9055,27 @@ function DATABASE:_RegisterDatabase() return self end +function DATABASE:_RegisterStatics() + + local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) } + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do + for DCSStaticId, DCSStatic in pairs( CoalitionData ) do + + if DCSStatic:isExist() then + local DCSStaticName = DCSStatic:getName() + + self:E( { "Register Static:", DCSStatic, DCSStaticName } ) + self:AddStatic( DCSStatic, DCSStaticName ) + else + self:E( { "Static does not exist: ", DCSStatic } ) + end + end + end + + return self +end + + --- Events --- Handles the OnBirth event for the alive units set. @@ -7917,6 +9338,201 @@ end +--- This module contains the POINT classes. +-- +-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE} +-- =============================================== +-- The @{Point#POINT_VEC3} class defines a 3D point in the simulator. +-- +-- 1.1) POINT_VEC3 constructor +-- --------------------------- +-- +-- A new POINT instance can be created with: +-- +-- * @{#POINT_VEC3.New}(): a 3D point. +-- +-- 2) @{Point#POINT_VEC2} class, extends @{Point#POINT_VEC3} +-- ========================================================= +-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified. +-- +-- 2.1) POINT_VEC2 constructor +-- --------------------------- +-- +-- A new POINT instance can be created with: +-- +-- * @{#POINT_VEC2.New}(): a 2D point. +-- +-- @module Point +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Point" ) + +--- The POINT_VEC3 class +-- @type POINT_VEC3 +-- @extends Base#BASE +-- @field #POINT_VEC3.SmokeColor SmokeColor +-- @field #POINT_VEC3.FlareColor FlareColor +POINT_VEC3 = { + ClassName = "POINT_VEC3", + SmokeColor = { + Green = trigger.smokeColor.Green, + Red = trigger.smokeColor.Red, + White = trigger.smokeColor.White, + Orange = trigger.smokeColor.Orange, + Blue = trigger.smokeColor.Blue + }, + FlareColor = { + Green = trigger.flareColor.Green, + Red = trigger.flareColor.Red, + White = trigger.flareColor.White, + Yellow = trigger.flareColor.Yellow + }, + } + +--- SmokeColor +-- @type POINT_VEC3.SmokeColor +-- @field Green +-- @field Red +-- @field White +-- @field Orange +-- @field Blue + +--- FlareColor +-- @type POINT_VEC3.FlareColor +-- @field Green +-- @field Red +-- @field White +-- @field Yellow + +-- Constructor. + +--- Create a new POINT_VEC3 object. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. +-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing Upwards. +-- @param DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right. +-- @return Point#POINT_VEC3 +function POINT_VEC3:New( x, y, z ) + + local self = BASE:Inherit( self, BASE:New() ) + self:F2( { x, y, z } ) + self.PointVec3 = { x = x, y = y, z = z } + return self +end + +--- Smokes the point in a color. +-- @param #POINT_VEC3 self +-- @param Point#POINT_VEC3.SmokeColor SmokeColor +function POINT_VEC3:Smoke( SmokeColor ) + self:F2( { SmokeColor, self.PointVec3 } ) + trigger.action.smoke( self.PointVec3, SmokeColor ) +end + +--- Smoke the POINT_VEC3 Green. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeGreen() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Green ) +end + +--- Smoke the POINT_VEC3 Red. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeRed() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Red ) +end + +--- Smoke the POINT_VEC3 White. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeWhite() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.White ) +end + +--- Smoke the POINT_VEC3 Orange. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeOrange() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Orange ) +end + +--- Smoke the POINT_VEC3 Blue. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeBlue() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Blue ) +end + +--- Flares the point in a color. +-- @param #POINT_VEC3 self +-- @param Point#POINT_VEC3.FlareColor +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:Flare( FlareColor, Azimuth ) + self:F2( { FlareColor, self.PointVec3 } ) + trigger.action.signalFlare( self.PointVec3, FlareColor, Azimuth and Azimuth or 0 ) +end + +--- Flare the POINT_VEC3 White. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareWhite( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.White, Azimuth ) +end + +--- Flare the POINT_VEC3 Yellow. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareYellow( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Yellow, Azimuth ) +end + +--- Flare the POINT_VEC3 Green. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareGreen( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Green, Azimuth ) +end + +--- Flare the POINT_VEC3 Red. +-- @param #POINT_VEC3 self +function POINT_VEC3:FlareRed( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Red, Azimuth ) +end + + +--- The POINT_VEC2 class +-- @type POINT_VEC2 +-- @extends Point#POINT_VEC3 +POINT_VEC2 = { + ClassName = "POINT_VEC2", + } + +--- Create a new POINT_VEC2 object. +-- @param #POINT_VEC2 self +-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. +-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right. +-- @param DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height. +-- @return Point#POINT_VEC2 +function POINT_VEC2:New( x, y, LandHeightAdd ) + + local LandHeight = land.getHeight( { ["x"] = x, ["y"] = y } ) + if LandHeightAdd then + LandHeight = LandHeight + LandHeightAdd + end + + local self = BASE:Inherit( self, POINT_VEC3:New( x, LandHeight, y ) ) + self:F2( { x, y, LandHeightAdd } ) + + return self +end + + --- The main include file for the MOOSE system. Include.File( "Routines" ) @@ -13160,10 +14776,10 @@ function CLEANUP:_CleanUpScheduler() return true end ---- Dynamic spawning of groups (and units). +--- This module contains the SPAWN class. -- --- @{#SPAWN} class --- =============== +-- 1) @{Spawn#SPAWN} class, extends @{Base#BASE} +-- ============================================= -- The @{#SPAWN} class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned. -- For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the *"Spawn Template"* of the SPAWN object. -- A reference to this Spawn Template needs to be provided when constructing the SPAWN object, by indicating the name of the group within the mission editor in the constructor methods. @@ -13186,8 +14802,8 @@ end -- * It is important to defined BEFORE you spawn new groups, a proper initialization of the SPAWN instance is done with the options you want to use. -- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn Template(s), or the SPAWN module logic won't work anymore. -- --- SPAWN construction methods: --- =========================== +-- 1.1) SPAWN construction methods +-- ------------------------------- -- Create a new SPAWN object with the @{#SPAWN.New} or the @{#SPAWN.NewWithAlias} methods: -- -- * @{#SPAWN.New}: Creates a new SPAWN object taking the name of the group that functions as the Template. @@ -13196,8 +14812,8 @@ end -- The initialization functions will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons. -- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient. -- --- SPAWN initialization methods: --- ============================= +-- 1.2) SPAWN initialization methods +-- --------------------------------- -- A spawn object will behave differently based on the usage of initialization methods: -- -- * @{#SPAWN.Limit}: Limits the amount of groups that can be alive at the same time and that can be dynamically spawned. @@ -13207,8 +14823,8 @@ end -- * @{#SPAWN.Array}: Make groups visible before they are actually activated, and order these groups like a batallion in an array. -- * @{#SPAWN.InitRepeat}: Re-spawn groups when they land at the home base. Similar functions are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}. -- --- SPAWN spawning methods: --- ======================= +-- 1.3) SPAWN spawning methods +-- --------------------------- -- Groups can be spawned at different times and methods: -- -- * @{#SPAWN.Spawn}: Spawn one new group based on the last spawned index. @@ -13220,8 +14836,8 @@ end -- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object. -- You can use the @{GROUP} object to do further actions with the DCSGroup. -- --- SPAWN object cleaning: --- ========================= +-- 1.4) SPAWN object cleaning +-- -------------------------- -- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive. -- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't, -- and it may occur that no new groups are or can be spawned as limits are reached. @@ -13232,7 +14848,7 @@ end -- This models AI that has succesfully returned to their airbase, to restart their combat activities. -- Check the @{#SPAWN.CleanUp} for further info. -- --- ==== +-- -- @module Spawn -- @author FlightControl @@ -13635,6 +15251,12 @@ function SPAWN:SpawnWithIndex( SpawnIndex ) end self.SpawnGroups[self.SpawnIndex].Spawned = true + + local SpawnGroup = self.SpawnGroups[self.SpawnIndex].Group -- Group#GROUP + local Route = SpawnGroup:GetTaskRoute() + SpawnGroup:Route(Route) + + return self.SpawnGroups[self.SpawnIndex].Group else --self:E( { self.SpawnTemplatePrefix, "No more Groups to Spawn:", SpawnIndex, self.SpawnMaxGroups } ) @@ -14142,11 +15764,12 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) SpawnTemplate.name = self:SpawnGroupName( SpawnIndex ) SpawnTemplate.groupId = nil - SpawnTemplate.lateActivation = false + --SpawnTemplate.lateActivation = false + SpawnTemplate.lateActivation = false -- TODO BUGFIX if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then self:T( "For ground units, visible needs to be false..." ) - SpawnTemplate.visible = false + SpawnTemplate.visible = false -- TODO BUGFIX end if SpawnTemplate.SpawnCategoryID == Group.Category.HELICOPTER or SpawnTemplate.SpawnCategoryID == Group.Category.AIRPLANE then @@ -14194,7 +15817,7 @@ end -- @param #number SpawnIndex -- @return #SPAWN self function SPAWN:_RandomizeTemplate( SpawnIndex ) - self:F( { self.SpawnTemplatePrefix, SpawnIndex } ) + self:F( { self.SpawnTemplatePrefix, SpawnIndex, self.SpawnRandomizeTemplate } ) if self.SpawnRandomizeTemplate then self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefixTable[ math.random( 1, #self.SpawnTemplatePrefixTable ) ] diff --git a/Moose Mission Setup/Moose.lua b/Moose Mission Setup/Moose.lua index a555b44df..92334c9b8 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: 20160527_1352' ) +env.info( 'Moose Generation Timestamp: 20160606_1516' ) local base = _G env.info("Loading MOOSE " .. base.timer.getAbsTime() ) @@ -2930,12 +2930,12 @@ end --- Trace a function call. Must be at the beginning of the function logic. -- @param #BASE self -- @param Arguments A #table or any field. -function BASE:F( Arguments ) +function BASE:F( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if _TraceOn and ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) then - local DebugInfoCurrent = debug.getinfo( 2, "nl" ) - local DebugInfoFrom = debug.getinfo( 3, "l" ) + local DebugInfoCurrent = DebugInfoCurrentParam and DebugInfoCurrentParam or debug.getinfo( 2, "nl" ) + local DebugInfoFrom = DebugInfoFromParam and DebugInfoFromParam or debug.getinfo( 3, "l" ) local Function = "function" if DebugInfoCurrent.name then @@ -2958,8 +2958,11 @@ end -- @param Arguments A #table or any field. function BASE:F2( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 2 then - self:F( Arguments ) + self:F( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -2969,8 +2972,11 @@ end -- @param Arguments A #table or any field. function BASE:F3( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 3 then - self:F( Arguments ) + self:F( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -2978,12 +2984,12 @@ end --- Trace a function logic. Can be anywhere within the function logic. -- @param #BASE self -- @param Arguments A #table or any field. -function BASE:T( Arguments ) +function BASE:T( Arguments, DebugInfoCurrentParam, DebugInfoFromParam ) if _TraceOn and ( _TraceClass[self.ClassName] or _TraceClassMethod[self.ClassName] ) then - local DebugInfoCurrent = debug.getinfo( 2, "nl" ) - local DebugInfoFrom = debug.getinfo( 3, "l" ) + local DebugInfoCurrent = DebugInfoCurrentParam and DebugInfoCurrentParam or debug.getinfo( 2, "nl" ) + local DebugInfoFrom = DebugInfoFromParam and DebugInfoFromParam or debug.getinfo( 3, "l" ) local Function = "function" if DebugInfoCurrent.name then @@ -3006,8 +3012,11 @@ end -- @param Arguments A #table or any field. function BASE:T2( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 2 then - self:T( Arguments ) + self:T( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -3017,8 +3026,11 @@ end -- @param Arguments A #table or any field. function BASE:T3( Arguments ) + local DebugInfoCurrent = debug.getinfo( 2, "nl" ) + local DebugInfoFrom = debug.getinfo( 3, "l" ) + if _TraceLevel >= 3 then - self:T( Arguments ) + self:T( Arguments, DebugInfoCurrent, DebugInfoFrom ) end end @@ -3170,7 +3182,7 @@ function SCHEDULER:_Scheduler() self:T( { Status, Result } ) - if Status and Status == true and Result and Result == true then + if Status and ( ( not Result ) or ( Result and Result ~= false ) ) then if self.Repeat and ( not self.StopSeconds or ( self.StopSeconds and timer.getTime() <= self.StartTime + self.StopSeconds ) ) then timer.scheduleFunction( self._Scheduler, @@ -4071,36 +4083,151 @@ function MENU_COALITION_COMMAND:Remove() self.ParentMenu.Menus[self.MenuPath] = nil return nil end ---- GROUP class. --- --- @{GROUP} class --- ============== --- The @{GROUP} class is a wrapper class to handle the DCS Group objects: +--- This module contains the GROUP class. -- +-- 1) @{Group#GROUP} class, extends @{Base#BASE} +-- ============================================= +-- The @{Group#GROUP} class is a wrapper class to handle the DCS Group objects: +-- -- * Support all DCS Group APIs. -- * Enhance with Group specific APIs not in the DCS Group API set. -- * Handle local Group Controller. -- * Manage the "state" of the DCS Group. --- --- --- GROUP reference methods --- ======================= +-- +-- **IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).** +-- +-- 1.1) GROUP reference methods +-- ----------------------- -- For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the @{SPAWN} class). --- +-- -- The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference -- using the DCS Group or the DCS GroupName. --- --- Another thing to know is that GROUP objects do not "contain" the DCS Group object. +-- +-- Another thing to know is that GROUP objects do not "contain" the DCS Group object. -- The GROUP methods will reference the DCS Group object by name when it is needed during API execution. -- If the DCS Group object does not exist or is nil, the GROUP methods will return nil and log an exception in the DCS.log file. --- +-- -- The GROUP class provides the following functions to retrieve quickly the relevant GROUP instance: --- +-- -- * @{#GROUP.Find}(): Find a GROUP instance from the _DATABASE object using a DCS Group object. -- * @{#GROUP.FindByName}(): Find a GROUP instance from the _DATABASE object using a DCS Group name. --- --- IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil). +-- +-- 1.2) GROUP task methods +-- ----------------------- +-- Several group task methods are available that help you to prepare tasks. +-- These methods return a string consisting of the task description, which can then be given to either a @{Group#GROUP.PushTask} or @{Group#SetTask} method to assign the task to the GROUP. +-- Tasks are specific for the category of the GROUP, more specific, for AIR, GROUND or AIR and GROUND. +-- Each task description where applicable indicates for which group category the task is valid. +-- There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks. +-- +-- ### 1.2.1) Assigned task methods +-- +-- Assigned task methods make the group execute the task where the location of the (possible) targets of the task are known before being detected. +-- This is different from the EnRoute tasks, where the targets of the task need to be detected before the task can be executed. +-- +-- Find below a list of the **assigned task** methods: +-- +-- * @{#GROUP.TaskAttackGroup}: (AIR) Attack a Group. +-- * @{#GROUP.TaskAttackMapObject}: (AIR) Attacking the map object (building, structure, e.t.c). +-- * @{#GROUP.TaskAttackUnit}: (AIR) Attack the Unit. +-- * @{#GROUP.TaskBombing}: (AIR) Delivering weapon at the point on the ground. +-- * @{#GROUP.TaskBombingRunway}: (AIR) Delivering weapon on the runway. +-- * @{#GROUP.TaskEmbarking}: (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group. +-- * @{#GROUP.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location. +-- * @{#GROUP.TaskEscort}: (AIR) Escort another airborne group. +-- * @{#GROUP.TaskFAC_AttackGroup}: (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction. +-- * @{#GROUP.TaskFireAtPoint}: (GROUND) Fire at a VEC2 point until ammunition is finished. +-- * @{#GROUP.TaskFollow}: (AIR) Following another airborne group. +-- * @{#GROUP.TaskHold}: (GROUND) Hold ground group from moving. +-- * @{#GROUP.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the group. +-- * @{#GROUP.TaskLand}: (AIR HELICOPTER) Landing at the ground. For helicopters only. +-- * @{#GROUP.TaskLandAtZone}: (AIR) Land the group at a @{Zone#ZONE_RADIUS). +-- * @{#GROUP.TaskOrbitCircle}: (AIR) Orbit at the current position of the first unit of the group at a specified alititude. +-- * @{#GROUP.TaskOrbitCircleAtVec2}: (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. +-- * @{#GROUP.TaskRefueling}: (AIR) Refueling from the nearest tanker. No parameters. +-- * @{#GROUP.TaskRoute}: (AIR + GROUND) Return a Misson task to follow a given route defined by Points. +-- * @{#GROUP.TaskRouteToVec2}: (AIR + GROUND) Make the Group move to a given point. +-- * @{#GROUP.TaskRouteToVec3}: (AIR + GROUND) Make the Group move to a given point. +-- * @{#GROUP.TaskRouteToZone}: (AIR + GROUND) Route the group to a given zone. +-- +-- ### 1.2.2) EnRoute task methods +-- +-- EnRoute tasks require the targets of the task need to be detected by the group (using its sensors) before the task can be executed: +-- +-- * @{#GROUP.EnRouteTaskAWACS}: (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters. +-- * @{#GROUP.EnRouteTaskEngageGroup}: (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskEngageTargets}: (AIR) Engaging targets of defined types. +-- * @{#GROUP.EnRouteTaskEWR}: (AIR) Attack the Unit. +-- * @{#GROUP.EnRouteTaskFAC}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskFAC_EngageGroup}: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets. +-- * @{#GROUP.EnRouteTaskTanker}: (AIR) Aircraft will act as a tanker for friendly units. No parameters. +-- +-- ### 1.2.3) Preparation task methods +-- +-- There are certain task methods that allow to tailor the task behaviour: +-- +-- * @{#GROUP.TaskWrappedAction}: Return a WrappedAction Task taking a Command. +-- * @{#GROUP.TaskCombo}: Return a Combo Task taking an array of Tasks. +-- * @{#GROUP.TaskCondition}: Return a condition section for a controlled task. +-- * @{#GROUP.TaskControlled}: Return a Controlled Task taking a Task and a TaskCondition. +-- +-- ### 1.2.4) Obtain the mission from group templates +-- +-- Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another: +-- +-- * @{#GROUP.TaskMission}: (AIR + GROUND) Return a mission task from a mission template. +-- +-- 1.3) GROUP Command methods +-- -------------------------- +-- Group **command methods** prepare the execution of commands using the @{#GROUP.SetCommand} method: +-- +-- * @{#GROUP.CommandDoScript}: Do Script command. +-- * @{#GROUP.CommandSwitchWayPoint}: Perform a switch waypoint command. +-- +-- 1.4) GROUP Option methods +-- ------------------------- +-- Group **Option methods** change the behaviour of the Group while being alive. +-- +-- ### 1.4.1) Rule of Engagement: +-- +-- * @{#GROUP.OptionROEWeaponFree} +-- * @{#GROUP.OptionROEOpenFire} +-- * @{#GROUP.OptionROEReturnFire} +-- * @{#GROUP.OptionROEEvadeFire} +-- +-- To check whether an ROE option is valid for a specific group, use: +-- +-- * @{#GROUP.OptionROEWeaponFreePossible} +-- * @{#GROUP.OptionROEOpenFirePossible} +-- * @{#GROUP.OptionROEReturnFirePossible} +-- * @{#GROUP.OptionROEEvadeFirePossible} +-- +-- ### 1.4.2) Rule on thread: +-- +-- * @{#GROUP.OptionROTNoReaction} +-- * @{#GROUP.OptionROTPassiveDefense} +-- * @{#GROUP.OptionROTEvadeFire} +-- * @{#GROUP.OptionROTVertical} +-- +-- To test whether an ROT option is valid for a specific group, use: +-- +-- * @{#GROUP.OptionROTNoReactionPossible} +-- * @{#GROUP.OptionROTPassiveDefensePossible} +-- * @{#GROUP.OptionROTEvadeFirePossible} +-- * @{#GROUP.OptionROTVerticalPossible} +-- +-- 1.5) GROUP Zone validation methods +-- ---------------------------------- +-- The group can be validated whether it is completely, partly or not within a @{Zone}. +-- Use the following Zone validation methods on the group: +-- +-- * @{#GROUP.IsCompletelyInZone}: Returns true if all units of the group are within a @{Zone}. +-- * @{#GROUP.IsPartlyInZone}: Returns true if some units of the group are within a @{Zone}. +-- * @{#GROUP.IsNotInZone}: Returns true if none of the group units of the group are within a @{Zone}. +-- +-- The zone can be of any @{Zone} class derived from @{Zone#ZONE_BASE}. So, these methods are polymorphic to the zones tested on. +-- -- @module Group -- @author FlightControl @@ -4115,14 +4242,14 @@ Include.File( "Unit" ) -- @field DCSGroup#Group DCSGroup The DCS group class. -- @field #string GroupName The name of the group. GROUP = { - ClassName = "GROUP", - GroupName = "", - GroupID = 0, - Controller = nil, - DCSGroup = nil, - WayPointFunctions = {}, - } - + ClassName = "GROUP", + GroupName = "", + GroupID = 0, + Controller = nil, + DCSGroup = nil, + WayPointFunctions = {}, +} + --- A DCSGroup -- @type DCSGroup -- @field id_ The ID of the group in DCS @@ -4132,10 +4259,10 @@ GROUP = { -- @param DCSGroup#Group GroupName The DCS Group name -- @return #GROUP self function GROUP:Register( GroupName ) - local self = BASE:Inherit( self, BASE:New() ) - self:F2( GroupName ) - self.GroupName = GroupName - return self + local self = BASE:Inherit( self, BASE:New() ) + self:F2( GroupName ) + self.GroupName = GroupName + return self end -- Reference methods. @@ -4168,11 +4295,11 @@ end -- @return DCSGroup#Group The DCS Group. function GROUP:GetDCSGroup() local DCSGroup = Group.getByName( self.GroupName ) - + if DCSGroup then return DCSGroup end - + return nil end @@ -4183,27 +4310,27 @@ end -- @return #boolean true if the DCS Group is alive. function GROUP:IsAlive() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupIsAlive = DCSGroup:isExist() self:T3( GroupIsAlive ) return GroupIsAlive end - + return nil end ---- Destroys the DCS Group and all of its DCS Units. +--- Destroys the DCS Group and all of its DCS Units. -- Note that this destroy method also raises a destroy event at run-time. -- So all event listeners will catch the destroy event of this DCS Group. -- @param #GROUP self function GROUP:Destroy() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then for Index, UnitData in pairs( DCSGroup:getUnits() ) do self:CreateEventCrash( timer.getTime(), UnitData ) @@ -4211,11 +4338,11 @@ function GROUP:Destroy() DCSGroup:destroy() DCSGroup = nil end - + return nil end ---- Returns category of the DCS Group. +--- Returns category of the DCS Group. -- @param #GROUP self -- @return DCSGroup#Group.Category The category ID function GROUP:GetCategory() @@ -4227,7 +4354,7 @@ function GROUP:GetCategory() self:T3( GroupCategory ) return GroupCategory end - + return nil end @@ -4243,14 +4370,14 @@ function GROUP:GetCategoryName() [Group.Category.AIRPLANE] = "Airplane", [Group.Category.HELICOPTER] = "Helicopter", [Group.Category.GROUND] = "Ground Unit", - [Group.Category.SHIP] = "Ship", + [Group.Category.SHIP] = "Ship", } local GroupCategory = DCSGroup:getCategory() self:T3( GroupCategory ) - + return CategoryNames[GroupCategory] end - + return nil end @@ -4267,14 +4394,14 @@ function GROUP:GetCoalition() self:T3( GroupCoalition ) return GroupCoalition end - + return nil end --- Returns the country of the DCS Group. -- @param #GROUP self -- @return DCScountry#country.id The country identifier. --- @return #nil The DCS Group is not existing or alive. +-- @return #nil The DCS Group is not existing or alive. function GROUP:GetCountry() self:F2( self.GroupName ) @@ -4284,7 +4411,7 @@ function GROUP:GetCountry() self:T3( GroupCountry ) return GroupCountry end - + return nil end @@ -4295,13 +4422,13 @@ function GROUP:GetName() self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupName = DCSGroup:getName() self:T3( GroupName ) return GroupName end - + return nil end @@ -4310,19 +4437,19 @@ end -- @return #number The identifier of the DCS Group. function GROUP:GetID() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupID = DCSGroup:getID() self:T3( GroupID ) return GroupID end - + return nil end ---- Returns the UNIT wrapper class with number UnitNumber. +--- Returns the UNIT wrapper class with number UnitNumber. -- If the underlying DCS Unit does not exist, the method will return nil. . -- @param #GROUP self -- @param #number UnitNumber The number of the UNIT wrapper class to be returned. @@ -4331,7 +4458,7 @@ function GROUP:GetUnit( UnitNumber ) self:F2( { self.GroupName, UnitNumber } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local UnitFound = UNIT:Find( DCSGroup:getUnit( UnitNumber ) ) self:T3( UnitFound.UnitName ) @@ -4342,7 +4469,7 @@ function GROUP:GetUnit( UnitNumber ) return nil end ---- Returns the DCS Unit with number UnitNumber. +--- Returns the DCS Unit with number UnitNumber. -- If the underlying DCS Unit does not exist, the method will return nil. . -- @param #GROUP self -- @param #number UnitNumber The number of the DCS Unit to be returned. @@ -4351,7 +4478,7 @@ function GROUP:GetDCSUnit( UnitNumber ) self:F2( { self.GroupName, UnitNumber } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnitFound = DCSGroup:getUnit( UnitNumber ) self:T3( DCSUnitFound ) @@ -4361,14 +4488,14 @@ function GROUP:GetDCSUnit( UnitNumber ) return nil end ---- Returns current size of the DCS Group. --- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed. +--- Returns current size of the DCS Group. +-- If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed. -- @param #GROUP self -- @return #number The DCS Group size. function GROUP:GetSize() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupSize = DCSGroup:getSize() self:T3( GroupSize ) @@ -4378,15 +4505,15 @@ function GROUP:GetSize() return nil end ---- ---- Returns the initial size of the DCS Group. --- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged. +--- +--- Returns the initial size of the DCS Group. +-- If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged. -- @param #GROUP self -- @return #number The DCS Group initial size. function GROUP:GetInitialSize() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupInitialSize = DCSGroup:getInitialSize() self:T3( GroupInitialSize ) @@ -4402,7 +4529,7 @@ end function GROUP:GetUnits() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnits = DCSGroup:getUnits() local Units = {} @@ -4423,7 +4550,7 @@ end function GROUP:GetDCSUnits() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local DCSUnits = DCSGroup:getUnits() self:T3( DCSUnits ) @@ -4439,7 +4566,7 @@ end function GROUP:_GetController() self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupController = DCSGroup:getController() self:T3( GroupController ) @@ -4459,7 +4586,7 @@ end function GROUP:WayPointInitialize() self.WayPoints = self:GetTaskRoute() - + return self end @@ -4472,7 +4599,7 @@ end -- @return #GROUP function GROUP:WayPointFunction( WayPoint, WayPointIndex, WayPointFunction, ... ) self:F2( { WayPoint, WayPointIndex, WayPointFunction } ) - + table.insert( self.WayPoints[WayPoint].task.params.tasks, WayPointIndex ) self.WayPoints[WayPoint].task.params.tasks[WayPointIndex] = self:TaskFunction( WayPoint, WayPointIndex, WayPointFunction, arg ) return self @@ -4482,7 +4609,7 @@ end function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionArguments ) local DCSTask - + local DCSScript = {} DCSScript[#DCSScript+1] = "local MissionGroup = GROUP:Find( ... ) " @@ -4490,16 +4617,16 @@ function GROUP:TaskFunction( WayPoint, WayPointIndex, FunctionString, FunctionAr DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup, " .. table.concat( FunctionArguments, "," ) .. ")" else DCSScript[#DCSScript+1] = FunctionString .. "( MissionGroup )" - end - - DCSTask = self:TaskWrappedAction( + end + + DCSTask = self:TaskWrappedAction( self:CommandDoScript( table.concat( DCSScript ) ), WayPointIndex ) - + self:T3( DCSTask ) - + return DCSTask end @@ -4511,21 +4638,21 @@ end -- Note that when the WayPoint parameter is used, the new start mission waypoint of the group will be 1! -- @param #GROUP self -- @param #number WayPoint The WayPoint from where to execute the mission. --- @param #WaitTime The amount seconds to wait before initiating the mission. +-- @param #number WaitTime The amount seconds to wait before initiating the mission. -- @return #GROUP function GROUP:WayPointExecute( WayPoint, WaitTime ) if not WayPoint then WayPoint = 1 end - + -- When starting the mission from a certain point, the TaskPoints need to be deleted before the given WayPoint. for TaskPointID = 1, WayPoint - 1 do table.remove( self.WayPoints, 1 ) end self:T3( self.WayPoints ) - + self:SetTask( self:TaskRoute( self.WayPoints ), WaitTime ) return self @@ -4535,9 +4662,9 @@ end --- Activates a GROUP. -- @param #GROUP self function GROUP:Activate() - self:F2( { self.GroupName } ) - trigger.action.activateGroup( self:GetDCSGroup() ) - return self:GetDCSGroup() + self:F2( { self.GroupName } ) + trigger.action.activateGroup( self:GetDCSGroup() ) + return self:GetDCSGroup() end @@ -4548,13 +4675,13 @@ function GROUP:GetTypeName() self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupTypeName = DCSGroup:getUnit(1):getTypeName() self:T3( GroupTypeName ) return( GroupTypeName ) end - + return nil end @@ -4563,33 +4690,33 @@ end -- @return #string The CallSign of the first DCS Unit of the DCS Group. function GROUP:GetCallsign() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCallSign = DCSGroup:getUnit(1):getCallsign() self:T3( GroupCallSign ) return GroupCallSign end - + return nil end --- Returns the current point (Vec2 vector) of the first DCS Unit in the DCS Group. -- @return DCSTypes#Vec2 Current Vec2 point of the first DCS Unit of the DCS Group. function GROUP:GetPointVec2() - self:F2( self.GroupName ) - - local GroupPointVec2 = self:GetUnit(1):GetPointVec2() - self:T3( GroupPointVec2 ) - return GroupPointVec2 + self:F2( self.GroupName ) + + local GroupPointVec2 = self:GetUnit(1):GetPointVec2() + self:T3( GroupPointVec2 ) + return GroupPointVec2 end --- Returns the current point (Vec3 vector) of the first DCS Unit in the DCS Group. -- @return DCSTypes#Vec3 Current Vec3 point of the first DCS Unit of the DCS Group. function GROUP:GetPointVec3() - self:F2( self.GroupName ) - + self:F2( self.GroupName ) + local GroupPointVec3 = self:GetUnit(1):GetPointVec3() self:T3( GroupPointVec3 ) return GroupPointVec3 @@ -4597,23 +4724,75 @@ end --- Is Functions +-- Is Zone Functions + +--- Returns true if all units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsCompletelyInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + else + return false + end + end + + return true +end + +--- Returns true if some units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsPartlyInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + return true + end + end + + return false +end + +--- Returns true if none of the group units of the group are within a @{Zone}. +-- @param #GROUP self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the Group is completely within the @{Zone#ZONE_BASE} +function GROUP:IsNotInZone( Zone ) + self:F2( { self.GroupName, Zone } ) + + for UnitID, UnitData in pairs( self:GetUnits() ) do + local Unit = UnitData -- Unit#UNIT + if Zone:IsPointVec3InZone( Unit:GetPointVec3() ) then + return false + end + end + + return true +end --- Returns if the group is of an air category. -- If the group is a helicopter or a plane, then this method will return true, otherwise false. -- @param #GROUP self -- @return #boolean Air category evaluation result. function GROUP:IsAir() - self:F2( self.GroupName ) + self:F2( self.GroupName ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER - self:T3( IsAirResult ) - return IsAirResult + local IsAirResult = DCSGroup:getCategory() == Group.Category.AIRPLANE or DCSGroup:getCategory() == Group.Category.HELICOPTER + self:T3( IsAirResult ) + return IsAirResult end - + return nil end @@ -4622,15 +4801,15 @@ end -- @return #boolean true if DCS Group contains Helicopters. function GROUP:IsHelicopter() self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.HELICOPTER end - + return nil end @@ -4639,15 +4818,15 @@ end -- @return #boolean true if DCS Group contains AirPlanes. function GROUP:IsAirPlane() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.AIRPLANE end - + return nil end @@ -4656,15 +4835,15 @@ end -- @return #boolean true if DCS Group contains Ground troops. function GROUP:IsGround() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.GROUND end - + return nil end @@ -4673,15 +4852,15 @@ end -- @return #boolean true if DCS Group contains Ships. function GROUP:IsShip() self:F2() - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupCategory = DCSGroup:getCategory() self:T2( GroupCategory ) return GroupCategory == Group.Category.SHIP end - + return nil end @@ -4690,23 +4869,23 @@ end -- @param #GROUP self -- @return #boolean All units on the ground result. function GROUP:AllOnGround() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local AllOnGroundResult = true - - for Index, UnitData in pairs( DCSGroup:getUnits() ) do - if UnitData:inAir() then - AllOnGroundResult = false - end - end - - self:T3( AllOnGroundResult ) - return AllOnGroundResult + local AllOnGroundResult = true + + for Index, UnitData in pairs( DCSGroup:getUnits() ) do + if UnitData:inAir() then + AllOnGroundResult = false + end + end + + self:T3( AllOnGroundResult ) + return AllOnGroundResult end - + return nil end @@ -4715,26 +4894,26 @@ end -- @param #GROUP self -- @return #number Maximum velocity found. function GROUP:GetMaxVelocity() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local MaxVelocity = 0 - - for Index, UnitData in pairs( DCSGroup:getUnits() ) do - - local Velocity = UnitData:getVelocity() - local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z ) - - if VelocityTotal < MaxVelocity then - MaxVelocity = VelocityTotal - end - end - - return MaxVelocity + local MaxVelocity = 0 + + for Index, UnitData in pairs( DCSGroup:getUnits() ) do + + local Velocity = UnitData:getVelocity() + local VelocityTotal = math.abs( Velocity.x ) + math.abs( Velocity.y ) + math.abs( Velocity.z ) + + if VelocityTotal < MaxVelocity then + MaxVelocity = VelocityTotal + end + end + + return MaxVelocity end - + return nil end @@ -4743,7 +4922,7 @@ end -- @param #GROUP self -- @return #number Minimum height found. function GROUP:GetMinHeight() - self:F2() + self:F2() end @@ -4752,7 +4931,7 @@ end -- @param #GROUP self -- @return #number Maximum height found. function GROUP:GetMaxHeight() - self:F2() + self:F2() end @@ -4762,16 +4941,16 @@ end -- @param #GROUP self -- @return Group#GROUP self function GROUP:PopCurrentTask() - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() Controller:popTask() return self end - + return nil end @@ -4779,27 +4958,27 @@ end -- @param #GROUP self -- @return Group#GROUP self function GROUP:PushTask( DCSTask, WaitTime ) - self:F2() + self:F2() local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() - + -- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Group. -- Controller:pushTask( DCSTask ) - + if WaitTime then --routines.scheduleFunction( Controller.pushTask, { Controller, DCSTask }, timer.getTime() + WaitTime ) SCHEDULER:New( Controller, Controller.pushTask, { DCSTask }, WaitTime ) else Controller:pushTask( DCSTask ) end - + return self end - + return nil end @@ -4810,40 +4989,40 @@ function GROUP:SetTask( DCSTask, WaitTime ) self:F2( { DCSTask } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - + local Controller = self:_GetController() - + -- When a group SPAWNs, it takes about a second to get the group in the simulator. Setting tasks to unspawned groups provides unexpected results. -- Therefore we schedule the functions to set the mission and options for the Group. -- Controller.setTask( Controller, DCSTask ) - + if not WaitTime then WaitTime = 1 end --routines.scheduleFunction( Controller.setTask, { Controller, DCSTask }, timer.getTime() + WaitTime ) SCHEDULER:New( Controller, Controller.setTask, { DCSTask }, WaitTime ) - + return self end - + return nil end ---- Return a condition section for a controlled task +--- Return a condition section for a controlled task. -- @param #GROUP self -- @param DCSTime#Time time --- @param #string userFlag --- @param #boolean userFlagValue +-- @param #string userFlag +-- @param #boolean userFlagValue -- @param #string condition --- @param DCSTime#Time duration --- @param #number lastWayPoint +-- @param DCSTime#Time duration +-- @param #number lastWayPoint -- return DCSTask#Task function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration, lastWayPoint ) - self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) - + self:F2( { time, userFlag, userFlagValue, condition, duration, lastWayPoint } ) + local DCSStopCondition = {} DCSStopCondition.time = time DCSStopCondition.userFlag = userFlag @@ -4851,54 +5030,54 @@ function GROUP:TaskCondition( time, userFlag, userFlagValue, condition, duration DCSStopCondition.condition = condition DCSStopCondition.duration = duration DCSStopCondition.lastWayPoint = lastWayPoint - + self:T3( { DCSStopCondition } ) - return DCSStopCondition + return DCSStopCondition end ---- Return a Controlled Task taking a Task and a TaskCondition +--- Return a Controlled Task taking a Task and a TaskCondition. -- @param #GROUP self -- @param DCSTask#Task DCSTask -- @param #DCSStopCondition DCSStopCondition -- @return DCSTask#Task function GROUP:TaskControlled( DCSTask, DCSStopCondition ) - self:F2( { DCSTask, DCSStopCondition } ) + self:F2( { DCSTask, DCSStopCondition } ) local DCSTaskControlled - - DCSTaskControlled = { - id = 'ControlledTask', - params = { - task = DCSTask, - stopCondition = DCSStopCondition - } + + DCSTaskControlled = { + id = 'ControlledTask', + params = { + task = DCSTask, + stopCondition = DCSStopCondition + } } - + self:T3( { DCSTaskControlled } ) return DCSTaskControlled end ---- Return a Combo Task taking an array of Tasks +--- Return a Combo Task taking an array of Tasks. -- @param #GROUP self --- @param #list DCSTasks +-- @param DCSTask#TaskArray DCSTasks Array of @{DCSTask#Task} -- @return DCSTask#Task function GROUP:TaskCombo( DCSTasks ) self:F2( { DCSTasks } ) local DCSTaskCombo - - DCSTaskCombo = { - id = 'ComboTask', - params = { + + DCSTaskCombo = { + id = 'ComboTask', + params = { tasks = DCSTasks - } + } } - + self:T3( { DCSTaskCombo } ) return DCSTaskCombo end ---- Return a WrappedAction Task taking a Command +--- Return a WrappedAction Task taking a Command. -- @param #GROUP self -- @param DCSCommand#Command DCSCommand -- @return DCSTask#Task @@ -4906,8 +5085,8 @@ function GROUP:TaskWrappedAction( DCSCommand, Index ) self:F2( { DCSCommand } ) local DCSTaskWrappedAction - - DCSTaskWrappedAction = { + + DCSTaskWrappedAction = { id = "WrappedAction", enabled = true, number = Index, @@ -4927,15 +5106,15 @@ end -- @return #GROUP self function GROUP:SetCommand( DCSCommand ) self:F2( DCSCommand ) - + local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local Controller = self:_GetController() Controller:setCommand( DCSCommand ) return self end - + return nil end @@ -4946,117 +5125,387 @@ end -- @return DCSTask#Task function GROUP:CommandSwitchWayPoint( FromWayPoint, ToWayPoint, Index ) self:F2( { FromWayPoint, ToWayPoint, Index } ) - + local CommandSwitchWayPoint = { - id = 'SwitchWaypoint', - params = { - fromWaypointIndex = FromWayPoint, - goToWaypointIndex = ToWayPoint, + id = 'SwitchWaypoint', + params = { + fromWaypointIndex = FromWayPoint, + goToWaypointIndex = ToWayPoint, }, } - + self:T3( { CommandSwitchWayPoint } ) return CommandSwitchWayPoint end - ---- Orbit at a specified position at a specified alititude during a specified duration with a specified speed. + +-- TASKS FOR AIR GROUPS + + +--- (AIR) Attack a Group. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackGroup( AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) + self:F2( { self.GroupName, AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) + + -- AttackGroup = { + -- id = 'AttackGroup', + -- params = { + -- groupId = Group.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend, + -- attackQty = number, + -- directionEnabled = boolean, + -- direction = Azimuth, + -- altitudeEnabled = boolean, + -- altitude = Distance, + -- attackQtyLimit = boolean, + -- } + -- } + + local DirectionEnabled = nil + if Direction then + DirectionEnabled = true + end + + local AltitudeEnabled = nil + if Altitude then + AltitudeEnabled = true + end + + local DCSTask + DCSTask = { id = 'AttackGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + directionEnabled = DirectionEnabled, + direction = Direction, + altitudeEnabled = AltitudeEnabled, + altitude = Altitude, + attackQtyLimit = AttackQtyLimit, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Attack the Unit. +-- @param #GROUP self +-- @param Unit#UNIT AttackUnit The unit. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackUnit( AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack ) + self:F2( { self.GroupName, AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack } ) + + -- AttackUnit = { + -- id = 'AttackUnit', + -- params = { + -- unitId = Unit.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend + -- attackQty = number, + -- direction = Azimuth, + -- attackQtyLimit = boolean, + -- groupAttack = boolean, + -- } + -- } + + local DCSTask + DCSTask = { id = 'AttackUnit', + params = { + unitId = AttackUnit:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + attackQtyLimit = AttackQtyLimit, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Delivering weapon at the point on the ground. +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the point to deliver weapon at. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) Desired quantity of passes. The parameter is not the same in AttackGroup and AttackUnit tasks. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskBombing( PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- Bombing = { +-- id = 'Bombing', +-- params = { +-- point = Vec2, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'Bombing', + params = { + point = PointVec2, + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point to hold the position. -- @param #number Altitude The altitude to hold the position. -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircleAtVec2( Point, Altitude, Speed ) - self:F2( { self.GroupName, Point, Altitude, Speed } ) + self:F2( { self.GroupName, Point, Altitude, Speed } ) + + -- pattern = enum AI.Task.OribtPattern, + -- point = Vec2, + -- point2 = Vec2, + -- speed = Distance, + -- altitude = Distance --- pattern = enum AI.Task.OribtPattern, --- point = Vec2, --- point2 = Vec2, --- speed = Distance, --- altitude = Distance - local LandHeight = land.getHeight( Point ) - + self:T3( { LandHeight } ) - local DCSTask = { id = 'Orbit', - params = { pattern = AI.Task.OrbitPattern.CIRCLE, - point = Point, - speed = Speed, - altitude = Altitude + LandHeight - } - } + local DCSTask = { id = 'Orbit', + params = { pattern = AI.Task.OrbitPattern.CIRCLE, + point = Point, + speed = Speed, + altitude = Altitude + LandHeight + } + } + + + -- local AITask = { id = 'ControlledTask', + -- params = { task = { id = 'Orbit', + -- params = { pattern = AI.Task.OrbitPattern.CIRCLE, + -- point = Point, + -- speed = Speed, + -- altitude = Altitude + LandHeight + -- } + -- }, + -- stopCondition = { duration = Duration + -- } + -- } + -- } + -- ) - --- local AITask = { id = 'ControlledTask', --- params = { task = { id = 'Orbit', --- params = { pattern = AI.Task.OrbitPattern.CIRCLE, --- point = Point, --- speed = Speed, --- altitude = Altitude + LandHeight --- } --- }, --- stopCondition = { duration = Duration --- } --- } --- } --- ) - return DCSTask end ---- Orbit at the current position of the first unit of the group at a specified alititude +--- (AIR) Orbit at the current position of the first unit of the group at a specified alititude. -- @param #GROUP self -- @param #number Altitude The altitude to hold the position. -- @param #number Speed The speed flying when holding the position. -- @return #GROUP self function GROUP:TaskOrbitCircle( Altitude, Speed ) - self:F2( { self.GroupName, Altitude, Speed } ) + self:F2( { self.GroupName, Altitude, Speed } ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then local GroupPoint = self:GetPointVec2() return self:TaskOrbitCircleAtVec2( GroupPoint, Altitude, Speed ) end - + return nil end ---- Hold position at the current position of the first unit of the group. +--- (AIR) Hold position at the current position of the first unit of the group. -- @param #GROUP self -- @param #number Duration The maximum duration in seconds to hold the position. -- @return #GROUP self function GROUP:TaskHoldPosition() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) return self:TaskOrbitCircle( 30, 10 ) end ---- Land the group at a Vec2Point. + + +--- (AIR) Attacking the map object (building, structure, e.t.c). +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskAttackMapObject( PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- AttackMapObject = { +-- id = 'AttackMapObject', +-- params = { +-- point = Vec2, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'AttackMapObject', + params = { + point = PointVec2, + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Delivering weapon on the runway. +-- @param #GROUP self +-- @param Airbase#AIRBASE Airbase Airbase to attack. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskBombingRunway( Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack ) + self:F2( { self.GroupName, Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack } ) + +-- BombingRunway = { +-- id = 'BombingRunway', +-- params = { +-- runwayId = AirdromeId, +-- weaponType = number, +-- expend = enum AI.Task.WeaponExpend, +-- attackQty = number, +-- direction = Azimuth, +-- groupAttack = boolean, +-- } +-- } + + local DCSTask + DCSTask = { id = 'BombingRunway', + params = { + point = Airbase:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + groupAttack = GroupAttack, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Refueling from the nearest tanker. No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskRefueling() + self:F2( { self.GroupName } ) + +-- Refueling = { +-- id = 'Refueling', +-- params = {} +-- } + + local DCSTask + DCSTask = { id = 'Refueling', + params = { + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR HELICOPTER) Landing at the ground. For helicopters only. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to land. -- @param #number Duration The duration in seconds to stay on the ground. -- @return #GROUP self function GROUP:TaskLandAtVec2( Point, Duration ) - self:F2( { self.GroupName, Point, Duration } ) + self:F2( { self.GroupName, Point, Duration } ) +-- Land = { +-- id= 'Land', +-- params = { +-- point = Vec2, +-- durationFlag = boolean, +-- duration = Time +-- } +-- } + local DCSTask - - if Duration and Duration > 0 then - DCSTask = { id = 'Land', params = { point = Point, durationFlag = true, duration = Duration } } - else - DCSTask = { id = 'Land', params = { point = Point, durationFlag = false } } - end + if Duration and Duration > 0 then + DCSTask = { id = 'Land', + params = { + point = Point, + durationFlag = true, + duration = Duration, + }, + } + else + DCSTask = { id = 'Land', + params = { + point = Point, + durationFlag = false, + }, + } + end self:T3( DCSTask ) - return DCSTask + return DCSTask end ---- Land the group at a @{Zone#ZONE). +--- (AIR) Land the group at a @{Zone#ZONE_RADIUS). -- @param #GROUP self -- @param Zone#ZONE Zone The zone where to land. -- @param #number Duration The duration in seconds to stay on the ground. @@ -5070,7 +5519,7 @@ function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint ) else Point = Zone:GetPointVec2() end - + local DCSTask = self:TaskLandAtVec2( Point, Duration ) self:T3( DCSTask ) @@ -5078,155 +5527,570 @@ function GROUP:TaskLandAtZone( Zone, Duration, RandomPoint ) end ---- Attack the Unit. --- @param #GROUP self --- @param Unit#UNIT The unit. --- @return DCSTask#Task The DCS task structure. -function GROUP:TaskAttackUnit( AttackUnit ) - self:F2( { self.GroupName, AttackUnit } ) --- AttackUnit = { --- id = 'AttackUnit', --- params = { --- unitId = Unit.ID, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend --- attackQty = number, --- direction = Azimuth, --- attackQtyLimit = boolean, --- groupAttack = boolean, --- } +--- (AIR) Following another airborne group. +-- The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +-- If another group is on land the unit / group will orbit around. +-- @param #GROUP self +-- @param Group#GROUP FollowGroup The group to be followed. +-- @param DCSTypes#Vec3 PointVec3 Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around. +-- @param #number LastWaypointIndex Detach waypoint of another group. Once reached the unit / group Follow task is finished. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskFollow( FollowGroup, PointVec3, LastWaypointIndex ) + self:F2( { self.GroupName, FollowGroup, PointVec3, LastWaypointIndex } ) + +-- Follow = { +-- id = 'Follow', +-- params = { +-- groupId = Group.ID, +-- pos = Vec3, +-- lastWptIndexFlag = boolean, +-- lastWptIndex = number +-- } -- } + + local LastWaypointIndexFlag = nil + if LastWaypointIndex then + LastWaypointIndexFlag = true + end - local DCSTask - DCSTask = { id = 'AttackUnit', - params = { unitId = AttackUnit:GetID(), - expend = AI.Task.WeaponExpend.TWO, - groupAttack = true, - }, - }, - + local DCSTask + DCSTask = { id = 'Follow', + params = { + groupId = FollowGroup:GetID(), + pos = PointVec3, + lastWptIndexFlag = LastWaypointIndexFlag, + lastWptIndex = LastWaypointIndex, + }, + }, + self:T3( { DCSTask } ) return DCSTask end ---- Attack a Group. + +--- (AIR) Escort another airborne group. +-- The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +-- The unit / group will also protect that group from threats of specified types. -- @param #GROUP self --- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param Group#GROUP EscortGroup The group to be escorted. +-- @param DCSTypes#Vec3 PointVec3 Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around. +-- @param #number LastWaypointIndex Detach waypoint of another group. Once reached the unit / group Follow task is finished. +-- @param #number EngagementDistanceMax Maximal distance from escorted group to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of AttributeName that is contains threat categories allowed to engage. -- @return DCSTask#Task The DCS task structure. -function GROUP:TaskAttackGroup( AttackGroup ) - self:F2( { self.GroupName, AttackGroup } ) +function GROUP:TaskEscort( FollowGroup, PointVec3, LastWaypointIndex, EngagementDistance, TargetTypes ) + self:F2( { self.GroupName, FollowGroup, PointVec3, LastWaypointIndex, EngagementDistance, TargetTypes } ) --- AttackGroup = { --- id = 'AttackGroup', --- params = { --- groupId = Group.ID, --- weaponType = number, --- expend = enum AI.Task.WeaponExpend, --- attackQty = number, --- directionEnabled = boolean, --- direction = Azimuth, --- altitudeEnabled = boolean, --- altitude = Distance, --- attackQtyLimit = boolean, --- } --- } +-- Escort = { +-- id = 'Escort', +-- params = { +-- groupId = Group.ID, +-- pos = Vec3, +-- lastWptIndexFlag = boolean, +-- lastWptIndex = number, +-- engagementDistMax = Distance, +-- targetTypes = array of AttributeName, +-- } +-- } - local DCSTask - DCSTask = { id = 'AttackGroup', - params = { groupId = AttackGroup:GetID(), - expend = AI.Task.WeaponExpend.TWO, - }, - }, + local LastWaypointIndexFlag = nil + if LastWaypointIndex then + LastWaypointIndexFlag = true + end + local DCSTask + DCSTask = { id = 'Follow', + params = { + groupId = FollowGroup:GetID(), + pos = PointVec3, + lastWptIndexFlag = LastWaypointIndexFlag, + lastWptIndex = LastWaypointIndex, + engagementDistMax = EngagementDistance, + targetTypes = TargetTypes, + }, + }, + self:T3( { DCSTask } ) return DCSTask end ---- Fires at a VEC2 point. + +-- GROUND TASKS + +--- (GROUND) Fire at a VEC2 point until ammunition is finished. -- @param #GROUP self --- @param DCSTypes#Vec2 The point to fire at. +-- @param DCSTypes#Vec2 PointVec2 The point to fire at. -- @param DCSTypes#Distance Radius The radius of the zone to deploy the fire at. -- @return DCSTask#Task The DCS task structure. function GROUP:TaskFireAtPoint( PointVec2, Radius ) self:F2( { self.GroupName, PointVec2, Radius } ) --- FireAtPoint = { --- id = 'FireAtPoint', --- params = { --- point = Vec2, --- radius = Distance, --- } --- } - - local DCSTask - DCSTask = { id = 'FireAtPoint', - params = { point = PointVec2, - radius = Radius, - } - } - + -- FireAtPoint = { + -- id = 'FireAtPoint', + -- params = { + -- point = Vec2, + -- radius = Distance, + -- } + -- } + + local DCSTask + DCSTask = { id = 'FireAtPoint', + params = { + point = PointVec2, + radius = Radius, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + +--- (GROUND) Hold ground group from moving. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskHold() + self:F2( { self.GroupName } ) + +-- Hold = { +-- id = 'Hold', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'Hold', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- TASKS FOR AIRBORNE AND GROUND UNITS/GROUPS + +--- (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup Target GROUP. +-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type. +-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @return DCSTask#Task The DCS task structure. +function GROUP:TaskFAC_AttackGroup( AttackGroup, WeaponType, Designation, Datalink ) + self:F2( { self.GroupName, AttackGroup, WeaponType, Designation, Datalink } ) + +-- FAC_AttackGroup = { +-- id = 'FAC_AttackGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- designation = enum AI.Task.Designation, +-- datalink = boolean +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC_AttackGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + designation = Designation, + datalink = Datalink, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + +-- EN-ROUTE TASKS FOR AIRBORNE GROUPS + +--- (AIR) Engaging targets of defined types. +-- @param #GROUP self +-- @param DCSTypes#Distance Distance Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage. +-- @param #number Priority All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageTargets( Distance, TargetTypes, Priority ) + self:F2( { self.GroupName, Distance, TargetTypes, Priority } ) + +-- EngageTargets ={ +-- id = 'EngageTargets', +-- params = { +-- maxDist = Distance, +-- targetTypes = array of AttributeName, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'EngageTargets', + params = { + maxDist = Distance, + targetTypes = TargetTypes, + priority = Priority + } + } + self:T3( { DCSTask } ) return DCSTask end ---- Move the group to a Vec2 Point, wait for a defined duration and embark a group. +--- (AIR) Engaging a targets of defined types at circle-shaped zone. +-- @param #GROUP self +-- @param DCSTypes#Vec2 PointVec2 2D-coordinates of the zone. +-- @param DCSTypes#Distance Radius Radius of the zone. +-- @param DCSTypes#AttributeNameArray TargetTypes Array of target categories allowed to engage. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageTargets( PointVec2, Radius, TargetTypes, Priority ) + self:F2( { self.GroupName, PointVec2, Radius, TargetTypes, Priority } ) + +-- EngageTargetsInZone = { +-- id = 'EngageTargetsInZone', +-- params = { +-- point = Vec2, +-- zoneRadius = Distance, +-- targetTypes = array of AttributeName, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'EngageTargetsInZone', + params = { + point = PointVec2, + zoneRadius = Radius, + targetTypes = TargetTypes, + priority = Priority + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup The Group to be attacked. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param DCSTypes#Distance Altitude (optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageGroup( AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit ) + self:F2( { self.GroupName, AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit } ) + + -- EngageGroup = { + -- id = 'EngageGroup ', + -- params = { + -- groupId = Group.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend, + -- attackQty = number, + -- directionEnabled = boolean, + -- direction = Azimuth, + -- altitudeEnabled = boolean, + -- altitude = Distance, + -- attackQtyLimit = boolean, + -- priority = number, + -- } + -- } + + local DirectionEnabled = nil + if Direction then + DirectionEnabled = true + end + + local AltitudeEnabled = nil + if Altitude then + AltitudeEnabled = true + end + + local DCSTask + DCSTask = { id = 'EngageGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + directionEnabled = DirectionEnabled, + direction = Direction, + altitudeEnabled = AltitudeEnabled, + altitude = Altitude, + attackQtyLimit = AttackQtyLimit, + priority = Priority, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Attack the Unit. +-- @param #GROUP self +-- @param Unit#UNIT AttackUnit The UNIT. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType (optional) Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.WeaponExpend WeaponExpend (optional) Determines how much weapon will be released at each attack. If parameter is not defined the unit / group will choose expend on its own discretion. +-- @param #number AttackQty (optional) This parameter limits maximal quantity of attack. The aicraft/group will not make more attack than allowed even if the target group not destroyed and the aicraft/group still have ammo. If not defined the aircraft/group will attack target until it will be destroyed or until the aircraft/group will run out of ammo. +-- @param DCSTypes#Azimuth Direction (optional) Desired ingress direction from the target to the attacking aircraft. Group/aircraft will make its attacks from the direction. Of course if there is no way to attack from the direction due the terrain group/aircraft will choose another direction. +-- @param #boolean AttackQtyLimit (optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks. +-- @param #boolean GroupAttack (optional) Flag indicates that the target must be engaged by all aircrafts of the group. Has effect only if the task is assigned to a group, not to a single aircraft. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEngageUnit( AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack ) + self:F2( { self.GroupName, AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack } ) + + -- EngageUnit = { + -- id = 'EngageUnit', + -- params = { + -- unitId = Unit.ID, + -- weaponType = number, + -- expend = enum AI.Task.WeaponExpend + -- attackQty = number, + -- direction = Azimuth, + -- attackQtyLimit = boolean, + -- groupAttack = boolean, + -- priority = number, + -- } + -- } + + local DCSTask + DCSTask = { id = 'EngageUnit', + params = { + unitId = AttackUnit:GetID(), + weaponType = WeaponType, + expend = WeaponExpend, + attackQty = AttackQty, + direction = Direction, + attackQtyLimit = AttackQtyLimit, + groupAttack = GroupAttack, + priority = Priority, + }, + }, + + self:T3( { DCSTask } ) + return DCSTask +end + + + +--- (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskAWACS( ) + self:F2( { self.GroupName } ) + +-- AWACS = { +-- id = 'AWACS', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'AWACS', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR) Aircraft will act as a tanker for friendly units. No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskTanker( ) + self:F2( { self.GroupName } ) + +-- Tanker = { +-- id = 'Tanker', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'Tanker', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- En-route tasks for ground units/groups + +--- (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts). No parameters. +-- @param #GROUP self +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskEWR( ) + self:F2( { self.GroupName } ) + +-- EWR = { +-- id = 'EWR', +-- params = { +-- } +-- } + + local DCSTask + DCSTask = { id = 'EWR', + params = { + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +-- En-route tasks for airborne and ground units/groups + +--- (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param Group#GROUP AttackGroup Target GROUP. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @param #number WeaponType Bitmask of weapon types those allowed to use. If parameter is not defined that means no limits on weapon usage. +-- @param DCSTypes#AI.Task.Designation Designation (optional) Designation type. +-- @param #boolean Datalink (optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskFAC_EngageGroup( AttackGroup, Priority, WeaponType, Designation, Datalink ) + self:F2( { self.GroupName, AttackGroup, WeaponType, Priority, Designation, Datalink } ) + +-- FAC_EngageGroup = { +-- id = 'FAC_EngageGroup', +-- params = { +-- groupId = Group.ID, +-- weaponType = number, +-- designation = enum AI.Task.Designation, +-- datalink = boolean, +-- priority = number, +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC_EngageGroup', + params = { + groupId = AttackGroup:GetID(), + weaponType = WeaponType, + designation = Designation, + datalink = Datalink, + priority = Priority, + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + +--- (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets. +-- The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +-- If the task is assigned to the group lead unit will be a FAC. +-- @param #GROUP self +-- @param DCSTypes#Distance Radius The maximal distance from the FAC to a target. +-- @param #number Priority All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first. +-- @return DCSTask#Task The DCS task structure. +function GROUP:EnRouteTaskFAC( Radius, Priority ) + self:F2( { self.GroupName, Radius, Priority } ) + +-- FAC = { +-- id = 'FAC', +-- params = { +-- radius = Distance, +-- priority = number +-- } +-- } + + local DCSTask + DCSTask = { id = 'FAC', + params = { + radius = Radius, + priority = Priority + } + } + + self:T3( { DCSTask } ) + return DCSTask +end + + + + +--- (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to wait. -- @param #number Duration The duration in seconds to wait. -- @param #GROUP EmbarkingGroup The group to be embarked. -- @return DCSTask#Task The DCS task structure -function GROUP:TaskEmbarkingAtVec2( Point, Duration, EmbarkingGroup ) - self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } ) +function GROUP:TaskEmbarking( Point, Duration, EmbarkingGroup ) + self:F2( { self.GroupName, Point, Duration, EmbarkingGroup.DCSGroup } ) - local DCSTask - DCSTask = { id = 'Embarking', - params = { x = Point.x, - y = Point.y, - duration = Duration, - groupsForEmbarking = { EmbarkingGroup.GroupID }, - durationFlag = true, - distributionFlag = false, - distribution = {}, - } - } - - self:T3( { DCSTask } ) - return DCSTask + local DCSTask + DCSTask = { id = 'Embarking', + params = { x = Point.x, + y = Point.y, + duration = Duration, + groupsForEmbarking = { EmbarkingGroup.GroupID }, + durationFlag = true, + distributionFlag = false, + distribution = {}, + } + } + + self:T3( { DCSTask } ) + return DCSTask end +--- (GROUND) Embark to a Transport landed at a location. + --- Move to a defined Vec2 Point, and embark to a group when arrived within a defined Radius. -- @param #GROUP self -- @param DCSTypes#Vec2 Point The point where to wait. -- @param #number Radius The radius of the embarking zone around the Point. -- @return DCSTask#Task The DCS task structure. -function GROUP:TaskEmbarkToTransportAtVec2( Point, Radius ) - self:F2( { self.GroupName, Point, Radius } ) +function GROUP:TaskEmbarkToTransport( Point, Radius ) + self:F2( { self.GroupName, Point, Radius } ) local DCSTask --DCSTask#Task - DCSTask = { id = 'EmbarkToTransport', - params = { x = Point.x, - y = Point.y, - zoneRadius = Radius, - } - } + DCSTask = { id = 'EmbarkToTransport', + params = { x = Point.x, + y = Point.y, + zoneRadius = Radius, + } + } self:T3( { DCSTask } ) - return DCSTask + return DCSTask end ---- Return a Misson task from a mission template. + + +--- (AIR + GROUND) Return a mission task from a mission template. -- @param #GROUP self -- @param #table TaskMission A table containing the mission task. --- @return DCSTask#Task +-- @return DCSTask#Task function GROUP:TaskMission( TaskMission ) - self:F2( Points ) - + self:F2( Points ) + local DCSTask DCSTask = { id = 'Mission', params = { TaskMission, }, } - + self:T3( { DCSTask } ) return DCSTask end @@ -5234,18 +6098,18 @@ end --- Return a Misson task to follow a given route defined by Points. -- @param #GROUP self -- @param #table Points A table of route points. --- @return DCSTask#Task +-- @return DCSTask#Task function GROUP:TaskRoute( Points ) self:F2( Points ) - + local DCSTask DCSTask = { id = 'Mission', params = { route = { points = Points, }, }, } - + self:T3( { DCSTask } ) return DCSTask end ---- Make the DCS Group to fly to a given point and hover. +--- (AIR + GROUND) Make the Group move to fly to a given point. -- @param #GROUP self -- @param DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param #number Speed The speed to travel. @@ -5254,22 +6118,22 @@ function GROUP:TaskRouteToVec2( Point, Speed ) self:F2( { Point, Speed } ) local GroupPoint = self:GetUnit( 1 ):GetPointVec2() - + local PointFrom = {} PointFrom.x = GroupPoint.x PointFrom.y = GroupPoint.y PointFrom.type = "Turning Point" PointFrom.action = "Turning Point" - PointFrom.speed = Speed + PointFrom.speed = Speed PointFrom.speed_locked = true PointFrom.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local PointTo = {} PointTo.x = Point.x @@ -5279,24 +6143,24 @@ function GROUP:TaskRouteToVec2( Point, Speed ) PointTo.speed = Speed PointTo.speed_locked = true PointTo.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local Points = { PointFrom, PointTo } - + self:T3( Points ) - + self:Route( Points ) return self end ---- Make the DCS Group to fly to a given point and hover. +--- (AIR + GROUND) Make the Group move to a given point. -- @param #GROUP self -- @param DCSTypes#Vec3 Point The destination point in Vec3 format. -- @param #number Speed The speed to travel. @@ -5305,7 +6169,7 @@ function GROUP:TaskRouteToVec3( Point, Speed ) self:F2( { Point, Speed } ) local GroupPoint = self:GetUnit( 1 ):GetPointVec3() - + local PointFrom = {} PointFrom.x = GroupPoint.x PointFrom.y = GroupPoint.z @@ -5313,39 +6177,39 @@ function GROUP:TaskRouteToVec3( Point, Speed ) PointFrom.alt_type = "BARO" PointFrom.type = "Turning Point" PointFrom.action = "Turning Point" - PointFrom.speed = Speed + PointFrom.speed = Speed PointFrom.speed_locked = true PointFrom.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local PointTo = {} PointTo.x = Point.x PointTo.y = Point.z - PointTo.alt = Point.y + PointTo.alt = Point.y PointTo.alt_type = "BARO" PointTo.type = "Turning Point" PointTo.action = "Fly Over Point" PointTo.speed = Speed PointTo.speed_locked = true PointTo.properties = { - ["vnav"] = 1, - ["scale"] = 0, - ["angle"] = 0, - ["vangle"] = 0, - ["steer"] = 2, + ["vnav"] = 1, + ["scale"] = 0, + ["angle"] = 0, + ["vangle"] = 0, + ["steer"] = 2, } - + local Points = { PointFrom, PointTo } - + self:T3( Points ) - + self:Route( Points ) return self @@ -5356,28 +6220,28 @@ end --- Make the group to follow a given route. -- @param #GROUP self -- @param #table GoPoints A table of Route Points. --- @return #GROUP self +-- @return #GROUP self function GROUP:Route( GoPoints ) - self:F2( GoPoints ) + self:F2( GoPoints ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - local Points = routines.utils.deepCopy( GoPoints ) - local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } - local Controller = self:_GetController() + local Points = routines.utils.deepCopy( GoPoints ) + local MissionTask = { id = 'Mission', params = { route = { points = Points, }, }, } + local Controller = self:_GetController() --Controller.setTask( Controller, MissionTask ) - --routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 ) + --routines.scheduleFunction( Controller.setTask, { Controller, MissionTask}, timer.getTime() + 1 ) SCHEDULER:New( Controller, Controller.setTask, { MissionTask }, 1 ) - return self + return self end - + return nil end ---- Route the group to a given zone. +--- (AIR + GROUND) Route the group to a given zone. -- The group final destination point can be randomized. -- A speed can be given in km/h. -- A given formation can be given. @@ -5387,56 +6251,56 @@ end -- @param #number Speed The speed. -- @param Base#FORMATION Formation The formation string. function GROUP:TaskRouteToZone( Zone, Randomize, Speed, Formation ) - self:F2( Zone ) + self:F2( Zone ) local DCSGroup = self:GetDCSGroup() - + if DCSGroup then - - local GroupPoint = self:GetPointVec2() - - local PointFrom = {} - PointFrom.x = GroupPoint.x - PointFrom.y = GroupPoint.y - PointFrom.type = "Turning Point" - PointFrom.action = "Cone" - PointFrom.speed = 20 / 1.6 - - - local PointTo = {} - local ZonePoint - - if Randomize then - ZonePoint = Zone:GetRandomPointVec2() - else - ZonePoint = Zone:GetPointVec2() - end - - PointTo.x = ZonePoint.x - PointTo.y = ZonePoint.y - PointTo.type = "Turning Point" - - if Formation then - PointTo.action = Formation - else - PointTo.action = "Cone" - end - - if Speed then - PointTo.speed = Speed - else - PointTo.speed = 20 / 1.6 - end - - local Points = { PointFrom, PointTo } - - self:T3( Points ) - - self:Route( Points ) - - return self + + local GroupPoint = self:GetPointVec2() + + local PointFrom = {} + PointFrom.x = GroupPoint.x + PointFrom.y = GroupPoint.y + PointFrom.type = "Turning Point" + PointFrom.action = "Cone" + PointFrom.speed = 20 / 1.6 + + + local PointTo = {} + local ZonePoint + + if Randomize then + ZonePoint = Zone:GetRandomPointVec2() + else + ZonePoint = Zone:GetPointVec2() + end + + PointTo.x = ZonePoint.x + PointTo.y = ZonePoint.y + PointTo.type = "Turning Point" + + if Formation then + PointTo.action = Formation + else + PointTo.action = "Cone" + end + + if Speed then + PointTo.speed = Speed + else + PointTo.speed = 20 / 1.6 + end + + local Points = { PointFrom, PointTo } + + self:T3( Points ) + + self:Route( Points ) + + return self end - + return nil end @@ -5483,48 +6347,48 @@ end -- @param #number Begin The route point from where the copy will start. The base route point is 0. -- @param #number End The route point where the copy will end. The End point is the last point - the End point. The last point has base 0. -- @param #boolean Randomize Randomization of the route, when true. --- @param #number Radius When randomization is on, the randomization is within the radius. +-- @param #number Radius When randomization is on, the randomization is within the radius. function GROUP:CopyRoute( Begin, End, Randomize, Radius ) - self:F2( { Begin, End } ) + self:F2( { Begin, End } ) - local Points = {} - - -- Could be a Spawned Group - local GroupName = string.match( self:GetName(), ".*#" ) - if GroupName then - GroupName = GroupName:sub( 1, -2 ) - else - GroupName = self:GetName() - end - - self:T3( { GroupName } ) - - local Template = _DATABASE.Templates.Groups[GroupName].Template - - if Template then - if not Begin then - Begin = 0 - end - if not End then - End = 0 - end - - for TPointID = Begin + 1, #Template.route.points - End do - if Template.route.points[TPointID] then - Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] ) - if Randomize then - if not Radius then - Radius = 500 - end - Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius ) - Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius ) - end - end - end - return Points - end - - return nil + local Points = {} + + -- Could be a Spawned Group + local GroupName = string.match( self:GetName(), ".*#" ) + if GroupName then + GroupName = GroupName:sub( 1, -2 ) + else + GroupName = self:GetName() + end + + self:T3( { GroupName } ) + + local Template = _DATABASE.Templates.Groups[GroupName].Template + + if Template then + if not Begin then + Begin = 0 + end + if not End then + End = 0 + end + + for TPointID = Begin + 1, #Template.route.points - End do + if Template.route.points[TPointID] then + Points[#Points+1] = routines.utils.deepCopy( Template.route.points[TPointID] ) + if Randomize then + if not Radius then + Radius = 500 + end + Points[#Points].x = Points[#Points].x + math.random( Radius * -1, Radius ) + Points[#Points].y = Points[#Points].y + math.random( Radius * -1, Radius ) + end + end + end + return Points + end + + return nil end @@ -5535,28 +6399,28 @@ function GROUP:GetDetectedTargets() if DCSGroup then return self:_GetController():getDetectedTargets() end - + return nil end function GROUP:IsTargetDetected( DCSObject ) self:F2( self.GroupName ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then - + local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity - = self:_GetController().isTargetDetected( self:_GetController(), DCSObject, - Controller.Detection.VISUAL, - Controller.Detection.OPTIC, - Controller.Detection.RADAR, - Controller.Detection.IRST, - Controller.Detection.RWR, - Controller.Detection.DLINK - ) + = self:_GetController().isTargetDetected( self:_GetController(), DCSObject, + Controller.Detection.VISUAL, + Controller.Detection.OPTIC, + Controller.Detection.RADAR, + Controller.Detection.IRST, + Controller.Detection.RWR, + Controller.Detection.DLINK + ) return TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity end - + return nil end @@ -5567,16 +6431,16 @@ end -- @return #boolean function GROUP:OptionROEHoldFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -5584,12 +6448,12 @@ end -- @param Group#GROUP self -- @return Group#GROUP self function GROUP:OptionROEHoldFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_HOLD ) elseif self:IsGround() then @@ -5597,10 +6461,10 @@ function GROUP:OptionROEHoldFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.WEAPON_HOLD ) end - + return self end - + return nil end @@ -5609,16 +6473,16 @@ end -- @return #boolean function GROUP:OptionROEReturnFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -5626,12 +6490,12 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEReturnFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.RETURN_FIRE ) elseif self:IsGround() then @@ -5639,10 +6503,10 @@ function GROUP:OptionROEReturnFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.RETURN_FIRE ) end - + return self end - + return nil end @@ -5657,10 +6521,10 @@ function GROUP:OptionROEOpenFirePossible() if self:IsAir() or self:IsGround() or self:IsShip() then return true end - + return false end - + return nil end @@ -5668,12 +6532,12 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEOpenFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.OPEN_FIRE ) elseif self:IsGround() then @@ -5681,10 +6545,10 @@ function GROUP:OptionROEOpenFire() elseif self:IsShip() then Controller:setOption( AI.Option.Naval.id.ROE, AI.Option.Naval.val.ROE.OPEN_FIRE ) end - + return self end - + return nil end @@ -5693,16 +6557,16 @@ end -- @return #boolean function GROUP:OptionROEWeaponFreePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5710,19 +6574,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROEWeaponFree() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.ROE, AI.Option.Air.val.ROE.WEAPON_FREE ) end - + return self end - + return nil end @@ -5731,16 +6595,16 @@ end -- @return #boolean function GROUP:OptionROTNoReactionPossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5749,19 +6613,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTNoReaction() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.NO_REACTION ) end - + return self end - + return nil end @@ -5776,10 +6640,10 @@ function GROUP:OptionROTPassiveDefensePossible() if self:IsAir() then return true end - + return false end - + return nil end @@ -5787,19 +6651,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTPassiveDefense() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.PASSIVE_DEFENCE ) end - + return self end - + return nil end @@ -5808,16 +6672,16 @@ end -- @return #boolean function GROUP:OptionROTEvadeFirePossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5826,19 +6690,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTEvadeFire() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.EVADE_FIRE ) end - + return self end - + return nil end @@ -5847,16 +6711,16 @@ end -- @return #boolean function GROUP:OptionROTVerticalPossible() self:F2( { self.GroupName } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then if self:IsAir() then return true end - + return false end - + return nil end @@ -5865,19 +6729,19 @@ end -- @param #GROUP self -- @return #GROUP self function GROUP:OptionROTVertical() - self:F2( { self.GroupName } ) + self:F2( { self.GroupName } ) local DCSGroup = self:GetDCSGroup() if DCSGroup then local Controller = self:_GetController() - + if self:IsAir() then Controller:setOption( AI.Option.Air.id.REACTION_ON_THREAT, AI.Option.Air.val.REACTION_ON_THREAT.BYPASS_AND_ESCAPE ) end - + return self end - + return nil end @@ -5886,16 +6750,16 @@ end --- Returns a message for a coalition or a client. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. -- @return Message#MESSAGE function GROUP:Message( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then return MESSAGE:New( Message, self:GetCallsign() .. " (" .. self:GetTypeName() .. ")", Duration, self:GetClassNameAndID() ) end - + return nil end @@ -5903,15 +6767,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. function GROUP:MessageToAll( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToAll() end - + return nil end @@ -5919,15 +6783,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTYpes#Duration Duration The duration of the message. function GROUP:MessageToRed( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToRed() end - + return nil end @@ -5935,15 +6799,15 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. function GROUP:MessageToBlue( Message, Duration ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToBlue() end - + return nil end @@ -5951,23 +6815,23 @@ end -- The message will appear in the message area. The message will begin with the callsign of the group and the type of the first unit sending the message. -- @param #GROUP self -- @param #string Message The message text --- @param #Duration Duration The duration of the message. +-- @param DCSTypes#Duration Duration The duration of the message. -- @param Client#CLIENT Client The client object receiving the message. function GROUP:MessageToClient( Message, Duration, Client ) self:F2( { Message, Duration } ) - + local DCSGroup = self:GetDCSGroup() if DCSGroup then self:Message( Message, Duration ):ToClient( Client ) end - + return nil end ---- UNIT Class +--- This module contains the UNIT class. -- --- @{UNIT} class --- ============== --- The @{UNIT} class is a wrapper class to handle the DCS Unit objects: +-- 1) @{Unit#UNIT} class, extends @{Base#BASE} +-- =========================================== +-- The @{Unit#UNIT} class is a wrapper class to handle the DCS Unit objects: -- -- * Support all DCS Unit APIs. -- * Enhance with Unit specific APIs not in the DCS Unit API set. @@ -5975,8 +6839,8 @@ end -- * Manage the "state" of the DCS Unit. -- -- --- UNIT reference methods --- ====================== +-- 1.1) UNIT reference methods +-- ---------------------- -- For each DCS Unit object alive within a running mission, a UNIT wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Unit objects are spawned (using the @{SPAWN} class). -- @@ -5994,19 +6858,15 @@ end -- -- IMPORTANT: ONE SHOULD NEVER SANATIZE these UNIT OBJECT REFERENCES! (make the UNIT object references nil). -- --- DCS UNIT APIs --- ============= +-- 1.2) DCS UNIT APIs +-- ------------------ -- The DCS Unit APIs are used extensively within MOOSE. The UNIT class has for each DCS Unit API a corresponding method. -- To be able to distinguish easily in your code the difference between a UNIT API call and a DCS Unit API call, -- the first letter of the method is also capitalized. So, by example, the DCS Unit method @{DCSUnit#Unit.getName}() -- is implemented in the UNIT class as @{#UNIT.GetName}(). -- --- Additional UNIT APIs --- ==================== --- The UNIT class comes with additional methods. Find below a summary. --- --- Smoke, Flare Units --- ------------------ +-- 1.3) Smoke, Flare Units +-- ----------------------- -- The UNIT class provides methods to smoke or flare units easily. -- The @{#UNIT.SmokeBlue}(), @{#UNIT.SmokeGreen}(),@{#UNIT.SmokeOrange}(), @{#UNIT.SmokeRed}(), @{#UNIT.SmokeRed}() methods -- will smoke the unit in the corresponding color. Note that smoking a unit is done at the current position of the DCS Unit. @@ -6014,26 +6874,25 @@ end -- The @{#UNIT.FlareGreen}(), @{#UNIT.FlareRed}(), @{#UNIT.FlareWhite}(), @{#UNIT.FlareYellow}() -- methods will fire off a flare in the air with the corresponding color. Note that a flare is a one-off shot and its effect is of very short duration. -- --- Position, Point --- --------------- +-- 1.4) Location Position, Point +-- ----------------------------- -- The UNIT class provides methods to obtain the current point or position of the DCS Unit. --- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetPointVec3}() will obtain the current location of the DCS Unit in a Vec2 (2D) or a Vec3 (3D) vector respectively. --- If you want to obtain the complete 3D position including oriëntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively. +-- The @{#UNIT.GetPointVec2}(), @{#UNIT.GetPointVec3}() will obtain the current **location** of the DCS Unit in a Vec2 (2D) or a **point** in a Vec3 (3D) vector respectively. +-- If you want to obtain the complete **3D position** including oriëntation and direction vectors, consult the @{#UNIT.GetPositionVec3}() method respectively. -- --- Alive --- ----- +-- 1.5) Test if alive +-- ------------------ -- The @{#UNIT.IsAlive}(), @{#UNIT.IsActive}() methods determines if the DCS Unit is alive, meaning, it is existing and active. -- --- Test for other units in radius --- ------------------------------ --- One can test if another DCS Unit is within a given radius of the current DCS Unit, by using the @{#UNIT.OtherUnitInRadius}() method. --- --- More functions will be added --- ---------------------------- --- During the MOOSE development, more functions will be added. A complete list of the current functions is below. --- +-- 1.6) Test for proximity +-- ----------------------- +-- The UNIT class contains methods to test the location or proximity against zones or other objects. -- +-- ### 1.6.1) Zones +-- To test whether the Unit is within a **zone**, use the @{#UNIT.IsInZone}() or the @{#UNIT.IsNotInZone}() methods. Any zone can be tested on, but the zone must be derived from @{Zone#ZONE_BASE}. -- +-- ### 1.6.2) Units +-- Test if another DCS Unit is within a given radius of the current DCS Unit, use the @{#UNIT.OtherUnitInRadius}() method. -- -- @module Unit -- @author FlightControl @@ -6505,7 +7364,7 @@ function UNIT:GetPointVec2() UnitPointVec2.x = UnitPointVec3.x UnitPointVec2.y = UnitPointVec3.z - self:T3( UnitPointVec2 ) + self:T2( UnitPointVec2 ) return UnitPointVec2 end @@ -6566,7 +7425,35 @@ function UNIT:GetVelocity() return nil end - + +-- Is functions + +--- Returns true if the unit is within a @{Zone}. +-- @param #UNIT self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the unit is within the @{Zone#ZONE_BASE} +function UNIT:IsInZone( Zone ) + self:F2( { self.UnitName, Zone } ) + + local IsInZone = Zone:IsPointVec3InZone( self:GetPointVec3() ) + + self:T( { IsInZone } ) + return IsInZone +end + +--- Returns true if the unit is not within a @{Zone}. +-- @param #UNIT self +-- @param Zone#ZONE_BASE Zone The zone to test. +-- @return #boolean Returns true if the unit is not within the @{Zone#ZONE_BASE} +function UNIT:IsNotInZone( Zone ) + self:F2( { self.UnitName, Zone } ) + + local IsInZone = not Zone:IsPointVec3InZone( self:GetPointVec3() ) + + self:T( { IsInZone } ) + return IsInZone +end + --- Returns true if the DCS Unit is in the air. -- @param Unit#UNIT self -- @return #boolean true if in the air. @@ -6738,92 +7625,492 @@ function UNIT:IsAir() return IsAirResult end ---- ZONE Classes +--- This module contains the ZONE classes, inherited from @{Zone#ZONE_BASE}. +-- There are essentially two core functions that zones accomodate: +-- +-- * Test if an object is within the zone boundaries. +-- * Provide the zone behaviour. Some zones are static, while others are moveable. +-- +-- The object classes are using the zone classes to test the zone boundaries, which can take various forms: +-- +-- * Test if completely within the zone. +-- * Test if partly within the zone (for @{Group#GROUP} objects). +-- * Test if not in the zone. +-- * Distance to the nearest intersecting point of the zone. +-- * Distance to the center of the zone. +-- * ... +-- +-- Each of these ZONE classes have a zone name, and specific parameters defining the zone type: +-- +-- * @{Zone#ZONE_BASE}: The ZONE_BASE class defining the base for all other zone classes. +-- * @{Zone#ZONE_RADIUS}: The ZONE_RADIUS class defined by a zone name, a location and a radius. +-- * @{Zone#ZONE}: The ZONE class, defined by the zone name as defined within the Mission Editor. +-- * @{Zone#ZONE_UNIT}: The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- * @{Zone#ZONE_POLYGON}: The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- +-- Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}: +-- +-- * @{#ZONE_BASE.IsPointVec2InZone}: Returns if a location is within the zone. +-- * @{#ZONE_BASE.IsPointVec3InZone}: Returns if a point is within the zone. +-- +-- === +-- +-- 1) @{Zone#ZONE_BASE} class, extends @{Base#BASE} +-- ================================================ +-- The ZONE_BASE class defining the base for all other zone classes. +-- +-- === +-- +-- 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE} +-- ======================================================= +-- The ZONE_RADIUS class defined by a zone name, a location and a radius. +-- +-- === +-- +-- 3) @{Zone#ZONE} class, extends @{Zone#ZONE_RADIUS} +-- ========================================== +-- The ZONE class, defined by the zone name as defined within the Mission Editor. +-- +-- === +-- +-- 4) @{Zone#ZONE_UNIT} class, extends @{Zone#ZONE_RADIUS} +-- ======================================================= +-- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- +-- === +-- +-- 5) @{Zone#ZONE_POLYGON} class, extends @{Zone#ZONE_BASE} +-- ======================================================== +-- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- +-- === +-- -- @module Zone +-- @author FlightControl + Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Message" ) +Include.File( "Point" ) ---- The ZONE class --- @type ZONE --- @Extends Base#BASE -ZONE = { - ClassName="ZONE", + + +--- The ZONE_BASE class +-- @type ZONE_BASE +-- @extends Base#BASE +ZONE_BASE = { + ClassName = "ZONE_BASE", + } + +--- ZONE_BASE constructor +-- @param #ZONE_BASE self +-- @param #string ZoneName Name of the zone. +-- @return #ZONE_BASE self +function ZONE_BASE:New( ZoneName ) + local self = BASE:Inherit( self, BASE:New() ) + self:F( ZoneName ) + + self.ZoneName = ZoneName + + return self +end + +--- Returns if a location is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_BASE:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + return false +end + +--- Returns if a point is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec3 PointVec3 The point to test. +-- @return #boolean true if the point is within the zone. +function ZONE_BASE:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( { x = PointVec3.x, y = PointVec3.z } ) + + return InZone +end + +--- Smokes the zone boundaries in a color. +-- @param #ZONE_BASE self +-- @param SmokeColor The smoke color. +function ZONE_BASE:SmokeZone( SmokeColor ) + self:F2( SmokeColor ) + +end + + +--- The ZONE_RADIUS class, defined by a zone name, a location and a radius. +-- @type ZONE_RADIUS +-- @field DCSTypes#Vec2 PointVec2 The current location of the zone. +-- @field DCSTypes#Distance Radius The radius of the zone. +-- @extends Zone#ZONE_BASE +ZONE_RADIUS = { + ClassName="ZONE_RADIUS", } - -function ZONE:New( ZoneName ) - local self = BASE:Inherit( self, BASE:New() ) - self:F( ZoneName ) - local Zone = trigger.misc.getZone( ZoneName ) - - if not Zone then - error( "Zone " .. ZoneName .. " does not exist." ) - return nil - end - - self.Zone = Zone - self.ZoneName = ZoneName +--- Constructor of ZONE_RADIUS, taking the zone name, the zone location and a radius. +-- @param #ZONE_RADIUS self +-- @param #string ZoneName Name of the zone. +-- @param DCSTypes#Vec2 PointVec2 The location of the zone. +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:New( ZoneName, PointVec2, Radius ) + local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) + self:F( { ZoneName, PointVec2, Radius } ) + + self.Radius = Radius + self.PointVec2 = PointVec2 return self end -function ZONE:GetPointVec2() - self:F( self.ZoneName ) +--- Smokes the zone boundaries in a color. +-- @param #ZONE_RADIUS self +-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color. +-- @param #number Points (optional) The amount of points in the circle. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:SmokeZone( SmokeColor, Points ) + self:F2( SmokeColor ) - local Zone = trigger.misc.getZone( self.ZoneName ) - local Point = { x = Zone.point.x, y = Zone.point.z } + local Point = {} + local PointVec2 = self:GetPointVec2() - self:T( { Zone, Point } ) - - return Point -end + Points = Points and Points or 360 -function ZONE:GetPointVec3( Height ) - self:F( self.ZoneName ) - - local Zone = trigger.misc.getZone( self.ZoneName ) - local Point = { x = Zone.point.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = Zone.point.z } - - self:T( { Zone, Point } ) + local Angle + local RadialBase = math.pi*2 - return Point + for Angle = 0, 360, 360 / Points do + local Radial = Angle * RadialBase / 360 + Point.x = PointVec2.x + math.cos( Radial ) * self:GetRadius() + Point.y = PointVec2.y + math.sin( Radial ) * self:GetRadius() + POINT_VEC2:New( Point.x, Point.y ):Smoke( SmokeColor ) + end + + return self end -function ZONE:GetRandomPointVec2() + +--- Flares the zone boundaries in a color. +-- @param #ZONE_RADIUS self +-- @param #POINT_VEC3.FlareColor FlareColor The flare color. +-- @param #number Points (optional) The amount of points in the circle. +-- @param DCSTypes#Azimuth Azimuth (optional) Azimuth The azimuth of the flare. +-- @return #ZONE_RADIUS self +function ZONE_RADIUS:FlareZone( FlareColor, Points, Azimuth ) + self:F2( { FlareColor, Azimuth } ) + + local Point = {} + local PointVec2 = self:GetPointVec2() + + Points = Points and Points or 360 + + local Angle + local RadialBase = math.pi*2 + + for Angle = 0, 360, 360 / Points do + local Radial = Angle * RadialBase / 360 + Point.x = PointVec2.x + math.cos( Radial ) * self:GetRadius() + Point.y = PointVec2.y + math.sin( Radial ) * self:GetRadius() + POINT_VEC2:New( Point.x, Point.y ):Flare( FlareColor, Azimuth ) + end + + return self +end + +--- Returns the radius of the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Distance The radius of the zone. +function ZONE_RADIUS:GetRadius() + self:F2( self.ZoneName ) + + self:T2( { self.Radius } ) + + return self.Radius +end + +--- Sets the radius of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return DCSTypes#Distance The radius of the zone. +function ZONE_RADIUS:SetRadius( Radius ) + self:F2( self.ZoneName ) + + self.Radius = Radius + self:T2( { self.Radius } ) + + return self.Radius +end + +--- Returns the location of the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Vec2 The location of the zone. +function ZONE_RADIUS:GetPointVec2() + self:F2( self.ZoneName ) + + self:T2( { self.PointVec2 } ) + + return self.PointVec2 +end + +--- Sets the location of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The new location of the zone. +-- @return DCSTypes#Vec2 The new location of the zone. +function ZONE_RADIUS:SetPointVec2( PointVec2 ) + self:F2( self.ZoneName ) + + self.PointVec2 = PointVec2 + + self:T2( { self.PointVec2 } ) + + return self.PointVec2 +end + +--- Returns the point of the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Distance Height The height to add to the land height where the center of the zone is located. +-- @return DCSTypes#Vec3 The point of the zone. +function ZONE_RADIUS:GetPointVec3( Height ) + self:F2( self.ZoneName ) + + local PointVec2 = self:GetPointVec2() + + local PointVec3 = { x = PointVec2.x, y = land.getHeight( self:GetPointVec2() ) + Height, z = PointVec2.y } + + self:T2( { PointVec3 } ) + + return PointVec3 +end + + +--- Returns if a location is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_RADIUS:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local ZonePointVec2 = self:GetPointVec2() + + if (( PointVec2.x - ZonePointVec2.x )^2 + ( PointVec2.y - ZonePointVec2.y ) ^2 ) ^ 0.5 <= self:GetRadius() then + return true + end + + return false +end + +--- Returns if a point is within the zone. +-- @param #ZONE_RADIUS self +-- @param DCSTypes#Vec3 PointVec3 The point to test. +-- @return #boolean true if the point is within the zone. +function ZONE_RADIUS:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( { x = PointVec3.x, y = PointVec3.z } ) + + return InZone +end + +--- Returns a random location within the zone. +-- @param #ZONE_RADIUS self +-- @return DCSTypes#Vec2 The random location within the zone. +function ZONE_RADIUS:GetRandomPointVec2() self:F( self.ZoneName ) local Point = {} + local PointVec2 = self:GetPointVec2() - local Zone = trigger.misc.getZone( self.ZoneName ) - local angle = math.random() * math.pi*2; - Point.x = Zone.point.x + math.cos( angle ) * math.random() * Zone.radius; - Point.y = Zone.point.z + math.sin( angle ) * math.random() * Zone.radius; + Point.x = PointVec2.x + math.cos( angle ) * math.random() * self:GetRadius(); + Point.y = PointVec2.y + math.sin( angle ) * math.random() * self:GetRadius(); - self:T( { Zone, Point } ) + self:T( { Point } ) return Point end -function ZONE:GetRadius() - self:F( self.ZoneName ) - local Zone = trigger.misc.getZone( self.ZoneName ) - self:T( { Zone } ) +--- The ZONE class, defined by the zone name as defined within the Mission Editor. The location and the radius are automatically collected from the mission settings. +-- @type ZONE +-- @extends Zone#ZONE_RADIUS +ZONE = { + ClassName="ZONE", + } - return Zone.radius + +--- Constructor of ZONE, taking the zone name. +-- @param #ZONE self +-- @param #string ZoneName The name of the zone as defined within the mission editor. +-- @return #ZONE +function ZONE:New( ZoneName ) + + local Zone = trigger.misc.getZone( ZoneName ) + + if not Zone then + error( "Zone " .. ZoneName .. " does not exist." ) + return nil + end + + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, { x = Zone.point.x, y = Zone.point.z }, Zone.radius ) ) + self:F( ZoneName ) + + self.Zone = Zone + + return self end ---- The CLIENT models client units in multi player missions. + +--- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. +-- @type ZONE_UNIT +-- @field Unit#UNIT ZoneUNIT +-- @extends Zone#ZONE_RADIUS +ZONE_UNIT = { + ClassName="ZONE_UNIT", + } + +--- Constructor to create a ZONE_UNIT instance, taking the zone name, a zone unit and a radius. +-- @param #ZONE_UNIT self +-- @param #string ZoneName Name of the zone. +-- @param Unit#UNIT ZoneUNIT The unit as the center of the zone. +-- @param DCSTypes#Distance Radius The radius of the zone. +-- @return #ZONE_UNIT self +function ZONE_UNIT:New( ZoneName, ZoneUNIT, Radius ) + local self = BASE:Inherit( self, ZONE_RADIUS:New( ZoneName, ZoneUNIT:GetPointVec2(), Radius ) ) + self:F( { ZoneName, ZoneUNIT:GetPointVec2(), Radius } ) + + self.ZoneUNIT = ZoneUNIT + + return self +end + + +--- Returns the current location of the @{Unit#UNIT}. +-- @param #ZONE_UNIT self +-- @return DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location. +function ZONE_UNIT:GetPointVec2() + self:F( self.ZoneName ) + + local ZonePointVec2 = self.ZoneUNIT:GetPointVec2() + + self:T( { ZonePointVec2 } ) + + return ZonePointVec2 +end + + +--- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. +-- @type ZONE_POLYGON +-- @extends Zone#ZONE_BASE +ZONE_POLYGON = { + ClassName="ZONE_POLYGON", + } + +--- Constructor to create a ZONE_POLYGON instance, taking the zone name and the name of the @{Group#GROUP} defined within the Mission Editor. +-- The @{Group#GROUP} waypoints define the polygon corners. The first and the last point are automatically connected by ZONE_POLYGON. +-- @param #ZONE_POLYGON self +-- @param #string ZoneName Name of the zone. +-- @param Group#GROUP ZoneGroup The GROUP waypoints as defined within the Mission Editor define the polygon shape. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:New( ZoneName, ZoneGroup ) + local self = BASE:Inherit( self, ZONE_BASE:New( ZoneName ) ) + self:F( { ZoneName, ZoneGroup } ) + + local GroupPoints = ZoneGroup:GetTaskRoute() + local i = 0 + + self.Polygon = {} + + for i = 1, #GroupPoints do + self.Polygon[i] = {} + self.Polygon[i].x = GroupPoints[i].x + self.Polygon[i].y = GroupPoints[i].y + end + + return self +end + +--- Smokes the zone boundaries in a color. +-- @param #ZONE_POLYGON self +-- @param #POINT_VEC3.SmokeColor SmokeColor The smoke color. +-- @return #ZONE_POLYGON self +function ZONE_POLYGON:SmokeZone( SmokeColor ) + self:F2( SmokeColor ) + + local i + local j + local Segments = 10 + + i = 1 + j = #self.Polygon + + while i <= #self.Polygon do + self:T( { i, j, self.Polygon[i], self.Polygon[j] } ) + + local DeltaX = self.Polygon[j].x - self.Polygon[i].x + local DeltaY = self.Polygon[j].y - self.Polygon[i].y + + for Segment = 0, Segments do -- We divide each line in 5 segments and smoke a point on the line. + local PointX = self.Polygon[i].x + ( Segment * DeltaX / Segments ) + local PointY = self.Polygon[i].y + ( Segment * DeltaY / Segments ) + POINT_VEC2:New( PointX, PointY ):Smoke( SmokeColor ) + end + j = i + i = i + 1 + end + + return self +end + + + + +--- Returns if a location is within the zone. +-- @param #ZONE_POLYGON self +-- @param DCSTypes#Vec2 PointVec2 The location to test. +-- @return #boolean true if the location is within the zone. +function ZONE_POLYGON:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local i + local j + local c = false + + i = 1 + j = #self.Polygon + + while i < #self.Polygon do + j = i + i = i + 1 + self:T( { i, j, self.Polygon[i], self.Polygon[j] } ) + if ( ( ( self.Polygon[i].y > PointVec2.y ) ~= ( self.Polygon[j].y > PointVec2.y ) ) and + ( PointVec2.x < ( self.Polygon[j].x - self.Polygon[i].x ) * ( PointVec2.y - self.Polygon[i].y ) / ( self.Polygon[j].y - self.Polygon[i].y ) + self.Polygon[i].x ) + ) then + c = not c + end + self:T2( { "c = ", c } ) + end + + self:T( { "c = ", c } ) + return c +end + +--- This module contains the CLIENT class. -- --- @{#CLIENT} class --- ================ +-- 1) @{Client#CLIENT} class, extends @{Unit#UNIT} +-- =============================================== -- Clients are those **Units** defined within the Mission Editor that have the skillset defined as __Client__ or __Player__. -- Note that clients are NOT the same as Units, they are NOT necessarily alive. --- The @{CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__: +-- The @{Client#CLIENT} class is a wrapper class to handle the DCS Unit objects that have the skillset defined as __Client__ or __Player__: -- -- * Wraps the DCS Unit objects with skill level set to Player or Client. -- * Support all DCS Unit APIs. @@ -6834,8 +8121,8 @@ end -- -- Clients are being used by the @{MISSION} class to follow players and register their successes. -- --- CLIENT reference methods --- ======================= +-- 1.1) CLIENT reference methods +-- ----------------------------- -- For each DCS Unit having skill level Player or Client, a CLIENT wrapper object (instance) will be created within the _@{DATABASE} object. -- This is done at the beginning of the mission (when the mission starts). -- @@ -7297,6 +8584,87 @@ function CLIENT:Message( Message, MessageDuration, MessageId, MessageCategory, M end end end +--- This module contains the STATIC class. +-- +-- 1) @{Static#STATIC} class, extends @{Unit#UNIT} +-- =============================================== +-- Statics are **Static Units** defined within the Mission Editor. +-- Note that Statics are almost the same as Units, but they don't have a controller. +-- The @{Static#STATIC} class is a wrapper class to handle the DCS Static objects: +-- +-- * Wraps the DCS Static objects. +-- * Support all DCS Static APIs. +-- * Enhance with Static specific APIs not in the DCS API set. +-- +-- 1.1) STATIC reference methods +-- ----------------------------- +-- For each DCS Static will have a STATIC wrapper object (instance) within the _@{DATABASE} object. +-- This is done at the beginning of the mission (when the mission starts). +-- +-- The STATIC class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference +-- using the Static Name. +-- +-- Another thing to know is that STATIC objects do not "contain" the DCS Static object. +-- The STATIc methods will reference the DCS Static object by name when it is needed during API execution. +-- If the DCS Static object does not exist or is nil, the STATIC methods will return nil and log an exception in the DCS.log file. +-- +-- The STATIc class provides the following functions to retrieve quickly the relevant STATIC instance: +-- +-- * @{#STATIC.FindByName}(): Find a STATIC instance from the _DATABASE object using a DCS Static name. +-- +-- IMPORTANT: ONE SHOULD NEVER SANATIZE these STATIC OBJECT REFERENCES! (make the STATIC object references nil). +-- +-- @module Static +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Message" ) + + +--- The STATIC class +-- @type STATIC +-- @extends Unit#UNIT +STATIC = { + ClassName = "STATIC", +} + + +--- Finds a STATIC from the _DATABASE using the relevant Static Name. +-- As an optional parameter, a briefing text can be given also. +-- @param #STATIC self +-- @param #string StaticName Name of the DCS **Static** as defined within the Mission Editor. +-- @return #STATIC +function STATIC:FindByName( StaticName ) + local StaticFound = _DATABASE:FindStatic( StaticName ) + + if StaticFound then + StaticFound:F( { StaticName } ) + + return StaticFound + end + + error( "STATIC not found for: " .. StaticName ) +end + +function STATIC:Register( StaticName ) + local self = BASE:Inherit( self, UNIT:Register( StaticName ) ) + + self:F( StaticName ) + + return self +end + + +function STATIC:GetDCSUnit() + local DCSStatic = StaticObject.getByName( self.UnitName ) + + if DCSStatic then + return DCSStatic + end + + return nil +end --- Manage the mission database. -- -- @{#DATABASE} class @@ -7335,9 +8703,11 @@ Include.File( "Routines" ) Include.File( "Base" ) Include.File( "Menu" ) Include.File( "Group" ) +Include.File( "Static" ) Include.File( "Unit" ) Include.File( "Event" ) Include.File( "Client" ) +Include.File( "Scheduler" ) --- DATABASE class @@ -7353,7 +8723,9 @@ DATABASE = { }, DCSUnits = {}, DCSGroups = {}, + DCSStatics = {}, UNITS = {}, + STATICS = {}, GROUPS = {}, PLAYERS = {}, PLAYERSALIVE = {}, @@ -7399,7 +8771,8 @@ function DATABASE:New() _EVENTDISPATCHER:OnPlayerLeaveUnit( self._EventOnPlayerLeaveUnit, self ) self:_RegisterTemplates() - self:_RegisterDatabase() + self:_RegisterGroupsAndUnits() + self:_RegisterStatics() self:_RegisterPlayers() return self @@ -7432,6 +8805,32 @@ function DATABASE:DeleteUnit( DCSUnitName ) self.DCSUnits[DCSUnitName] = nil end +--- Adds a Static based on the Static Name in the DATABASE. +-- @param #DATABASE self +function DATABASE:AddStatic( DCSStatic, DCSStaticName ) + + self.DCSStatics[DCSStaticName] = DCSStatic + self.STATICS[DCSStaticName] = STATIC:Register( DCSStaticName ) +end + + +--- Deletes a Static from the DATABASE based on the Static Name. +-- @param #DATABASE self +function DATABASE:DeleteStatic( DCSStaticName ) + + self.DCSStatics[DCSStaticName] = nil +end + +--- Finds a STATIC based on the StaticName. +-- @param #DATABASE self +-- @param #string StaticName +-- @return Static#STATIC The found STATIC. +function DATABASE:FindStatic( StaticName ) + + local StaticFound = self.STATICS[StaticName] + return StaticFound +end + --- Finds a CLIENT based on the ClientName. -- @param #DATABASE self @@ -7519,6 +8918,8 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.SpawnCategoryID = nil self:_RegisterTemplate( SpawnTemplate ) + + self:T3( SpawnTemplate ) coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate ) -- Restore @@ -7526,7 +8927,6 @@ function DATABASE:Spawn( SpawnTemplate ) SpawnTemplate.SpawnCountryID = SpawnCountryID SpawnTemplate.SpawnCategoryID = SpawnCategoryID - local SpawnGroup = GROUP:Register( SpawnTemplate.name ) return SpawnGroup end @@ -7619,10 +9019,10 @@ function DATABASE:_RegisterPlayers() end ---- Private method that registers all datapoints within in the mission. +--- Private method that registers all Groups and Units within in the mission. -- @param #DATABASE self -- @return #DATABASE self -function DATABASE:_RegisterDatabase() +function DATABASE:_RegisterGroupsAndUnits() local CoalitionsData = { GroupsRed = coalition.getGroups( coalition.side.RED ), GroupsBlue = coalition.getGroups( coalition.side.BLUE ) } for CoalitionId, CoalitionData in pairs( CoalitionsData ) do @@ -7655,6 +9055,27 @@ function DATABASE:_RegisterDatabase() return self end +function DATABASE:_RegisterStatics() + + local CoalitionsData = { GroupsRed = coalition.getStaticObjects( coalition.side.RED ), GroupsBlue = coalition.getStaticObjects( coalition.side.BLUE ) } + for CoalitionId, CoalitionData in pairs( CoalitionsData ) do + for DCSStaticId, DCSStatic in pairs( CoalitionData ) do + + if DCSStatic:isExist() then + local DCSStaticName = DCSStatic:getName() + + self:E( { "Register Static:", DCSStatic, DCSStaticName } ) + self:AddStatic( DCSStatic, DCSStaticName ) + else + self:E( { "Static does not exist: ", DCSStatic } ) + end + end + end + + return self +end + + --- Events --- Handles the OnBirth event for the alive units set. @@ -7917,6 +9338,201 @@ end +--- This module contains the POINT classes. +-- +-- 1) @{Point#POINT_VEC3} class, extends @{Base#BASE} +-- =============================================== +-- The @{Point#POINT_VEC3} class defines a 3D point in the simulator. +-- +-- 1.1) POINT_VEC3 constructor +-- --------------------------- +-- +-- A new POINT instance can be created with: +-- +-- * @{#POINT_VEC3.New}(): a 3D point. +-- +-- 2) @{Point#POINT_VEC2} class, extends @{Point#POINT_VEC3} +-- ========================================================= +-- The @{Point#POINT_VEC2} class defines a 2D point in the simulator. The height coordinate (if needed) will be the land height + an optional added height specified. +-- +-- 2.1) POINT_VEC2 constructor +-- --------------------------- +-- +-- A new POINT instance can be created with: +-- +-- * @{#POINT_VEC2.New}(): a 2D point. +-- +-- @module Point +-- @author FlightControl + +Include.File( "Routines" ) +Include.File( "Base" ) +Include.File( "Point" ) + +--- The POINT_VEC3 class +-- @type POINT_VEC3 +-- @extends Base#BASE +-- @field #POINT_VEC3.SmokeColor SmokeColor +-- @field #POINT_VEC3.FlareColor FlareColor +POINT_VEC3 = { + ClassName = "POINT_VEC3", + SmokeColor = { + Green = trigger.smokeColor.Green, + Red = trigger.smokeColor.Red, + White = trigger.smokeColor.White, + Orange = trigger.smokeColor.Orange, + Blue = trigger.smokeColor.Blue + }, + FlareColor = { + Green = trigger.flareColor.Green, + Red = trigger.flareColor.Red, + White = trigger.flareColor.White, + Yellow = trigger.flareColor.Yellow + }, + } + +--- SmokeColor +-- @type POINT_VEC3.SmokeColor +-- @field Green +-- @field Red +-- @field White +-- @field Orange +-- @field Blue + +--- FlareColor +-- @type POINT_VEC3.FlareColor +-- @field Green +-- @field Red +-- @field White +-- @field Yellow + +-- Constructor. + +--- Create a new POINT_VEC3 object. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. +-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing Upwards. +-- @param DCSTypes#Distance z The z coordinate of the Vec3 point, pointing to the Right. +-- @return Point#POINT_VEC3 +function POINT_VEC3:New( x, y, z ) + + local self = BASE:Inherit( self, BASE:New() ) + self:F2( { x, y, z } ) + self.PointVec3 = { x = x, y = y, z = z } + return self +end + +--- Smokes the point in a color. +-- @param #POINT_VEC3 self +-- @param Point#POINT_VEC3.SmokeColor SmokeColor +function POINT_VEC3:Smoke( SmokeColor ) + self:F2( { SmokeColor, self.PointVec3 } ) + trigger.action.smoke( self.PointVec3, SmokeColor ) +end + +--- Smoke the POINT_VEC3 Green. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeGreen() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Green ) +end + +--- Smoke the POINT_VEC3 Red. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeRed() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Red ) +end + +--- Smoke the POINT_VEC3 White. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeWhite() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.White ) +end + +--- Smoke the POINT_VEC3 Orange. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeOrange() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Orange ) +end + +--- Smoke the POINT_VEC3 Blue. +-- @param #POINT_VEC3 self +function POINT_VEC3:SmokeBlue() + self:F2() + self:Smoke( POINT_VEC3.SmokeColor.Blue ) +end + +--- Flares the point in a color. +-- @param #POINT_VEC3 self +-- @param Point#POINT_VEC3.FlareColor +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:Flare( FlareColor, Azimuth ) + self:F2( { FlareColor, self.PointVec3 } ) + trigger.action.signalFlare( self.PointVec3, FlareColor, Azimuth and Azimuth or 0 ) +end + +--- Flare the POINT_VEC3 White. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareWhite( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.White, Azimuth ) +end + +--- Flare the POINT_VEC3 Yellow. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareYellow( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Yellow, Azimuth ) +end + +--- Flare the POINT_VEC3 Green. +-- @param #POINT_VEC3 self +-- @param DCSTypes#Azimuth (optional) Azimuth The azimuth of the flare direction. The default azimuth is 0. +function POINT_VEC3:FlareGreen( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Green, Azimuth ) +end + +--- Flare the POINT_VEC3 Red. +-- @param #POINT_VEC3 self +function POINT_VEC3:FlareRed( Azimuth ) + self:F2( Azimuth ) + self:Flare( POINT_VEC3.FlareColor.Red, Azimuth ) +end + + +--- The POINT_VEC2 class +-- @type POINT_VEC2 +-- @extends Point#POINT_VEC3 +POINT_VEC2 = { + ClassName = "POINT_VEC2", + } + +--- Create a new POINT_VEC2 object. +-- @param #POINT_VEC2 self +-- @param DCSTypes#Distance x The x coordinate of the Vec3 point, pointing to the North. +-- @param DCSTypes#Distance y The y coordinate of the Vec3 point, pointing to the Right. +-- @param DCSTypes#Distance LandHeightAdd (optional) The default height if required to be evaluated will be the land height of the x, y coordinate. You can specify an extra height to be added to the land height. +-- @return Point#POINT_VEC2 +function POINT_VEC2:New( x, y, LandHeightAdd ) + + local LandHeight = land.getHeight( { ["x"] = x, ["y"] = y } ) + if LandHeightAdd then + LandHeight = LandHeight + LandHeightAdd + end + + local self = BASE:Inherit( self, POINT_VEC3:New( x, LandHeight, y ) ) + self:F2( { x, y, LandHeightAdd } ) + + return self +end + + --- The main include file for the MOOSE system. Include.File( "Routines" ) @@ -13160,10 +14776,10 @@ function CLEANUP:_CleanUpScheduler() return true end ---- Dynamic spawning of groups (and units). +--- This module contains the SPAWN class. -- --- @{#SPAWN} class --- =============== +-- 1) @{Spawn#SPAWN} class, extends @{Base#BASE} +-- ============================================= -- The @{#SPAWN} class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned. -- For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the *"Spawn Template"* of the SPAWN object. -- A reference to this Spawn Template needs to be provided when constructing the SPAWN object, by indicating the name of the group within the mission editor in the constructor methods. @@ -13186,8 +14802,8 @@ end -- * It is important to defined BEFORE you spawn new groups, a proper initialization of the SPAWN instance is done with the options you want to use. -- * When designing a mission, NEVER name groups using a "#" within the name of the group Spawn Template(s), or the SPAWN module logic won't work anymore. -- --- SPAWN construction methods: --- =========================== +-- 1.1) SPAWN construction methods +-- ------------------------------- -- Create a new SPAWN object with the @{#SPAWN.New} or the @{#SPAWN.NewWithAlias} methods: -- -- * @{#SPAWN.New}: Creates a new SPAWN object taking the name of the group that functions as the Template. @@ -13196,8 +14812,8 @@ end -- The initialization functions will modify this list of groups so that when a group gets spawned, ALL information is already prepared when spawning. This is done for performance reasons. -- So in principle, the group list will contain all parameters and configurations after initialization, and when groups get actually spawned, this spawning can be done quickly and efficient. -- --- SPAWN initialization methods: --- ============================= +-- 1.2) SPAWN initialization methods +-- --------------------------------- -- A spawn object will behave differently based on the usage of initialization methods: -- -- * @{#SPAWN.Limit}: Limits the amount of groups that can be alive at the same time and that can be dynamically spawned. @@ -13207,8 +14823,8 @@ end -- * @{#SPAWN.Array}: Make groups visible before they are actually activated, and order these groups like a batallion in an array. -- * @{#SPAWN.InitRepeat}: Re-spawn groups when they land at the home base. Similar functions are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}. -- --- SPAWN spawning methods: --- ======================= +-- 1.3) SPAWN spawning methods +-- --------------------------- -- Groups can be spawned at different times and methods: -- -- * @{#SPAWN.Spawn}: Spawn one new group based on the last spawned index. @@ -13220,8 +14836,8 @@ end -- Note that @{#SPAWN.Spawn} and @{#SPAWN.ReSpawn} return a @{GROUP#GROUP.New} object, that contains a reference to the DCSGroup object. -- You can use the @{GROUP} object to do further actions with the DCSGroup. -- --- SPAWN object cleaning: --- ========================= +-- 1.4) SPAWN object cleaning +-- -------------------------- -- Sometimes, it will occur during a mission run-time, that ground or especially air objects get damaged, and will while being damged stop their activities, while remaining alive. -- In such cases, the SPAWN object will just sit there and wait until that group gets destroyed, but most of the time it won't, -- and it may occur that no new groups are or can be spawned as limits are reached. @@ -13232,7 +14848,7 @@ end -- This models AI that has succesfully returned to their airbase, to restart their combat activities. -- Check the @{#SPAWN.CleanUp} for further info. -- --- ==== +-- -- @module Spawn -- @author FlightControl @@ -13635,6 +15251,12 @@ function SPAWN:SpawnWithIndex( SpawnIndex ) end self.SpawnGroups[self.SpawnIndex].Spawned = true + + local SpawnGroup = self.SpawnGroups[self.SpawnIndex].Group -- Group#GROUP + local Route = SpawnGroup:GetTaskRoute() + SpawnGroup:Route(Route) + + return self.SpawnGroups[self.SpawnIndex].Group else --self:E( { self.SpawnTemplatePrefix, "No more Groups to Spawn:", SpawnIndex, self.SpawnMaxGroups } ) @@ -14142,11 +15764,12 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) SpawnTemplate.name = self:SpawnGroupName( SpawnIndex ) SpawnTemplate.groupId = nil - SpawnTemplate.lateActivation = false + --SpawnTemplate.lateActivation = false + SpawnTemplate.lateActivation = false -- TODO BUGFIX if SpawnTemplate.SpawnCategoryID == Group.Category.GROUND then self:T( "For ground units, visible needs to be false..." ) - SpawnTemplate.visible = false + SpawnTemplate.visible = false -- TODO BUGFIX end if SpawnTemplate.SpawnCategoryID == Group.Category.HELICOPTER or SpawnTemplate.SpawnCategoryID == Group.Category.AIRPLANE then @@ -14194,7 +15817,7 @@ end -- @param #number SpawnIndex -- @return #SPAWN self function SPAWN:_RandomizeTemplate( SpawnIndex ) - self:F( { self.SpawnTemplatePrefix, SpawnIndex } ) + self:F( { self.SpawnTemplatePrefix, SpawnIndex, self.SpawnRandomizeTemplate } ) if self.SpawnRandomizeTemplate then self.SpawnGroups[SpawnIndex].SpawnTemplatePrefix = self.SpawnTemplatePrefixTable[ math.random( 1, #self.SpawnTemplatePrefixTable ) ] diff --git a/Moose Mission Setup/Moose_Create.bat b/Moose Mission Setup/Moose_Create.bat index d697db503..6e6de19f7 100644 --- a/Moose Mission Setup/Moose_Create.bat +++ b/Moose Mission Setup/Moose_Create.bat @@ -46,7 +46,9 @@ COPY /b Moose.lua + %1\Group.lua Moose.lua COPY /b Moose.lua + %1\Unit.lua Moose.lua COPY /b Moose.lua + %1\Zone.lua Moose.lua COPY /b Moose.lua + %1\Client.lua Moose.lua +COPY /b Moose.lua + %1\Static.lua Moose.lua COPY /b Moose.lua + %1\Database.lua Moose.lua +COPY /b Moose.lua + %1\Point.lua Moose.lua COPY /b Moose.lua + %1\Moose.lua Moose.lua COPY /b Moose.lua + %1\Scoring.lua Moose.lua COPY /b Moose.lua + %1\Cargo.lua Moose.lua diff --git a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz index 4e11868b2..9f4f2e9e2 100644 Binary files a/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz and b/Moose Test Missions/Moose_Test_CLEANUP/Moose_Test_CLEANUP.miz differ diff --git a/Moose Test Missions/Moose_Test_DATABASE/Moose_Test_DATABASE.miz b/Moose Test Missions/Moose_Test_DATABASE/Moose_Test_DATABASE.miz index 9977c082b..43c66de8a 100644 Binary files a/Moose Test Missions/Moose_Test_DATABASE/Moose_Test_DATABASE.miz and b/Moose Test Missions/Moose_Test_DATABASE/Moose_Test_DATABASE.miz differ diff --git a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz index 2a439db3c..5079bd0a0 100644 Binary files a/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz and b/Moose Test Missions/Moose_Test_DESTROY/MOOSE_Test_DESTROY.miz differ diff --git a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz index 41ca99bd5..522bbe78d 100644 Binary files a/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz and b/Moose Test Missions/Moose_Test_ESCORT/MOOSE_Test_ESCORT.miz differ diff --git a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz index 70fd8bf2c..dd599556b 100644 Binary files a/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz and b/Moose Test Missions/Moose_Test_MISSILETRAINER/Moose_Test_MISSILETRAINER.miz differ diff --git a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz index 707f40154..c90dd03c8 100644 Binary files a/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz and b/Moose Test Missions/Moose_Test_SEAD/MOOSE_Test_SEAD.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz index d661eba53..c2b0e0d9e 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz and b/Moose Test Missions/Moose_Test_SPAWN/MOOSE_Test_SPAWN.miz differ diff --git a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz index 12db2587b..06bc8230b 100644 Binary files a/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz and b/Moose Test Missions/Moose_Test_SPAWN_Repeat/MOOSE_Test_SPAWN_Repeat.miz differ diff --git a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz index 304ea1296..f9458fe79 100644 Binary files a/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz and b/Moose Test Missions/Moose_Test_TASK_Pickup_and_Deploy/MOOSE_Test_TASK_Pickup_and_Deploy.miz differ diff --git a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz index 5f4bfcb56..b2a0c3611 100644 Binary files a/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz and b/Moose Test Missions/Moose_Test_WRAPPER/Moose_Test_WRAPPER.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.lua b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.lua new file mode 100644 index 000000000..d9bbe059d --- /dev/null +++ b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.lua @@ -0,0 +1,19 @@ + +Include.File( "Zone" ) +Include.File( "Group" ) +Include.File( "Scheduler" ) + +local GroupInside = GROUP:FindByName( "Test Inside Polygon" ) +local GroupOutside = GROUP:FindByName( "Test Outside Polygon" ) + +local ZoneA = ZONE:New( "Zone A" ):SmokeZone( POINT_VEC3.SmokeColor.White, 90 ) + +Messager = SCHEDULER:New( nil, + function() + GroupInside:MessageToAll( ( GroupInside:IsCompletelyInZone( ZoneA ) ) and "Inside Zone A" or "Outside Zone A", 1 ) + if GroupInside:IsCompletelyInZone( ZoneA ) then + GroupInside:GetUnit(1):SmokeRed() + end + end, + {}, 0, 1 ) + diff --git a/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz new file mode 100644 index 000000000..1e35a70be Binary files /dev/null and b/Moose Test Missions/Moose_Test_ZONE/Moose_Test_ZONE.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.lua b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.lua new file mode 100644 index 000000000..bfa24fa60 --- /dev/null +++ b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.lua @@ -0,0 +1,21 @@ + +Include.File( "Zone" ) +Include.File( "Group" ) +Include.File( "Scheduler" ) + +local GroupInside = GROUP:FindByName( "Test Inside Polygon" ) +local GroupOutside = GROUP:FindByName( "Test Outside Polygon" ) + +local GroupPolygon = GROUP:FindByName( "Polygon A" ) + +local PolygonZone = ZONE_POLYGON:New( "Polygon A", GroupPolygon ):SmokeZone( POINT_VEC3.SmokeColor.White, 20 ) + +Messager = SCHEDULER:New( nil, + function() + GroupInside:MessageToAll( ( GroupInside:IsCompletelyInZone( PolygonZone ) ) and "Inside Polygon A" or "Outside Polygon A", 1 ) + if GroupInside:IsCompletelyInZone( PolygonZone ) then + GroupInside:GetUnit(1):SmokeRed() + end + end, + {}, 0, 1 ) + diff --git a/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz new file mode 100644 index 000000000..6e2e2e40a Binary files /dev/null and b/Moose Test Missions/Moose_Test_ZONE_POLYGON/Moose_Test_ZONE_POLYGON.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.lua b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.lua new file mode 100644 index 000000000..1d01e5451 --- /dev/null +++ b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.lua @@ -0,0 +1,20 @@ + +Include.File( "Zone" ) +Include.File( "Group" ) +Include.File( "Scheduler" ) + +local GroupInside = GROUP:FindByName( "Test Inside Polygon" ) +local GroupOutside = GROUP:FindByName( "Test Outside Polygon" ) + +local House = STATIC:FindByName( "House" ) +local ZoneA = ZONE_RADIUS:New( "Zone A", House:GetPointVec2(), 300 ):SmokeZone( POINT_VEC3.SmokeColor.White, 90 ) + +Messager = SCHEDULER:New( nil, + function() + GroupInside:MessageToAll( ( GroupInside:IsCompletelyInZone( ZoneA ) ) and "Inside Zone A" or "Outside Zone A", 1 ) + if GroupInside:IsCompletelyInZone( ZoneA ) then + GroupInside:GetUnit(1):SmokeRed() + end + end, + {}, 0, 1 ) + diff --git a/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz new file mode 100644 index 000000000..f207c8b9b Binary files /dev/null and b/Moose Test Missions/Moose_Test_ZONE_RADIUS/Moose_Test_ZONE_RADIUS.miz differ diff --git a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.lua b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.lua new file mode 100644 index 000000000..3573a123c --- /dev/null +++ b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.lua @@ -0,0 +1,25 @@ + +Include.File( "Zone" ) +Include.File( "Group" ) +Include.File( "Scheduler" ) + +local GroupInside = GROUP:FindByName( "Test Inside Polygon" ) +local GroupOutside = GROUP:FindByName( "Test Outside Polygon" ) + +local Tank = UNIT:FindByName( "Tank" ) +local ZoneA = ZONE_UNIT:New( "Zone A", Tank, 100 ) + +Messager = SCHEDULER:New( nil, + function() + GroupInside:MessageToAll( ( GroupInside:IsCompletelyInZone( ZoneA ) ) and "Inside Zone A" or "Outside Zone A", 1 ) + if GroupInside:IsCompletelyInZone( ZoneA ) then + GroupInside:GetUnit(1):SmokeRed() + end + end, + {}, 0, 1 ) + +TankZoneColoring = SCHEDULER:New( nil, + function() + ZoneA:FlareZone( POINT_VEC3.FlareColor.White, 90, 60 ) + end, + {}, 0, 5 ) \ No newline at end of file diff --git a/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz new file mode 100644 index 000000000..5d4aabf7f Binary files /dev/null and b/Moose Test Missions/Moose_Test_ZONE_UNIT/Moose_Test_ZONE_UNIT.miz differ diff --git a/Moose Training/Documentation/Airbase.html b/Moose Training/Documentation/Airbase.html new file mode 100644 index 000000000..be9848189 --- /dev/null +++ b/Moose Training/Documentation/Airbase.html @@ -0,0 +1,664 @@ + + + + + + +
+
+ +
+
+
+
+ +
+

Module Airbase

+ +

AIRBASE Class

+ +

AIRBASE class

+

The AIRBASE class is a wrapper class to handle the DCS Airbase objects:

+ +
    +
  • Support all DCS Airbase APIs.
  • +
+ + +
    +
  • Enhance with Airbase specific APIs not in the DCS Airbase API set.
  • +
+ + +

AIRBASE reference methods

+

For each DCS Airbase object alive within a running mission, a AIRBASE wrapper object (instance) will be created within the _DATABASE object. +This is done at the beginning of the mission (when the mission starts).

+ +

The AIRBASE class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference +using the DCS Airbase or the DCS AirbaseName.

+ +

Another thing to know is that AIRBASE objects do not "contain" the DCS Airbase object. +The AIRBASE methods will reference the DCS Airbase object by name when it is needed during API execution. +If the DCS Airbase object does not exist or is nil, the AIRBASE methods will return nil and log an exception in the DCS.log file.

+ +

The AIRBASE class provides the following functions to retrieve quickly the relevant AIRBASE instance:

+ +
    +
  • AIRBASE.Find(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase object.
  • +
  • AIRBASE.FindByName(): Find a AIRBASE instance from the _DATABASE object using a DCS Airbase name.
  • +
+ +

IMPORTANT: ONE SHOULD NEVER SANATIZE these AIRBASE OBJECT REFERENCES! (make the AIRBASE object references nil).

+ +

DCS AIRBASE APIs

+

The DCS Airbase APIs are used extensively within MOOSE. The AIRBASE class has for each DCS Airbase API a corresponding method. +To be able to distinguish easily in your code the difference between a AIRBASE API call and a DCS Airbase API call, +the first letter of the method is also capitalized. So, by example, the DCS Airbase method DCSAirbase#Airbase.getName() +is implemented in the AIRBASE class as AIRBASE.GetName().

+ +

More functions will be added

+

During the MOOSE development, more functions will be added.

+ + +

Global(s)

+ + + + + +
AIRBASE + +
+

Type AIRBASE

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AIRBASE.CategoryName + +
AIRBASE.ClassName + +
AIRBASE:Find(DCSAirbase) +

Finds a AIRBASE from the _DATABASE using a DCSAirbase object.

+
AIRBASE:FindByName(AirbaseName) +

Find a AIRBASE in the _DATABASE using the name of an existing DCS Airbase.

+
AIRBASE:GetCallSign() +

Returns the Airbase's callsign - the localized string.

+
AIRBASE:GetCategoryName() +

Returns the DCS Airbase category name as defined within the DCS Airbase Descriptor.

+
AIRBASE:GetCoalition() +

Returns coalition of the Airbase.

+
AIRBASE:GetCountry() +

Returns country of the Airbase.

+
AIRBASE:GetDCSAirbase() + +
AIRBASE:GetDesc() +

Returns unit descriptor.

+
AIRBASE:GetID() +

Returns the unit's unique identifier.

+
AIRBASE:GetName() +

Returns DCS Airbase object name.

+
AIRBASE:GetPointVec2() +

Returns the DCSTypes#Vec2 vector indicating the point in 2D of the DCS Airbase within the mission.

+
AIRBASE:GetTypeName() +

Returns the type name of the DCS Airbase.

+
AIRBASE:IsAlive() +

Returns if the airbase is alive.

+
AIRBASE:Register(DCSAirbase, Database, AirbaseName) +

Create a new AIRBASE from DCSAirbase.

+
+ +

Global(s)

+
+
+ + #AIRBASE + +AIRBASE + +
+
+ + + +
+
+

Type Airbase

+ +

Type AIRBASE

+ +

The AIRBASE class

+ +

Field(s)

+
+
+ + + +AIRBASE.CategoryName + +
+
+ + + +
+
+
+
+ + #string + +AIRBASE.ClassName + +
+
+ + + +
+
+
+
+ + +AIRBASE:Find(DCSAirbase) + +
+
+ +

Finds a AIRBASE from the _DATABASE using a DCSAirbase object.

+ +

Parameter

+ +

Return value

+ +

Airbase#AIRBASE: +self

+ +
+
+
+
+ + +AIRBASE:FindByName(AirbaseName) + +
+
+ +

Find a AIRBASE in the _DATABASE using the name of an existing DCS Airbase.

+ +

Parameter

+
    +
  • + +

    #string AirbaseName : +The Airbase Name.

    + +
  • +
+

Return value

+ +

Airbase#AIRBASE: +self

+ +
+
+
+
+ + +AIRBASE:GetCallSign() + +
+
+ +

Returns the Airbase's callsign - the localized string.

+ +

Return values

+
    +
  1. + +

    #string: +The Callsign of the Airbase.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetCategoryName() + +
+
+ +

Returns the DCS Airbase category name as defined within the DCS Airbase Descriptor.

+ +

Return value

+ +

#string: +The DCS Airbase Category Name

+ +
+
+
+
+ + +AIRBASE:GetCoalition() + +
+
+ +

Returns coalition of the Airbase.

+ +

Return values

+
    +
  1. + +

    DCSCoalitionObject#coalition.side: +The side of the coalition.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetCountry() + +
+
+ +

Returns country of the Airbase.

+ +

Return values

+
    +
  1. + +

    DCScountry#country.id: +The country identifier.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetDCSAirbase() + +
+
+ + + +
+
+
+
+ + +AIRBASE:GetDesc() + +
+
+ +

Returns unit descriptor.

+ + +

Descriptor type depends on unit category.

+ +

Return values

+
    +
  1. + +

    DCSAirbase#Airbase.Desc: +The Airbase descriptor.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetID() + +
+
+ +

Returns the unit's unique identifier.

+ +

Return values

+
    +
  1. + +

    DCSAirbase#Airbase.ID: +Airbase ID

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetName() + +
+
+ +

Returns DCS Airbase object name.

+ + +

The function provides access to non-activated units too.

+ +

Return values

+
    +
  1. + +

    #string: +The name of the DCS Airbase.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetPointVec2() + +
+
+ +

Returns the DCSTypes#Vec2 vector indicating the point in 2D of the DCS Airbase within the mission.

+ +

Return values

+
    +
  1. + +

    DCSTypes#Vec2: +The 2D point vector of the DCS Airbase.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:GetTypeName() + +
+
+ +

Returns the type name of the DCS Airbase.

+ +

Return values

+
    +
  1. + +

    #string: +The type name of the DCS Airbase.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:IsAlive() + +
+
+ +

Returns if the airbase is alive.

+ +

Return values

+
    +
  1. + +

    #boolean: +true if Airbase is alive.

    + +
  2. +
  3. + +

    #nil: +The DCS Airbase is not existing or alive.

    + +
  4. +
+
+
+
+
+ + +AIRBASE:Register(DCSAirbase, Database, AirbaseName) + +
+
+ +

Create a new AIRBASE from DCSAirbase.

+ +

Parameters

+ +

Return value

+ +

Airbase#AIRBASE:

+ + +
+
+ +
+ +
+ + diff --git a/Moose Training/Documentation/Base.html b/Moose Training/Documentation/Base.html index c35a7adac..bd96b901b 100644 --- a/Moose Training/Documentation/Base.html +++ b/Moose Training/Documentation/Base.html @@ -17,6 +17,7 @@ index
diff --git a/Moose Training/Documentation/DCSTypes.html b/Moose Training/Documentation/DCSTypes.html index 56ccd79ff..e4fa753f7 100644 --- a/Moose Training/Documentation/DCSTypes.html +++ b/Moose Training/Documentation/DCSTypes.html @@ -17,6 +17,7 @@ index
    +
  • Airbase
  • Base
  • CARGO
  • CleanUp
  • @@ -50,6 +51,7 @@
  • Mission
  • NOTASK
  • PICKUPTASK
  • +
  • Point
  • ROUTETASK
  • STAGE
  • Scheduler
  • @@ -57,6 +59,7 @@
  • Sead
  • Set
  • Spawn
  • +
  • Static
  • StaticObject
  • TASK
  • Unit
  • @@ -2203,6 +2206,21 @@

    An angle type

    +

    Type AttributeName

    + +

    AttributeName = string +Each object type may have attributes.

    + + +

    Attributes are enlisted in ./Scripts/Database/db_attributes.Lua. +To know what attributes the object type has, look for the unit type script in sub-directories planes/, helicopter/s, vehicles, navy/ of ./Scripts/Database/ directory.

    + + +

    Type AttributeNameArray

    + +

    List of #AttributeName

    + +

    Type Azimuth

    Azimuth is an angle of rotation around world axis y counter-clockwise.

    diff --git a/Moose Training/Documentation/DCSUnit.html b/Moose Training/Documentation/DCSUnit.html index e40060e37..20b5c9f57 100644 --- a/Moose Training/Documentation/DCSUnit.html +++ b/Moose Training/Documentation/DCSUnit.html @@ -17,6 +17,7 @@ index
    +
  • Airbase
  • Base
  • CARGO
  • CleanUp
  • @@ -50,6 +51,7 @@
  • Mission
  • NOTASK
  • PICKUPTASK
  • +
  • Point
  • ROUTETASK
  • STAGE
  • Scheduler
  • @@ -57,6 +59,7 @@
  • Sead
  • Set
  • Spawn
  • +
  • Static
  • StaticObject
  • TASK
  • Unit
  • @@ -70,12 +73,12 @@

    Module Group

    -

    GROUP class.

    +

    This module contains the GROUP class.

    -

    GROUP class

    -

    The GROUP class is a wrapper class to handle the DCS Group objects:

    +

    1) Group#GROUP class, extends Base#BASE

    +

    The Group#GROUP class is a wrapper class to handle the DCS Group objects:

    • Support all DCS Group APIs.
    • @@ -84,15 +87,16 @@
    • Manage the "state" of the DCS Group.
    +

    IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).

    -

    GROUP reference methods

    +

    1.1) GROUP reference methods

    For each DCS Group object alive within a running mission, a GROUP wrapper object (instance) will be created within the _DATABASE object. This is done at the beginning of the mission (when the mission starts), and dynamically when new DCS Group objects are spawned (using the SPAWN class).

    The GROUP class does not contain a :New() method, rather it provides :Find() methods to retrieve the object reference using the DCS Group or the DCS GroupName.

    -

    Another thing to know is that GROUP objects do not "contain" the DCS Group object. +

    Another thing to know is that GROUP objects do not "contain" the DCS Group object. The GROUP methods will reference the DCS Group object by name when it is needed during API execution. If the DCS Group object does not exist or is nil, the GROUP methods will return nil and log an exception in the DCS.log file.

    @@ -103,7 +107,136 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return
  • GROUP.FindByName(): Find a GROUP instance from the _DATABASE object using a DCS Group name.
-

IMPORTANT: ONE SHOULD NEVER SANATIZE these GROUP OBJECT REFERENCES! (make the GROUP object references nil).

+

1.2) GROUP task methods

+

Several group task methods are available that help you to prepare tasks. +These methods return a string consisting of the task description, which can then be given to either a Group#GROUP.PushTask or Group#SetTask method to assign the task to the GROUP. +Tasks are specific for the category of the GROUP, more specific, for AIR, GROUND or AIR and GROUND. +Each task description where applicable indicates for which group category the task is valid. +There are 2 main subdivisions of tasks: Assigned tasks and EnRoute tasks.

+ +

1.2.1) Assigned task methods

+ +

Assigned task methods make the group execute the task where the location of the (possible) targets of the task are known before being detected. +This is different from the EnRoute tasks, where the targets of the task need to be detected before the task can be executed.

+ +

Find below a list of the assigned task methods:

+ + + +

1.2.2) EnRoute task methods

+ +

EnRoute tasks require the targets of the task need to be detected by the group (using its sensors) before the task can be executed:

+ +
    +
  • GROUP.EnRouteTaskAWACS: (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts). No parameters.
  • +
  • GROUP.EnRouteTaskEngageGroup: (AIR) Engaging a group. The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets.
  • +
  • GROUP.EnRouteTaskEngageTargets: (AIR) Engaging targets of defined types.
  • +
  • GROUP.EnRouteTaskEWR: (AIR) Attack the Unit.
  • +
  • GROUP.EnRouteTaskFAC: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets.
  • +
  • GROUP.EnRouteTaskFAC_EngageGroup: (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets.
  • +
  • GROUP.EnRouteTaskTanker: (AIR) Aircraft will act as a tanker for friendly units. No parameters.
  • +
+ +

1.2.3) Preparation task methods

+ +

There are certain task methods that allow to tailor the task behaviour:

+ + + +

1.2.4) Obtain the mission from group templates

+ +

Group templates contain complete mission descriptions. Sometimes you want to copy a complete mission from a group and assign it to another:

+ +
    +
  • GROUP.TaskMission: (AIR + GROUND) Return a mission task from a mission template.
  • +
+ +

1.3) GROUP Command methods

+

Group command methods prepare the execution of commands using the GROUP.SetCommand method:

+ + + +

1.4) GROUP Option methods

+

Group Option methods change the behaviour of the Group while being alive.

+ +

1.4.1) Rule of Engagement:

+ + + +

To check whether an ROE option is valid for a specific group, use:

+ + + +

1.4.2) Rule on thread:

+ + + +

To test whether an ROT option is valid for a specific group, use:

+ + + +

1.5) GROUP Zone validation methods

+

The group can be validated whether it is completely, partly or not within a Zone. +Use the following Zone validation methods on the group:

+ + + +

The zone can be of any Zone class derived from Zone#ZONE_BASE. So, these methods are polymorphic to the zones tested on.

+

Global(s)

@@ -178,6 +311,54 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -201,7 +382,7 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return @@ -360,6 +541,12 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return + + + + @@ -372,6 +559,18 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return + + + + + + + + @@ -549,93 +748,141 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return - + - + - + + + + + + + + + + + + + - + - + - + + + + + + + + + + + + + + + + + + + + + @@ -647,29 +894,29 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return - + @@ -746,8 +993,6 @@ If the DCS Group object does not exist or is nil, the GROUP methods will return

Type DCSStopCondition

-

Type Duration

-

Type GROUP

The GROUP class

@@ -910,7 +1155,7 @@ Randomization of the route, when true.

  • #number Radius : -When randomization is on, the randomization is within the radius.

    +When randomization is on, the randomization is within the radius.

  • @@ -950,6 +1195,341 @@ So all event listeners will catch the destroy event of this DCS Group.

    + +GROUP:EnRouteTaskAWACS() + +
    +
    + +

    (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts).

    + + +

    No parameters.

    + +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskEWR() + +
    +
    + +

    (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts).

    + + +

    No parameters.

    + +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskEngageGroup(AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit) + +
    +
    + +

    (AIR) Engaging a group.

    + + +

    The task does not assign the target group to the unit/group to attack now; it just allows the unit/group to engage the target group as well as other assigned targets.

    + +

    Parameters

    +
      +
    • + +

      Group#GROUP AttackGroup : +The Group to be attacked.

      + +
    • +
    • + +

      #number Priority : +All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

      DCSTypes#Distance Altitude : +(optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude.

      + +
    • +
    • + +

      #boolean AttackQtyLimit : +(optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskEngageTargets(Distance, TargetTypes, Priority) + +
    +
    + +

    (AIR) Engaging targets of defined types.

    + +

    Parameters

    +
      +
    • + +

      DCSTypes#Distance Distance : +Maximal distance from the target to a route leg. If the target is on a greater distance it will be ignored.

      + +
    • +
    • + +

      DCSTypes#AttributeNameArray TargetTypes : +Array of target categories allowed to engage.

      + +
    • +
    • + +

      #number Priority : +All enroute tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskEngageUnit(AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack) + +
    +
    + +

    (AIR) Attack the Unit.

    + +

    Parameters

    +
      +
    • + +

      Unit#UNIT AttackUnit : +The UNIT.

      + +
    • +
    • + +

      #number Priority : +All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

      #boolean AttackQtyLimit : +(optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.

      + +
    • +
    • + +

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

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskFAC(Radius, Priority) + +
    +
    + +

    (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets.

    + + +

    The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +If the task is assigned to the group lead unit will be a FAC.

    + +

    Parameters

    +
      +
    • + +

      DCSTypes#Distance Radius : + The maximal distance from the FAC to a target.

      + +
    • +
    • + +

      #number Priority : +All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskFAC_EngageGroup(AttackGroup, Priority, WeaponType, Designation, Datalink) + +
    +
    + +

    (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets.

    + + +

    The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +If the task is assigned to the group lead unit will be a FAC.

    + +

    Parameters

    +
      +
    • + +

      Group#GROUP AttackGroup : +Target GROUP.

      + +
    • +
    • + +

      #number Priority : +All en-route tasks have the priority parameter. This is a number (less value - higher priority) that determines actions related to what task will be performed first.

      + +
    • +
    • + +

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

      + +
    • +
    • + +

      DCSTypes#AI.Task.Designation Designation : +(optional) Designation type.

      + +
    • +
    • + +

      #boolean Datalink : +(optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:EnRouteTaskTanker() + +
    +
    + +

    (AIR) Aircraft will act as a tanker for friendly units.

    + + +

    No parameters.

    + +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + GROUP:Find(DCSGroup) @@ -1028,7 +1608,7 @@ The CallSign of the first DCS Unit of the DCS Group.

    -

    Returns category of the DCS Group.

    +

    Returns category of the DCS Group.

    Return value

    @@ -1095,7 +1675,7 @@ The country identifier.

  • #nil: -The DCS Group is not existing or alive.

    +The DCS Group is not existing or alive.

  • @@ -1212,7 +1792,7 @@ The identifier of the DCS Group.

    -

    If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged.

    +

    If some of the DCS Units of the DCS Group are destroyed, the initial size of the DCS Group is unchanged.

    Return value

    @@ -1350,7 +1930,7 @@ Current Vec3 point of the first DCS Unit of the DCS Group.

    Returns current size of the DCS Group.

    -

    If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed.

    +

    If some of the DCS Units of the DCS Group are destroyed the size of the DCS Group is changed.

    Return value

    @@ -1552,6 +2132,33 @@ true if the DCS Group is alive.

    + +GROUP:IsCompletelyInZone(Zone) + +
    +
    + +

    Returns true if all units of the group are within a Zone.

    + +

    Parameter

    + +

    Return value

    + +

    #boolean: +Returns true if the Group is completely within the Zone#ZONE_BASE

    + +
    +
    +
    +
    + GROUP:IsGround() @@ -1588,6 +2195,60 @@ true if DCS Group contains Helicopters.

    + +GROUP:IsNotInZone(Zone) + +
    +
    + +

    Returns true if none of the group units of the group are within a Zone.

    + +

    Parameter

    + +

    Return value

    + +

    #boolean: +Returns true if the Group is completely within the Zone#ZONE_BASE

    + +
    +
    +
    +
    + + +GROUP:IsPartlyInZone(Zone) + +
    +
    + +

    Returns true if some units of the group are within a Zone.

    + +

    Parameter

    + +

    Return value

    + +

    #boolean: +Returns true if the Group is completely within the Zone#ZONE_BASE

    + +
    +
    +
    +
    + GROUP:IsShip() @@ -1645,7 +2306,7 @@ The message text

  • -

    #Duration Duration : +

    DCSTypes#Duration Duration : The duration of the message.

  • @@ -1681,7 +2342,7 @@ The message text

  • -

    #Duration Duration : +

    DCSTypes#Duration Duration : The duration of the message.

  • @@ -1712,7 +2373,7 @@ The message text

  • -

    #Duration Duration : +

    DCSTypes#Duration Duration : The duration of the message.

  • @@ -1743,7 +2404,7 @@ The message text

  • -

    #Duration Duration : +

    DCSTypes#Duration Duration : The duration of the message.

  • @@ -1780,7 +2441,7 @@ The message text

  • -

    #Duration Duration : +

    DCSTYpes#Duration Duration : The duration of the message.

  • @@ -2174,7 +2835,7 @@ A table of Route Points.

    Return value

    #GROUP: -self

    +self

    @@ -2239,20 +2900,113 @@ self

    -GROUP:TaskAttackGroup(AttackGroup) +GROUP:TaskAttackGroup(AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit)
    -

    Attack a Group.

    +

    (AIR) Attack a Group.

    -

    Parameter

    +

    Parameters

    • Group#GROUP AttackGroup : The Group to be attacked.

      +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

      DCSTypes#Distance Altitude : +(optional) Desired attack start altitude. Group/aircraft will make its attacks from the altitude. If the altitude is too low or too high to use weapon aircraft/group will choose closest altitude to the desired attack start altitude. If the desired altitude is defined group/aircraft will not attack from safe altitude.

      + +
    • +
    • + +

      #boolean AttackQtyLimit : +(optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    + +
    +
    + + +GROUP:TaskAttackMapObject(PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) + +
    +
    + +

    (AIR) Attacking the map object (building, structure, e.t.c).

    + +

    Parameters

    +
      +
    • + +

      DCSTypes#Vec2 PointVec2 : +2D-coordinates of the point the map object is closest to. The distance between the point and the map object must not be greater than 2000 meters. Object id is not used here because Mission Editor doesn't support map object identificators.

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      +

    Return value

    @@ -2266,24 +3020,169 @@ The DCS task structure.

    -GROUP:TaskAttackUnit(The, AttackUnit) +GROUP:TaskAttackUnit(AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack)
    -

    Attack the Unit.

    +

    (AIR) Attack the Unit.

    Parameters

    • -

      Unit#UNIT The : -unit.

      +

      Unit#UNIT AttackUnit : +The unit.

    • -

      AttackUnit :

      +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

      #boolean AttackQtyLimit : +(optional) The flag determines how to interpret attackQty parameter. If the flag is true then attackQty is a limit on maximal attack quantity for "AttackGroup" and "AttackUnit" tasks. If the flag is false then attackQty is a desired attack quantity for "Bombing" and "BombingRunway" tasks.

      + +
    • +
    • + +

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

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:TaskBombing(PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) + +
    +
    + +

    (AIR) Delivering weapon at the point on the ground.

    + +

    Parameters

    +
      +
    • + +

      DCSTypes#Vec2 PointVec2 : +2D-coordinates of the point to deliver weapon at.

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    +

    Return value

    + +

    DCSTask#Task: +The DCS task structure.

    + +
    +
    +
    +
    + + +GROUP:TaskBombingRunway(Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) + +
    +
    + +

    (AIR) Delivering weapon on the runway.

    + +

    Parameters

    +
      +
    • + +

      Airbase#AIRBASE Airbase : +Airbase to attack.

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

      + +
    • +
    • + +

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

    @@ -2298,24 +3197,19 @@ The DCS task structure.

    -GROUP:TaskCombo(<, DCSTasks) +GROUP:TaskCombo(DCSTasks)
    -

    Return a Combo Task taking an array of Tasks

    +

    Return a Combo Task taking an array of Tasks.

    -

    Parameters

    +

    Parameter

    @@ -2335,7 +3229,7 @@ CSTask#Task> DCSTasks

    -

    Return a condition section for a controlled task

    +

    Return a condition section for a controlled task.

    Parameters

      @@ -2366,9 +3260,8 @@ CSTask#Task> DCSTasks

    • -

      #number lastWayPoint :

      - -

      return DCSTask#Task

      +

      #number lastWayPoint : +return DCSTask#Task

    @@ -2383,7 +3276,7 @@ CSTask#Task> DCSTasks

    -

    Return a Controlled Task taking a Task and a TaskCondition

    +

    Return a Controlled Task taking a Task and a TaskCondition.

    Parameters

      @@ -2408,8 +3301,8 @@ CSTask#Task> DCSTasks

      - -GROUP:TaskEmbarkToTransportAtVec2(Point, Radius) + +GROUP:TaskEmbarkToTransport(Point, Radius)
      @@ -2441,13 +3334,13 @@ The DCS task structure.

      - -GROUP:TaskEmbarkingAtVec2(Point, Duration, EmbarkingGroup) + +GROUP:TaskEmbarking(Point, Duration, EmbarkingGroup)
      -

      Move the group to a Vec2 Point, wait for a defined duration and embark a group.

      +

      (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group.

      Parameters

        @@ -2480,20 +3373,134 @@ The DCS task structure

        - -GROUP:TaskFireAtPoint(The, Radius, PointVec2) + +GROUP:TaskEscort(EscortGroup, PointVec3, LastWaypointIndex, EngagementDistanceMax, TargetTypes, FollowGroup, EngagementDistance)
        -

        Fires at a VEC2 point.

        +

        (AIR) Escort another airborne group.

        + + +

        The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +The unit / group will also protect that group from threats of specified types.

        Parameters

        • -

          DCSTypes#Vec2 The : -point to fire at.

          +

          Group#GROUP EscortGroup : +The group to be escorted.

          + +
        • +
        • + +

          DCSTypes#Vec3 PointVec3 : +Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around.

          + +
        • +
        • + +

          #number LastWaypointIndex : +Detach waypoint of another group. Once reached the unit / group Follow task is finished.

          + +
        • +
        • + +

          #number EngagementDistanceMax : +Maximal distance from escorted group to threat. If the threat is already engaged by escort escort will disengage if the distance becomes greater than 1.5 * engagementDistMax.

          + +
        • +
        • + +

          DCSTypes#AttributeNameArray TargetTypes : +Array of AttributeName that is contains threat categories allowed to engage.

          + +
        • +
        • + +

          FollowGroup :

          + +
        • +
        • + +

          EngagementDistance :

          + +
        • +
        +

        Return value

        + +

        DCSTask#Task: +The DCS task structure.

        + +
        +
        +
        +
        + + +GROUP:TaskFAC_AttackGroup(AttackGroup, WeaponType, Designation, Datalink) + +
        +
        + +

        (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction.

        + + +

        The killer is player-controlled allied CAS-aircraft that is in contact with the FAC. +If the task is assigned to the group lead unit will be a FAC.

        + +

        Parameters

        +
          +
        • + +

          Group#GROUP AttackGroup : +Target GROUP.

          + +
        • +
        • + +

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

          + +
        • +
        • + +

          DCSTypes#AI.Task.Designation Designation : +(optional) Designation type.

          + +
        • +
        • + +

          #boolean Datalink : +(optional) Allows to use datalink to send the target information to attack aircraft. Enabled by default.

          + +
        • +
        +

        Return value

        + +

        DCSTask#Task: +The DCS task structure.

        + +
        +
        +
        +
        + + +GROUP:TaskFireAtPoint(PointVec2, Radius) + +
        +
        + +

        (GROUND) Fire at a VEC2 point until ammunition is finished.

        + +

        Parameters

        +
          +
        • + +

          DCSTypes#Vec2 PointVec2 : +The point to fire at.

        • @@ -2502,9 +3509,47 @@ point to fire at.

          The radius of the zone to deploy the fire at.

        • +
        +

        Return value

        + +

        DCSTask#Task: +The DCS task structure.

        + +
        +
        +
        +
        + + +GROUP:TaskFollow(FollowGroup, PointVec3, LastWaypointIndex) + +
        +
        + +

        (AIR) Following another airborne group.

        + + +

        The unit / group will follow lead unit of another group, wingmens of both groups will continue following their leaders. +If another group is on land the unit / group will orbit around.

        + +

        Parameters

        +
        • -

          PointVec2 :

          +

          Group#GROUP FollowGroup : +The group to be followed.

          + +
        • +
        • + +

          DCSTypes#Vec3 PointVec3 : +Position of the unit / lead unit of the group relative lead unit of another group in frame reference oriented by course of lead unit of another group. If another group is on land the unit / group will orbit around.

          + +
        • +
        • + +

          #number LastWaypointIndex : +Detach waypoint of another group. Once reached the unit / group Follow task is finished.

        @@ -2554,13 +3599,31 @@ The DCS task structure.

        + +GROUP:TaskHold() + +
        +
        + +

        (GROUND) Hold ground group from moving.

        + +

        Return value

        + +

        DCSTask#Task: +The DCS task structure.

        + +
        +
        +
        +
        + GROUP:TaskHoldPosition(Duration)
        -

        Hold position at the current position of the first unit of the group.

        +

        (AIR) Hold position at the current position of the first unit of the group.

        Parameter

          @@ -2587,7 +3650,10 @@ self

          -

          Land the group at a Vec2Point.

          +

          (AIR HELICOPTER) Landing at the ground.

          + + +

          For helicopters only.

          Parameters

            @@ -2620,7 +3686,7 @@ self

            -

            Land the group at a @{Zone#ZONE).

            +

            (AIR) Land the group at a @{Zone#ZONE_RADIUS).

            Parameters

              @@ -2658,7 +3724,7 @@ self

              -

              Return a Misson task from a mission template.

              +

              (AIR + GROUND) Return a mission task from a mission template.

              Parameter

                @@ -2685,7 +3751,7 @@ A table containing the mission task.

                -

                Orbit at the current position of the first unit of the group at a specified alititude

                +

                (AIR) Orbit at the current position of the first unit of the group at a specified alititude.

                Parameters

                  @@ -2718,7 +3784,7 @@ self

                  -

                  Orbit at a specified position at a specified alititude during a specified duration with a specified speed.

                  +

                  (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.

                  Parameters

                    @@ -2751,6 +3817,27 @@ self

                    + +GROUP:TaskRefueling() + +
                    +
                    + +

                    (AIR) Refueling from the nearest tanker.

                    + + +

                    No parameters.

                    + +

                    Return value

                    + +

                    DCSTask#Task: +The DCS task structure.

                    + +
                    +
                    +
                    +
                    + GROUP:TaskRoute(Points) @@ -2784,7 +3871,7 @@ A table of route points.

                    -

                    Make the DCS Group to fly to a given point and hover.

                    +

                    (AIR + GROUND) Make the Group move to fly to a given point.

                    Parameters

                      @@ -2817,7 +3904,7 @@ self

                      -

                      Make the DCS Group to fly to a given point and hover.

                      +

                      (AIR + GROUND) Make the Group move to a given point.

                      Parameters

                        @@ -2850,7 +3937,7 @@ self

                        -

                        Route the group to a given zone.

                        +

                        (AIR + GROUND) Route the group to a given zone.

                        The group final destination point can be randomized. @@ -2895,7 +3982,7 @@ The formation string.

                        -

                        Return a WrappedAction Task taking a Command

                        +

                        Return a WrappedAction Task taking a Command.

                        Parameters

                        @@ -3073,10 +4155,6 @@ The waypoint function to be called when the group moves over the waypoint. The w
                    -

                    Type WaitTime

                    - -

                    Type list

                    - diff --git a/Moose Training/Documentation/GroupSet.html b/Moose Training/Documentation/GroupSet.html index 20bf94a0d..e0ae7f72c 100644 --- a/Moose Training/Documentation/GroupSet.html +++ b/Moose Training/Documentation/GroupSet.html @@ -17,6 +17,7 @@ index
    + + + + @@ -198,13 +207,7 @@ The following iterator methods are currently available within the GROUPSET:

    - - - - - + @@ -219,12 +222,6 @@ The following iterator methods are currently available within the GROUPSET:

    - - - -
    GROUP:Destroy()

    Destroys the DCS Group and all of its DCS Units.

    +
    GROUP:EnRouteTaskAWACS() +

    (AIR) Aircraft will act as an AWACS for friendly units (will provide them with information about contacts).

    +
    GROUP:EnRouteTaskEWR() +

    (GROUND) Ground unit (EW-radar) will act as an EWR for friendly units (will provide them with information about contacts).

    +
    GROUP:EnRouteTaskEngageGroup(AttackGroup, Priority, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit) +

    (AIR) Engaging a group.

    +
    GROUP:EnRouteTaskEngageTargets(Distance, TargetTypes, Priority) +

    (AIR) Engaging targets of defined types.

    +
    GROUP:EnRouteTaskEngageUnit(AttackUnit, Priority, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack) +

    (AIR) Attack the Unit.

    +
    GROUP:EnRouteTaskFAC(Radius, Priority) +

    (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose a targets (enemy ground group) around as well as other assigned targets.

    +
    GROUP:EnRouteTaskFAC_EngageGroup(AttackGroup, Priority, WeaponType, Designation, Datalink) +

    (AIR + GROUND) The task makes the group/unit a FAC and lets the FAC to choose the target (enemy ground group) as well as other assigned targets.

    +
    GROUP:EnRouteTaskTanker() +

    (AIR) Aircraft will act as a tanker for friendly units.

    GROUP:GetCategory() -

    Returns category of the DCS Group.

    +

    Returns category of the DCS Group.

    GROUP:IsAlive()

    Returns if the DCS Group is alive.

    +
    GROUP:IsCompletelyInZone(Zone) +

    Returns true if all units of the group are within a Zone.

    GROUP:IsHelicopter()

    Returns if the DCS Group contains Helicopters.

    +
    GROUP:IsNotInZone(Zone) +

    Returns true if none of the group units of the group are within a Zone.

    +
    GROUP:IsPartlyInZone(Zone) +

    Returns true if some units of the group are within a Zone.

    GROUP:TaskAttackGroup(AttackGroup)GROUP:TaskAttackGroup(AttackGroup, WeaponType, WeaponExpend, AttackQty, Direction, Altitude, AttackQtyLimit) -

    Attack a Group.

    +

    (AIR) Attack a Group.

    GROUP:TaskAttackUnit(The, AttackUnit)GROUP:TaskAttackMapObject(PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) -

    Attack the Unit.

    +

    (AIR) Attacking the map object (building, structure, e.t.c).

    GROUP:TaskCombo(<, DCSTasks)GROUP:TaskAttackUnit(AttackUnit, WeaponType, WeaponExpend, AttackQty, Direction, AttackQtyLimit, GroupAttack) -

    Return a Combo Task taking an array of Tasks

    +

    (AIR) Attack the Unit.

    +
    GROUP:TaskBombing(PointVec2, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) +

    (AIR) Delivering weapon at the point on the ground.

    +
    GROUP:TaskBombingRunway(Airbase, WeaponType, WeaponExpend, AttackQty, Direction, GroupAttack) +

    (AIR) Delivering weapon on the runway.

    +
    GROUP:TaskCombo(DCSTasks) +

    Return a Combo Task taking an array of Tasks.

    GROUP:TaskCondition(time, userFlag, userFlagValue, condition, duration, lastWayPoint) -

    Return a condition section for a controlled task

    +

    Return a condition section for a controlled task.

    GROUP:TaskControlled(DCSTask, DCSStopCondition) -

    Return a Controlled Task taking a Task and a TaskCondition

    +

    Return a Controlled Task taking a Task and a TaskCondition.

    GROUP:TaskEmbarkToTransportAtVec2(Point, Radius)GROUP:TaskEmbarkToTransport(Point, Radius)

    Move to a defined Vec2 Point, and embark to a group when arrived within a defined Radius.

    GROUP:TaskEmbarkingAtVec2(Point, Duration, EmbarkingGroup)GROUP:TaskEmbarking(Point, Duration, EmbarkingGroup) -

    Move the group to a Vec2 Point, wait for a defined duration and embark a group.

    +

    (AIR) Move the group to a Vec2 Point, wait for a defined duration and embark a group.

    GROUP:TaskFireAtPoint(The, Radius, PointVec2)GROUP:TaskEscort(EscortGroup, PointVec3, LastWaypointIndex, EngagementDistanceMax, TargetTypes, FollowGroup, EngagementDistance) -

    Fires at a VEC2 point.

    +

    (AIR) Escort another airborne group.

    +
    GROUP:TaskFAC_AttackGroup(AttackGroup, WeaponType, Designation, Datalink) +

    (AIR + GROUND) The task makes the group/unit a FAC and orders the FAC to control the target (enemy ground group) destruction.

    +
    GROUP:TaskFireAtPoint(PointVec2, Radius) +

    (GROUND) Fire at a VEC2 point until ammunition is finished.

    +
    GROUP:TaskFollow(FollowGroup, PointVec3, LastWaypointIndex) +

    (AIR) Following another airborne group.

    GROUP:TaskFunction(WayPoint, WayPointIndex, FunctionString, FunctionArguments) +
    GROUP:TaskHold() +

    (GROUND) Hold ground group from moving.

    GROUP:TaskHoldPosition(Duration) -

    Hold position at the current position of the first unit of the group.

    +

    (AIR) Hold position at the current position of the first unit of the group.

    GROUP:TaskLandAtVec2(Point, Duration) -

    Land the group at a Vec2Point.

    +

    (AIR HELICOPTER) Landing at the ground.

    GROUP:TaskLandAtZone(Zone, Duration, RandomPoint) -

    Land the group at a @{Zone#ZONE).

    +

    (AIR) Land the group at a @{Zone#ZONE_RADIUS).

    GROUP:TaskMission(TaskMission) -

    Return a Misson task from a mission template.

    +

    (AIR + GROUND) Return a mission task from a mission template.

    GROUP:TaskOrbitCircle(Altitude, Speed) -

    Orbit at the current position of the first unit of the group at a specified alititude

    +

    (AIR) Orbit at the current position of the first unit of the group at a specified alititude.

    GROUP:TaskOrbitCircleAtVec2(Point, Altitude, Speed) -

    Orbit at a specified position at a specified alititude during a specified duration with a specified speed.

    +

    (AIR) Orbit at a specified position at a specified alititude during a specified duration with a specified speed.

    +
    GROUP:TaskRefueling() +

    (AIR) Refueling from the nearest tanker.

    GROUP:TaskRouteToVec2(Point, Speed) -

    Make the DCS Group to fly to a given point and hover.

    +

    (AIR + GROUND) Make the Group move to fly to a given point.

    GROUP:TaskRouteToVec3(Point, Speed) -

    Make the DCS Group to fly to a given point and hover.

    +

    (AIR + GROUND) Make the Group move to a given point.

    GROUP:TaskRouteToZone(Zone, Randomize, Speed, Formation) -

    Route the group to a given zone.

    +

    (AIR + GROUND) Route the group to a given zone.

    GROUP:TaskWrappedAction(DCSCommand, Index) -

    Return a WrappedAction Task taking a Command

    +

    Return a WrappedAction Task taking a Command.

    GROUP:WayPointExecute(WayPoint, The, WaitTime)GROUP:WayPointExecute(WayPoint, WaitTime)

    Executes the WayPoint plan.

    GROUPSET:FilterStart()

    Starts the filtering.

    +
    GROUPSET:FindGroup(GroupName) +

    Finds a Group based on the Group Name.

    GROUPSET:FindUnit(GroupName) -

    Finds a Group based on the Group Name.

    -
    GROUPSET:ForEachUnit(IteratorFunction, ...)GROUPSET:ForEachGroup(IteratorFunction, ...)

    Interate the GROUPSET and call an interator function for each alive GROUP, providing the GROUP and optional parameters.

    GROUPSET:New()

    Creates a new GROUPSET object, building a set of groups belonging to a coalitions, categories, countries, types or with defined prefix names.

    -
    GROUPSET.Units -
    @@ -473,6 +470,32 @@ self

    + +GROUPSET:FindGroup(GroupName) + +
    +
    + +

    Finds a Group based on the Group Name.

    + +

    Parameter

    +
      +
    • + +

      #string GroupName :

      + +
    • +
    +

    Return value

    + +

    Group#GROUP: +The found Group.

    + +
    +
    +
    +
    + GROUPSET:FindInDatabase(Event) @@ -512,34 +535,8 @@ The GROUP

    - -GROUPSET:FindUnit(GroupName) - -
    -
    - -

    Finds a Group based on the Group Name.

    - -

    Parameter

    -
      -
    • - -

      #string GroupName :

      - -
    • -
    -

    Return value

    - -

    Group#GROUP: -The found Group.

    - -
    -
    -
    -
    - - -GROUPSET:ForEachUnit(IteratorFunction, ...) + +GROUPSET:ForEachGroup(IteratorFunction, ...)
    @@ -613,20 +610,6 @@ self

    -- Define a new GROUPSET Object. This DBObject will contain a reference to all alive GROUPS.
     DBObject = GROUPSET:New()
    -
    -
    -
    -
    - - - -GROUPSET.Units - -
    -
    - - -
    diff --git a/Moose Training/Documentation/MISSION.html b/Moose Training/Documentation/MISSION.html index 785f9854a..977eb7641 100644 --- a/Moose Training/Documentation/MISSION.html +++ b/Moose Training/Documentation/MISSION.html @@ -17,6 +17,7 @@ index
      +
    • Airbase
    • Base
    • CARGO
    • CleanUp
    • @@ -50,6 +51,7 @@
    • Mission
    • NOTASK
    • PICKUPTASK
    • +
    • Point
    • ROUTETASK
    • STAGE
    • Scheduler
    • @@ -57,6 +59,7 @@
    • Sead
    • Set
    • Spawn
    • +
    • Static
    • StaticObject
    • TASK
    • Unit
    • @@ -70,11 +73,11 @@

      Module Spawn

      -

      Dynamic spawning of groups (and units).

      +

      This module contains the SPAWN class.

      -

      #SPAWN class

      +

      1) Spawn#SPAWN class, extends Base#BASE

      The #SPAWN class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned. For each group to be spawned, within the mission editor, a group has to be created with the "late activation flag" set. We call this group the "Spawn Template" of the SPAWN object. A reference to this Spawn Template needs to be provided when constructing the SPAWN object, by indicating the name of the group within the mission editor in the constructor methods.

      @@ -101,7 +104,7 @@ Groups will follow the following naming structure when spawned at run-time:

    • When designing a mission, NEVER name groups using a "#" within the name of the group Spawn Template(s), or the SPAWN module logic won't work anymore.
    -

    SPAWN construction methods:

    +

    1.1) SPAWN construction methods

    Create a new SPAWN object with the SPAWN.New or the SPAWN.NewWithAlias methods: