diff --git a/Moose Development/Moose/Core/Base.lua b/Moose Development/Moose/Core/Base.lua
index e047c76d1..018f2eb02 100644
--- a/Moose Development/Moose/Core/Base.lua
+++ b/Moose Development/Moose/Core/Base.lua
@@ -219,9 +219,9 @@ local _ClassID = 0
BASE = {
ClassName = "BASE",
ClassID = 0,
- _Private = {},
Events = {},
- States = {}
+ States = {},
+ _ = {},
}
--- The Formation Class
@@ -360,7 +360,7 @@ do -- Event Handling
-- @param #BASE self
-- @return #number The @{Event} processing Priority.
function BASE:GetEventPriority()
- return self._Private.EventPriority or 5
+ return self._.EventPriority or 5
end
--- Set the Class @{Event} processing Priority.
@@ -370,7 +370,7 @@ do -- Event Handling
-- @param #number EventPriority The @{Event} processing Priority.
-- @return self
function BASE:SetEventPriority( EventPriority )
- self._Private.EventPriority = EventPriority
+ self._.EventPriority = EventPriority
end
--- Remove all subscribed events
diff --git a/Moose Development/Moose/Core/Database.lua b/Moose Development/Moose/Core/Database.lua
index 3e9eea077..bdf743d0d 100644
--- a/Moose Development/Moose/Core/Database.lua
+++ b/Moose Development/Moose/Core/Database.lua
@@ -44,6 +44,7 @@ DATABASE = {
Templates = {
Units = {},
Groups = {},
+ Statics = {},
ClientsByName = {},
ClientsByID = {},
},
@@ -282,7 +283,7 @@ function DATABASE:Spawn( SpawnTemplate )
SpawnTemplate.CountryID = nil
SpawnTemplate.CategoryID = nil
- self:_RegisterTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID )
+ self:_RegisterGroupTemplate( SpawnTemplate, SpawnCoalitionID, SpawnCategoryID, SpawnCountryID )
self:T3( SpawnTemplate )
coalition.addGroup( SpawnCountryID, SpawnCategoryID, SpawnTemplate )
@@ -318,7 +319,7 @@ end
-- @param #DATABASE self
-- @param #table GroupTemplate
-- @return #DATABASE self
-function DATABASE:_RegisterTemplate( GroupTemplate, CoalitionID, CategoryID, CountryID )
+function DATABASE:_RegisterGroupTemplate( GroupTemplate, CoalitionID, CategoryID, CountryID )
local GroupTemplateName = env.getValueDictByKey(GroupTemplate.name)
@@ -396,6 +397,54 @@ function DATABASE:GetGroupTemplate( GroupName )
return GroupTemplate
end
+--- Private method that registers new Static Templates within the DATABASE Object.
+-- @param #DATABASE self
+-- @param #table GroupTemplate
+-- @return #DATABASE self
+function DATABASE:_RegisterStaticTemplate( StaticTemplate, CoalitionID, CategoryID, CountryID )
+
+ local TraceTable = {}
+
+ local StaticTemplateName = env.getValueDictByKey(StaticTemplate.name)
+
+ self.Templates.Statics[StaticTemplateName] = self.Templates.Statics[StaticTemplateName] or {}
+
+ StaticTemplate.CategoryID = CategoryID
+ StaticTemplate.CoalitionID = CoalitionID
+ StaticTemplate.CountryID = CountryID
+
+ self.Templates.Statics[StaticTemplateName].StaticName = StaticTemplateName
+ self.Templates.Statics[StaticTemplateName].GroupTemplate = StaticTemplate
+ self.Templates.Statics[StaticTemplateName].UnitTemplate = StaticTemplate.units[1]
+ self.Templates.Statics[StaticTemplateName].CategoryID = CategoryID
+ self.Templates.Statics[StaticTemplateName].CoalitionID = CoalitionID
+ self.Templates.Statics[StaticTemplateName].CountryID = CountryID
+
+
+ TraceTable[#TraceTable+1] = "Static"
+ TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].GroupName
+
+ TraceTable[#TraceTable+1] = "Coalition"
+ TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CoalitionID
+ TraceTable[#TraceTable+1] = "Category"
+ TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CategoryID
+ TraceTable[#TraceTable+1] = "Country"
+ TraceTable[#TraceTable+1] = self.Templates.Statics[StaticTemplateName].CountryID
+
+ self:E( TraceTable )
+end
+
+
+--- @param #DATABASE self
+function DATABASE:GetStaticUnitTemplate( StaticName )
+ local StaticTemplate = self.Templates.Statics[StaticName].UnitTemplate
+ StaticTemplate.SpawnCoalitionID = self.Templates.Statics[StaticName].CoalitionID
+ StaticTemplate.SpawnCategoryID = self.Templates.Statics[StaticName].CategoryID
+ StaticTemplate.SpawnCountryID = self.Templates.Statics[StaticName].CountryID
+ return StaticTemplate
+end
+
+
function DATABASE:GetGroupNameFromUnitName( UnitName )
return self.Templates.Units[UnitName].GroupName
end
@@ -725,7 +774,7 @@ function DATABASE:ForEachClient( IteratorFunction, ... )
return self
end
-
+--- @param #DATABASE self
function DATABASE:_RegisterTemplates()
self:F2()
@@ -781,11 +830,18 @@ function DATABASE:_RegisterTemplates()
--self.Units[coa_name][countryName][category] = {}
- for group_num, GroupTemplate in pairs(obj_type_data.group) do
+ for group_num, Template 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:_RegisterTemplate(
- GroupTemplate,
+ if obj_type_name ~= "static" and Template and Template.units and type(Template.units) == 'table' then --making sure again- this is a valid group
+ self:_RegisterGroupTemplate(
+ Template,
+ CoalitionSide,
+ _DATABASECategory[string.lower(CategoryName)],
+ CountryID
+ )
+ else
+ self:_RegisterStaticTemplate(
+ Template,
CoalitionSide,
_DATABASECategory[string.lower(CategoryName)],
CountryID
diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua
index f3bcb4e95..2d206d453 100644
--- a/Moose Development/Moose/Core/Set.lua
+++ b/Moose Development/Moose/Core/Set.lua
@@ -1374,7 +1374,7 @@ function SET_UNIT:ForEachUnitCompletelyInZone( ZoneObject, IteratorFunction, ...
--- @param Core.Zone#ZONE_BASE ZoneObject
-- @param Wrapper.Unit#UNIT UnitObject
function( ZoneObject, UnitObject )
- if UnitObject:IsCompletelyInZone( ZoneObject ) then
+ if UnitObject:IsInZone( ZoneObject ) then
return true
else
return false
diff --git a/Moose Development/Moose/Core/SpawnStatic.lua b/Moose Development/Moose/Core/SpawnStatic.lua
new file mode 100644
index 000000000..9e744d971
--- /dev/null
+++ b/Moose Development/Moose/Core/SpawnStatic.lua
@@ -0,0 +1,178 @@
+--- **Functional** -- Spawn dynamically new @{Static}s in your missions.
+--
+-- 
+--
+-- ====
+--
+-- # Demo Missions
+--
+-- ### [SPAWNSTATIC Demo Missions source code]()
+--
+-- ### [SPAWNSTATIC Demo Missions, only for beta testers]()
+--
+-- ### [ALL Demo Missions pack of the last release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
+--
+-- ====
+--
+-- # YouTube Channel
+--
+-- ### [SPAWNSTATIC YouTube Channel]()
+--
+-- ====
+--
+-- # **API CHANGE HISTORY**
+--
+-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
+--
+-- * **Added** parts are expressed in bold type face.
+-- * _Removed_ parts are expressed in italic type face.
+--
+-- Hereby the change log:
+--
+-- ===
+--
+-- # **AUTHORS and CONTRIBUTIONS**
+--
+-- ### Contributions:
+--
+-- ### Authors:
+--
+-- * **FlightControl**: Design & Programming
+--
+-- @module SpawnStatic
+
+
+
+--- @type SPAWNSTATIC
+-- @extends Core.Base#BASE
+
+
+--- # SPAWNSTATIC class, extends @{Base#BASE}
+--
+-- The SPAWNSTATIC class allows to spawn dynamically new @{Static}s.
+--
+-- There are two modes how SPAWNSTATIC can spawn:
+--
+-- * Through creating a copy of an existing Template @{Static} as defined in the Mission Editor (ME).
+-- * Through the provision of the type name of the Static.
+--
+-- Spawned @{Static}s get **the same name** as the name of the Template Static,
+-- or gets the given name when a Static Type is used.
+-- Newly spawned @{Static}s will get the following naming structure at run-time:
+--
+-- * Spawned @{Static}s will have the name _StaticName_#_nnn_, where _StaticName_ is the name of the **Template Static**,
+-- and _nnn_ is a **counter from 0 to 99999**.
+--
+--
+-- ## SPAWNSTATIC construction methods
+--
+-- Create a new SPAWNSTATIC object with the @{#SPAWNSTATIC.NewFromStatic}() or the @{#SPAWNSTATIC.NewFromType}() methods:
+--
+-- * @{#SPAWNSTATIC.NewFromStatic}(): Creates a new SPAWNSTATIC object given a name that is used as the base of the naming of each spawned Static.
+-- * @{#SPAWNSTATIC.NewFromType}(): Creates a new SPAWNSTATIC object given a type name and a name to be given when spawned.
+--
+-- ## SPAWNSTATIC **Spawn** methods
+--
+-- Groups can be spawned at different times and methods:
+--
+-- * @{#SPAWNSTATIC.SpawnInZone}(): Spawn a new group in a @{Zone}.
+-- * @{#SPAWNSTATIC.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
+-- * @{#SPAWNSTATIC.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
+-- * @{#SPAWNSTATIC.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
+-- * @{#SPAWNSTATIC.SpawnFromUnit}(): Spawn a new group taking the position of a @{Unit}.
+--
+-- @field #SPAWNSTATIC SPAWNSTATIC
+--
+SPAWNSTATIC = {
+ ClassName = "SPAWNSTATIC",
+}
+
+
+--- @type SPAWNSTATIC.SpawnZoneTable
+-- @list SpawnZone
+
+
+--- Creates the main object to spawn a @{Static} defined in the ME.
+-- @param #SPAWNSTATIC self
+-- @param #string SpawnTemplatePrefix is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.
+-- @return #SPAWNSTATIC
+function SPAWNSTATIC:NewFromStatic( SpawnTemplatePrefix, CountryID )
+ local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
+ self:F( { SpawnTemplatePrefix } )
+
+ local TemplateStatic = StaticObject.getByName( SpawnTemplatePrefix )
+ if TemplateStatic then
+ self.SpawnTemplatePrefix = SpawnTemplatePrefix
+ self.CountryID = CountryID
+ self.SpawnIndex = 0
+ else
+ error( "SPAWNSTATIC:New: There is no group declared in the mission editor with SpawnTemplatePrefix = '" .. SpawnTemplatePrefix .. "'" )
+ end
+
+ self:SetEventPriority( 5 )
+
+ return self
+end
+
+--- Creates the main object to spawn a @{Static} based on a type name.
+-- @param #SPAWNSTATIC self
+-- @param #string SpawnTypeName is the name of the type.
+-- @return #SPAWNSTATIC
+function SPAWNSTATIC:NewFromType( SpawnTypeName, SpawnShapeName, SpawnCategory, CountryID )
+ local self = BASE:Inherit( self, BASE:New() ) -- #SPAWNSTATIC
+ self:F( { SpawnTypeName } )
+
+ self.SpawnTypeName = SpawnTypeName
+ self.CountryID = CountryID
+ self.SpawnIndex = 0
+
+ self:SetEventPriority( 5 )
+
+ return self
+end
+
+
+--- Creates a new @{Static} from a POINT_VEC2.
+-- @param #SPAWNSTATIC self
+-- @param Core.Point#POINT_VEC2 PointVec2 The 2D coordinate where to spawn the static.
+-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
+-- @param #string (optional) The name of the new static.
+-- @return #SPAWNSTATIC
+function SPAWNSTATIC:SpawnFromPointVec2( PointVec2, Heading, NewName )
+ self:F( { PointVec2, Heading, NewName } )
+
+ local CountryName = _DATABASE.COUNTRY_NAME[self.CountryID]
+
+ local StaticTemplate = _DATABASE:GetStaticUnitTemplate( self.SpawnTemplatePrefix )
+
+ StaticTemplate.x = PointVec2:GetLat()
+ StaticTemplate.y = PointVec2:GetLon()
+
+ StaticTemplate.name = NewName or string.format("%s#%05d", self.SpawnTemplatePrefix, self.SpawnIndex )
+ StaticTemplate.heading = ( Heading / 180 ) * math.pi
+
+ StaticTemplate.CountryID = nil
+ StaticTemplate.CoalitionID = nil
+ StaticTemplate.CategoryID = nil
+
+ local Static = coalition.addStaticObject( self.CountryID, StaticTemplate )
+
+ self.SpawnIndex = self.SpawnIndex + 1
+
+ return Static
+end
+
+--- Creates a new @{Static} from a @{Zone}.
+-- @param #SPAWNSTATIC self
+-- @param Core.Zone#ZONE_BASE Zone The Zone where to spawn the static.
+-- @param #number Heading The heading of the static, which is a number in degrees from 0 to 360.
+-- @param #string (optional) The name of the new static.
+-- @return #SPAWNSTATIC
+function SPAWNSTATIC:SpawnFromZone( Zone, Heading, NewName )
+ self:F( { Zone, Heading, NewName } )
+
+ local Static = self:SpawnFromPointVec2( Zone:GetPointVec2(), Heading, NewName )
+
+ return Static
+end
+
diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua
index 432a360a7..8456729a8 100644
--- a/Moose Development/Moose/Core/Zone.lua
+++ b/Moose Development/Moose/Core/Zone.lua
@@ -615,7 +615,7 @@ end
--- @type ZONE
+--- @type ZONE
-- @extends Core.Zone#ZONE_RADIUS
diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua
index 15d3efd4c..004d93c59 100644
--- a/Moose Development/Moose/Functional/Detection.lua
+++ b/Moose Development/Moose/Functional/Detection.lua
@@ -7,8 +7,25 @@
-- DETECTION classes facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
-- DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities.
--
--- Please watch this [youtube video](https://youtu.be/C7p81dUwP-E) that explains the detection concepts.
+-- Find the DETECTION classes documentation further in this document in the globals section.
--
+-- ====
+--
+-- # Demo Missions
+--
+-- ### [DETECTION Demo Missions and Source Code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/DET%20-%20Detection)
+--
+-- ### [DETECTION Demo Missions, only for Beta Testers](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master/DET%20-%20Detection)
+--
+-- ### [ALL Demo Missions pack of the Latest Release](https://github.com/FlightControl-Master/MOOSE_MISSIONS/releases)
+--
+-- ====
+--
+-- # YouTube Channel
+--
+-- ### [DETECTION YouTube Channel](https://www.youtube.com/playlist?list=PL7ZUrU4zZUl3Cf5jpI6BS0sBOVWK__tji)
+--
+-- ====
--
-- ### Contributions:
--
@@ -23,16 +40,24 @@
do -- DETECTION_BASE
- --- # 1) DETECTION_BASE class, extends @{Fsm#FSM}
+ --- @type DETECTION_BASE
+ -- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
+ -- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
+ -- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
+ -- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
+ -- @field #number DetectionRun
+ -- @extends Core.Fsm#FSM
+
+ --- DETECTION_BASE class, extends @{Fsm#FSM}
--
-- The DETECTION_BASE class defines the core functions to administer detected objects.
-- The DETECTION_BASE class will detect objects within the battle zone for a list of @{Group}s detecting targets following (a) detection method(s).
--
- -- ## 1.1) DETECTION_BASE constructor
+ -- ## DETECTION_BASE constructor
--
-- Construct a new DETECTION_BASE instance using the @{#DETECTION_BASE.New}() method.
--
- -- ## 1.2) DETECTION_BASE initialization
+ -- ## Initialization
--
-- By default, detection will return detected objects with all the detection sensors available.
-- However, you can ask how the objects were found with specific detection methods.
@@ -48,7 +73,29 @@ do -- DETECTION_BASE
-- * @{#DETECTION_BASE.InitDetectRWR}(): Detected using RWR.
-- * @{#DETECTION_BASE.InitDetectDLINK}(): Detected using DLINK.
--
- -- ## 1.3) DETECTION_BASE derived classes group the detected units into a DetectedItems[] list
+ -- ## **Filter** detected units based on **category of the unit**
+ --
+ -- Filter the detected units based on Unit.Category using the method @{#DETECTION_BASE.FilterCategories}().
+ -- The different values of Unit.Category can be:
+ --
+ -- * Unit.Category.AIRPLANE
+ -- * Unit.Category.GROUND_UNIT
+ -- * Unit.Category.HELICOPTER
+ -- * Unit.Category.SHIP
+ -- * Unit.Category.STRUCTURE
+ --
+ -- Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
+ --
+ -- Example to filter a single category (Unit.Category.AIRPLANE).
+ --
+ -- DetectionObject:FilterCategories( Unit.Category.AIRPLANE )
+ --
+ -- Example to filter multiple categories (Unit.Category.AIRPLANE, Unit.Category.HELICOPTER). Note the {}.
+ --
+ -- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
+ --
+ --
+ -- ## **DETECTION_ derived classes** group the detected units into a **DetectedItems[]** list
--
-- DETECTION_BASE derived classes build a list called DetectedItems[], which is essentially a first later
-- of grouping of detected units. Each DetectedItem within the DetectedItems[] list contains
@@ -67,7 +114,7 @@ do -- DETECTION_BASE
-- * A DetectedSet from the DetectedItems[] list can be retrieved using the method @{Detection#DETECTION_BASE.GetDetectedSet}( DetectedItemIndex ).
-- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
--
- -- ## 1.4) Apply additional Filters to fine-tune the detected objects
+ -- ## **Visual filters** to fine-tune the probability of the detected objects
--
-- By default, DCS World will return any object that is in LOS and within "visual reach", or detectable through one of the electronic detection means.
-- That being said, the DCS World detection algorithm can sometimes be unrealistic.
@@ -88,7 +135,8 @@ do -- DETECTION_BASE
-- I advise however, that, when you first use the DETECTION derived classes, that you don't use these filters.
-- Only when you experience unrealistic behaviour in your missions, these filters could be applied.
--
- -- ### 1.4.1 ) Distance visual detection probability
+ --
+ -- ### Distance visual detection probability
--
-- Upon a **visual** detection, the further away a detected object is, the less likely it is to be detected properly.
-- Also, the speed of accurate detection plays a role.
@@ -102,7 +150,7 @@ do -- DETECTION_BASE
--
-- Use the method @{Detection#DETECTION_BASE.SetDistanceProbability}() to set the probability factor upon a 10 km distance.
--
- -- ### 1.4.2 ) Alpha Angle visual detection probability
+ -- ### Alpha Angle visual detection probability
--
-- Upon a **visual** detection, the higher the unit is during the detecting process, the more likely the detected unit is to be detected properly.
-- A detection at a 90% alpha angle is the most optimal, a detection at 10% is less and a detection at 0% is less likely to be correct.
@@ -114,7 +162,7 @@ do -- DETECTION_BASE
--
-- Use the method @{Detection#DETECTION_BASE.SetAlphaAngleProbability}() to set the probability factor if 0°.
--
- -- ### 1.4.3 ) Cloudy Zones detection probability
+ -- ### Cloudy Zones detection probability
--
-- Upon a **visual** detection, the more a detected unit is within a cloudy zone, the less likely the detected unit is to be detected successfully.
-- The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
@@ -129,12 +177,12 @@ do -- DETECTION_BASE
-- Typically, this kind of filter would be applied for very specific areas were a detection needs to be very realisting for
-- AI not to detect so easily targets within a forrest or village rich area.
--
- -- ## 1.5 ) Accept / Reject detected units
+ -- ## Accept / Reject detected units
--
-- DETECTION_BASE can accept or reject successful detections based on the location of the detected object,
-- if it is located in range or located inside or outside of specific zones.
--
- -- ### 1.5.1 ) Detection acceptance of within range limit
+ -- ### Detection acceptance of within range limit
--
-- A range can be set that will limit a successful detection for a unit.
-- Use the method @{Detection#DETECTION_BASE.SetAcceptRange}() to apply a range in meters till where detected units will be accepted.
@@ -151,7 +199,7 @@ do -- DETECTION_BASE
-- Detection:Start()
--
--
- -- ### 1.5.2 ) Detection acceptance if within zone(s).
+ -- ### Detection acceptance if within zone(s).
--
-- Specific ZONE_BASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONE_BASE object(s).
-- Use the method @{Detection#DETECTION_BASE.SetAcceptZones}() will accept detected units if they are within the specified zones.
@@ -171,7 +219,7 @@ do -- DETECTION_BASE
-- -- Start the Detection.
-- Detection:Start()
--
- -- ### 1.5.3 ) Detection rejectance if within zone(s).
+ -- ### Detection rejectance if within zone(s).
--
-- Specific ZONE_BASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONE_BASE object(s).
-- Use the method @{Detection#DETECTION_BASE.SetRejectZones}() will reject detected units if they are within the specified zones.
@@ -192,29 +240,24 @@ do -- DETECTION_BASE
-- -- Start the Detection.
-- Detection:Start()
--
- -- ## 1.6) DETECTION_BASE is a Finite State Machine
+ -- ## DETECTION_BASE is a Finite State Machine
--
-- Various Events and State Transitions can be tailored using DETECTION_BASE.
--
- -- ### 1.6.1) DETECTION_BASE States
+ -- ### DETECTION_BASE States
--
-- * **Detecting**: The detection is running.
-- * **Stopped**: The detection is stopped.
--
- -- ### 1.6.2) DETECTION_BASE Events
+ -- ### DETECTION_BASE Events
--
-- * **Start**: Start the detection process.
-- * **Detect**: Detect new units.
-- * **Detected**: New units have been detected.
-- * **Stop**: Stop the detection process.
+ --
+ -- @field #DETECTION_BASE DETECTION_BASE
--
- -- @type DETECTION_BASE
- -- @field Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
- -- @field Dcs.DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
- -- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
- -- @field #table DetectedObjectsIdentified Map of the DetectedObjects identified.
- -- @field #number DetectionRun
- -- @extends Core.Fsm#FSM
DETECTION_BASE = {
ClassName = "DETECTION_BASE",
DetectionSetGroup = nil,
@@ -267,11 +310,19 @@ do -- DETECTION_BASE
self.DetectionInterval = 30
self:InitDetectVisual( true )
- self:InitDetectOptical( false )
- self:InitDetectRadar( false )
- self:InitDetectRWR( false )
- self:InitDetectIRST( false )
- self:InitDetectDLINK( false )
+ self:InitDetectOptical( true )
+ self:InitDetectRadar( true )
+ self:InitDetectRWR( true )
+ self:InitDetectIRST( true )
+ self:InitDetectDLINK( true )
+
+ self:FilterCategories( {
+ Unit.Category.AIRPLANE,
+ Unit.Category.GROUND_UNIT,
+ Unit.Category.HELICOPTER,
+ Unit.Category.SHIP,
+ Unit.Category.STRUCTURE
+ } )
-- Create FSM transitions.
@@ -498,9 +549,8 @@ do -- DETECTION_BASE
for DetectionObjectID, Detection in pairs( DetectedTargets ) do
local DetectedObject = Detection.object -- Dcs.DCSWrapper.Object#Object
- self:T2( DetectedObject )
- if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then
+ if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
local DetectionAccepted = true
@@ -515,10 +565,14 @@ do -- DETECTION_BASE
( DetectedObjectVec3.y - DetectionGroupVec3.y )^2 +
( DetectedObjectVec3.z - DetectionGroupVec3.z )^2
) ^ 0.5 / 1000
+
+ local DetectedUnitCategory = DetectedObject:getDesc().category
- self:T( { "Detected Target", DetectionGroupName, DetectedObjectName, Distance } )
-
+ self:T( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory, DetectedCategory } )
+
-- Calculate Acceptance
+
+ DetectionAccepted = self._.FilterCategories[DetectedUnitCategory] ~= nil and DetectionAccepted or false
if self.AcceptRange and Distance > self.AcceptRange then
DetectionAccepted = false
@@ -625,10 +679,10 @@ do -- DETECTION_BASE
end
if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then
- self:__Detect( self.DetectionInterval )
-
self:T( "--> Create Detection Sets" )
self:CreateDetectionSets()
+
+ self:__Detect( self.DetectionInterval )
end
end
@@ -645,6 +699,8 @@ do -- DETECTION_BASE
function DETECTION_BASE:InitDetectVisual( DetectVisual )
self.DetectVisual = DetectVisual
+
+ return self
end
--- Detect Optical.
@@ -655,6 +711,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectOptical = DetectOptical
+
+ return self
end
--- Detect Radar.
@@ -665,6 +723,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectRadar = DetectRadar
+
+ return self
end
--- Detect IRST.
@@ -675,6 +735,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectIRST = DetectIRST
+
+ return self
end
--- Detect RWR.
@@ -685,6 +747,8 @@ do -- DETECTION_BASE
self:F2()
self.DetectRWR = DetectRWR
+
+ return self
end
--- Detect DLINK.
@@ -695,9 +759,52 @@ do -- DETECTION_BASE
self:F2()
self.DetectDLINK = DetectDLINK
+
+ return self
end
end
+
+ do -- Filter methods
+
+ --- Filter the detected units based on Unit.Category
+ -- The different values of Unit.Category can be:
+ --
+ -- * Unit.Category.AIRPLANE
+ -- * Unit.Category.GROUND_UNIT
+ -- * Unit.Category.HELICOPTER
+ -- * Unit.Category.SHIP
+ -- * Unit.Category.STRUCTURE
+ --
+ -- Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
+ --
+ -- Example to filter a single category (Unit.Category.AIRPLANE).
+ --
+ -- DetectionObject:FilterCategories( Unit.Category.AIRPLANE )
+ --
+ -- Example to filter multiple categories (Unit.Category.AIRPLANE, Unit.Category.HELICOPTER). Note the {}.
+ --
+ -- DetectionObject:FilterCategories( { Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
+ --
+ -- @param #DETECTION_BASE self
+ -- @param #list FilterCategories The Categories entries
+ -- @return #DETECTION_BASE self
+ function DETECTION_BASE:FilterCategories( FilterCategories )
+ self:F2()
+
+ self._.FilterCategories = {}
+ if type( FilterCategories ) == "table" then
+ for CategoryID, Category in pairs( FilterCategories ) do
+ self._.FilterCategories[Category] = Category
+ end
+ else
+ self._.FilterCategories[FilterCategories] = FilterCategories
+ end
+ return self
+
+ end
+
+ end
do
diff --git a/Moose Development/Moose/Functional/Spawn.lua b/Moose Development/Moose/Functional/Spawn.lua
index 7e612ec5b..129cde05b 100644
--- a/Moose Development/Moose/Functional/Spawn.lua
+++ b/Moose Development/Moose/Functional/Spawn.lua
@@ -4,6 +4,10 @@
--
-- ====
--
+-- The documentation of the SPAWN class can be found further in this document.
+--
+-- ====
+--
-- # Demo Missions
--
-- ### [SPAWN Demo Missions source code](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/master-release/SPA%20-%20Spawning)
@@ -174,30 +178,62 @@
--
-- A spawn object will behave differently based on the usage of **initialization** methods, which all start with the **Init** prefix:
--
+-- ### Unit Names
+--
-- * @{#SPAWN.InitKeepUnitNames}(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
--- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
+--
+-- ### Route randomization
+--
-- * @{#SPAWN.InitRandomizeRoute}(): Randomize the routes of spawned groups, and for air groups also optionally the height.
+--
+-- ### Group composition randomization
+--
-- * @{#SPAWN.InitRandomizeTemplate}(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
+--
+-- ### Uncontrolled
+--
-- * @{#SPAWN.InitUnControlled}(): Spawn plane groups uncontrolled.
+--
+-- ### Array formation
+--
-- * @{#SPAWN.InitArray}(): 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 methods are @{#SPAWN.InitRepeatOnLanding} and @{#SPAWN.InitRepeatOnEngineShutDown}.
+--
+-- ### Position randomization
+--
-- * @{#SPAWN.InitRandomizePosition}(): Randomizes the position of @{Group}s that are spawned within a **radius band**, given an Outer and Inner radius, from the point that the spawn happens.
-- * @{#SPAWN.InitRandomizeUnits}(): Randomizes the @{Unit}s in the @{Group} that is spawned within a **radius band**, given an Outer and Inner radius.
-- * @{#SPAWN.InitRandomizeZones}(): Randomizes the spawning between a predefined list of @{Zone}s that are declared using this function. Each zone can be given a probability factor.
+--
+-- ### Enable / Disable AI when spawning a new @{Group}
+--
-- * @{#SPAWN.InitAIOn}(): Turns the AI On when spawning the new @{Group} object.
-- * @{#SPAWN.InitAIOff}(): Turns the AI Off when spawning the new @{Group} object.
-- * @{#SPAWN.InitAIOnOff}(): Turns the AI On or Off when spawning the new @{Group} object.
--- * @{#SPAWN.InitDelayOnOff}(): Turns the inital delay On/Off when spawning the first @{Group} object.
--- * @{#SPAWN.InitDelayOn}(): Turns the inital delay On when spawning the first @{Group} object.
--- * @{#SPAWN.InitDelayOff}(): Turns the inital delay On when spawning the first @{Group} object.
+--
+-- ### Limit scheduled spawning
+--
+-- * @{#SPAWN.InitLimit}(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
+--
+-- ### Delay initial scheduled spawn
+--
+-- * @{#SPAWN.InitDelayOnOff}(): Turns the inital delay On/Off when scheduled spawning the first @{Group} object.
+-- * @{#SPAWN.InitDelayOn}(): Turns the inital delay On when scheduled spawning the first @{Group} object.
+-- * @{#SPAWN.InitDelayOff}(): Turns the inital delay Off when scheduled spawning the first @{Group} object.
+--
+-- ### Repeat spawned @{Group}s upon landing
+--
+-- * @{#SPAWN.InitRepeat}() or @{#SPAWN.InitRepeatOnLanding}(): This method is used to re-spawn automatically the same group after it has landed.
+-- * @{#SPAWN.InitRepeatOnEngineShutDown}(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp.
+--
--
-- ## SPAWN **Spawn** methods
--
-- Groups can be spawned at different times and methods:
--
+-- ### **Single** spawning methods
+--
-- * @{#SPAWN.Spawn}(): Spawn one new group based on the last spawned index.
-- * @{#SPAWN.ReSpawn}(): Re-spawn a group based on a given index.
--- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals. You can use @{#SPAWN.SpawnScheduleStart}() and @{#SPAWN.SpawnScheduleStop}() to start and stop the schedule respectively.
-- * @{#SPAWN.SpawnFromVec3}(): Spawn a new group from a Vec3 coordinate. (The group will can be spawned at a point in the air).
-- * @{#SPAWN.SpawnFromVec2}(): Spawn a new group from a Vec2 coordinate. (The group will be spawned at land height ).
-- * @{#SPAWN.SpawnFromStatic}(): Spawn a new group from a structure, taking the position of a @{Static}.
@@ -206,6 +242,14 @@
--
-- 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.
+--
+-- ### **Scheduled** spawning methods
+--
+-- * @{#SPAWN.SpawnScheduled}(): Spawn groups at scheduled but randomized intervals.
+-- * @{#SPAWN.SpawnScheduledStart}(): Start or continue to spawn groups at scheduled time intervals.
+-- * @{#SPAWN.SpawnScheduledStop}(): Stop the spawning of groups at scheduled time intervals.
+--
+--
--
-- ## Retrieve alive GROUPs spawned by the SPAWN object
--
@@ -242,6 +286,15 @@
-- As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned @{Group} object.
-- A coding example is provided at the description of the @{#SPAWN.OnSpawnGroup}( **function( SpawnedGroup ) end ** ) method.
--
+-- ## Delay the initial spawning
+--
+-- When using the @{#SPAWN.SpawnScheduled)() method, the default behaviour of this method will be that it will spawn the initial (first) @{Group}
+-- immediately when :SpawnScheduled() is initiated. The methods @{#SPAWN.InitDelayOnOff}() and @{#SPAWN.InitDelayOn}() can be used to
+-- activate a delay before the first @{Group} is spawned. For completeness, a method @{#SPAWN.InitDelayOff}() is also available, that
+-- can be used to switch off the initial delay. Because there is no delay by default, this method would only be used when a
+-- @{#SPAWN.SpawnScheduledStop}() ; @{#SPAWN.SpawnScheduledStart}() sequence would have been used.
+--
+--
-- @field #SPAWN SPAWN
--
SPAWN = {
@@ -285,7 +338,7 @@ function SPAWN:New( SpawnTemplatePrefix )
self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
- self.DelayOnOff = true -- An intial delay when spawning the first group.
+ self.DelayOnOff = false -- No intial delay when spawning the first group.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else
@@ -329,7 +382,7 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
self.AIOnOff = true -- The AI is on by default when spawning a group.
self.SpawnUnControlled = false
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
- self.DelayOnOff = true -- An intial delay when spawning the first group.
+ self.DelayOnOff = false -- No intial delay when spawning the first group.
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
else
@@ -1022,7 +1075,7 @@ end
function SPAWN:SpawnFromUnit( HostUnit, SpawnIndex )
self:F( { self.SpawnTemplatePrefix, HostUnit, SpawnIndex } )
- if HostUnit and HostUnit:IsAlive() then -- and HostUnit:getUnit(1):inAir() == false then
+ if HostUnit and HostUnit:IsAlive() ~= nil then -- and HostUnit:getUnit(1):inAir() == false then
return self:SpawnFromVec3( HostUnit:GetVec3(), SpawnIndex )
end
diff --git a/Moose Mission Setup/Moose.files b/Moose Mission Setup/Moose.files
index fac9aa46b..b8084a749 100644
--- a/Moose Mission Setup/Moose.files
+++ b/Moose Mission Setup/Moose.files
@@ -13,6 +13,7 @@ Core/Point.lua
Core/Message.lua
Core/Fsm.lua
Core/Radio.lua
+Core/SpawnStatic.lua
Wrapper/Object.lua
Wrapper/Identifiable.lua
diff --git a/docs/Documentation/AI_Balancer.html b/docs/Documentation/AI_Balancer.html
index 3c6b3b617..15193880f 100644
--- a/docs/Documentation/AI_Balancer.html
+++ b/docs/Documentation/AI_Balancer.html
@@ -74,6 +74,7 @@
DETECTION classes facilitate the detection of enemy units within the battle zone executed by FACs (Forward Air Controllers) or RECCEs (Reconnassance Units).
DETECTION uses the in-built detection capabilities of DCS World, but adds new functionalities.
-
Please watch this youtube video that explains the detection concepts.
+
Find the DETECTION classes documentation further in this document in the globals section.
The DETECTION_BASE class defines the core functions to administer detected objects.
+
+
+
The DETECTION_BASE class will detect objects within the battle zone for a list of Groups detecting targets following (a) detection method(s).
+
+
DETECTION_BASE constructor
+
+
Construct a new DETECTION_BASE instance using the DETECTION_BASE.New() method.
+
+
Initialization
+
+
By default, detection will return detected objects with all the detection sensors available.
+However, you can ask how the objects were found with specific detection methods.
+If you use one of the below methods, the detection will work with the detection method specified.
+You can specify to apply multiple detection methods.
+
+
Use the following functions to report the objects it detected using the methods Visual, Optical, Radar, IRST, RWR, DLINK:
DETECTION_ derived classes group the detected units into a DetectedItems[] list
+
+
DETECTIONBASE derived classes build a list called DetectedItems[], which is essentially a first later
+of grouping of detected units. Each DetectedItem within the DetectedItems[] list contains
+a SETUNIT object that contains the detected units that belong to that group.
+
+
Derived classes will apply different methods to group the detected units.
+Examples are per area, per quadrant, per distance, per type.
+See further the derived DETECTION classes on which grouping methods are currently supported.
+
+
Various methods exist how to retrieve the grouped items from a DETECTION_BASE derived class:
A DetectedItem from the DetectedItems[] list can be retrieved using the method Detection#DETECTION_BASE.GetDetectedItem( DetectedItemIndex ).
+ Note that this method returns a DetectedItem element from the list, that contains a Set variable and further information
+ about the DetectedItem that is set by the DETECTION_BASE derived classes, used to group the DetectedItem.
+
A DetectedSet from the DetectedItems[] list can be retrieved using the method Detection#DETECTION_BASE.GetDetectedSet( DetectedItemIndex ).
+ This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
+
+
+
Filter detected units based on category of the unit
+
+
Filter the detected units based on Unit.Category using the method DETECTION_BASE.FilterCategories().
+The different values of Unit.Category can be:
+
+
+
Unit.Category.AIRPLANE
+
Unit.Category.GROUND_UNIT
+
Unit.Category.HELICOPTER
+
Unit.Category.SHIP
+
Unit.Category.STRUCTURE
+
+
+
Multiple Unit.Category entries can be given as a table and then these will be evaluated as an OR expression.
+
+
Example to filter a single category (Unit.Category.AIRPLANE).
Visual filters to fine-tune the probability of the detected objects
+
+
By default, DCS World will return any object that is in LOS and within "visual reach", or detectable through one of the electronic detection means.
+That being said, the DCS World detection algorithm can sometimes be unrealistic.
+Especially for a visual detection, DCS World is able to report within 1 second a detailed detection of a group of 20 units (including types of the units) that are 10 kilometers away, using only visual capabilities.
+Additionally, trees and other obstacles are not accounted during the DCS World detection.
+
+
Therefore, an additional (optional) filtering has been built into the DETECTION_BASE class, that can be set for visual detected units.
+For electronic detection, this filtering is not applied, only for visually detected targets.
+
+
The following additional filtering can be applied for visual filtering:
+
+
+
A probability factor per kilometer distance.
+
A probability factor based on the alpha angle between the detected object and the unit detecting.
+ A detection from a higher altitude allows for better detection than when on the ground.
+
Define a probability factor for "cloudy zones", which are zones where forests or villages are located. In these zones, detection will be much more difficult.
+ The mission designer needs to define these cloudy zones within the mission, and needs to register these zones in the DETECTION_ objects additing a probability factor per zone.
+
+
+
I advise however, that, when you first use the DETECTION derived classes, that you don't use these filters.
+Only when you experience unrealistic behaviour in your missions, these filters could be applied.
+
+
+
Distance visual detection probability
+
+
Upon a visual detection, the further away a detected object is, the less likely it is to be detected properly.
+Also, the speed of accurate detection plays a role.
+
+
A distance probability factor between 0 and 1 can be given, that will model a linear extrapolated probability over 10 km distance.
+
+
For example, if a probability factor of 0.6 (60%) is given, the extrapolated probabilities over 15 kilometers would like like:
+1 km: 96%, 2 km: 92%, 3 km: 88%, 4 km: 84%, 5 km: 80%, 6 km: 76%, 7 km: 72%, 8 km: 68%, 9 km: 64%, 10 km: 60%, 11 km: 56%, 12 km: 52%, 13 km: 48%, 14 km: 44%, 15 km: 40%.
+
+
Note that based on this probability factor, not only the detection but also the type of the unit will be applied!
Upon a visual detection, the higher the unit is during the detecting process, the more likely the detected unit is to be detected properly.
+A detection at a 90% alpha angle is the most optimal, a detection at 10% is less and a detection at 0% is less likely to be correct.
+
+
A probability factor between 0 and 1 can be given, that will model a progressive extrapolated probability if the target would be detected at a 0° angle.
+
+
For example, if a alpha angle probability factor of 0.7 is given, the extrapolated probabilities of the different angles would look like:
+0°: 70%, 10°: 75,21%, 20°: 80,26%, 30°: 85%, 40°: 89,28%, 50°: 92,98%, 60°: 95,98%, 70°: 98,19%, 80°: 99,54%, 90°: 100%
Upon a visual detection, the more a detected unit is within a cloudy zone, the less likely the detected unit is to be detected successfully.
+The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
+zones that reflect cloudy areas where detected units may not be so easily visually detected.
Note however, that the more zones are defined to be "cloudy" within a detection, the more performance it will take
+from the DETECTIONBASE to calculate the presence of the detected unit within each zone.
+Expecially for ZONEPOLYGON, try to limit the amount of nodes of the polygon!
+
+
Typically, this kind of filter would be applied for very specific areas were a detection needs to be very realisting for
+AI not to detect so easily targets within a forrest or village rich area.
+
+
Accept / Reject detected units
+
+
DETECTION_BASE can accept or reject successful detections based on the location of the detected object,
+if it is located in range or located inside or outside of specific zones.
+
+
Detection acceptance of within range limit
+
+
A range can be set that will limit a successful detection for a unit.
+Use the method Detection#DETECTION_BASE.SetAcceptRange() to apply a range in meters till where detected units will be accepted.
+
+
local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
+
+ -- Build a detect object.
+ local Detection = DETECTION_BASE:New( SetGroup )
+
+ -- This will accept detected units if the range is below 5000 meters.
+ Detection:SetAcceptRange( 5000 )
+
+ -- Start the Detection.
+ Detection:Start()
+
+
+
+
Detection acceptance if within zone(s).
+
+
Specific ZONEBASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONEBASE object(s).
+Use the method Detection#DETECTION_BASE.SetAcceptZones() will accept detected units if they are within the specified zones.
+
+
local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
+
+ -- Search fo the zones where units are to be accepted.
+ local ZoneAccept1 = ZONE:New( "AcceptZone1" )
+ local ZoneAccept2 = ZONE:New( "AcceptZone2" )
+
+ -- Build a detect object.
+ local Detection = DETECTION_BASE:New( SetGroup )
+
+ -- This will accept detected units by Detection when the unit is within ZoneAccept1 OR ZoneAccept2.
+ Detection:SetAcceptZones( { ZoneAccept1, ZoneAccept2 } )
+
+ -- Start the Detection.
+ Detection:Start()
+
+
+
Detection rejectance if within zone(s).
+
+
Specific ZONEBASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONEBASE object(s).
+Use the method Detection#DETECTION_BASE.SetRejectZones() will reject detected units if they are within the specified zones.
+An example of how to use the method is shown below.
+
+
local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
+
+ -- Search fo the zones where units are to be rejected.
+ local ZoneReject1 = ZONE:New( "RejectZone1" )
+ local ZoneReject2 = ZONE:New( "RejectZone2" )
+
+ -- Build a detect object.
+ local Detection = DETECTION_BASE:New( SetGroup )
+
+ -- This will reject detected units by Detection when the unit is within ZoneReject1 OR ZoneReject2.
+ Detection:SetRejectZones( { ZoneReject1, ZoneReject2 } )
+
+ -- Start the Detection.
+ Detection:Start()
+
+
+
DETECTION_BASE is a Finite State Machine
+
+
Various Events and State Transitions can be tailored using DETECTION_BASE.
The DETECTION_BASE class defines the core functions to administer detected objects.
-
-
-
The DETECTION_BASE class will detect objects within the battle zone for a list of Groups detecting targets following (a) detection method(s).
-
-
1.1) DETECTION_BASE constructor
-
-
Construct a new DETECTION_BASE instance using the DETECTION_BASE.New() method.
-
-
1.2) DETECTION_BASE initialization
-
-
By default, detection will return detected objects with all the detection sensors available.
-However, you can ask how the objects were found with specific detection methods.
-If you use one of the below methods, the detection will work with the detection method specified.
-You can specify to apply multiple detection methods.
-
-
Use the following functions to report the objects it detected using the methods Visual, Optical, Radar, IRST, RWR, DLINK:
1.3) DETECTION_BASE derived classes group the detected units into a DetectedItems[] list
-
-
DETECTIONBASE derived classes build a list called DetectedItems[], which is essentially a first later
-of grouping of detected units. Each DetectedItem within the DetectedItems[] list contains
-a SETUNIT object that contains the detected units that belong to that group.
-
-
Derived classes will apply different methods to group the detected units.
-Examples are per area, per quadrant, per distance, per type.
-See further the derived DETECTION classes on which grouping methods are currently supported.
-
-
Various methods exist how to retrieve the grouped items from a DETECTION_BASE derived class:
A DetectedItem from the DetectedItems[] list can be retrieved using the method Detection#DETECTION_BASE.GetDetectedItem( DetectedItemIndex ).
- Note that this method returns a DetectedItem element from the list, that contains a Set variable and further information
- about the DetectedItem that is set by the DETECTION_BASE derived classes, used to group the DetectedItem.
-
A DetectedSet from the DetectedItems[] list can be retrieved using the method Detection#DETECTION_BASE.GetDetectedSet( DetectedItemIndex ).
- This method retrieves the Set from a DetectedItem element from the DetectedItem list (DetectedItems[ DetectedItemIndex ].Set ).
-
-
-
1.4) Apply additional Filters to fine-tune the detected objects
-
-
By default, DCS World will return any object that is in LOS and within "visual reach", or detectable through one of the electronic detection means.
-That being said, the DCS World detection algorithm can sometimes be unrealistic.
-Especially for a visual detection, DCS World is able to report within 1 second a detailed detection of a group of 20 units (including types of the units) that are 10 kilometers away, using only visual capabilities.
-Additionally, trees and other obstacles are not accounted during the DCS World detection.
-
-
Therefore, an additional (optional) filtering has been built into the DETECTION_BASE class, that can be set for visual detected units.
-For electronic detection, this filtering is not applied, only for visually detected targets.
-
-
The following additional filtering can be applied for visual filtering:
-
-
-
A probability factor per kilometer distance.
-
A probability factor based on the alpha angle between the detected object and the unit detecting.
- A detection from a higher altitude allows for better detection than when on the ground.
-
Define a probability factor for "cloudy zones", which are zones where forests or villages are located. In these zones, detection will be much more difficult.
- The mission designer needs to define these cloudy zones within the mission, and needs to register these zones in the DETECTION_ objects additing a probability factor per zone.
-
-
-
I advise however, that, when you first use the DETECTION derived classes, that you don't use these filters.
-Only when you experience unrealistic behaviour in your missions, these filters could be applied.
-
-
1.4.1 ) Distance visual detection probability
-
-
Upon a visual detection, the further away a detected object is, the less likely it is to be detected properly.
-Also, the speed of accurate detection plays a role.
-
-
A distance probability factor between 0 and 1 can be given, that will model a linear extrapolated probability over 10 km distance.
-
-
For example, if a probability factor of 0.6 (60%) is given, the extrapolated probabilities over 15 kilometers would like like:
-1 km: 96%, 2 km: 92%, 3 km: 88%, 4 km: 84%, 5 km: 80%, 6 km: 76%, 7 km: 72%, 8 km: 68%, 9 km: 64%, 10 km: 60%, 11 km: 56%, 12 km: 52%, 13 km: 48%, 14 km: 44%, 15 km: 40%.
-
-
Note that based on this probability factor, not only the detection but also the type of the unit will be applied!
Upon a visual detection, the higher the unit is during the detecting process, the more likely the detected unit is to be detected properly.
-A detection at a 90% alpha angle is the most optimal, a detection at 10% is less and a detection at 0% is less likely to be correct.
-
-
A probability factor between 0 and 1 can be given, that will model a progressive extrapolated probability if the target would be detected at a 0° angle.
-
-
For example, if a alpha angle probability factor of 0.7 is given, the extrapolated probabilities of the different angles would look like:
-0°: 70%, 10°: 75,21%, 20°: 80,26%, 30°: 85%, 40°: 89,28%, 50°: 92,98%, 60°: 95,98%, 70°: 98,19%, 80°: 99,54%, 90°: 100%
Upon a visual detection, the more a detected unit is within a cloudy zone, the less likely the detected unit is to be detected successfully.
-The Cloudy Zones work with the ZONE_BASE derived classes. The mission designer can define within the mission
-zones that reflect cloudy areas where detected units may not be so easily visually detected.
Note however, that the more zones are defined to be "cloudy" within a detection, the more performance it will take
-from the DETECTIONBASE to calculate the presence of the detected unit within each zone.
-Expecially for ZONEPOLYGON, try to limit the amount of nodes of the polygon!
-
-
Typically, this kind of filter would be applied for very specific areas were a detection needs to be very realisting for
-AI not to detect so easily targets within a forrest or village rich area.
-
-
1.5 ) Accept / Reject detected units
-
-
DETECTION_BASE can accept or reject successful detections based on the location of the detected object,
-if it is located in range or located inside or outside of specific zones.
-
-
1.5.1 ) Detection acceptance of within range limit
-
-
A range can be set that will limit a successful detection for a unit.
-Use the method Detection#DETECTION_BASE.SetAcceptRange() to apply a range in meters till where detected units will be accepted.
-
-
local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
-
- -- Build a detect object.
- local Detection = DETECTION_BASE:New( SetGroup )
-
- -- This will accept detected units if the range is below 5000 meters.
- Detection:SetAcceptRange( 5000 )
-
- -- Start the Detection.
- Detection:Start()
-
-
-
-
1.5.2 ) Detection acceptance if within zone(s).
-
-
Specific ZONEBASE object(s) can be given as a parameter, which will only accept a detection if the unit is within the specified ZONEBASE object(s).
-Use the method Detection#DETECTION_BASE.SetAcceptZones() will accept detected units if they are within the specified zones.
-
-
local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
-
- -- Search fo the zones where units are to be accepted.
- local ZoneAccept1 = ZONE:New( "AcceptZone1" )
- local ZoneAccept2 = ZONE:New( "AcceptZone2" )
-
- -- Build a detect object.
- local Detection = DETECTION_BASE:New( SetGroup )
-
- -- This will accept detected units by Detection when the unit is within ZoneAccept1 OR ZoneAccept2.
- Detection:SetAcceptZones( { ZoneAccept1, ZoneAccept2 } )
-
- -- Start the Detection.
- Detection:Start()
-
-
-
1.5.3 ) Detection rejectance if within zone(s).
-
-
Specific ZONEBASE object(s) can be given as a parameter, which will reject detection if the unit is within the specified ZONEBASE object(s).
-Use the method Detection#DETECTION_BASE.SetRejectZones() will reject detected units if they are within the specified zones.
-An example of how to use the method is shown below.
-
-
local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
-
- -- Search fo the zones where units are to be rejected.
- local ZoneReject1 = ZONE:New( "RejectZone1" )
- local ZoneReject2 = ZONE:New( "RejectZone2" )
-
- -- Build a detect object.
- local Detection = DETECTION_BASE:New( SetGroup )
-
- -- This will reject detected units by Detection when the unit is within ZoneReject1 OR ZoneReject2.
- Detection:SetRejectZones( { ZoneReject1, ZoneReject2 } )
-
- -- Start the Detection.
- Detection:Start()
-
-
-
1.6) DETECTION_BASE is a Finite State Machine
-
-
Various Events and State Transitions can be tailored using DETECTION_BASE.
-
-
1.6.1) DETECTION_BASE States
-
-
-
Detecting: The detection is running.
-
Stopped: The detection is stopped.
-
-
-
1.6.2) DETECTION_BASE Events
-
-
-
Start: Start the detection process.
-
Detect: Detect new units.
-
Detected: New units have been detected.
-
Stop: Stop the detection process.
-
-
-
-
Field(s)
+
Field(s)
@@ -1966,20 +2021,6 @@ The index of the DetectedItem.
-
-
@@ -917,33 +928,83 @@ So in principle, the group list will contain all parameters and configurations a
A spawn object will behave differently based on the usage of initialization methods, which all start with the Init prefix:
+
Unit Names
+
SPAWN.InitKeepUnitNames(): Keeps the unit names as defined within the mission editor, but note that anything after a # mark is ignored, and any spaces before and after the resulting name are removed. IMPORTANT! This method MUST be the first used after :New !!!
-
SPAWN.InitLimit(): Limits the amount of groups that can be alive at the same time and that can be dynamically spawned.
+
+
+
Route randomization
+
+
SPAWN.InitRandomizeRoute(): Randomize the routes of spawned groups, and for air groups also optionally the height.
+
+
+
Group composition randomization
+
+
SPAWN.InitRandomizeTemplate(): Randomize the group templates so that when a new group is spawned, a random group template is selected from one of the templates defined.
SPAWN.InitRandomizePosition(): Randomizes the position of Groups that are spawned within a radius band, given an Outer and Inner radius, from the point that the spawn happens.
SPAWN.InitRandomizeUnits(): Randomizes the Units in the Group that is spawned within a radius band, given an Outer and Inner radius.
SPAWN.InitRandomizeZones(): Randomizes the spawning between a predefined list of Zones that are declared using this function. Each zone can be given a probability factor.
SPAWN.InitRepeatOnEngineShutDown(): This method is used to re-spawn automatically the same group after it has landed and it shuts down the engines at the ramp.
+
+
+
SPAWN Spawn methods
Groups can be spawned at different times and methods:
+
Single spawning methods
+
SPAWN.Spawn(): Spawn one new group based on the last spawned index.
SPAWN.ReSpawn(): Re-spawn a group based on a given index.
@@ -954,6 +1015,16 @@ So in principle, the group list will contain all parameters and configurations a
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.
The SPAWN class administers which GROUPS it has reserved (in stock) or has created during mission execution.
@@ -991,6 +1062,15 @@ Whenever a new Group is spawned, the given function is
As a result, your spawn event handling function requires one parameter to be declared, which will contain the spawned Group object.
A coding example is provided at the description of the SPAWN.OnSpawnGroup( *function( SpawnedGroup ) end * ) method.
The SPAWNSTATIC class allows to spawn dynamically new Statics.
+
+
+
+
There are two modes how SPAWNSTATIC can spawn:
+
+
+
Through creating a copy of an existing Template Static as defined in the Mission Editor (ME).
+
Through the provision of the type name of the Static.
+
+
+
Spawned Statics get the same name as the name of the Template Static,
+or gets the given name when a Static Type is used.
+Newly spawned Statics will get the following naming structure at run-time:
+
+
+
Spawned Statics will have the name _StaticName#nnn_, where StaticName is the name of the Template Static,
+ and nnn is a counter from 0 to 99999.
Creates the main object to spawn a Static defined in the ME.
+
+
Parameters
+
+
+
+
#string SpawnTemplatePrefix :
+is the name of the Group in the ME that defines the Template. Each new group will have the name starting with SpawnTemplatePrefix.