mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Updated detection algorithm
Now the detected sets are kept consistent to previous sets. New algorithm developed. This is important to keep assigned tasks consistent with the detected sets.
This commit is contained in:
parent
40a9c1f7d1
commit
17abcb7b7f
@ -73,23 +73,26 @@
|
||||
-- @type DETECTION_BASE
|
||||
-- @field Group#GROUP DetectionGroups The GROUP in the Forward Air Controller role.
|
||||
-- @field DCSTypes#Distance DetectionRange The range till which targets are accepted to be detected.
|
||||
-- @field #DETECTION_BASE.DetectedSets DetectedSets A list of @{Set#SET_BASE}s containing the objects in each set that were detected. The base class will not build the detected sets, but will leave that to the derived classes.
|
||||
-- @field #DETECTION_BASE.DetectedObjects DetectedObjects The list of detected objects.
|
||||
-- @field #number DetectionRun
|
||||
-- @extends Base#BASE
|
||||
DETECTION_BASE = {
|
||||
ClassName = "DETECTION_BASE",
|
||||
DetectedSets = {},
|
||||
DetectedObjects = {},
|
||||
DetectionGroups = nil,
|
||||
DetectionRange = nil,
|
||||
DetectedObjects = {},
|
||||
DetectionRun = 0,
|
||||
}
|
||||
|
||||
--- @type DETECTION_BASE.DetectedSets
|
||||
-- @list <Set#SET_BASE>
|
||||
|
||||
|
||||
--- @type DETECTION_BASE.DetectedZones
|
||||
-- @list <Zone#ZONE_BASE>
|
||||
--- @type DETECTION_BASE.DetectedObjects
|
||||
-- @list <#DETECTION_BASE.DetectedObject>
|
||||
|
||||
--- @type DETECTION_BASE.DetectedObject
|
||||
-- @field #string Name
|
||||
-- @field #boolean Visible
|
||||
-- @field #string Type
|
||||
-- @field #number Distance
|
||||
-- @field #boolean Identified
|
||||
|
||||
--- DETECTION constructor.
|
||||
-- @param #DETECTION_BASE self
|
||||
@ -173,13 +176,19 @@ function DETECTION_BASE:InitDetectDLINK( DetectDLINK )
|
||||
self.DetectDLINK = DetectDLINK
|
||||
end
|
||||
|
||||
--- Gets the Detection group.
|
||||
--- Gets a detected object with a given name.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @return Group#GROUP self
|
||||
function DETECTION_BASE:GetDetectionGroups()
|
||||
self:F2()
|
||||
|
||||
return self.DetectionGroups
|
||||
-- @param #string ObjectName
|
||||
-- @return #DETECTION_BASE.DetectedObject
|
||||
function DETECTION_BASE:GetDetectedObject( ObjectName )
|
||||
self:F( ObjectName )
|
||||
|
||||
if ObjectName then
|
||||
local DetectedObject = self.DetectedObjects[ObjectName]
|
||||
return DetectedObject
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the detected @{Set#SET_BASE}s.
|
||||
@ -214,13 +223,13 @@ function DETECTION_BASE:GetDetectedSet( Index )
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the detected @{Zone}s.
|
||||
--- Get the detection Groups.
|
||||
-- @param #DETECTION_BASE self
|
||||
-- @return #DETECTION_BASE.DetectedZones DetectedZones
|
||||
function DETECTION_BASE:GetDetectedZones()
|
||||
-- @return Group#GROUP
|
||||
function DETECTION_BASE:GetDetectionGroups()
|
||||
|
||||
local DetectionZones = self.DetectedZones
|
||||
return DetectionZones
|
||||
local DetectionGroups = self.DetectionGroups
|
||||
return DetectionGroups
|
||||
end
|
||||
|
||||
--- Make a DetectionSet table. This function will be overridden in the derived clsses.
|
||||
@ -255,8 +264,7 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName )
|
||||
self:F2( { SchedulerName } )
|
||||
|
||||
self.DetectedObjects = {}
|
||||
self.DetectedSets = {}
|
||||
self.DetectedZones = {}
|
||||
self.DetectionRun = self.DetectionRun + 1
|
||||
|
||||
if self.DetectionGroups:IsAlive() then
|
||||
local DetectionGroupsName = self.DetectionGroups:GetName()
|
||||
@ -286,7 +294,7 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName )
|
||||
( DetectionDetectedObjectPositionVec3.z - DetectionGroupsPositionVec3.z )^2
|
||||
) ^ 0.5 / 1000
|
||||
|
||||
self:T( { DetectionGroupsName, DetectionDetectedObjectName, Distance } )
|
||||
self:T2( { DetectionGroupsName, DetectionDetectedObjectName, Distance } )
|
||||
|
||||
if Distance <= self.DetectionRange then
|
||||
|
||||
@ -297,6 +305,7 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName )
|
||||
self.DetectedObjects[DetectionDetectedObjectName].Visible = DetectionDetectedTarget.visible
|
||||
self.DetectedObjects[DetectionDetectedObjectName].Type = DetectionDetectedTarget.type
|
||||
self.DetectedObjects[DetectionDetectedObjectName].Distance = DetectionDetectedTarget.distance
|
||||
self.DetectedObjects[DetectionDetectedObjectName].Identified = false -- This flag is used to control identification.
|
||||
else
|
||||
-- if beyond the DetectionRange then nullify...
|
||||
if self.DetectedObjects[DetectionDetectedObjectName] then
|
||||
@ -324,27 +333,26 @@ function DETECTION_BASE:_DetectionScheduler( SchedulerName )
|
||||
end
|
||||
end
|
||||
|
||||
--- @type DETECTION_UNITGROUPS.DetectedSets
|
||||
-- @list <Set#SET_UNIT>
|
||||
--
|
||||
|
||||
|
||||
--- @type DETECTION_UNITGROUPS.DetectedZones
|
||||
-- @list <Zone#ZONE_UNIT>
|
||||
--
|
||||
|
||||
|
||||
--- DETECTION_UNITGROUPS class
|
||||
-- @type DETECTION_UNITGROUPS
|
||||
-- @param DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||
-- @field #DETECTION_UNITGROUPS.DetectedSets DetectedSets A list of @{Set#SET_UNIT}s containing the units in each set that were detected within a DetectionZoneRange.
|
||||
-- @field #DETECTION_UNITGROUPS.DetectedZones DetectedZones A list of @{Zone#ZONE_UNIT}s containing the zones of the reference detected units.
|
||||
-- @field DCSTypes#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
|
||||
-- @field #DETECTION_UNITGROUPS.DetectedAreas DetectedAreas A list of areas containing the set of @{Unit}s, @{Zone}s, the center @{Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
|
||||
-- @extends Detection#DETECTION_BASE
|
||||
DETECTION_UNITGROUPS = {
|
||||
ClassName = "DETECTION_UNITGROUPS",
|
||||
DetectedZones = {},
|
||||
DetectedAreas = { n = 0 },
|
||||
DetectionZoneRange = nil,
|
||||
}
|
||||
|
||||
--- @type DETECTION_UNITGROUPS.DetectedAreas
|
||||
-- @list <#DETECTION_UNITGROUPS.DetectedArea>
|
||||
|
||||
--- @type DETECTION_UNITGROUPS.DetectedArea
|
||||
-- @field Set#SET_UNIT Set -- The Set of Units in the detected area.
|
||||
-- @field Zone#ZONE_UNIT Zone -- The Zone of the detected area.
|
||||
-- @field #number AreaID -- The identifier of the detected area.
|
||||
|
||||
|
||||
--- DETECTION_UNITGROUPS constructor.
|
||||
@ -357,6 +365,7 @@ function DETECTION_UNITGROUPS:New( DetectionGroups, DetectionRange, DetectionZon
|
||||
|
||||
-- Inherits from DETECTION_BASE
|
||||
local self = BASE:Inherit( self, DETECTION_BASE:New( DetectionGroups, DetectionRange ) )
|
||||
|
||||
self.DetectionZoneRange = DetectionZoneRange
|
||||
|
||||
self:Schedule( 10, 30 )
|
||||
@ -364,31 +373,73 @@ function DETECTION_UNITGROUPS:New( DetectionGroups, DetectionRange, DetectionZon
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get the detected @{Zone#ZONE_UNIT}s.
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @return #DETECTION_UNITGROUPS.DetectedZones DetectedZones
|
||||
function DETECTION_UNITGROUPS:GetDetectedZones()
|
||||
|
||||
local DetectedZones = self.DetectedZones
|
||||
return DetectedZones
|
||||
--- Add a detected @{#DETECTION_UNITGROUPS.DetectedArea}.
|
||||
-- @param Set#SET_UNIT Set -- The Set of Units in the detected area.
|
||||
-- @param Zone#ZONE_UNIT Zone -- The Zone of the detected area.
|
||||
-- @return #DETECTION_UNITGROUPS.DetectedArea DetectedArea
|
||||
function DETECTION_UNITGROUPS:AddDetectedArea( Set, Zone )
|
||||
local DetectedAreas = self:GetDetectedAreas()
|
||||
DetectedAreas.n = self:GetDetectedAreaCount() + 1
|
||||
DetectedAreas[DetectedAreas.n] = {}
|
||||
local DetectedArea = DetectedAreas[DetectedAreas.n]
|
||||
DetectedArea.Set = Set
|
||||
DetectedArea.Zone = Zone
|
||||
DetectedArea.AreaID = #DetectedAreas
|
||||
return DetectedArea
|
||||
end
|
||||
|
||||
--- Get the amount of @{Zone#ZONE_UNIT}s with detected units.
|
||||
--- Remove a detected @{#DETECTION_UNITGROUPS.DetectedArea} with a given Index.
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @return #number Count
|
||||
function DETECTION_UNITGROUPS:GetDetectedZoneCount()
|
||||
|
||||
local DetectedZoneCount = #self.DetectedZones
|
||||
return DetectedZoneCount
|
||||
-- @param #number Index The Index of the detection are to be removed.
|
||||
-- @return #nil
|
||||
function DETECTION_UNITGROUPS:RemoveDetectedArea( Index )
|
||||
local DetectedAreas = self:GetDetectedAreas()
|
||||
local DetectedAreaCount = self:GetDetectedAreaCount()
|
||||
DetectedAreas[Index] = nil
|
||||
DetectedAreas.n = DetectedAreas.n - 1
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get a SET of detected objects using a given numeric index.
|
||||
|
||||
--- Get the detected @{#DETECTION_UNITGROUPS.DetectedAreas}.
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @return #DETECTION_UNITGROUPS.DetectedAreas DetectedAreas
|
||||
function DETECTION_UNITGROUPS:GetDetectedAreas()
|
||||
|
||||
local DetectedAreas = self.DetectedAreas
|
||||
return DetectedAreas
|
||||
end
|
||||
|
||||
--- Get the amount of @{#DETECTION_UNITGROUPS.DetectedAreas}.
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @return #number DetectedAreaCount
|
||||
function DETECTION_UNITGROUPS:GetDetectedAreaCount()
|
||||
|
||||
local DetectedAreaCount = self.DetectedAreas.n
|
||||
return DetectedAreaCount
|
||||
end
|
||||
|
||||
--- Get the @{Set#SET_UNIT} of a detecttion area using a given numeric index.
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @param #number Index
|
||||
-- @return Zone#ZONE_UNIT
|
||||
-- @return Set#SET_UNIT DetectedSet
|
||||
function DETECTION_UNITGROUPS:GetDetectedSet( Index )
|
||||
|
||||
local DetectedSetUnit = self.DetectedAreas[Index].Set
|
||||
if DetectedSetUnit then
|
||||
return DetectedSetUnit
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index.
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @param #number Index
|
||||
-- @return Zone#ZONE_UNIT DetectedZone
|
||||
function DETECTION_UNITGROUPS:GetDetectedZone( Index )
|
||||
|
||||
local DetectedZone = self.DetectedZones[Index]
|
||||
local DetectedZone = self.DetectedAreas[Index].Zone
|
||||
if DetectedZone then
|
||||
return DetectedZone
|
||||
end
|
||||
@ -396,6 +447,7 @@ function DETECTION_UNITGROUPS:GetDetectedZone( Index )
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
--- Smoke the detected units
|
||||
-- @param #DETECTION_UNITGROUPS self
|
||||
-- @return #DETECTION_UNITGROUPS self
|
||||
@ -443,34 +495,126 @@ end
|
||||
function DETECTION_UNITGROUPS:CreateDetectionSets()
|
||||
self:F2()
|
||||
|
||||
for DetectedUnitName, DetectedUnitData in pairs( self.DetectedObjects ) do
|
||||
self:T( DetectedUnitData.Name )
|
||||
local DetectedUnit = UNIT:FindByName( DetectedUnitData.Name ) -- Unit#UNIT
|
||||
if DetectedUnit and DetectedUnit:IsAlive() then
|
||||
self:T( DetectedUnit:GetName() )
|
||||
if #self.DetectedSets == 0 then
|
||||
self:T( { "Adding Unit Set #", 1 } )
|
||||
self.DetectedZones[1] = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange )
|
||||
self.DetectedSets[1] = SET_UNIT:New()
|
||||
self.DetectedSets[1]:AddUnit( DetectedUnit )
|
||||
-- First go through all detected sets, and check if there are new detected units, match all existing detected units and identify undetected units.
|
||||
-- Regroup when needed, split groups when needed.
|
||||
for DetectedAreaID, DetectedAreaData in ipairs( self.DetectedAreas ) do
|
||||
|
||||
local DetectedArea = DetectedAreaData -- #DETECTION_UNITGROUPS.DetectedArea
|
||||
if DetectedArea then
|
||||
|
||||
local DetectedSet = DetectedArea.Set
|
||||
local DetectedZone = DetectedArea.Zone
|
||||
|
||||
-- first test if the center unit is detected in the detection area.
|
||||
|
||||
local AreaExists = false -- This flag will determine of the detected area is still existing.
|
||||
|
||||
local DetectedObject = self:GetDetectedObject( DetectedArea.Zone.ZoneUNIT.UnitName )
|
||||
self:T( DetectedObject )
|
||||
if DetectedObject then
|
||||
DetectedObject.Identified = true
|
||||
AreaExists = true
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "Detected Center Unit " .. DetectedArea.Zone.ZoneUNIT.UnitName } )
|
||||
else
|
||||
local AddedToSet = false
|
||||
for DetectedZoneIndex = 1, #self.DetectedZones do
|
||||
self:T( "Detected Unit Set #" .. DetectedZoneIndex )
|
||||
local DetectedUnitSet = self.DetectedSets[DetectedZoneIndex] -- Set#SET_BASE
|
||||
local DetectedZone = self.DetectedZones[DetectedZoneIndex] -- Zone#ZONE_UNIT
|
||||
if DetectedUnit:IsInZone( DetectedZone ) then
|
||||
self:T( "Adding to Unit Set #" .. DetectedZoneIndex )
|
||||
DetectedUnitSet:AddUnit( DetectedUnit )
|
||||
AddedToSet = true
|
||||
-- The center object of the detected area has not been detected. Find an other unit of the set to become the center of the area.
|
||||
-- First remove the center unit from the set.
|
||||
DetectedSet:RemoveUnitsByName( DetectedArea.Zone.ZoneUNIT.UnitName )
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "Removed Center Unit " .. DetectedArea.Zone.ZoneUNIT.UnitName } )
|
||||
for DetectedUnitName, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
|
||||
local DetectedUnit = DetectedUnitData -- Unit#UNIT
|
||||
local DetectedObject = self:GetDetectedObject( DetectedUnit.UnitName )
|
||||
if DetectedObject then
|
||||
if DetectedObject.Identified == false and DetectedUnit:IsAlive() then
|
||||
DetectedObject.Identified = true
|
||||
AreaExists = true
|
||||
-- Assign the Unit as the new center unit of the detected area.
|
||||
DetectedArea.Zone = ZONE_UNIT:New( DetectedUnit:GetName(), DetectedUnit, self.DetectionZoneRange )
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "New Center Unit " .. DetectedArea.Zone.ZoneUNIT.UnitName } )
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
if AddedToSet == false then
|
||||
local DetectedZoneIndex = #self.DetectedZones + 1
|
||||
self:T( "Adding new zone #" .. DetectedZoneIndex )
|
||||
self.DetectedZones[DetectedZoneIndex] = ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange )
|
||||
self.DetectedSets[DetectedZoneIndex] = SET_UNIT:New()
|
||||
self.DetectedSets[DetectedZoneIndex]:AddUnit( DetectedUnit )
|
||||
end
|
||||
|
||||
-- Now we've determined the center unit of the area, now we can iterate the units in the detected area.
|
||||
-- Note that the position of the area may have moved due to the center unit repositioning.
|
||||
-- If no center unit was identified, then the detected area does not exist anymore and should be deleted, as there are no valid units that can be the center unit.
|
||||
if AreaExists then
|
||||
-- ok, we found the center unit of the area, now iterate through the detected area set and see which units are still within the center unit zone ...
|
||||
-- Those units within the zone are flagged as Identified.
|
||||
-- If a unit was not found in the set, remove it from the set. This may be added later to other existing or new sets.
|
||||
for DetectedUnitName, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
|
||||
local DetectedUnit = DetectedUnitData -- Unit#UNIT
|
||||
local DetectedObject = self:GetDetectedObject( DetectedUnit:GetName() )
|
||||
if DetectedObject then
|
||||
if DetectedObject.Identified == false then
|
||||
if DetectedUnit:IsInZone( DetectedZone ) then
|
||||
DetectedObject.Identified = true
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "Unit in zone " .. DetectedUnit.UnitName } )
|
||||
else
|
||||
-- Not anymore in the zone. Remove from the set.
|
||||
DetectedSet:Remove( DetectedUnitName )
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "Unit not in zone " .. DetectedUnit.UnitName } )
|
||||
end
|
||||
end
|
||||
else
|
||||
-- The detected object has not been found, delete from the Set!
|
||||
DetectedSet:Remove( DetectedUnitName )
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "Unit not found " .. DetectedUnit.UnitName } )
|
||||
end
|
||||
end
|
||||
else
|
||||
self:T( { DetectedArea = DetectedArea.AreaID, "Removed detected area " } )
|
||||
self:RemoveDetectedArea( DetectedAreaID )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- We iterated through the existing detection areas and:
|
||||
-- - We checked which units are still detected in each detection area. Those units were flagged as Identified.
|
||||
-- - We recentered the detection area to new center units where it was needed.
|
||||
--
|
||||
-- Now we need to loop through the unidentified detected units and see where they belong:
|
||||
-- - They can be added to a new detection area and become the new center unit.
|
||||
-- - They can be added to a new detection area.
|
||||
for DetectedUnitName, DetectedObjectData in pairs( self.DetectedObjects ) do
|
||||
|
||||
local DetectedObject = DetectedObjectData -- #DETECTION_BASE.DetectedObject
|
||||
|
||||
if DetectedObject.Identified == false then
|
||||
-- We found an unidentified unit outside of any existing detection area.
|
||||
|
||||
local DetectedUnit = UNIT:FindByName( DetectedObjectData.Name ) -- Unit#UNIT
|
||||
|
||||
if DetectedUnit and DetectedUnit:IsAlive() then
|
||||
self:T( { "Search for " .. DetectedObjectData.Name, DetectedObjectData.Identified } )
|
||||
|
||||
local AddedToDetectionArea = false
|
||||
for DetectedAreaID, DetectedAreaData in ipairs( self.DetectedAreas ) do
|
||||
|
||||
local DetectedArea = DetectedAreaData -- #DETECTION_UNITGROUPS.DetectedArea
|
||||
if DetectedArea then
|
||||
self:T( "Detection Area #" .. DetectedArea.AreaID )
|
||||
local DetectedSet = DetectedArea.Set
|
||||
local DetectedZone = DetectedArea.Zone -- Zone#ZONE_UNIT
|
||||
if DetectedUnit:IsInZone( DetectedZone ) then
|
||||
DetectedSet:AddUnit( DetectedUnit )
|
||||
AddedToDetectionArea = true
|
||||
DetectedObject.Identified = true
|
||||
self:T( "Detection Area #" .. DetectedArea.AreaID .. " added unit " .. DetectedUnit.UnitName )
|
||||
end
|
||||
end
|
||||
end
|
||||
if AddedToDetectionArea == false then
|
||||
-- New detection area
|
||||
local DetectedArea = self:AddDetectedArea(
|
||||
SET_UNIT:New(),
|
||||
ZONE_UNIT:New( DetectedUnitName, DetectedUnit, self.DetectionZoneRange )
|
||||
)
|
||||
self:T( { "Added Detection Area #", DetectedArea.AreaID } )
|
||||
DetectedArea.Set:AddUnit( DetectedUnit )
|
||||
self:T( "Detection Area #" .. DetectedArea.AreaID .. " added unit " .. DetectedUnit.UnitName )
|
||||
DetectedObject.Identified = true
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -478,14 +622,17 @@ function DETECTION_UNITGROUPS:CreateDetectionSets()
|
||||
|
||||
-- Now all the tests should have been build, now make some smoke and flares...
|
||||
|
||||
for DetectedZoneIndex = 1, #self.DetectedZones do
|
||||
local DetectedUnitSet = self.DetectedSets[DetectedZoneIndex] -- Set#SET_BASE
|
||||
local DetectedZone = self.DetectedZones[DetectedZoneIndex] -- Zone#ZONE_UNIT
|
||||
self:T( "Detected Set #" .. DetectedZoneIndex )
|
||||
DetectedUnitSet:ForEachUnit(
|
||||
for DetectedAreaID, DetectedAreaData in ipairs( self.DetectedAreas ) do
|
||||
|
||||
|
||||
local DetectedArea = DetectedAreaData -- #DETECTION_UNITGROUPS.DetectedArea
|
||||
local DetectedSet = DetectedArea.Set
|
||||
local DetectedZone = DetectedArea.Zone
|
||||
DetectedZone.ZoneUNIT:SmokeRed()
|
||||
DetectedSet:ForEachUnit(
|
||||
--- @param Unit#UNIT DetectedUnit
|
||||
function( DetectedUnit )
|
||||
self:T( DetectedUnit:GetName() )
|
||||
self:T( "Detected Set #" .. DetectedArea.AreaID .. ":" .. DetectedUnit:GetName() )
|
||||
if self._FlareDetectedUnits then
|
||||
DetectedUnit:FlareRed()
|
||||
end
|
||||
|
||||
@ -1,44 +1,45 @@
|
||||
--- This module contains the FAC classes.
|
||||
--- This module contains the DETECTION_MANAGER class and derived classes.
|
||||
-- @module DetectionManager
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 1) @{Fac#DETECTION_MANAGER} class, extends @{Base#BASE}
|
||||
-- ==============================================
|
||||
-- The @{Fac#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
||||
-- 1) @{DetectionManager#DETECTION_MANAGER} class, extends @{Base#BASE}
|
||||
-- ====================================================================
|
||||
-- The @{DetectionManager#DETECTION_MANAGER} class defines the core functions to report detected objects to groups.
|
||||
-- Reportings can be done in several manners, and it is up to the derived classes if DETECTION_MANAGER to model the reporting behaviour.
|
||||
--
|
||||
-- 1.1) DETECTION_MANAGER constructor:
|
||||
-- ----------------------------
|
||||
-- * @{Fac#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
||||
-- -----------------------------------
|
||||
-- * @{DetectionManager#DETECTION_MANAGER.New}(): Create a new DETECTION_MANAGER instance.
|
||||
--
|
||||
-- 1.2) DETECTION_MANAGER reporting:
|
||||
-- ------------------------
|
||||
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{Fac#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
|
||||
-- ---------------------------------
|
||||
-- Derived DETECTION_MANAGER classes will reports detected units using the method @{DetectionManager#DETECTION_MANAGER.ReportDetected}(). This method implements polymorphic behaviour.
|
||||
--
|
||||
-- The time interval in seconds of the reporting can be changed using the methods @{Fac#DETECTION_MANAGER.SetReportInterval}().
|
||||
-- To control how long a reporting message is displayed, use @{Fac#DETECTION_MANAGER.SetReportDisplayTime}().
|
||||
-- Derived classes need to implement the method @{Fac#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
|
||||
-- The time interval in seconds of the reporting can be changed using the methods @{DetectionManager#DETECTION_MANAGER.SetReportInterval}().
|
||||
-- To control how long a reporting message is displayed, use @{DetectionManager#DETECTION_MANAGER.SetReportDisplayTime}().
|
||||
-- Derived classes need to implement the method @{DetectionManager#DETECTION_MANAGER.GetReportDisplayTime}() to use the correct display time for displayed messages during a report.
|
||||
--
|
||||
-- Reporting can be started and stopped using the methods @{Fac#DETECTION_MANAGER.StartReporting}() and @{Fac#DETECTION_MANAGER.StopReporting}() respectively.
|
||||
-- If an ad-hoc report is requested, use the method @{Fac#DETECTION_MANAGER#ReportNow}().
|
||||
-- Reporting can be started and stopped using the methods @{DetectionManager#DETECTION_MANAGER.StartReporting}() and @{DetectionManager#DETECTION_MANAGER.StopReporting}() respectively.
|
||||
-- If an ad-hoc report is requested, use the method @{DetectionManager#DETECTION_MANAGER#ReportNow}().
|
||||
--
|
||||
-- The default reporting interval is every 60 seconds. The reporting messages are displayed 15 seconds.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- 2) @{Fac#FAC_REPORTING} class, extends @{Fac#DETECTION_MANAGER}
|
||||
-- 2) @{DetectionManager#FAC_REPORTING} class, extends @{DetectionManager#DETECTION_MANAGER}
|
||||
-- ======================================================
|
||||
-- The @{Fac#FAC_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{Fac#DETECTION_MANAGER} class.
|
||||
-- The @{DetectionManager#FAC_REPORTING} class implements detected units reporting. Reporting can be controlled using the reporting methods available in the @{DetectionManager#DETECTION_MANAGER} class.
|
||||
--
|
||||
-- 2.1) FAC_REPORTING constructor:
|
||||
-- -------------------------------
|
||||
-- The @{Fac#FAC_REPORTING.New}() method creates a new FAC_REPORTING instance.
|
||||
-- The @{DetectionManager#FAC_REPORTING.New}() method creates a new FAC_REPORTING instance.
|
||||
--
|
||||
-- ===
|
||||
--
|
||||
-- @module Fac
|
||||
-- @author Mechanic, Prof_Hilactic, FlightControl : Concept & Testing
|
||||
-- @author FlightControl : Design & Programming
|
||||
-- ### Contributions - Mechanic, Prof_Hilactic, FlightControl : Concept & Testing
|
||||
-- ### Author - FlightControl : Framework Design & Programming
|
||||
--
|
||||
|
||||
|
||||
|
||||
@ -68,7 +69,7 @@ function DETECTION_MANAGER:New( SetGroup, Detection )
|
||||
|
||||
self:SetReportInterval( 60 )
|
||||
self:SetReportDisplayTime( 15 )
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -102,47 +103,15 @@ function DETECTION_MANAGER:GetReportDisplayTime()
|
||||
return self._ReportDisplayTime
|
||||
end
|
||||
|
||||
--- Creates a string of the detected items in a @{Set}.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Set#SET_BASE DetectedSets The detected Sets created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @return #DETECTION_MANAGER self
|
||||
function DETECTION_MANAGER:GetDetectedItemsText( DetectedSet )
|
||||
self:F2()
|
||||
|
||||
local MT = {} -- Message Text
|
||||
local UnitTypes = {}
|
||||
|
||||
for DetectedUnitID, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
|
||||
local DetectedUnit = DetectedUnitData -- Unit#UNIT
|
||||
local UnitType = DetectedUnit:GetTypeName()
|
||||
|
||||
if not UnitTypes[UnitType] then
|
||||
UnitTypes[UnitType] = 1
|
||||
else
|
||||
UnitTypes[UnitType] = UnitTypes[UnitType] + 1
|
||||
end
|
||||
end
|
||||
|
||||
for UnitTypeID, UnitType in pairs( UnitTypes ) do
|
||||
MT[#MT+1] = UnitType .. " of " .. UnitTypeID
|
||||
end
|
||||
|
||||
local MessageText = table.concat( MT, ", " )
|
||||
|
||||
return MessageText
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Reports the detected items to the @{Set#SET_GROUP}.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Set#SET_BASE DetectedSets The detected Sets created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @param Detection#DETECTION_BASE Detection
|
||||
-- @return #DETECTION_MANAGER self
|
||||
function DETECTION_MANAGER:ReportDetected( DetectedSets )
|
||||
function DETECTION_MANAGER:ReportDetected( Detection )
|
||||
self:F2()
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- Schedule the FAC reporting.
|
||||
@ -157,7 +126,7 @@ function DETECTION_MANAGER:Schedule( DelayTime, ReportInterval )
|
||||
|
||||
self:SetReportInterval( ReportInterval )
|
||||
|
||||
self.FacScheduler = SCHEDULER:New(self, self._FacScheduler, { self, "Fac" }, self._ScheduleDelayTime, self._ReportInterval )
|
||||
self.FacScheduler = SCHEDULER:New(self, self._FacScheduler, { self, "DetectionManager" }, self._ScheduleDelayTime, self._ReportInterval )
|
||||
return self
|
||||
end
|
||||
|
||||
@ -170,9 +139,7 @@ function DETECTION_MANAGER:_FacScheduler( SchedulerName )
|
||||
--- @param Group#GROUP Group
|
||||
function( Group )
|
||||
if Group:IsAlive() then
|
||||
local DetectedSets = self.Detection:GetDetectedSets()
|
||||
local DetectedZones =self.Detection:GetDetectedZones()
|
||||
return self:ProcessDetected( Group, DetectedSets, DetectedZones )
|
||||
return self:ProcessDetected( Group, self.Detection )
|
||||
end
|
||||
end
|
||||
)
|
||||
@ -195,7 +162,7 @@ FAC_REPORTING = {
|
||||
--- FAC_REPORTING constructor.
|
||||
-- @param #FAC_REPORTING self
|
||||
-- @param Set#SET_GROUP SetGroup
|
||||
-- @param Detection#DETECTION_BASE Detection
|
||||
-- @param Detection#DETECTION_UNITGROUPS Detection
|
||||
-- @return #FAC_REPORTING self
|
||||
function FAC_REPORTING:New( SetGroup, Detection )
|
||||
|
||||
@ -206,22 +173,51 @@ function FAC_REPORTING:New( SetGroup, Detection )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Creates a string of the detected items in a @{Detection}.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Set#SET_UNIT DetectedSet The detected Set created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @return #DETECTION_MANAGER self
|
||||
function FAC_REPORTING:GetDetectedItemsText( DetectedSet )
|
||||
self:F2()
|
||||
|
||||
local MT = {} -- Message Text
|
||||
local UnitTypes = {}
|
||||
|
||||
for DetectedUnitID, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
|
||||
local DetectedUnit = DetectedUnitData -- Unit#UNIT
|
||||
local UnitType = DetectedUnit:GetTypeName()
|
||||
|
||||
if not UnitTypes[UnitType] then
|
||||
UnitTypes[UnitType] = 1
|
||||
else
|
||||
UnitTypes[UnitType] = UnitTypes[UnitType] + 1
|
||||
end
|
||||
end
|
||||
|
||||
for UnitTypeID, UnitType in pairs( UnitTypes ) do
|
||||
MT[#MT+1] = UnitType .. " of " .. UnitTypeID
|
||||
end
|
||||
|
||||
return table.concat( MT, ", " )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Reports the detected items to the @{Set#SET_GROUP}.
|
||||
-- @param #FAC_REPORTING self
|
||||
-- @param Group#GROUP Group The @{Group} object to where the report needs to go.
|
||||
-- @param Set#SET_BASE DetectedSets The detected Sets created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @param Detection#DETECTION_UNITGROUPS Detection The detection created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @return #boolean Return true if you want the reporting to continue... false will cancel the reporting loop.
|
||||
function FAC_REPORTING:ProcessDetected( Group, DetectedSets, DetectedZones )
|
||||
function FAC_REPORTING:ProcessDetected( Group, Detection )
|
||||
self:F2( Group )
|
||||
|
||||
self:E( Group )
|
||||
local DetectedMsg = {}
|
||||
for DetectedUnitSetID, DetectedUnitSet in pairs( DetectedSets ) do
|
||||
local UnitSet = DetectedUnitSet -- Set#SET_UNIT
|
||||
DetectedMsg[#DetectedMsg+1] = " - Group #" .. DetectedUnitSetID .. ": " .. self:GetDetectedItemsText( UnitSet )
|
||||
for DetectedAreaID, DetectedAreaData in pairs( Detection:GetDetectedAreas() ) do
|
||||
local DetectedArea = DetectedAreaData -- Detection#DETECTION_UNITGROUPS.DetectedArea
|
||||
DetectedMsg[#DetectedMsg+1] = " - Group #" .. DetectedAreaID .. ": " .. self:GetDetectedItemsText( DetectedArea.Set )
|
||||
end
|
||||
local FACGroup = self.Detection:GetDetectionGroups()
|
||||
local FACGroup = Detection:GetDetectionGroups()
|
||||
FACGroup:MessageToGroup( "Reporting detected target groups:\n" .. table.concat( DetectedMsg, "\n" ), self:GetReportDisplayTime(), Group )
|
||||
|
||||
return true
|
||||
@ -236,7 +232,7 @@ end
|
||||
-- @field Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects.
|
||||
-- @field Mission#MISSION Mission
|
||||
-- @field Group#GROUP CommandCenter
|
||||
-- @extends #DETECTION_MANAGER
|
||||
-- @extends DetectionManager#DETECTION_MANAGER
|
||||
TASK_DISPATCHER = {
|
||||
ClassName = "TASK_DISPATCHER",
|
||||
Mission = nil,
|
||||
@ -264,13 +260,106 @@ function TASK_DISPATCHER:New( Mission, CommandCenter, SetGroup, Detection )
|
||||
end
|
||||
|
||||
|
||||
--- Creates a SEAD task when there are targets for it.
|
||||
-- @param #TASK_DISPATCHER self
|
||||
-- @param Mission#MISSION Mission
|
||||
-- @param Detection#DETECTION_UNITGROUPS.DetectedArea DetectedArea
|
||||
-- @return #string Message explaining which task was added.
|
||||
function TASK_DISPATCHER:EvaluateTaskSEAD( Mission, DetectedArea )
|
||||
self:F( { Mission, DetectedArea.AreaID } )
|
||||
|
||||
MT = {}
|
||||
|
||||
local DetectedSet = DetectedArea.Set
|
||||
local DetectedZone = DetectedArea.Zone
|
||||
|
||||
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
||||
local RadarCount = DetectedSet:HasRadar( Unit.RadarType.AS )
|
||||
DetectedArea.Tasks = DetectedArea.Tasks or {}
|
||||
if RadarCount > 0 then
|
||||
if not DetectedArea.Tasks.SEADTask then
|
||||
local Task = TASK_SEAD:New( Mission, DetectedSet, DetectedZone )
|
||||
self.Mission:AddTask( Task )
|
||||
MT[#MT+1] = "SEAD"
|
||||
DetectedArea.Tasks.SEADTask = Task
|
||||
end
|
||||
else
|
||||
if DetectedArea.Tasks.SEADTask then
|
||||
-- Abort Task
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat( MT, "," )
|
||||
end
|
||||
|
||||
--- Creates a CAS task when there are targets for it.
|
||||
-- @param #TASK_DISPATCHER self
|
||||
-- @param Mission#MISSION Mission
|
||||
-- @param Detection#DETECTION_UNITGROUPS.DetectedArea DetectedArea
|
||||
-- @return #string Message explaining which task was added.
|
||||
function TASK_DISPATCHER:EvaluateTaskCAS( Mission, DetectedArea )
|
||||
self:F2( { Mission, DetectedArea.AreaID } )
|
||||
|
||||
MT = {}
|
||||
|
||||
local DetectedSet = DetectedArea.Set
|
||||
local DetectedZone = DetectedArea.Zone
|
||||
|
||||
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
||||
local GroundUnitCount = DetectedSet:HasGroundUnits()
|
||||
DetectedArea.Tasks = DetectedArea.Tasks or {}
|
||||
if GroundUnitCount > 0 then
|
||||
if not DetectedArea.Tasks.CASTask then
|
||||
local Task = TASK_CAS:New( Mission, DetectedSet , DetectedZone )
|
||||
self.Mission:AddTask( Task )
|
||||
MT[#MT+1] = "CAS"
|
||||
DetectedArea.Tasks.CASTask = Task
|
||||
end
|
||||
else
|
||||
if DetectedArea.Tasks.CASTask then
|
||||
-- Abort Mission
|
||||
end
|
||||
end
|
||||
|
||||
return table.concat( MT, "," )
|
||||
end
|
||||
|
||||
--- Creates a string of the detected items in a @{Detection}.
|
||||
-- @param #DETECTION_MANAGER self
|
||||
-- @param Set#SET_UNIT DetectedSet The detected Set created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @return #DETECTION_MANAGER self
|
||||
function TASK_DISPATCHER:GetDetectedItemsText( DetectedSet )
|
||||
self:F2()
|
||||
|
||||
local MT = {} -- Message Text
|
||||
local UnitTypes = {}
|
||||
|
||||
for DetectedUnitID, DetectedUnitData in pairs( DetectedSet:GetSet() ) do
|
||||
local DetectedUnit = DetectedUnitData -- Unit#UNIT
|
||||
local UnitType = DetectedUnit:GetTypeName()
|
||||
|
||||
if not UnitTypes[UnitType] then
|
||||
UnitTypes[UnitType] = 1
|
||||
else
|
||||
UnitTypes[UnitType] = UnitTypes[UnitType] + 1
|
||||
end
|
||||
end
|
||||
|
||||
for UnitTypeID, UnitType in pairs( UnitTypes ) do
|
||||
MT[#MT+1] = UnitType .. " of " .. UnitTypeID
|
||||
end
|
||||
|
||||
return table.concat( MT, ", " )
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
|
||||
-- @param #TASK_DISPATCHER self
|
||||
-- @param Group#GROUP Group The @{Group} object to where the report needs to go.
|
||||
-- @param #table DetectedSets The detected Sets created by the @{Detection#DETECTION_BASE} object.
|
||||
-- @param #table DetectedZones The detected Zones cretaed by the @{Detection#DETECTION_BASE} object.
|
||||
-- @param Detection#DETECTION_UNITGROUPS Detection The detection created by the @{Detection#DETECTION_UNITGROUPS} object.
|
||||
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
|
||||
function TASK_DISPATCHER:ProcessDetected( TaskGroup, DetectedSets, DetectedZones )
|
||||
function TASK_DISPATCHER:ProcessDetected( TaskGroup, Detection )
|
||||
self:F2( TaskGroup )
|
||||
|
||||
local DetectedMsg = {}
|
||||
@ -281,33 +370,31 @@ function TASK_DISPATCHER:ProcessDetected( TaskGroup, DetectedSets, DetectedZones
|
||||
self:E( TaskGroup )
|
||||
|
||||
--- First we need to the detected targets.
|
||||
for DetectedID, DetectedUnitSet in pairs( DetectedSets ) do
|
||||
local UnitSet = DetectedUnitSet -- Set#SET_UNIT
|
||||
for DetectedAreaID, DetectedAreaData in ipairs( Detection:GetDetectedAreas() ) do
|
||||
local DetectedArea = DetectedAreaData -- Detection#DETECTION_UNITGROUPS.DetectedArea
|
||||
local TargetSetUnit = DetectedArea.Set
|
||||
local MT = {} -- Message Text
|
||||
local UnitTypes = {}
|
||||
local TargetZone = DetectedArea.Zone -- Zone#ZONE_BASE
|
||||
Detection:FlareDetectedZones()
|
||||
Detection:FlareDetectedUnits()
|
||||
|
||||
for DetectedUnitID, DetectedUnitData in pairs( UnitSet:GetSet() ) do
|
||||
for DetectedUnitID, DetectedUnitData in pairs( TargetSetUnit:GetSet() ) do
|
||||
|
||||
local DetectedUnit = DetectedUnitData -- Unit#UNIT
|
||||
self:E( DetectedUnit )
|
||||
local DetectedUnitName = DetectedUnit:GetName()
|
||||
local UnitType = DetectedUnit:GetTypeName()
|
||||
local TargetUnit = DetectedUnitData -- Unit#UNIT
|
||||
self:E( TargetUnit )
|
||||
local TargetUnitName = TargetUnit:GetName()
|
||||
local TargetUnitType = TargetUnit:GetTypeName()
|
||||
|
||||
-- Determine if the set has radar targets. If it does, construct a SEAD task.
|
||||
local RadarCount = UnitSet:HasRadar( Unit.RadarType.AS )
|
||||
if RadarCount > 0 then
|
||||
local DetectedZone = DetectedZones[DetectedID]
|
||||
local Task = TASK_SEAD:New( self.Mission, UnitSet, DetectedZone, UnitSet )
|
||||
self.Mission:AddTask( Task )
|
||||
MT[#MT+1] = "SEAD task added."
|
||||
end
|
||||
MT[#MT+1] = self:EvaluateTaskSEAD( self.Mission, DetectedArea )
|
||||
MT[#MT+1] = self:EvaluateTaskCAS( self.Mission, DetectedArea )
|
||||
end
|
||||
|
||||
DetectedMsg[#DetectedMsg+1] = " - Group #" .. DetectedID .. ": " .. self:GetDetectedItemsText( UnitSet ) .. ". " .. table.concat( MT, "," )
|
||||
DetectedMsg[#DetectedMsg+1] = " - Group #" .. DetectedAreaID .. ": " .. self:GetDetectedItemsText( TargetSetUnit ) .. ". " .. table.concat( MT, "," ) .. " tasks addded."
|
||||
end
|
||||
|
||||
self.CommandCenter:MessageToGroup( "Reporting tasks for target groups:\n" .. table.concat( DetectedMsg, "\n" ), self:GetReportDisplayTime(), TaskGroup )
|
||||
self.Mission:FillMissionMenu( TaskGroup )
|
||||
self.Mission:CreateTaskMenus( TaskGroup )
|
||||
|
||||
return true
|
||||
end
|
||||
@ -112,7 +112,7 @@ end
|
||||
--- Fill mission menu for the Group.
|
||||
-- @param #MISSION self
|
||||
-- @return #MISSION self
|
||||
function MISSION:FillMissionMenu( TaskGroup )
|
||||
function MISSION:CreateTaskMenus( TaskGroup )
|
||||
|
||||
local MissionMenu = self:GetMissionMenu()
|
||||
local TaskMenus = self.TaskMenus
|
||||
@ -142,6 +142,9 @@ function MISSION:FillMissionMenu( TaskGroup )
|
||||
end
|
||||
TaskMenus[TaskMenuID].MenuType = TaskTypeMenus[TaskType]
|
||||
|
||||
if TaskMenus[TaskMenuID].Menu then
|
||||
TaskMenus[TaskMenuID].Menu:Remove()
|
||||
end
|
||||
TaskMenus[TaskMenuID].Menu = MENU_GROUP_COMMAND:New( TaskGroup, TaskName .. "." .. TaskID, TaskMenus[TaskMenuID].MenuType, self.AssignTaskToGroup, { self = self, Task = Task, TaskGroup = TaskGroup } )
|
||||
|
||||
end
|
||||
|
||||
@ -45,13 +45,14 @@ Include.File( "PatrolZone" )
|
||||
Include.File( "AIBalancer" )
|
||||
Include.File( "AirbasePolice" )
|
||||
Include.File( "Detection" )
|
||||
Include.File( "FAC" )
|
||||
Include.File( "DetectionManager" )
|
||||
Include.File( "StateMachine" )
|
||||
Include.File( "Process" )
|
||||
Include.File( "Process_Assign" )
|
||||
Include.File( "Process_Route" )
|
||||
Include.File( "Process_SEAD" )
|
||||
Include.File( "Task" )
|
||||
Include.File( "Task_CAS" )
|
||||
Include.File( "Task_SEAD" )
|
||||
|
||||
-- The order of the declarations is important here. Don't touch it.
|
||||
|
||||
142
Moose Development/Moose/Process_CAS.lua
Normal file
142
Moose Development/Moose/Process_CAS.lua
Normal file
@ -0,0 +1,142 @@
|
||||
--- @module Process_CAS
|
||||
|
||||
--- PROCESS_CAS class
|
||||
-- @type PROCESS_CAS
|
||||
-- @field Unit#UNIT ProcessUnit
|
||||
-- @field Set#SET_UNIT TargetSetUnit
|
||||
-- @extends Process#PROCESS
|
||||
PROCESS_CAS = {
|
||||
ClassName = "PROCESS_CAS",
|
||||
Fsm = {},
|
||||
TargetSetUnit = nil,
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new CAS task.
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param Task#TASK Task
|
||||
-- @param Unit#UNIT ProcessUnit
|
||||
-- @param Set#SET_UNIT TargetSetUnit
|
||||
-- @return #PROCESS_CAS self
|
||||
function PROCESS_CAS:New( Task, ProcessUnit, TargetSetUnit )
|
||||
|
||||
-- Inherits from BASE
|
||||
local self = BASE:Inherit( self, PROCESS:New( Task, ProcessUnit ) ) -- #PROCESS_CAS
|
||||
|
||||
self.TargetSetUnit = TargetSetUnit
|
||||
|
||||
self.Fsm = STATEMACHINE_PROCESS:New( self, {
|
||||
initial = 'Assigned',
|
||||
events = {
|
||||
{ name = 'Await', from = 'Assigned', to = 'Waiting' },
|
||||
{ name = 'HitTarget', from = 'Waiting', to = 'Destroy' },
|
||||
{ name = 'MoreTargets', from = 'Destroy', to = 'Waiting' },
|
||||
{ name = 'Destroyed', from = 'Destroy', to = 'Success' },
|
||||
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
|
||||
{ name = 'Fail', from = 'Waiting', to = 'Failed' },
|
||||
{ name = 'Fail', from = 'Destroy', to = 'Failed' },
|
||||
},
|
||||
callbacks = {
|
||||
onAwait = self.OnAwait,
|
||||
onHitTarget = self.OnHitTarget,
|
||||
onMoreTargets = self.OnMoreTargets,
|
||||
onDestroyed = self.OnDestroyed,
|
||||
onKilled = self.OnKilled,
|
||||
},
|
||||
endstates = { 'Success', 'Failed' }
|
||||
} )
|
||||
|
||||
|
||||
_EVENTDISPATCHER:OnDead( self.EventDead, self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Process Events
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_CAS:OnAwait( Fsm, Event, From, To )
|
||||
self:E( { Event, From, To, self.ProcessUnit.UnitName} )
|
||||
|
||||
self:NextEvent( Fsm.Await )
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Event#EVENTDATA Event
|
||||
function PROCESS_CAS:OnHitTarget( Fsm, Event, From, To, Event )
|
||||
|
||||
if self.TargetSetUnit:Count() > 0 then
|
||||
self:NextEvent( Fsm.MoreTargets )
|
||||
else
|
||||
self:NextEvent( Fsm.Destroyed )
|
||||
end
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_CAS:OnMoreTargets( Fsm, Event, From, To )
|
||||
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Event#EVENTDATA DCSEvent
|
||||
function PROCESS_CAS:OnKilled( Fsm, Event, From, To )
|
||||
|
||||
self:NextEvent( Fsm.Restart )
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_CAS:OnRestart( Fsm, Event, From, To )
|
||||
|
||||
self:NextEvent( Fsm.Menu )
|
||||
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a PROCESS
|
||||
-- @param #PROCESS_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_PROCESS Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_CAS:OnDestroyed( Fsm, Event, From, To )
|
||||
|
||||
end
|
||||
|
||||
--- DCS Events
|
||||
|
||||
--- @param #PROCESS_CAS self
|
||||
-- @param Event#EVENTDATA Event
|
||||
function PROCESS_CAS:EventDead( Event )
|
||||
|
||||
if Event.IniUnit then
|
||||
self:NextEvent( self.Fsm.HitTarget, Event )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -224,9 +224,13 @@
|
||||
|
||||
--- SET_BASE class
|
||||
-- @type SET_BASE
|
||||
-- @field #table Filter
|
||||
-- @field #table Set
|
||||
-- @field #table List
|
||||
-- @extends Base#BASE
|
||||
SET_BASE = {
|
||||
ClassName = "SET_BASE",
|
||||
Filter = {},
|
||||
Set = {},
|
||||
List = {},
|
||||
}
|
||||
@ -280,7 +284,7 @@ end
|
||||
-- @param Base#BASE Object
|
||||
-- @return Base#BASE The added BASE Object.
|
||||
function SET_BASE:Add( ObjectName, Object )
|
||||
self:E( ObjectName )
|
||||
self:F2( ObjectName )
|
||||
|
||||
local t = { _ = Object }
|
||||
|
||||
@ -304,7 +308,7 @@ end
|
||||
-- @param #SET_BASE self
|
||||
-- @param #string ObjectName
|
||||
function SET_BASE:Remove( ObjectName )
|
||||
self:E( ObjectName )
|
||||
self:F2( ObjectName )
|
||||
|
||||
local t = self.Set[ObjectName]
|
||||
|
||||
@ -345,6 +349,18 @@ function SET_BASE:Count()
|
||||
return self.List.Count
|
||||
end
|
||||
|
||||
--- Copies the Filter criteria from a given Set (for rebuilding a new Set based on an existing Set).
|
||||
-- @param #SET_BASE self
|
||||
-- @param #SET_BASE OtherSet
|
||||
-- @return #SET_BASE
|
||||
function SET_BASE:CopyFilter( OtherSet )
|
||||
|
||||
local OtherFilter = routines.utils.deepCopy( OtherSet.Filter )
|
||||
self.Filter = OtherFilter
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Define the SET iterator **"yield interval"** and the **"time interval"**.
|
||||
-- @param #SET_BASE self
|
||||
@ -1184,6 +1200,22 @@ function SET_UNIT:FilterPrefixes( Prefixes )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Builds a set of units having a radar of give types.
|
||||
-- All the units having a radar of a given type will be included within the set.
|
||||
-- @param #SET_UNIT self
|
||||
-- @param #table RadarTypes The radar types.
|
||||
-- @return #SET_UNIT self
|
||||
function SET_UNIT:FilterHasRadar( RadarTypes )
|
||||
|
||||
self.Filter.RadarTypes = self.Filter.RadarTypes or {}
|
||||
if type( RadarTypes ) ~= "table" then
|
||||
RadarTypes = { RadarTypes }
|
||||
end
|
||||
for RadarTypeID, RadarType in pairs( RadarTypes ) do
|
||||
self.Filter.RadarTypes[RadarType] = RadarType
|
||||
end
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
@ -1310,6 +1342,23 @@ function SET_UNIT:HasRadar( RadarType )
|
||||
end
|
||||
|
||||
|
||||
--- Returns if the @{Set} has ground targets.
|
||||
-- @param #SET_UNIT self
|
||||
-- @return #number The amount of ground targets in the Set.
|
||||
function SET_UNIT:HasGroundUnits()
|
||||
self:F2()
|
||||
|
||||
local GroundUnitCount = 0
|
||||
for UnitID, UnitData in pairs( self:GetSet()) do
|
||||
local UnitTest = UnitData -- Unit#UNIT
|
||||
if UnitTest:IsGround() then
|
||||
GroundUnitCount = GroundUnitCount + 1
|
||||
end
|
||||
end
|
||||
|
||||
return GroundUnitCount
|
||||
end
|
||||
|
||||
|
||||
|
||||
----- Iterate the SET_UNIT and call an interator function for each **alive** player, providing the Unit of the player and optional parameters.
|
||||
@ -1401,6 +1450,17 @@ function SET_UNIT:IsIncludeObject( MUnit )
|
||||
MUnitInclude = MUnitInclude and MUnitPrefix
|
||||
end
|
||||
|
||||
if self.Filter.RadarTypes then
|
||||
local MUnitRadar = false
|
||||
for RadarTypeID, RadarType in pairs( self.Filter.RadarTypes ) do
|
||||
self:T3( { "Radar:", RadarType } )
|
||||
if MUnit:HasSensors( Unit.SensorType.RADAR, RadarType ) then
|
||||
MUnitRadar = true
|
||||
end
|
||||
end
|
||||
MUnitInclude = MUnitInclude and MUnitRadar
|
||||
end
|
||||
|
||||
self:T2( MUnitInclude )
|
||||
return MUnitInclude
|
||||
end
|
||||
|
||||
105
Moose Development/Moose/Task_CAS.lua
Normal file
105
Moose Development/Moose/Task_CAS.lua
Normal file
@ -0,0 +1,105 @@
|
||||
--- @module Task_CAS
|
||||
|
||||
--- The TASK_CAS class
|
||||
-- @type TASK_CAS
|
||||
-- @extends Task#TASK_BASE
|
||||
TASK_CAS = {
|
||||
ClassName = "TASK_CAS",
|
||||
}
|
||||
|
||||
--- Instantiates a new TASK_CAS.
|
||||
-- @param #TASK_CAS self
|
||||
-- @param Mission#MISSION Mission
|
||||
-- @param Set#SET_UNIT UnitSetTargets
|
||||
-- @param Zone#ZONE_BASE TargetZone
|
||||
-- @return #TASK_CAS self
|
||||
function TASK_CAS:New( Mission, TargetSetUnit, TargetZone )
|
||||
local self = BASE:Inherit( self, TASK_BASE:New( Mission, "CAS Attack", "CAS", "A2G" ) )
|
||||
self:F()
|
||||
|
||||
self.TargetSetUnit = TargetSetUnit
|
||||
self.TargetZone = TargetZone
|
||||
|
||||
_EVENTDISPATCHER:OnBirth( self._EventAssignUnit, self )
|
||||
_EVENTDISPATCHER:OnPlayerEnterUnit(self._EventAssignUnit, self )
|
||||
_EVENTDISPATCHER:OnPlayerLeaveUnit(self._EventUnAssignUnit, self )
|
||||
_EVENTDISPATCHER:OnCrash(self._EventUnAssignUnit, self )
|
||||
_EVENTDISPATCHER:OnDead(self._EventUnAssignUnit, self )
|
||||
_EVENTDISPATCHER:OnPilotDead(self._EventUnAssignUnit, self )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Assign the @{Task} to a @{Unit}.
|
||||
-- @param #TASK_CAS self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #TASK_CAS self
|
||||
function TASK_CAS:AssignToUnit( TaskUnit )
|
||||
self:F( TaskUnit:GetName() )
|
||||
|
||||
local ProcessAssign = self:AddProcess( TaskUnit, PROCESS_ASSIGN:New( self, TaskUnit, self.TaskBriefing ) )
|
||||
local ProcessRoute = self:AddProcess( TaskUnit, PROCESS_ROUTE:New( self, TaskUnit, self.TargetZone ) )
|
||||
local ProcessSEAD = self:AddProcess( TaskUnit, PROCESS_SEAD:New( self, TaskUnit, self.TargetSetUnit ) )
|
||||
|
||||
local Process = self:AddStateMachine( TaskUnit, STATEMACHINE_TASK:New( self, {
|
||||
initial = 'None',
|
||||
events = {
|
||||
{ name = 'Next', from = 'None', to = 'Planned' },
|
||||
{ name = 'Next', from = 'Planned', to = 'Assigned' },
|
||||
{ name = 'Reject', from = 'Planned', to = 'Rejected' },
|
||||
{ name = 'Next', from = 'Assigned', to = 'Success' },
|
||||
{ name = 'Fail', from = 'Assigned', to = 'Failed' },
|
||||
{ name = 'Fail', from = 'Arrived', to = 'Failed' }
|
||||
},
|
||||
callbacks = {
|
||||
onNext = self.OnNext,
|
||||
onRemove = self.OnRemove,
|
||||
},
|
||||
subs = {
|
||||
Assign = { onstateparent = 'Planned', oneventparent = 'Next', fsm = ProcessAssign.Fsm, event = 'Menu', returnevents = { 'Next', 'Reject' } },
|
||||
Route = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessRoute.Fsm, event = 'Route' },
|
||||
Sead = { onstateparent = 'Assigned', oneventparent = 'Next', fsm = ProcessSEAD.Fsm, event = 'Await', returnevents = { 'Next' } }
|
||||
}
|
||||
} ) )
|
||||
|
||||
ProcessRoute:AddScore( "Failed", "failed to destroy a ground unit", -100 )
|
||||
ProcessSEAD:AddScore( "Destroy", "destroyed a ground unit", 25 )
|
||||
ProcessSEAD:AddScore( "Failed", "failed to destroy a ground unit", -100 )
|
||||
|
||||
Process:Next()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a TASK
|
||||
-- @param #TASK_CAS self
|
||||
-- @param StateMachine#STATEMACHINE_TASK Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Event#EVENTDATA Event
|
||||
function TASK_CAS:OnNext( Fsm, Event, From, To, Event )
|
||||
|
||||
self:SetState( self, "State", To )
|
||||
|
||||
end
|
||||
|
||||
--- @param #TASK_CAS self
|
||||
function TASK_CAS:_Schedule()
|
||||
self:F2()
|
||||
|
||||
self.TaskScheduler = SCHEDULER:New( self, _Scheduler, {}, 15, 15 )
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- @param #TASK_CAS self
|
||||
function TASK_CAS._Scheduler()
|
||||
self:F2()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ TASK_SEAD = {
|
||||
ClassName = "TASK_SEAD",
|
||||
}
|
||||
|
||||
--- Instantiates a new TASK_SEAD. Should never be used. Interface Class.
|
||||
--- Instantiates a new TASK_SEAD.
|
||||
-- @param #TASK_SEAD self
|
||||
-- @param Mission#MISSION Mission
|
||||
-- @param Set#SET_UNIT UnitSetTargets
|
||||
|
||||
@ -586,12 +586,62 @@ end
|
||||
function UNIT:IsAir()
|
||||
self:F2()
|
||||
|
||||
local UnitDescriptor = self.DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
local IsAirResult = ( UnitDescriptor.category == Unit.Category.AIRPLANE ) or ( UnitDescriptor.category == Unit.Category.HELICOPTER )
|
||||
|
||||
self:T3( IsAirResult )
|
||||
return IsAirResult
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
|
||||
|
||||
local IsAirResult = ( UnitDescriptor.category == Unit.Category.AIRPLANE ) or ( UnitDescriptor.category == Unit.Category.HELICOPTER )
|
||||
|
||||
self:T3( IsAirResult )
|
||||
return IsAirResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns if the unit is of an ground category.
|
||||
-- If the unit is a ground vehicle or infantry, this method will return true, otherwise false.
|
||||
-- @param #UNIT self
|
||||
-- @return #boolean Ground category evaluation result.
|
||||
function UNIT:IsGround()
|
||||
self:F2()
|
||||
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.GROUND_UNIT } )
|
||||
|
||||
local IsGroundResult = ( UnitDescriptor.category == Unit.Category.GROUND_UNIT )
|
||||
|
||||
self:T3( IsGroundResult )
|
||||
return IsGroundResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- Returns if the unit is of a ship category.
|
||||
-- If the unit is a ship, this method will return true, otherwise false.
|
||||
-- @param #UNIT self
|
||||
-- @return #boolean Ship category evaluation result.
|
||||
function UNIT:IsShip()
|
||||
self:F2()
|
||||
|
||||
local DCSUnit = self:GetDCSObject()
|
||||
|
||||
if DCSUnit then
|
||||
local UnitDescriptor = DCSUnit:getDesc()
|
||||
self:T3( { UnitDescriptor.category, Unit.Category.SHIP } )
|
||||
|
||||
local IsShipResult = ( UnitDescriptor.category == Unit.Category.SHIP )
|
||||
|
||||
self:T3( IsShipResult )
|
||||
return IsShipResult
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -83,13 +83,14 @@ COPY /b Moose.lua + %1\PatrolZone.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\AIBalancer.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\AirbasePolice.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Detection.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\FAC.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\DetectionManager.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\StateMachine.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Process.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Process_Assign.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Process_Route.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Process_SEAD.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Task.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Task_CAS.lua Moose.lua
|
||||
COPY /b Moose.lua + %1\Task_SEAD.lua Moose.lua
|
||||
|
||||
COPY /b Moose.lua + "Moose Create Static\Moose_Trace_Off.lua" Moose.lua
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
|
||||
local FACGroup = GROUP:FindByName( "FAC Group" )
|
||||
|
||||
local FACDetection = DETECTION_UNITGROUPS:New( FACGroup, 1000, 250 ):SmokeDetectedZones():FlareDetectedUnits()
|
||||
local FACDetection = DETECTION_UNITGROUPS:New( FACGroup, 1000, 250 ):FlareDetectedZones():FlareDetectedUnits()
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@ -6,12 +6,12 @@ Mission:AddScoring( Scoring )
|
||||
|
||||
local FACGroup = GROUP:FindByName( "FAC" )
|
||||
|
||||
local FACDetection = DETECTION_UNITGROUPS:New( FACGroup, 1000, 250 )
|
||||
local FACDetection = DETECTION_UNITGROUPS:New( FACGroup, 6000, 1000 )
|
||||
|
||||
local SEAD_Attack = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "SEAD Attack" ):FilterStart()
|
||||
local AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "SEAD Attack" ):FilterStart()
|
||||
|
||||
|
||||
local CommandCenter = GROUP:FindByName( "HQ" )
|
||||
|
||||
local TaskAssign = TASK_DISPATCHER:New( Mission, CommandCenter, SEAD_Attack, FACDetection )
|
||||
local TaskAssign = TASK_DISPATCHER:New( Mission, CommandCenter, AttackGroups, FACDetection )
|
||||
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user