First version

This commit is contained in:
FlightControl 2019-03-15 09:57:50 +01:00
parent 6a301060bf
commit 0f9591464a
2 changed files with 636 additions and 15 deletions

View File

@ -631,8 +631,8 @@ end
-- * @{ZONE_RADIUS.IsNoneInZone}(): Scan if the zone is empty.
-- @{#ZONE_RADIUS.
-- @param #ZONE_RADIUS self
-- @param ObjectCategories
-- @param UnitCategories
-- @param ObjectCategories An array of categories of the objects to find in the zone.
-- @param UnitCategories An array of unit categories of the objects to find in the zone.
-- @usage
-- self.Zone:Scan()
-- local IsAttacked = self.Zone:IsSomeInZoneOfCoalition( self.Coalition )

View File

@ -305,9 +305,9 @@ do -- DETECTION_BASE
--- DETECTION constructor.
-- @param #DETECTION_BASE self
-- @param Core.Set#SET_GROUP DetectionSetGroup The @{Set} of GROUPs in the Forward Air Controller role.
-- @param Core.Set#SET_BASE DetectionSet The @{Set} that is used to detect the units.
-- @return #DETECTION_BASE self
function DETECTION_BASE:New( DetectionSetGroup )
function DETECTION_BASE:New( DetectionSet )
-- Inherits from BASE
local self = BASE:Inherit( self, FSM:New() ) -- #DETECTION_BASE
@ -316,7 +316,7 @@ do -- DETECTION_BASE
self.DetectedItemMax = 0
self.DetectedItems = {}
self.DetectionSetGroup = DetectionSetGroup
self.DetectionSet = DetectionSet
self.RefreshTimeInterval = 30
@ -398,7 +398,7 @@ do -- DETECTION_BASE
-- @param #string To The To State string.
self:AddTransition( "Detecting", "Detect", "Detecting" )
self:AddTransition( "Detecting", "DetectionGroup", "Detecting" )
self:AddTransition( "Detecting", "Detection", "Detecting" )
--- OnBefore Transition Handler for Event Detect.
-- @function [parent=#DETECTION_BASE] OnBeforeDetect
@ -540,10 +540,11 @@ do -- DETECTION_BASE
self.DetectedObjects[DetectionObjectName].Distance = 10000000
end
for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
for DetectionID, DetectionData in pairs( self.DetectionSet:GetSet() ) do
--self:F( { DetectionGroupData } )
self:F( { DetectionGroup = DetectionGroupData:GetName() } )
self:__DetectionGroup( DetectDelay, DetectionGroupData, DetectionTimeStamp ) -- Process each detection asynchronously.
self:F( { DetectionGroup = DetectionData:GetName() } )
self:__Detection( DetectDelay, DetectionData, DetectionTimeStamp ) -- Process each detection asynchronously.
self.DetectionCount = self.DetectionCount + 1
DetectDelay = DetectDelay + 1
end
@ -555,7 +556,7 @@ do -- DETECTION_BASE
-- @param #string To The To State string.
-- @param Wrapper.Group#GROUP DetectionGroup The Group detecting.
-- @param #number DetectionTimeStamp Time stamp of detection event.
function DETECTION_BASE:onafterDetectionGroup( From, Event, To, DetectionGroup, DetectionTimeStamp )
function DETECTION_BASE:onafterDetection( From, Event, To, Detection, DetectionTimeStamp )
--self:F( { DetectedObjects = self.DetectedObjects } )
@ -563,16 +564,16 @@ do -- DETECTION_BASE
local HasDetectedObjects = false
if DetectionGroup:IsAlive() then
if Detection:IsAlive() then
--self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } )
local DetectionGroupName = DetectionGroup:GetName()
local DetectionUnit = DetectionGroup:GetUnit(1)
local DetectionGroupName = Detection:GetName()
local DetectionUnit = Detection:GetUnit(1)
local DetectedUnits = {}
local DetectedTargets = DetectionGroup:GetDetectedTargets(
local DetectedTargets = Detection:GetDetectedTargets(
self.DetectVisual,
self.DetectOptical,
self.DetectRadar,
@ -624,7 +625,7 @@ do -- DETECTION_BASE
local DetectedObjectVec3 = DetectedObject:getPoint()
local DetectedObjectVec2 = { x = DetectedObjectVec3.x, y = DetectedObjectVec3.z }
local DetectionGroupVec3 = DetectionGroup:GetVec3()
local DetectionGroupVec3 = Detection:GetVec3()
local DetectionGroupVec2 = { x = DetectionGroupVec3.x, y = DetectionGroupVec3.z }
local Distance = ( ( DetectedObjectVec3.x - DetectionGroupVec3.x )^2 +
@ -2819,3 +2820,623 @@ do -- DETECTION_AREAS
end
end
do -- DETECTION_ZONES
--- @type DETECTION_ZONES
-- @field DCS#Distance DetectionZoneRange The range till which targets are grouped upon the first detected target.
-- @field #DETECTION_BASE.DetectedItems DetectedItems A list of areas containing the set of @{Wrapper.Unit}s, @{Zone}s, the center @{Wrapper.Unit} within the zone, and ID of each area that was detected within a DetectionZoneRange.
-- @extends Functional.Detection#DETECTION_BASE
--- Detect units within the battle zone for a list of @{Wrapper.Group}s detecting targets following (a) detection method(s),
-- and will build a list (table) of @{Core.Set#SET_UNIT}s containing the @{Wrapper.Unit#UNIT}s detected.
-- The class is group the detected units within zones given a DetectedZoneRange parameter.
-- A set with multiple detected zones will be created as there are groups of units detected.
--
-- ## 4.1) Retrieve the Detected Unit Sets and Detected Zones
--
-- The methods to manage the DetectedItems[].Set(s) are implemented in @{Functional.Detection#DECTECTION_BASE} and
-- the methods to manage the DetectedItems[].Zone(s) is implemented in @{Functional.Detection#DETECTION_ZONES}.
--
-- Retrieve the DetectedItems[].Set with the method @{Functional.Detection#DETECTION_BASE.GetDetectedSet}(). A @{Core.Set#SET_UNIT} object will be returned.
--
-- Retrieve the formed @{Zone@ZONE_UNIT}s as a result of the grouping the detected units within the DetectionZoneRange, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZones}().
-- To understand the amount of zones created, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZoneCount}().
-- If you want to obtain a specific zone from the DetectedZones, use the method @{Functional.Detection#DETECTION_BASE.GetDetectionZone}() with a given index.
--
-- ## 4.4) Flare or Smoke detected units
--
-- Use the methods @{Functional.Detection#DETECTION_ZONES.FlareDetectedUnits}() or @{Functional.Detection#DETECTION_ZONES.SmokeDetectedUnits}() to flare or smoke the detected units when a new detection has taken place.
--
-- ## 4.5) Flare or Smoke or Bound detected zones
--
-- Use the methods:
--
-- * @{Functional.Detection#DETECTION_ZONES.FlareDetectedZones}() to flare in a color
-- * @{Functional.Detection#DETECTION_ZONES.SmokeDetectedZones}() to smoke in a color
-- * @{Functional.Detection#DETECTION_ZONES.SmokeDetectedZones}() to bound with a tire with a white flag
--
-- the detected zones when a new detection has taken place.
--
-- @field #DETECTION_ZONES
DETECTION_ZONES = {
ClassName = "DETECTION_ZONES",
DetectionZoneRange = nil,
}
--- DETECTION_ZONES constructor.
-- @param #DETECTION_ZONES self
-- @param Core.Set#SET_ZONE_RADIUS DetectionSetZoneRadius The @{Set} of ZONE_RADIUS.
-- @param DCS#Coalition.side DetectionCoalition The coalition of the detection.
-- @return #DETECTION_ZONES
function DETECTION_ZONES:New( DetectionSetZoneRadius, DetectionCoalition )
-- Inherits from DETECTION_BASE
local self = BASE:Inherit( self, DETECTION_BASE:New() )
self.DetectionSetZoneRadius = DetectionSetZoneRadius
self.DetectionCoalition = DetectionCoalition
self._SmokeDetectedUnits = false
self._FlareDetectedUnits = false
self._SmokeDetectedZones = false
self._FlareDetectedZones = false
self._BoundDetectedZones = false
return self
end
--- Report summary of a detected item using a given numeric index.
-- @param #DETECTION_ZONES self
-- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem.
-- @param Wrapper.Group#GROUP AttackGroup The group to get the settings for.
-- @param Core.Settings#SETTINGS Settings (Optional) Message formatting settings to use.
-- @return Core.Report#REPORT The report of the detection items.
function DETECTION_ZONES:DetectedItemReportSummary( DetectedItem, AttackGroup, Settings )
self:F( { DetectedItem = DetectedItem } )
local DetectedItemID = self:GetDetectedItemID( DetectedItem )
if DetectedItem then
local DetectedSet = self:GetDetectedSet( DetectedItem )
local ReportSummaryItem
local DetectedZone = self:GetDetectedItemZone( DetectedItem )
local DetectedItemCoordinate = DetectedZone:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString( AttackGroup, Settings )
local ThreatLevelA2G = self:GetDetectedItemThreatLevel( DetectedItem )
local DetectedItemsCount = DetectedSet:Count()
local DetectedItemsTypes = DetectedSet:GetTypeNames()
local Report = REPORT:New()
Report:Add(DetectedItemID .. ", " .. DetectedItemCoordText)
Report:Add( string.format( "Threat: [%s]", string.rep( "", ThreatLevelA2G ), string.rep( "", 10-ThreatLevelA2G ) ) )
Report:Add( string.format("Type: %2d of %s", DetectedItemsCount, DetectedItemsTypes ) )
Report:Add( string.format("Detected: %s", DetectedItem.IsDetected and "yes" or "no" ) )
return Report
end
return nil
end
--- Report detailed of a detection result.
-- @param #DETECTION_ZONES self
-- @param Wrapper.Group#GROUP AttackGroup The group to generate the report for.
-- @return #string
function DETECTION_ZONES:DetectedReportDetailed( AttackGroup ) --R2.1 Fixed missing report
self:F()
local Report = REPORT:New()
for DetectedItemIndex, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItem -- #DETECTION_BASE.DetectedItem
local ReportSummary = self:DetectedItemReportSummary( DetectedItem, AttackGroup )
Report:SetTitle( "Detected areas:" )
Report:Add( ReportSummary:Text() )
end
local ReportText = Report:Text()
return ReportText
end
--- Calculate the optimal intercept point of the DetectedItem.
-- @param #DETECTION_ZONES self
-- @param #DETECTION_BASE.DetectedItem DetectedItem
function DETECTION_ZONES:CalculateIntercept( DetectedItem )
local DetectedCoord = DetectedItem.Coordinate
local DetectedSpeed = DetectedCoord:GetVelocity()
local DetectedHeading = DetectedCoord:GetHeading()
if self.Intercept then
local DetectedSet = DetectedItem.Set
-- todo: speed
local TranslateDistance = DetectedSpeed * self.InterceptDelay
local InterceptCoord = DetectedCoord:Translate( TranslateDistance, DetectedHeading )
DetectedItem.InterceptCoord = InterceptCoord
else
DetectedItem.InterceptCoord = DetectedCoord
end
end
--- Smoke the detected units
-- @param #DETECTION_ZONES self
-- @return #DETECTION_ZONES self
function DETECTION_ZONES:SmokeDetectedUnits()
self:F2()
self._SmokeDetectedUnits = true
return self
end
--- Flare the detected units
-- @param #DETECTION_ZONES self
-- @return #DETECTION_ZONES self
function DETECTION_ZONES:FlareDetectedUnits()
self:F2()
self._FlareDetectedUnits = true
return self
end
--- Smoke the detected zones
-- @param #DETECTION_ZONES self
-- @return #DETECTION_ZONES self
function DETECTION_ZONES:SmokeDetectedZones()
self:F2()
self._SmokeDetectedZones = true
return self
end
--- Flare the detected zones
-- @param #DETECTION_ZONES self
-- @return #DETECTION_ZONES self
function DETECTION_ZONES:FlareDetectedZones()
self:F2()
self._FlareDetectedZones = true
return self
end
--- Bound the detected zones
-- @param #DETECTION_ZONES self
-- @return #DETECTION_ZONES self
function DETECTION_ZONES:BoundDetectedZones()
self:F2()
self._BoundDetectedZones = true
return self
end
--- Make text documenting the changes of the detected zone.
-- @param #DETECTION_ZONES self
-- @param #DETECTION_BASE.DetectedItem DetectedItem
-- @return #string The Changes text
function DETECTION_ZONES:GetChangeText( DetectedItem )
self:F( DetectedItem )
local MT = {}
for ChangeCode, ChangeData in pairs( DetectedItem.Changes ) do
if ChangeCode == "AA" then
MT[#MT+1] = "Detected new area " .. ChangeData.ID .. ". The center target is a " .. ChangeData.ItemUnitType .. "."
end
if ChangeCode == "RAU" then
MT[#MT+1] = "Changed area " .. ChangeData.ID .. ". Removed the center target."
end
if ChangeCode == "AAU" then
MT[#MT+1] = "Changed area " .. ChangeData.ID .. ". The new center target is a " .. ChangeData.ItemUnitType .. "."
end
if ChangeCode == "RA" then
MT[#MT+1] = "Removed old area " .. ChangeData.ID .. ". No more targets in this area."
end
if ChangeCode == "AU" then
local MTUT = {}
for ChangeUnitType, ChangeUnitCount in pairs( ChangeData ) do
if ChangeUnitType ~= "ID" then
MTUT[#MTUT+1] = ChangeUnitCount .. " of " .. ChangeUnitType
end
end
MT[#MT+1] = "Detected for area " .. ChangeData.ID .. " new target(s) " .. table.concat( MTUT, ", " ) .. "."
end
if ChangeCode == "RU" then
local MTUT = {}
for ChangeUnitType, ChangeUnitCount in pairs( ChangeData ) do
if ChangeUnitType ~= "ID" then
MTUT[#MTUT+1] = ChangeUnitCount .. " of " .. ChangeUnitType
end
end
MT[#MT+1] = "Removed for area " .. ChangeData.ID .. " invisible or destroyed target(s) " .. table.concat( MTUT, ", " ) .. "."
end
end
return table.concat( MT, "\n" )
end
--- Make a DetectionSet table. This function will be overridden in the derived clsses.
-- @param #DETECTION_ZONES self
-- @return #DETECTION_ZONES self
function DETECTION_ZONES:CreateDetectionItems()
self:F( "Checking Detected Items for new Detected Units ..." )
--self:F( { DetectedObjects = self.DetectedObjects } )
-- 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 DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem
if DetectedItem then
self:T2( { "Detected Item ID: ", DetectedItemID } )
local Zone = DetectedItem.Zone -- Core.Zone#ZONE_RADIUS
-- Scan the zone
Zone:Scan( { Object.Category.UNIT }, { Unit.Category.GROUND_UNIT } )
local ZoneUnits = Zone:GetScannedUnits()
for DCSUnitID, DCSUnit in pairs( ZoneUnits ) do
local UnitName = DCSUnit:getName()
local ZoneUnit = UNIT:FindByName( UnitName )
local ZoneUnitCoalition = ZoneUnit:GetCoalition()
if ZoneUnitCoalition == self.DetectionCoalition then
DetectedItem.Set:AddUnit( ZoneUnit )
end
end
end
end
-- Now all the tests should have been build, now make some smoke and flares...
-- We also report here the friendlies within the detected areas.
for DetectedItemID, DetectedItemData in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItemData -- #DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set
local DetectedFirstUnit = DetectedSet:GetFirst()
local DetectedZone = DetectedItem.Zone
-- Set the last known coordinate to the detection item.
local DetectedZoneCoord = DetectedZone:GetCoordinate()
self:SetDetectedItemCoordinate( DetectedItem, DetectedZoneCoord, DetectedFirstUnit )
self:CalculateIntercept( DetectedItem )
-- We search for friendlies nearby.
-- If there weren't any friendlies nearby, and now there are friendlies nearby, we flag the area as "changed".
-- If there were friendlies nearby, and now there aren't any friendlies nearby, we flag the area as "changed".
-- This is for the A2G dispatcher to detect if there is a change in the tactical situation.
local OldFriendliesNearbyGround = self:IsFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT )
self:ReportFriendliesNearBy( { DetectedItem = DetectedItem, ReportSetGroup = self.DetectionSetGroup } ) -- Fill the Friendlies table
local NewFriendliesNearbyGround = self:IsFriendliesNearBy( DetectedItem, Unit.Category.GROUND_UNIT )
if OldFriendliesNearbyGround ~= NewFriendliesNearbyGround then
DetectedItem.Changed = true
end
self:SetDetectedItemThreatLevel( DetectedItem ) -- Calculate A2G threat level
self:NearestRecce( DetectedItem )
if DETECTION_ZONES._SmokeDetectedUnits or self._SmokeDetectedUnits then
DetectedZone.ZoneUNIT:SmokeRed()
end
--DetectedSet:Flush( self )
DetectedSet:ForEachUnit(
--- @param Wrapper.Unit#UNIT DetectedUnit
function( DetectedUnit )
if DetectedUnit:IsAlive() then
--self:T( "Detected Set #" .. DetectedItem.ID .. ":" .. DetectedUnit:GetName() )
if DETECTION_ZONES._FlareDetectedUnits or self._FlareDetectedUnits then
DetectedUnit:FlareGreen()
end
if DETECTION_ZONES._SmokeDetectedUnits or self._SmokeDetectedUnits then
DetectedUnit:SmokeGreen()
end
end
end
)
if DETECTION_ZONES._FlareDetectedZones or self._FlareDetectedZones then
DetectedZone:FlareZone( SMOKECOLOR.White, 30, math.random( 0,90 ) )
end
if DETECTION_ZONES._SmokeDetectedZones or self._SmokeDetectedZones then
DetectedZone:SmokeZone( SMOKECOLOR.White, 30 )
end
if DETECTION_ZONES._BoundDetectedZones or self._BoundDetectedZones then
self.CountryID = DetectedSet:GetFirst():GetCountry()
DetectedZone:BoundZone( 12, self.CountryID )
end
end
end
--- @param #DETECTION_ZONES self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @param Detection The element on which the detection is based.
-- @param #number DetectionTimeStamp Time stamp of detection event.
function DETECTION_ZONES:onafterDetection( From, Event, To, Detection, DetectionTimeStamp )
--self:F( { DetectedObjects = self.DetectedObjects } )
self.DetectionRun = self.DetectionRun + 1
local HasDetectedObjects = false
if Detection:IsAlive() then
--self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } )
local DetectionGroupName = Detection:GetName()
local DetectionUnit = Detection:GetUnit(1)
local DetectedUnits = {}
local DetectedTargets = Detection:GetDetectedTargets(
self.DetectVisual,
self.DetectOptical,
self.DetectRadar,
self.DetectIRST,
self.DetectRWR,
self.DetectDLINK
)
self:F( { DetectedTargets = DetectedTargets } )
for DetectionObjectID, Detection in pairs( DetectedTargets ) do
local DetectedObject = Detection.object -- DCS#Object
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
local DetectedObjectName = DetectedObject:getName()
if not self.DetectedObjects[DetectedObjectName] then
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
self.DetectedObjects[DetectedObjectName].Object = DetectedObject
end
end
end
for DetectionObjectName, DetectedObjectData in pairs( self.DetectedObjects ) do
local DetectedObject = DetectedObjectData.Object
if DetectedObject:isExist() then
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
DetectedObject,
self.DetectVisual,
self.DetectOptical,
self.DetectRadar,
self.DetectIRST,
self.DetectRWR,
self.DetectDLINK
)
--self:T2( { TargetIsDetected = TargetIsDetected, TargetIsVisible = TargetIsVisible, TargetLastTime = TargetLastTime, TargetKnowType = TargetKnowType, TargetKnowDistance = TargetKnowDistance, TargetLastPos = TargetLastPos, TargetLastVelocity = TargetLastVelocity } )
-- Only process if the target is visible. Detection also returns invisible units.
--if Detection.visible == true then
local DetectionAccepted = true
local DetectedObjectName = DetectedObject:getName()
local DetectedObjectType = DetectedObject:getTypeName()
local DetectedObjectVec3 = DetectedObject:getPoint()
local DetectedObjectVec2 = { x = DetectedObjectVec3.x, y = DetectedObjectVec3.z }
local DetectionGroupVec3 = Detection:GetVec3()
local DetectionGroupVec2 = { x = DetectionGroupVec3.x, y = DetectionGroupVec3.z }
local Distance = ( ( DetectedObjectVec3.x - DetectionGroupVec3.x )^2 +
( DetectedObjectVec3.y - DetectionGroupVec3.y )^2 +
( DetectedObjectVec3.z - DetectionGroupVec3.z )^2
) ^ 0.5 / 1000
local DetectedUnitCategory = DetectedObject:getDesc().category
--self:F( { "Detected Target:", DetectionGroupName, DetectedObjectName, DetectedObjectType, Distance, DetectedUnitCategory } )
-- Calculate Acceptance
DetectionAccepted = self._.FilterCategories[DetectedUnitCategory] ~= nil and DetectionAccepted or false
-- if Distance > 15000 then
-- if DetectedUnitCategory == Unit.Category.GROUND_UNIT or DetectedUnitCategory == Unit.Category.SHIP then
-- if DetectedObject:hasSensors( Unit.SensorType.RADAR, Unit.RadarType.AS ) == false then
-- DetectionAccepted = false
-- end
-- end
-- end
if self.AcceptRange and Distance * 1000 > self.AcceptRange then
DetectionAccepted = false
end
if self.AcceptZones then
local AnyZoneDetection = false
for AcceptZoneID, AcceptZone in pairs( self.AcceptZones ) do
local AcceptZone = AcceptZone -- Core.Zone#ZONE_BASE
if AcceptZone:IsVec2InZone( DetectedObjectVec2 ) then
AnyZoneDetection = true
end
end
if not AnyZoneDetection then
DetectionAccepted = false
end
end
if self.RejectZones then
for RejectZoneID, RejectZone in pairs( self.RejectZones ) do
local RejectZone = RejectZone -- Core.Zone#ZONE_BASE
if RejectZone:IsPointVec2InZone( DetectedObjectVec2 ) == true then
DetectionAccepted = false
end
end
end
-- Calculate additional probabilities
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.DistanceProbability then
local DistanceFactor = Distance / 4
local DistanceProbabilityReversed = ( 1 - self.DistanceProbability ) * DistanceFactor
local DistanceProbability = 1 - DistanceProbabilityReversed
DistanceProbability = DistanceProbability * 30 / 300
local Probability = math.random() -- Selects a number between 0 and 1
--self:T( { Probability, DistanceProbability } )
if Probability > DistanceProbability then
DetectionAccepted = false
end
end
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.AlphaAngleProbability then
local NormalVec2 = { x = DetectedObjectVec2.x - DetectionGroupVec2.x, y = DetectedObjectVec2.y - DetectionGroupVec2.y }
local AlphaAngle = math.atan2( NormalVec2.y, NormalVec2.x )
local Sinus = math.sin( AlphaAngle )
local AlphaAngleProbabilityReversed = ( 1 - self.AlphaAngleProbability ) * ( 1 - Sinus )
local AlphaAngleProbability = 1 - AlphaAngleProbabilityReversed
AlphaAngleProbability = AlphaAngleProbability * 30 / 300
local Probability = math.random() -- Selects a number between 0 and 1
--self:T( { Probability, AlphaAngleProbability } )
if Probability > AlphaAngleProbability then
DetectionAccepted = false
end
end
if not self.DetectedObjects[DetectedObjectName] and TargetIsVisible and self.ZoneProbability then
for ZoneDataID, ZoneData in pairs( self.ZoneProbability ) do
self:F({ZoneData})
local ZoneObject = ZoneData[1] -- Core.Zone#ZONE_BASE
local ZoneProbability = ZoneData[2] -- #number
ZoneProbability = ZoneProbability * 30 / 300
if ZoneObject:IsPointVec2InZone( DetectedObjectVec2 ) == true then
local Probability = math.random() -- Selects a number between 0 and 1
--self:T( { Probability, ZoneProbability } )
if Probability > ZoneProbability then
DetectionAccepted = false
break
end
end
end
end
if DetectionAccepted then
HasDetectedObjects = true
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
if TargetIsDetected and TargetIsDetected == true then
self.DetectedObjects[DetectedObjectName].IsDetected = TargetIsDetected
end
if TargetIsDetected and TargetIsVisible and TargetIsVisible == true then
self.DetectedObjects[DetectedObjectName].IsVisible = TargetIsDetected and TargetIsVisible
end
if TargetIsDetected and not self.DetectedObjects[DetectedObjectName].KnowType then
self.DetectedObjects[DetectedObjectName].KnowType = TargetIsDetected and TargetKnowType
end
self.DetectedObjects[DetectedObjectName].KnowDistance = TargetKnowDistance -- Detection.distance -- TargetKnowDistance
self.DetectedObjects[DetectedObjectName].LastTime = ( TargetIsDetected and TargetIsVisible == false ) and TargetLastTime
self.DetectedObjects[DetectedObjectName].LastPos = ( TargetIsDetected and TargetIsVisible == false ) and TargetLastPos
self.DetectedObjects[DetectedObjectName].LastVelocity = ( TargetIsDetected and TargetIsVisible == false ) and TargetLastVelocity
if not self.DetectedObjects[DetectedObjectName].Distance or ( Distance and self.DetectedObjects[DetectedObjectName].Distance > Distance ) then
self.DetectedObjects[DetectedObjectName].Distance = Distance
end
self.DetectedObjects[DetectedObjectName].DetectionTimeStamp = DetectionTimeStamp
self:F( { DetectedObject = self.DetectedObjects[DetectedObjectName] } )
local DetectedUnit = UNIT:FindByName( DetectedObjectName )
DetectedUnits[DetectedObjectName] = DetectedUnit
else
-- if beyond the DetectionRange then nullify...
self:F( { DetectedObject = "No more detection for " .. DetectedObjectName } )
if self.DetectedObjects[DetectedObjectName] then
self.DetectedObjects[DetectedObjectName] = nil
end
end
--self:T2( self.DetectedObjects )
else
-- The previously detected object does not exist anymore, delete from the cache.
self:F( "Removing from DetectedObjects: " .. DetectionObjectName )
self.DetectedObjects[DetectionObjectName] = nil
end
end
if HasDetectedObjects then
self:__Detected( 0.1, DetectedUnits )
end
end
if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then
-- First check if all DetectedObjects were detected.
-- This is important. When there are DetectedObjects in the list, but were not detected,
-- And these remain undetected for more than 60 seconds, then these DetectedObjects will be flagged as not Detected.
-- IsDetected = false!
-- This is used in A2A_TASK_DISPATCHER to initiate fighter sweeping! The TASK_A2A_INTERCEPT tasks will be replaced with TASK_A2A_SWEEP tasks.
for DetectedObjectName, DetectedObject in pairs( self.DetectedObjects ) do
if self.DetectedObjects[DetectedObjectName].IsDetected == true and self.DetectedObjects[DetectedObjectName].DetectionTimeStamp + 300 <= DetectionTimeStamp then
self.DetectedObjects[DetectedObjectName].IsDetected = false
end
end
self:CreateDetectionItems() -- Polymorphic call to Create/Update the DetectionItems list for the DETECTION_ class grouping method.
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
self:UpdateDetectedItemDetection( DetectedItem )
self:CleanDetectionItem( DetectedItem, DetectedItemID ) -- Any DetectionItem that has a Set with zero elements in it, must be removed from the DetectionItems list.
if DetectedItem then
self:__DetectedItem( 0.1, DetectedItem )
end
end
self:__Detect( self.RefreshTimeInterval )
end
end
end
end