From 70e7857b627a7a7055ca9c1bf0bcc484c0f38f08 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Mon, 18 Mar 2019 19:53:12 +0100 Subject: [PATCH] Implemented the linking of TASK_CAPTURE_DISPATCHER and AI_A2G_DISPATCHER. --- .../Moose/AI/AI_A2G_Dispatcher.lua | 193 ++++++++++-------- .../Moose/Functional/Detection.lua | 66 ++++++ .../Moose/Tasking/Task_Capture_Dispatcher.lua | 21 +- 3 files changed, 193 insertions(+), 87 deletions(-) diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index 034b2ba06..825d2e124 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -1126,7 +1126,7 @@ do -- AI_A2G_DISPATCHER self.TakeoffScheduleID = self:ScheduleRepeat( 10, 10, 0, nil, self.ResourceTakeoff, self ) - self:__Start( 5 ) + self:__Start( 1 ) return self end @@ -1150,9 +1150,30 @@ do -- AI_A2G_DISPATCHER --- Locks the DefenseItem from being defended. -- @param #AI_A2G_DISPATCHER self - -- @param #string DefenseItemKey The key of the defense item. + -- @param #string DetectedItemIndex The index of the detected item. + function AI_A2G_DISPATCHER:Lock( DetectedItemIndex ) + self:F( { DetectedItemIndex = DetectedItemIndex } ) + local DetectedItem = self.Detection:GetDetectedItemByIndex( DetectedItemIndex ) + if DetectedItem then + self:F( { Locked = DetectedItem } ) + self.Detection:LockDetectedItem( DetectedItem ) + end + end + --- Unlocks the DefenseItem from being defended. + -- @param #AI_A2G_DISPATCHER self + -- @param #string DetectedItemIndex The index of the detected item. + function AI_A2G_DISPATCHER:Unlock( DetectedItemIndex ) + self:F( { DetectedItemIndex = DetectedItemIndex } ) + self:F( { Index = self.Detection.DetectedItemsByIndex } ) + local DetectedItem = self.Detection:GetDetectedItemByIndex( DetectedItemIndex ) + if DetectedItem then + self:F( { Unlocked = DetectedItem } ) + self.Detection:UnlockDetectedItem( DetectedItem ) + end + end + --- @param #AI_A2G_DISPATCHER self @@ -4032,100 +4053,102 @@ do -- AI_A2G_DISPATCHER -- Now that all obsolete tasks are removed, loop through the detected targets. for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do - local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem - local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT - local DetectedCount = DetectedSet:Count() - local DetectedZone = DetectedItem.Zone - - self:F( { "Target ID", DetectedItem.ItemID } ) - DetectedSet:Flush( self ) - - local DetectedID = DetectedItem.ID - local DetectionIndex = DetectedItem.Index - local DetectedItemChanged = DetectedItem.Changed - - local AttackCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem ) - - -- Calculate if for this DetectedItem if a defense needs to be initiated. - -- This calculation is based on the distance between the defense point and the attackers, and the defensiveness parameter. - -- The attackers closest to the defense coordinates will be handled first, or course! - - local EngageCoordinate = nil - - for DefenseCoordinateName, DefenseCoordinate in pairs( self.DefenseCoordinates ) do - local DefenseCoordinate = DefenseCoordinate -- Core.Point#COORDINATE - - local EvaluateDistance = AttackCoordinate:Get2DDistance( DefenseCoordinate ) + if not self.Detection:IsDetectedItemLocked( DetectedItem ) == true then + local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem + local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT + local DetectedCount = DetectedSet:Count() + local DetectedZone = DetectedItem.Zone + + self:F( { "Target ID", DetectedItem.ItemID } ) + DetectedSet:Flush( self ) + + local DetectedID = DetectedItem.ID + local DetectionIndex = DetectedItem.Index + local DetectedItemChanged = DetectedItem.Changed - if EvaluateDistance <= self.DefenseRadius then + local AttackCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem ) - local DistanceProbability = ( self.DefenseRadius / EvaluateDistance * self.DefenseReactivity ) - local DefenseProbability = math.random() + -- Calculate if for this DetectedItem if a defense needs to be initiated. + -- This calculation is based on the distance between the defense point and the attackers, and the defensiveness parameter. + -- The attackers closest to the defense coordinates will be handled first, or course! + + local EngageCoordinate = nil + + for DefenseCoordinateName, DefenseCoordinate in pairs( self.DefenseCoordinates ) do + local DefenseCoordinate = DefenseCoordinate -- Core.Point#COORDINATE + + local EvaluateDistance = AttackCoordinate:Get2DDistance( DefenseCoordinate ) - self:F( { DistanceProbability = DistanceProbability, DefenseProbability = DefenseProbability } ) + if EvaluateDistance <= self.DefenseRadius then - if DefenseProbability <= DistanceProbability / ( 300 / 30 ) then - EngageCoordinate = DefenseCoordinate - break + local DistanceProbability = ( self.DefenseRadius / EvaluateDistance * self.DefenseReactivity ) + local DefenseProbability = math.random() + + self:F( { DistanceProbability = DistanceProbability, DefenseProbability = DefenseProbability } ) + + if DefenseProbability <= DistanceProbability / ( 300 / 30 ) then + EngageCoordinate = DefenseCoordinate + break + end end end - end - - if EngageCoordinate then - do - local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_SEAD( DetectedItem ) -- Returns a SET_UNIT with the SEAD targets to be engaged... - if DefendersMissing and DefendersMissing > 0 then - self:F( { DefendersTotal = DefendersTotal, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing } ) - self:Defend( DetectedItem, DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies, "SEAD", EngageCoordinate ) + + if EngageCoordinate then + do + local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_SEAD( DetectedItem ) -- Returns a SET_UNIT with the SEAD targets to be engaged... + if DefendersMissing and DefendersMissing > 0 then + self:F( { DefendersTotal = DefendersTotal, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing } ) + self:Defend( DetectedItem, DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies, "SEAD", EngageCoordinate ) + end + end + + do + local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_CAS( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged... + if DefendersMissing and DefendersMissing > 0 then + self:F( { DefendersTotal = DefendersTotal, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing } ) + self:Defend( DetectedItem, DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies, "CAS", EngageCoordinate ) + end + end + + do + local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_BAI( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged... + if DefendersMissing and DefendersMissing > 0 then + self:F( { DefendersTotal = DefendersTotal, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing } ) + self:Defend( DetectedItem, DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies, "BAI", EngageCoordinate ) + end end end - do - local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_CAS( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged... - if DefendersMissing and DefendersMissing > 0 then - self:F( { DefendersTotal = DefendersTotal, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing } ) - self:Defend( DetectedItem, DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies, "CAS", EngageCoordinate ) - end - end + -- do + -- local DefendersMissing, Friendlies = self:Evaluate_CAS( DetectedItem ) + -- if DefendersMissing and DefendersMissing > 0 then + -- self:F( { DefendersMissing = DefendersMissing } ) + -- self:CAS( DetectedItem, DefendersMissing, Friendlies ) + -- end + -- end - do - local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_BAI( DetectedItem ) -- Returns a SET_UNIT with the CAS targets to be engaged... - if DefendersMissing and DefendersMissing > 0 then - self:F( { DefendersTotal = DefendersTotal, DefendersEngaged = DefendersEngaged, DefendersMissing = DefendersMissing } ) - self:Defend( DetectedItem, DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies, "BAI", EngageCoordinate ) - end - end - end - --- do --- local DefendersMissing, Friendlies = self:Evaluate_CAS( DetectedItem ) --- if DefendersMissing and DefendersMissing > 0 then --- self:F( { DefendersMissing = DefendersMissing } ) --- self:CAS( DetectedItem, DefendersMissing, Friendlies ) --- end --- end - - if self.TacticalDisplay then - -- Show tactical situation - local ThreatLevel = DetectedItem.Set:CalculateThreatLevelA2G() - Report:Add( string.format( " - %1s%s ( %4s ): ( #%d - %4s ) %s" , ( DetectedItem.IsDetected == true ) and "!" or " ", DetectedItem.ItemID, DetectedItem.Index, DetectedItem.Set:Count(), DetectedItem.Type or " --- ", string.rep( "■", ThreatLevel ) ) ) - for Defender, DefenderTask in pairs( self:GetDefenderTasks() ) do - local Defender = Defender -- Wrapper.Group#GROUP - if DefenderTask.Target and DefenderTask.Target.Index == DetectedItem.Index then - if Defender:IsAlive() then - DefenderGroupCount = DefenderGroupCount + 1 - local Fuel = Defender:GetFuelMin() * 100 - local Damage = Defender:GetLife() / Defender:GetLife0() * 100 - Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s", - Defender:GetName(), - DefenderTask.Type, - DefenderTask.Fsm:GetState(), - Defender:GetSize(), - Fuel, - Damage, - Defender:HasTask() == true and "Executing" or "Idle" ) ) + if self.TacticalDisplay then + -- Show tactical situation + local ThreatLevel = DetectedItem.Set:CalculateThreatLevelA2G() + Report:Add( string.format( " - %1s%s ( %4s ): ( #%d - %4s ) %s" , ( DetectedItem.IsDetected == true ) and "!" or " ", DetectedItem.ItemID, DetectedItem.Index, DetectedItem.Set:Count(), DetectedItem.Type or " --- ", string.rep( "■", ThreatLevel ) ) ) + for Defender, DefenderTask in pairs( self:GetDefenderTasks() ) do + local Defender = Defender -- Wrapper.Group#GROUP + if DefenderTask.Target and DefenderTask.Target.Index == DetectedItem.Index then + if Defender:IsAlive() then + DefenderGroupCount = DefenderGroupCount + 1 + local Fuel = Defender:GetFuelMin() * 100 + local Damage = Defender:GetLife() / Defender:GetLife0() * 100 + Report:Add( string.format( " - %s ( %s - %s ): ( #%d ) F: %3d, D:%3d - %s", + Defender:GetName(), + DefenderTask.Type, + DefenderTask.Fsm:GetState(), + Defender:GetSize(), + Fuel, + Damage, + Defender:HasTask() == true and "Executing" or "Idle" ) ) + end end - end + end end end end diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index 76b3d0274..99f98848b 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -1536,6 +1536,10 @@ do -- DETECTION_BASE DetectedItem.ID = self.DetectedItemMax DetectedItem.Removed = false + if self.Locking then + self:LockDetectedItem( DetectedItem ) + end + return DetectedItem end @@ -1725,6 +1729,68 @@ do -- DETECTION_BASE end + --- Lock the detected items when created and lock all existing detected items. + -- @param #DETECTION_BASE self + -- @return #DETECTION_BASE + function DETECTION_BASE:LockDetectedItems() + + for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do + self:LockDetectedItem( DetectedItem ) + end + self.Locking = true + + return self + end + + + --- Unlock the detected items when created and unlock all existing detected items. + -- @param #DETECTION_BASE self + -- @return #DETECTION_BASE + function DETECTION_BASE:UnlockDetectedItems() + + for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do + self:UnlockDetectedItem( DetectedItem ) + end + self.Locking = nil + + return self + end + + --- Validate if the detected item is locked. + -- @param #DETECTION_BASE self + -- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem. + -- @return #boolean + function DETECTION_BASE:IsDetectedItemLocked( DetectedItem ) + + return self.Locking and DetectedItem.Locked == true + + end + + + --- Lock a detected item. + -- @param #DETECTION_BASE self + -- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem. + -- @return #DETECTION_BASE + function DETECTION_BASE:LockDetectedItem( DetectedItem ) + + DetectedItem.Locked = true + + return self + end + + --- Unlock a detected item. + -- @param #DETECTION_BASE self + -- @param #DETECTION_BASE.DetectedItem DetectedItem The DetectedItem. + -- @return #DETECTION_BASE + function DETECTION_BASE:UnlockDetectedItem( DetectedItem ) + + DetectedItem.Locked = nil + + return self + end + + + --- Set the detected item coordinate. -- @param #DETECTION_BASE self diff --git a/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua b/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua index 514c355d0..3fc4a86c8 100644 --- a/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua +++ b/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua @@ -233,6 +233,7 @@ do -- TASK_CAPTURE_DISPATCHER function TASK_CAPTURE_DISPATCHER:Link_AI_A2G_Dispatcher( AI_A2G_Dispatcher ) self.AI_A2G_Dispatcher = AI_A2G_Dispatcher -- AI.AI_A2G_Dispatcher#AI_A2G_DISPATCHER + AI_A2G_Dispatcher.Detection:LockDetectedItems() return self end @@ -276,34 +277,50 @@ do -- TASK_CAPTURE_DISPATCHER CaptureZone.Task:UpdateTaskInfo() function CaptureZone.Task.OnEnterAssigned( Task, From, Event, To ) - self.AI_A2G_Dispatcher:Unlock( Task.TaskZoneName ) -- This will unlock the zone to be defended by AI. + if self.AI_A2G_Dispatcher then + self.AI_A2G_Dispatcher:Unlock( Task.TaskZoneName ) -- This will unlock the zone to be defended by AI. + end CaptureZone.Task:UpdateTaskInfo() end function CaptureZone.Task.OnEnterSuccess( Task, From, Event, To ) self:Success( Task ) + if self.AI_A2G_Dispatcher then + self.AI_A2G_Dispatcher:Lock( Task.TaskZoneName ) -- This will lock the zone from being defended by AI. + end CaptureZone.Task:UpdateTaskInfo() end function CaptureZone.Task.OnEnterCancelled( Task, From, Event, To ) self:Cancelled( Task ) - self.AI_A2G_Dispatcher:Unlock( Task.TaskZoneName ) -- This will lock the zone from being defended by AI. + if self.AI_A2G_Dispatcher then + self.AI_A2G_Dispatcher:Lock( Task.TaskZoneName ) -- This will lock the zone from being defended by AI. + end CaptureZone.Task:UpdateTaskInfo() end function CaptureZone.Task.OnEnterFailed( Task, From, Event, To ) self:Failed( Task ) + if self.AI_A2G_Dispatcher then + self.AI_A2G_Dispatcher:Lock( Task.TaskZoneName ) -- This will lock the zone from being defended by AI. + end CaptureZone.Task:UpdateTaskInfo() end function CaptureZone.Task.OnEnterAborted( Task, From, Event, To ) self:Aborted( Task ) + if self.AI_A2G_Dispatcher then + self.AI_A2G_Dispatcher:Lock( Task.TaskZoneName ) -- This will lock the zone from being defended by AI. + end CaptureZone.Task:UpdateTaskInfo() end -- Now broadcast the onafterCargoPickedUp event to the Task Cargo Dispatcher. function CaptureZone.Task.OnAfterCaptured( Task, From, Event, To, TaskUnit ) self:Captured( Task, Task.TaskPrefix, TaskUnit ) + if self.AI_A2G_Dispatcher then + self.AI_A2G_Dispatcher:Lock( Task.TaskZoneName ) -- This will lock the zone from being defended by AI. + end CaptureZone.Task:UpdateTaskInfo() end