diff --git a/Embedded/Moose_Embedded.lua b/Embedded/Moose_Embedded.lua index 91d90b24f..90fdd181c 100644 --- a/Embedded/Moose_Embedded.lua +++ b/Embedded/Moose_Embedded.lua @@ -450,14 +450,14 @@ end do -- THE MAIN FUNCTION -- Accessed 100 times/sec. routines.main = function() - timer.scheduleFunction(routines.main, {}, timer.getTime() + 0.1) --reschedule first in case of Lua error + timer.scheduleFunction(routines.main, {}, timer.getTime() + 2) --reschedule first in case of Lua error ---------------------------------------------------------------------------------------------------------- --area to add new stuff in routines.do_scheduled_functions() end -- end of routines.main - timer.scheduleFunction(routines.main, {}, timer.getTime() + 0.1) + timer.scheduleFunction(routines.main, {}, timer.getTime() + 2) end @@ -2578,7 +2578,58 @@ end env.info(( 'Init: Scripts Loaded v1.1' )) ---- The BASE class for all the classes defined within MOOSE. +--- BASE classes. +-- +-- @{#BASE} class +-- ============== +-- The @{#BASE} class is the super class for most of the classes defined within MOOSE. +-- +-- It handles: +-- +-- * The construction and inheritance of child classes. +-- * The tracing of objects during mission execution within the DCS.log file (under saved games folder). +-- +-- Note: Normally you would not use the BASE class unless you are extending the MOOSE framework with new classes. +-- +-- BASE Trace functionality +-- ======================== +-- The BASE class contains trace methods to trace progress within a mission execution of a certain object. +-- Note that these trace methods are inherited by each MOOSE class interiting BASE. +-- As such, each object created from derived class from BASE can use the tracing functions to trace its execution. +-- +-- Trace a function call +-- --------------------- +-- There are basically 3 types of tracing methods available within BASE: +-- +-- * @{#BASE.F}: Trace the beginning of a function and its given parameters. +-- * @{#BASE.T}: Trace further logic within a function giving optional variables or parameters. +-- * @{#BASE.E}: Trace an execption within a function giving optional variables or parameters. An exception will always be traced. +-- +-- Tracing levels +-- -------------- +-- There are 3 tracing levels within MOOSE. +-- These tracing levels were defined to avoid bulks of tracing to be generated by lots of objects. +-- +-- As such, the F and T methods have additional variants to trace level 2 and 3 respectively: +-- +-- * @{#BASE.F2}: Trace the beginning of a function and its given parameters with tracing level 2. +-- * @{#BASE.F3}: Trace the beginning of a function and its given parameters with tracing level 3. +-- * @{#BASE.T2}: Trace further logic within a function giving optional variables or parameters with tracing level 2. +-- * @{#BASE.T3}: Trace further logic within a function giving optional variables or parameters with tracing level 3. +-- +-- BASE Inheritance support +-- ======================== +-- The following methods are available to support inheritance: +-- +-- * @{#BASE.Inherit}: Inherits from a class. +-- * @{#BASE.Inherited}: Returns the parent class from the class. +-- +-- Future +-- ====== +-- Further methods may be added to BASE whenever there is a need to make "overall" functions available within MOOSE. +-- +-- ==== +-- -- @module Base -- @author FlightControl @@ -5218,9 +5269,10 @@ function ZONE:GetRandomPointVec2() local Point = {} local Zone = trigger.misc.getZone( self.ZoneName ) - - Point.x = Zone.point.x + math.random( Zone.radius * -1, Zone.radius ) - Point.y = Zone.point.z + math.random( Zone.radius * -1, Zone.radius ) + + 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; self:T( { Zone, Point } ) @@ -5237,8 +5289,67 @@ function ZONE:GetRadius() return Zone.radius end ---- Administers the Initial Sets of the Mission Templates as defined within the Mission Editor. --- Administers the Spawning of new Groups within the DCSRTE and administers these new Groups within the DATABASE object(s). +--- Manage sets of units and groups. +-- +-- @{#Database} class +-- ================== +-- Mission designers can use the DATABASE class to build sets of units belonging to certain: +-- +-- * Coalitions +-- * Categories +-- * Countries +-- * Unit types +-- * Starting with certain prefix strings. +-- +-- This list will grow over time. Planned developments are to include filters and iterators. +-- Additional filters will be added around @{Zone#ZONEs}, Radiuses, Active players, ... +-- More iterators will be implemented in the near future ... +-- +-- Administers the Initial Sets of the Mission Templates as defined within the Mission Editor. +-- +-- DATABASE construction methods: +-- ================================= +-- Create a new DATABASE object with the @{#DATABASE.New} method: +-- +-- * @{#DATABASE.New}: Creates a new DATABASE object. +-- +-- +-- DATABASE filter criteria: +-- ========================= +-- You can set filter criteria to define the set of units within the database. +-- Filter criteria are defined by: +-- +-- * @{#DATABASE.FilterCoalitions}: Builds the DATABASE with the units belonging to the coalition(s). +-- * @{#DATABASE.FilterCategories}: Builds the DATABASE with the units belonging to the category(ies). +-- * @{#DATABASE.FilterTypes}: Builds the DATABASE with the units belonging to the unit type(s). +-- * @{#DATABASE.FilterCountries}: Builds the DATABASE with the units belonging to the country(ies). +-- * @{#DATABASE.FilterUnitPrefixes}: Builds the DATABASE with the units starting with the same prefix string(s). +-- +-- Once the filter criteria have been set for the DATABASE, you can start filtering using: +-- +-- * @{#DATABASE.FilterStart}: Starts the filtering of the units within the database. +-- +-- Planned filter criteria within development are (so these are not yet available): +-- +-- * @{#DATABASE.FilterGroupPrefixes}: Builds the DATABASE with the groups of the units starting with the same prefix string(s). +-- * @{#DATABASE.FilterZones}: Builds the DATABASE with the units within a @{Zone#ZONE}. +-- +-- +-- DATABASE iterators: +-- =================== +-- Once the filters have been defined and the DATABASE has been built, you can iterate the database with the available iterator methods. +-- The iterator methods will walk the DATABASE set, and call for each element within the set a function that you provide. +-- The following iterator methods are currently available within the DATABASE: +-- +-- * @{#DATABASE.ForEachAliveUnit}: Calls a function for each alive unit it finds within the DATABASE. +-- +-- Planned iterators methods in development are (so these are not yet available): +-- +-- * @{#DATABASE.ForEachUnit}: Calls a function for each unit contained within the DATABASE. +-- * @{#DATABASE.ForEachGroup}: Calls a function for each group contained within the DATABASE. +-- * @{#DATABASE.ForEachUnitInZone}: Calls a function for each unit within a certain zone contained within the DATABASE. +-- +-- ==== -- @module Database -- @author FlightControl @@ -5248,7 +5359,7 @@ Include.File( "Menu" ) Include.File( "Group" ) Include.File( "Event" ) ---- The DATABASE class +--- DATABASE class -- @type DATABASE -- @extends Base#BASE DATABASE = { @@ -5328,7 +5439,7 @@ end -- @param #DATABASE self -- @param #string Coalitions Can take the following values: "red", "blue", "neutral". -- @return #DATABASE self -function DATABASE:FilterCoalition( Coalitions ) +function DATABASE:FilterCoalitions( Coalitions ) if not self.Filter.Coalitions then self.Filter.Coalitions = {} end @@ -5346,7 +5457,7 @@ end -- @param #DATABASE self -- @param #string Categories Can take the following values: "plane", "helicopter", "ground", "ship". -- @return #DATABASE self -function DATABASE:FilterCategory( Categories ) +function DATABASE:FilterCategories( Categories ) if not self.Filter.Categories then self.Filter.Categories = {} end @@ -5364,7 +5475,7 @@ end -- @param #DATABASE self -- @param #string Types Can take those type strings known within DCS world. -- @return #DATABASE self -function DATABASE:FilterType( Types ) +function DATABASE:FilterTypes( Types ) if not self.Filter.Types then self.Filter.Types = {} end @@ -5400,7 +5511,7 @@ end -- @param #DATABASE self -- @param #string Prefixes The prefix of which the unit name starts with. -- @return #DATABASE self -function DATABASE:FilterUnitPrefix( Prefixes ) +function DATABASE:FilterUnitPrefixes( Prefixes ) if not self.Filter.UnitPrefixes then self.Filter.UnitPrefixes = {} end @@ -5418,7 +5529,7 @@ end -- @param #DATABASE self -- @param #string Prefixes The prefix of which the group name where the unit belongs to starts with. -- @return #DATABASE self -function DATABASE:FilterGroupPrefix( Prefixes ) +function DATABASE:FilterGroupPrefixes( Prefixes ) if not self.Filter.GroupPrefixes then self.Filter.GroupPrefixes = {} end @@ -5443,10 +5554,10 @@ function DATABASE:FilterStart() for UnitRegistrationID, UnitRegistration in pairs( _DATABASE.Units ) do self:T( UnitRegistration ) local DCSUnit = Unit.getByName( UnitRegistration.UnitName ) - if self:IsIncludeDCSUnit( DCSUnit ) then + if self:_IsIncludeDCSUnit( DCSUnit ) then self.DCSUnits[DCSUnit:getName()] = DCSUnit end - if self:IsAliveDCSUnit( DCSUnit ) then + if self:_IsAliveDCSUnit( DCSUnit ) then self.DCSUnitsAlive[DCSUnit:getName()] = DCSUnit end end @@ -5457,155 +5568,6 @@ function DATABASE:FilterStart() return self end ---- --- @param #DATABASE self --- @param DCSUnit#Unit DCSUnit --- @return #DATABASE self -function DATABASE:IsIncludeDCSUnit( DCSUnit ) - self:F( DCSUnit ) - local DCSUnitInclude = true - - if self.Filter.Coalitions then - local DCSUnitCoalition = false - for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do - self:T( { "Coalition:", DCSUnit:getCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } ) - if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == DCSUnit:getCoalition() then - DCSUnitCoalition = true - end - end - DCSUnitInclude = DCSUnitInclude and DCSUnitCoalition - end - - if self.Filter.Categories then - local DCSUnitCategory = false - for CategoryID, CategoryName in pairs( self.Filter.Categories ) do - self:T( { "Category:", DCSUnit:getDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } ) - if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == DCSUnit:getDesc().category then - DCSUnitCategory = true - end - end - DCSUnitInclude = DCSUnitInclude and DCSUnitCategory - end - - if self.Filter.Types then - local DCSUnitType = false - for TypeID, TypeName in pairs( self.Filter.Types ) do - self:T( { "Type:", DCSUnit:getTypeName(), TypeName } ) - if TypeName == DCSUnit:getTypeName() then - DCSUnitType = true - end - end - DCSUnitInclude = DCSUnitInclude and DCSUnitType - end - - if self.Filter.Countries then - local DCSUnitCountry = false - for CountryID, CountryName in pairs( self.Filter.Countries ) do - self:T( { "Country:", DCSUnit:getCountry(), CountryName } ) - if country.id[CountryName] == DCSUnit:getCountry() then - DCSUnitCountry = true - end - end - DCSUnitInclude = DCSUnitInclude and DCSUnitCountry - end - - if self.Filter.UnitPrefixes then - local DCSUnitPrefix = false - for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do - self:T( { "Unit Prefix:", string.find( DCSUnit:getName(), UnitPrefix, 1 ), UnitPrefix } ) - if string.find( DCSUnit:getName(), UnitPrefix, 1 ) then - DCSUnitPrefix = true - end - end - DCSUnitInclude = DCSUnitInclude and DCSUnitPrefix - end - - self:T( DCSUnitInclude ) - return DCSUnitInclude -end - ---- --- @param #DATABASE self --- @param DCSUnit#Unit DCSUnit --- @return #DATABASE self -function DATABASE:IsAliveDCSUnit( DCSUnit ) - self:F( DCSUnit ) - local DCSUnitAlive = false - if DCSUnit and DCSUnit:isExist() and DCSUnit:isActive() then - if self.DCSUnits[DCSUnit:getName()] then - DCSUnitAlive = true - end - end - self:T( DCSUnitAlive ) - return DCSUnitAlive -end - - -function DATABASE:ScanEnvironment() - self:F() - - self.Navpoints = {} - self.Units = {} - --Build routines.db.units and self.Navpoints - for coa_name, coa_data in pairs(env.mission.coalition) do - - if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then - --self.Units[coa_name] = {} - - ---------------------------------------------- - -- build nav points DB - self.Navpoints[coa_name] = {} - if coa_data.nav_points then --navpoints - for nav_ind, nav_data in pairs(coa_data.nav_points) do - - if type(nav_data) == 'table' then - self.Navpoints[coa_name][nav_ind] = routines.utils.deepCopy(nav_data) - - self.Navpoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory. - self.Navpoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it. - self.Navpoints[coa_name][nav_ind]['point']['x'] = nav_data.x - self.Navpoints[coa_name][nav_ind]['point']['y'] = 0 - self.Navpoints[coa_name][nav_ind]['point']['z'] = nav_data.y - end - end - end - ------------------------------------------------- - if coa_data.country then --there is a country table - for cntry_id, cntry_data in pairs(coa_data.country) do - - local countryName = string.lower(cntry_data.name) - --self.Units[coa_name][countryName] = {} - --self.Units[coa_name][countryName]["countryId"] = cntry_data.id - - if type(cntry_data) == 'table' then --just making sure - - for obj_type_name, obj_type_data in pairs(cntry_data) do - - if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then --should be an unncessary check - - local category = obj_type_name - - if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's a group! - - --self.Units[coa_name][countryName][category] = {} - - for group_num, GroupTemplate in pairs(obj_type_data.group) do - - if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group - self:_RegisterGroup( GroupTemplate ) - end --if GroupTemplate and GroupTemplate.units then - end --for group_num, GroupTemplate in pairs(obj_type_data.group) do - end --if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then - end --if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then - end --for obj_type_name, obj_type_data in pairs(cntry_data) do - end --if type(cntry_data) == 'table' then - end --for cntry_id, cntry_data in pairs(coa_data.country) do - end --if coa_data.country then --there is a country table - end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then - end --for coa_name, coa_data in pairs(mission.coalition) do - - return self -end --- Instantiate new Groups within the DCSRTE. -- This method expects EXACTLY the same structure as a structure within the ME, and needs 2 additional fields defined: @@ -5700,7 +5662,7 @@ function DATABASE:_EventOnBirth( Event ) self:F( { Event } ) if Event.IniDCSUnit then - if self:IsIncludeDCSUnit( Event.IniDCSUnit ) then + if self:_IsIncludeDCSUnit( Event.IniDCSUnit ) then self.DCSUnits[Event.IniDCSUnitName] = Event.IniDCSUnit self.DCSUnitsAlive[Event.IniDCSUnitName] = Event.IniDCSUnit end @@ -5721,6 +5683,197 @@ function DATABASE:_EventOnDeadOrCrash( Event ) end end +--- Interate the DATABASE and call an interator function for each **alive** unit, providing the Unit and optional parameters. +-- @param #DATABASE self +-- @param #function IteratorFunction The function that will be called when there is an alive unit in the database. The function needs to accept a UNIT parameter. +-- @return #DATABASE self +function DATABASE:ForEachAliveUnit( IteratorFunction, ... ) + self:F( arg ) + + local function CoRoutine() + local Count = 0 + for DCSUnitID, DCSUnit in pairs( self.DCSUnitsAlive ) do + self:T2( DCSUnit ) + IteratorFunction( DCSUnit, unpack( arg ) ) + Count = Count + 1 + if Count % 10 == 0 then + coroutine.yield( false ) + end + end + return true + end + + local co = coroutine.create( CoRoutine ) + + local function Schedule() + + local status, res = coroutine.resume( co ) + self:T( { status, res } ) + + if status == false then + error( res ) + end + if res == false then + timer.scheduleFunction( Schedule, {}, timer.getTime() + 0.001 ) + end + end + + timer.scheduleFunction( Schedule, {}, timer.getTime() + 1 ) + + return self +end + +function DATABASE:ScanEnvironment() + self:F() + + self.Navpoints = {} + self.Units = {} + --Build routines.db.units and self.Navpoints + for coa_name, coa_data in pairs(env.mission.coalition) do + + if (coa_name == 'red' or coa_name == 'blue') and type(coa_data) == 'table' then + --self.Units[coa_name] = {} + + ---------------------------------------------- + -- build nav points DB + self.Navpoints[coa_name] = {} + if coa_data.nav_points then --navpoints + for nav_ind, nav_data in pairs(coa_data.nav_points) do + + if type(nav_data) == 'table' then + self.Navpoints[coa_name][nav_ind] = routines.utils.deepCopy(nav_data) + + self.Navpoints[coa_name][nav_ind]['name'] = nav_data.callsignStr -- name is a little bit more self-explanatory. + self.Navpoints[coa_name][nav_ind]['point'] = {} -- point is used by SSE, support it. + self.Navpoints[coa_name][nav_ind]['point']['x'] = nav_data.x + self.Navpoints[coa_name][nav_ind]['point']['y'] = 0 + self.Navpoints[coa_name][nav_ind]['point']['z'] = nav_data.y + end + end + end + ------------------------------------------------- + if coa_data.country then --there is a country table + for cntry_id, cntry_data in pairs(coa_data.country) do + + local countryName = string.lower(cntry_data.name) + --self.Units[coa_name][countryName] = {} + --self.Units[coa_name][countryName]["countryId"] = cntry_data.id + + if type(cntry_data) == 'table' then --just making sure + + for obj_type_name, obj_type_data in pairs(cntry_data) do + + if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then --should be an unncessary check + + local category = obj_type_name + + if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then --there's a group! + + --self.Units[coa_name][countryName][category] = {} + + for group_num, GroupTemplate in pairs(obj_type_data.group) do + + if GroupTemplate and GroupTemplate.units and type(GroupTemplate.units) == 'table' then --making sure again- this is a valid group + self:_RegisterGroup( GroupTemplate ) + end --if GroupTemplate and GroupTemplate.units then + end --for group_num, GroupTemplate in pairs(obj_type_data.group) do + end --if ((type(obj_type_data) == 'table') and obj_type_data.group and (type(obj_type_data.group) == 'table') and (#obj_type_data.group > 0)) then + end --if obj_type_name == "helicopter" or obj_type_name == "ship" or obj_type_name == "plane" or obj_type_name == "vehicle" or obj_type_name == "static" then + end --for obj_type_name, obj_type_data in pairs(cntry_data) do + end --if type(cntry_data) == 'table' then + end --for cntry_id, cntry_data in pairs(coa_data.country) do + end --if coa_data.country then --there is a country table + end --if coa_name == 'red' or coa_name == 'blue' and type(coa_data) == 'table' then + end --for coa_name, coa_data in pairs(mission.coalition) do + + return self +end + + +--- +-- @param #DATABASE self +-- @param DCSUnit#Unit DCSUnit +-- @return #DATABASE self +function DATABASE:_IsIncludeDCSUnit( DCSUnit ) + self:F( DCSUnit ) + local DCSUnitInclude = true + + if self.Filter.Coalitions then + local DCSUnitCoalition = false + for CoalitionID, CoalitionName in pairs( self.Filter.Coalitions ) do + self:T( { "Coalition:", DCSUnit:getCoalition(), self.FilterMeta.Coalitions[CoalitionName], CoalitionName } ) + if self.FilterMeta.Coalitions[CoalitionName] and self.FilterMeta.Coalitions[CoalitionName] == DCSUnit:getCoalition() then + DCSUnitCoalition = true + end + end + DCSUnitInclude = DCSUnitInclude and DCSUnitCoalition + end + + if self.Filter.Categories then + local DCSUnitCategory = false + for CategoryID, CategoryName in pairs( self.Filter.Categories ) do + self:T( { "Category:", DCSUnit:getDesc().category, self.FilterMeta.Categories[CategoryName], CategoryName } ) + if self.FilterMeta.Categories[CategoryName] and self.FilterMeta.Categories[CategoryName] == DCSUnit:getDesc().category then + DCSUnitCategory = true + end + end + DCSUnitInclude = DCSUnitInclude and DCSUnitCategory + end + + if self.Filter.Types then + local DCSUnitType = false + for TypeID, TypeName in pairs( self.Filter.Types ) do + self:T( { "Type:", DCSUnit:getTypeName(), TypeName } ) + if TypeName == DCSUnit:getTypeName() then + DCSUnitType = true + end + end + DCSUnitInclude = DCSUnitInclude and DCSUnitType + end + + if self.Filter.Countries then + local DCSUnitCountry = false + for CountryID, CountryName in pairs( self.Filter.Countries ) do + self:T( { "Country:", DCSUnit:getCountry(), CountryName } ) + if country.id[CountryName] == DCSUnit:getCountry() then + DCSUnitCountry = true + end + end + DCSUnitInclude = DCSUnitInclude and DCSUnitCountry + end + + if self.Filter.UnitPrefixes then + local DCSUnitPrefix = false + for UnitPrefixId, UnitPrefix in pairs( self.Filter.UnitPrefixes ) do + self:T( { "Unit Prefix:", string.find( DCSUnit:getName(), UnitPrefix, 1 ), UnitPrefix } ) + if string.find( DCSUnit:getName(), UnitPrefix, 1 ) then + DCSUnitPrefix = true + end + end + DCSUnitInclude = DCSUnitInclude and DCSUnitPrefix + end + + self:T( DCSUnitInclude ) + return DCSUnitInclude +end + +--- +-- @param #DATABASE self +-- @param DCSUnit#Unit DCSUnit +-- @return #DATABASE self +function DATABASE:_IsAliveDCSUnit( DCSUnit ) + self:F( DCSUnit ) + local DCSUnitAlive = false + if DCSUnit and DCSUnit:isExist() and DCSUnit:isActive() then + if self.DCSUnits[DCSUnit:getName()] then + DCSUnitAlive = true + end + end + self:T( DCSUnitAlive ) + return DCSUnitAlive +end + + --- Traces the current database contents in the log ... (for debug reasons). -- @param #DATABASE self -- @return #DATABASE self @@ -11217,7 +11370,10 @@ function CLEANUP:_CleanUpScheduler() end --- Dynamic spawning of groups (and units). --- The SPAWN class allows to spawn dynamically new groups, based on pre-defined initialization settings, modifying the behaviour when groups are spawned. +-- +-- @{#SPAWN} class +-- =============== +-- 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. -- @@ -11239,8 +11395,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. -- --- 1. SPAWN object construction methods: --- ------------------------------------- +-- 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. @@ -11249,8 +11405,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. -- --- 2. SPAWN object initialization methods: --- --------------------------------------- +-- 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. @@ -11260,8 +11416,8 @@ end -- * @{#SPAWN.Array}: Make groups visible before they are actually activated, and order these groups like a batallion in an array. -- * @{#SPAWN.Repeat}: Re-spawn groups when they land at the home base. Similar functions are @{#SPAWN.RepeatOnLanding} and @{#SPAWN.RepeatOnEngineShutDown}. -- --- 2. SPAWN object spawning methods: --- --------------------------------- +-- SPAWN spawning methods: +-- ======================= -- Groups can be spawned at different times and methods: -- -- * @{#SPAWN.Spawn}: Spawn one new group based on the last spawned index. @@ -11273,8 +11429,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. -- --- 3. SPAWN object cleaning: --- ------------------------- +-- 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. @@ -11285,6 +11441,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 @@ -12754,71 +12911,92 @@ function SEAD:EventShot( Event ) end end --- Taking the lead of AI escorting your flight. --- The ESCORT class allows you to interact with escorting AI on your flight and take the lead. +-- +-- @{#ESCORT} class +-- ================ +-- The @{#ESCORT} class allows you to interact with escorting AI on your flight and take the lead. -- Each escorting group can be commanded with a whole set of radio commands (radio menu in your flight, and then F10). -- -- The radio commands will vary according the category of the group. The richest set of commands are with Helicopters and AirPlanes. -- Ships and Ground troops will have a more limited set, but they can provide support through the bombing of targets designated by the other escorts. -- +-- RADIO MENUs that can be created: +-- ================================ -- Find a summary below of the current available commands: -- --- **1. Navigation ...:** Escort group navigation functions: +-- Navigation ...: +-- --------------- +-- Escort group navigation functions: -- --- * **"Join-Up and Follow at x meters":** The escort group fill follow you at about x meters, and they will follow you. --- * **"Flare":** Provides menu commands to let the escort group shoot a flare in the air in a color. --- * **"Smoke":** Provides menu commands to let the escort group smoke the air in a color. Note that smoking is only available for ground and naval troops. +-- * **"Join-Up and Follow at x meters":** The escort group fill follow you at about x meters, and they will follow you. +-- * **"Flare":** Provides menu commands to let the escort group shoot a flare in the air in a color. +-- * **"Smoke":** Provides menu commands to let the escort group smoke the air in a color. Note that smoking is only available for ground and naval troops. -- --- **2. Hold position ...:** Escort group navigation functions: +-- Hold position ...: +-- ------------------ +-- Escort group navigation functions: -- --- * **"At current location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped. --- * **"At client location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped. +-- * **"At current location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped. +-- * **"At client location":** Stops the escort group and they will hover 30 meters above the ground at the position they stopped. -- --- **3. Report targets ...:** Report targets will make the escort group to report any target that it identifies within a 8km range. Any detected target can be attacked using the 4. Attack nearby targets function. (see below). +-- Report targets ...: +-- ------------------- +-- Report targets will make the escort group to report any target that it identifies within a 8km range. Any detected target can be attacked using the 4. Attack nearby targets function. (see below). -- --- * **"Report now":** Will report the current detected targets. --- * **"Report targets on":** Will make the escort group to report detected targets and will fill the "Attack nearby targets" menu list. --- * **"Report targets off":** Will stop detecting targets. +-- * **"Report now":** Will report the current detected targets. +-- * **"Report targets on":** Will make the escort group to report detected targets and will fill the "Attack nearby targets" menu list. +-- * **"Report targets off":** Will stop detecting targets. -- --- **4. Scan targets ...:** Menu items to pop-up the escort group for target scanning. After scanning, the escort group will resume with the mission or defined task. +-- Scan targets ...: +-- ----------------- +-- Menu items to pop-up the escort group for target scanning. After scanning, the escort group will resume with the mission or defined task. -- --- * **"Scan targets 30 seconds":** Scan 30 seconds for targets. --- * **"Scan targets 60 seconds":** Scan 60 seconds for targets. +-- * **"Scan targets 30 seconds":** Scan 30 seconds for targets. +-- * **"Scan targets 60 seconds":** Scan 60 seconds for targets. -- --- **5. Attack targets ...:** This menu item will list all detected targets within a 15km range. Depending on the level of detection (known/unknown) and visuality, the targets type will also be listed. +-- Attack targets ...: +-- ------------------- +-- This menu item will list all detected targets within a 15km range. Depending on the level of detection (known/unknown) and visuality, the targets type will also be listed. -- --- **6. Request assistance from ...:** This menu item will list all detected targets within a 15km range, as with the menu item **Attack Targets**. +-- Request assistance from ...: +-- ---------------------------- +-- This menu item will list all detected targets within a 15km range, as with the menu item **Attack Targets**. -- This menu item allows to request attack support from other escorts supporting the current client group. -- eg. the function allows a player to request support from the Ship escort to attack a target identified by the Plane escort with its Tomahawk missiles. -- eg. the function allows a player to request support from other Planes escorting to bomb the unit with illumination missiles or bombs, so that the main plane escort can attack the area. -- --- **7. ROE ...:** Defines the Rules of Engagement of the escort group when in flight. +-- ROE ...: +-- -------- +-- Sets the Rules of Engagement (ROE) of the escort group when in flight. -- --- * **"Hold Fire":** The escort group will hold fire. --- * **"Return Fire":** The escort group will return fire. --- * **"Open Fire":** The escort group will open fire on designated targets. --- * **"Weapon Free":** The escort group will engage with any target. +-- * **"Hold Fire":** The escort group will hold fire. +-- * **"Return Fire":** The escort group will return fire. +-- * **"Open Fire":** The escort group will open fire on designated targets. +-- * **"Weapon Free":** The escort group will engage with any target. -- --- **8. Evasion ...:** Will define the evasion techniques that the escort group will perform during flight or combat. +-- Evasion ...: +-- ------------ +-- Will define the evasion techniques that the escort group will perform during flight or combat. -- --- * **"Fight until death":** The escort group will have no reaction to threats. --- * **"Use flares, chaff and jammers":** The escort group will use passive defense using flares and jammers. No evasive manoeuvres are executed. --- * **"Evade enemy fire":** The rescort group will evade enemy fire before firing. --- * **"Go below radar and evade fire":** The escort group will perform evasive vertical manoeuvres. +-- * **"Fight until death":** The escort group will have no reaction to threats. +-- * **"Use flares, chaff and jammers":** The escort group will use passive defense using flares and jammers. No evasive manoeuvres are executed. +-- * **"Evade enemy fire":** The rescort group will evade enemy fire before firing. +-- * **"Go below radar and evade fire":** The escort group will perform evasive vertical manoeuvres. -- --- **9. Resume Mission ...:** Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint. +-- Resume Mission ...: +-- ------------------- +-- Escort groups can have their own mission. This menu item will allow the escort group to resume their Mission from a given waypoint. -- Note that this is really fantastic, as you now have the dynamic of taking control of the escort groups, and allowing them to resume their path or mission. -- --- **10. Abort Current Task:** Cancel the current task and rejoin formation. --- --- 1. ESCORT object construction methods. --- -------------------------------------- +-- ESCORT construction methods. +-- ============================ -- Create a new SPAWN object with the @{#ESCORT.New} method: -- -- * @{#ESCORT.New}: Creates a new ESCORT object from a @{Group#GROUP} for a @{Client#CLIENT}, with an optional briefing text. -- --- 2. ESCORT object initialization methods. --- ---------------------------------------- --- The following menus can be setup: +-- ESCORT initialization methods. +-- ============================== +-- The following menus are created within the RADIO MENU of an active unit hosted by a player: -- -- * @{#ESCORT.MenuFollowAt}: Creates a menu to make the escort follow the client. -- * @{#ESCORT.MenuHoldAtEscortPosition}: Creates a menu to hold the escort at its current position. @@ -12832,7 +13010,7 @@ end -- * @{#ESCORT.MenuROE: Creates a menu structure to set the rules of engagement of the escort. -- * @{#ESCORT.MenuEvasion: Creates a menu structure to set the evasion techniques when the escort is under threat. -- * @{#ESCORT.MenuResumeMission}: Creates a menu structure so that the escort can resume from a waypoint. --- +-- -- @module Escort -- @author FlightControl @@ -12842,8 +13020,7 @@ Include.File( "Database" ) Include.File( "Group" ) Include.File( "Zone" ) - ---- ESCORT class +--- -- @type ESCORT -- @extends Base#BASE -- @field Client#CLIENT EscortClient