From 531f8a9106df657bf7be92bfe7078cace24f536b Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 31 May 2017 22:41:29 +0200 Subject: [PATCH] Progress --- .../Moose/AI/AI_A2A_Dispatcher.lua | 210 +++++++++++------- Moose Development/Moose/Core/Set.lua | 5 - .../Moose/Functional/Detection.lua | 4 + .../Moose/Wrapper/Controllable.lua | 4 +- 4 files changed, 140 insertions(+), 83 deletions(-) diff --git a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua index 7bff5dab1..f14d02b3a 100644 --- a/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2A_Dispatcher.lua @@ -10,6 +10,8 @@ -- -- @module AI_A2A_Dispatcher +BASE:TraceClass("AI_A2A_DISPATCHER") + do -- AI_A2A_DISPATCHER --- AI_A2A_DISPATCHER class. @@ -56,12 +58,10 @@ do -- AI_A2A_DISPATCHER self.Detection = Detection - -- This table models the currently alive AI_A2A processes. - self.AI_A2A = self.AI_A2A or {} - - -- These two tables model the AIGroups having an assignment and the Targets having an AIGroup. - self.A2A_Targets = self.A2A_Targets or {} - self.A2A_Tasks = self.A2A_Tasks or {} + -- This table models the DefenderSquadron templates. + self.DefenderSquadrons = self.DefenderSquadrons or {} -- The Defender Squadrons. + self.DefenderTargets = self.DefenderTargets or {} -- The Intruders currently attacked by the Defenders. + self.DefenderTasks = self.DefenderTasks or {} -- The Defenders Tasks. -- TODO: Check detection through radar. self.Detection:FilterCategories( Unit.Category.AIRPLANE, Unit.Category.HELICOPTER ) @@ -166,25 +166,37 @@ do -- AI_A2A_DISPATCHER end - function AI_A2A_DISPATCHER:onafterCAP() + function AI_A2A_DISPATCHER:onafterCAP( SquadronName, Repeat ) local A2AType = "CAP" - for CAPName, CAP in pairs( self.AI_A2A[A2AType] or {} ) do - - local AIGroup = CAP.Spawn:Spawn() - self:F( { AIGroup = AIGroup:GetName() } ) - - if AIGroup then - - local Fsm = AI_A2A_CAP:New( AIGroup, CAP.Zone, CAP.FloorAltitude, CAP.CeilingAltitude, CAP.MinSpeed, CAP.MaxSpeed, CAP.AltType ) - Fsm:__Patrol( 1 ) - - self.A2A_Tasks = self.A2A_Tasks or {} - self.A2A_Tasks[AIGroup] = self.A2A_Tasks[AIGroup] or {} - self.A2A_Tasks[AIGroup].Type = A2AType - self.A2A_Tasks[AIGroup].Fsm = Fsm + self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} + self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + + local CAP = self.DefenderSquadrons["CAP"][SquadronName] + if CAP then + + if self:CanCAP( SquadronName ) then + local AIGroup = CAP.Spawn:Spawn() + self:F( { AIGroup = AIGroup:GetName() } ) + + if AIGroup then + + local Fsm = AI_A2A_CAP:New( AIGroup, CAP.Zone, CAP.FloorAltitude, CAP.CeilingAltitude, CAP.MinSpeed, CAP.MaxSpeed, CAP.AltType ) + Fsm:__Patrol( 1 ) + + self.DefenderTasks = self.DefenderTasks or {} + self.DefenderTasks[AIGroup] = self.DefenderTasks[AIGroup] or {} + self.DefenderTasks[AIGroup].Type = A2AType + self.DefenderTasks[AIGroup].Fsm = Fsm + end end + else + error( "This squadron does not exist:" .. SquadronName ) + end + + if Repeat then + self:__CAP( self:GetCAPDelay( SquadronName ), SquadronName, true ) end end @@ -198,15 +210,16 @@ do -- AI_A2A_DISPATCHER for AIGroupID, AIGroup in pairs( AIGroups ) do - local Fsm = self.A2A_Tasks[AIGroup].Fsm + local Fsm = self.DefenderTasks[AIGroup].Fsm + TargetSetUnit:Flush() Fsm:__Engage( 1, TargetSetUnit ) -- Engage on the TargetSetUnit - self.A2A_Tasks[AIGroup].Target = TargetReference + self.DefenderTasks[AIGroup].Target = TargetReference - self.A2A_Targets[TargetReference] = self.A2A_Targets[TargetReference] or {} - self.A2A_Targets[TargetReference].Set = TargetSetUnit - self.A2A_Targets[TargetReference].Groups = self.A2A_Targets[TargetReference].Groups or {} - local Groups = self.A2A_Targets[TargetReference].Groups + self.DefenderTargets[TargetReference] = self.DefenderTargets[TargetReference] or {} + self.DefenderTargets[TargetReference].Set = TargetSetUnit + self.DefenderTargets[TargetReference].Groups = self.DefenderTargets[TargetReference].Groups or {} + local Groups = self.DefenderTargets[TargetReference].Groups local GroupName = AIGroup:GetName() Groups[GroupName] = AIGroup end @@ -222,11 +235,11 @@ do -- AI_A2A_DISPATCHER local ClosestINTERCEPTName = nil local AttackerCount = TargetSetUnit:Count() - DefendersMissing = AttackerCount - DefendersMissing + local DefendersCount = 0 - while( DefendersMissing < AttackerCount ) do + while( DefendersCount < DefendersMissing ) do - for INTERCEPTName, INTERCEPT in pairs( self.AI_A2A[A2AType] or {} ) do + for INTERCEPTName, INTERCEPT in pairs( self.DefenderSquadrons[A2AType] or {} ) do local SpawnCoord = INTERCEPT.Spawn:GetCoordinate() -- Core.Point#COORDINATE local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate() @@ -240,28 +253,28 @@ do -- AI_A2A_DISPATCHER if ClosestINTERCEPTName then - local INTERCEPT = self.AI_A2A[A2AType][ClosestINTERCEPTName] + local INTERCEPT = self.DefenderSquadrons[A2AType][ClosestINTERCEPTName] local AIGroup = INTERCEPT.Spawn:Spawn() self:F( { AIGroup = AIGroup:GetName() } ) if AIGroup then - DefendersMissing = DefendersMissing + AIGroup:GetSize() + DefendersCount = DefendersCount + AIGroup:GetSize() local Fsm = AI_A2A_INTERCEPT:New( AIGroup ) Fsm:__Engage( 1, TargetSetUnit ) -- Engage on the TargetSetUnit - self.A2A_Tasks = self.A2A_Tasks or {} - self.A2A_Tasks[AIGroup] = self.A2A_Tasks[AIGroup] or {} - self.A2A_Tasks[AIGroup].Type = A2AType - self.A2A_Tasks[AIGroup].Fsm = Fsm - self.A2A_Tasks[AIGroup].Target = TargetReference + self.DefenderTasks = self.DefenderTasks or {} + self.DefenderTasks[AIGroup] = self.DefenderTasks[AIGroup] or {} + self.DefenderTasks[AIGroup].Type = A2AType + self.DefenderTasks[AIGroup].Fsm = Fsm + self.DefenderTasks[AIGroup].Target = TargetReference - self.A2A_Targets[TargetReference] = self.A2A_Targets[TargetReference] or {} - self.A2A_Targets[TargetReference].Set = TargetSetUnit - self.A2A_Targets[TargetReference].Groups = self.A2A_Targets[TargetReference].Groups or {} - local Groups = self.A2A_Targets[TargetReference].Groups + self.DefenderTargets[TargetReference] = self.DefenderTargets[TargetReference] or {} + self.DefenderTargets[TargetReference].Set = TargetSetUnit + self.DefenderTargets[TargetReference].Groups = self.DefenderTargets[TargetReference].Groups or {} + local Groups = self.DefenderTargets[TargetReference].Groups local GroupName = AIGroup:GetName() Groups[GroupName] = AIGroup @@ -272,29 +285,82 @@ do -- AI_A2A_DISPATCHER - function AI_A2A_DISPATCHER:SetCAP( CAPName, CAPSpawn, CAPZone, CAPFloorAltitude, CAPCeilingAltitude, CAPMinSpeed, CAPMaxSpeed, CAPAltType ) + function AI_A2A_DISPATCHER:SetCAP( SquadronName, Spawn, Zone, FloorAltitude, CeilingAltitude, MinSpeed, MaxSpeed, AltType ) - self.AI_A2A["CAP"] = self.AI_A2A["CAP"] or {} - self.AI_A2A["CAP"][CAPName] = self.AI_A2A["CAP"][CAPName] or {} + self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} + self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} - local CAP = self.AI_A2A["CAP"][CAPName] - CAP.Name = CAPName - CAP.Spawn = CAPSpawn -- Funtional.Spawn#SPAWN - CAP.Zone = CAPZone - CAP.FloorAltitude = CAPFloorAltitude - CAP.CeilingAltitude = CAPCeilingAltitude - CAP.MinSpeed = CAPMinSpeed - CAP.MaxSpeed = CAPMaxSpeed - CAP.AltType = CAPAltType + local CAP = self.DefenderSquadrons["CAP"][SquadronName] + CAP.Name = SquadronName + CAP.Spawn = Spawn -- Funtional.Spawn#SPAWN + CAP.Zone = Zone + CAP.FloorAltitude = FloorAltitude + CAP.CeilingAltitude = CeilingAltitude + CAP.MinSpeed = MinSpeed + CAP.MaxSpeed = MaxSpeed + CAP.AltType = AltType + + self:SetCAPInterval( SquadronName, 60, 300, 1 ) end + function AI_A2A_DISPATCHER:SetCAPInterval( SquadronName, LowInterval, HighInterval, Probability ) + + self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} + self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + + local CAP = self.DefenderSquadrons["CAP"][SquadronName] + + if CAP then + CAP.LowInterval = LowInterval + CAP.HighInterval = HighInterval + CAP.Probability = Probability + else + error( "This squadron does not exist:" .. SquadronName ) + end + + self:__CAP( self:GetCAPDelay( SquadronName ), SquadronName, true ) + end + + function AI_A2A_DISPATCHER:GetCAPDelay( SquadronName ) + + self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} + self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + + local CAP = self.DefenderSquadrons["CAP"][SquadronName] + + if CAP then + return math.random( CAP.LowInterval, CAP.HighInterval ) + else + error( "This squadron does not exist:" .. SquadronName ) + end + end + + function AI_A2A_DISPATCHER:CanCAP( SquadronName ) + + self.DefenderSquadrons["CAP"] = self.DefenderSquadrons["CAP"] or {} + self.DefenderSquadrons["CAP"][SquadronName] = self.DefenderSquadrons["CAP"][SquadronName] or {} + + local CAP = self.DefenderSquadrons["CAP"][SquadronName] + + if CAP then + local Probability = math.random() + if Probability < CAP.Probability then + return true + else + return false + end + else + error( "This squadron does not exist:" .. SquadronName ) + end + end + function AI_A2A_DISPATCHER:SetINTERCEPT( Name, Spawn, MinSpeed, MaxSpeed ) - self.AI_A2A["INTERCEPT"] = self.AI_A2A["INTERCEPT"] or {} - self.AI_A2A["INTERCEPT"][Name] = self.AI_A2A["INTERCEPT"][Name] or {} + self.DefenderSquadrons["INTERCEPT"] = self.DefenderSquadrons["INTERCEPT"] or {} + self.DefenderSquadrons["INTERCEPT"][Name] = self.DefenderSquadrons["INTERCEPT"][Name] or {} - local INTERCEPT = self.AI_A2A["INTERCEPT"][Name] + local INTERCEPT = self.DefenderSquadrons["INTERCEPT"][Name] INTERCEPT.Name = Name INTERCEPT.Spawn = Spawn INTERCEPT.MinSpeed = MinSpeed @@ -333,7 +399,7 @@ do -- AI_A2A_DISPATCHER -- First, count the active AIGroups Units, targetting the DetectedSet local AIUnitCount = 0 - for AIGroupName, AIGroup in pairs( ( self.A2A_Targets[DetectedItem] and self.A2A_Targets[DetectedItem].Groups ) or {} ) do + for AIGroupName, AIGroup in pairs( ( self.DefenderTargets[DetectedItem] and self.DefenderTargets[DetectedItem].Groups ) or {} ) do local AIGroup = AIGroup -- Wrapper.Group#GROUP if AIGroup:IsAlive() then AIUnitCount = AIUnitCount + AIGroup:GetSize() @@ -352,7 +418,7 @@ do -- AI_A2A_DISPATCHER local AIFriendlies = self:GetAIFriendliesNearBy( DetectedItem ) - for AIName, AIFriendly in pairs( AIFriendlies ) do + for AIName, AIFriendly in pairs( AIFriendlies or {} ) do -- We only allow to ENGAGE targets as long as the Units on both sides are balanced. if DetectedCount > DefenderCount then local AIGroup = AIFriendly :GetGroup() -- Wrapper.Group#GROUP @@ -360,8 +426,8 @@ do -- AI_A2A_DISPATCHER if AIGroup:IsAlive() then -- Ok, so we have a friendly near the potential target. -- Now we need to check if the AIGroup has a Task. - local AIGroupTask = self.A2A_Tasks[AIGroup] - self:F({AIGroupTask = AIGroupTask}) + local AIGroupTask = self.DefenderTasks[AIGroup] + self:F( {AIGroupTask = AIGroupTask } ) if AIGroupTask then -- The Task should be CAP self:F( { Type = AIGroupTask.Type } ) @@ -418,7 +484,6 @@ do -- AI_A2A_DISPATCHER self:F( { DetectedItem.ItemID } ) local AttackerSet = DetectedItem.Set - AttackerSet:Flush() local AttackerCount = AttackerSet:Count() -- First, count the active AIGroups Units, targetting the DetectedSet @@ -550,27 +615,25 @@ do -- AI_A2A_DISPATCHER -- @return Tasking.Task#TASK function AI_A2A_DISPATCHER:EvaluateRemoveTask( DetectedItem, A2A_Index ) - local A2A_Target = self.A2A_Targets[A2A_Index] + local A2A_Target = self.DefenderTargets[A2A_Index] if A2A_Target then for AIGroupName, AIGroup in pairs( A2A_Target.Groups ) do local AIGroup = AIGroup -- Wrapper.Group#GROUP if not AIGroup:IsAlive() then - self.A2A_Tasks[AIGroup] = nil - self.A2A_Targets[A2A_Index].Groups[AIGroupName] = nil + self.DefenderTasks[AIGroup] = nil + self.DefenderTargets[A2A_Index].Groups[AIGroupName] = nil end end local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT - DetectedSet:Flush() - self:E( { DetectedSetCount = DetectedSet:Count() } ) if DetectedSet:Count() == 0 then - self.A2A_Targets[A2A_Index] = nil + self.DefenderTargets[A2A_Index] = nil end end - return self.A2A_Targets[A2A_Index] + return self.DefenderTargets[A2A_Index] end @@ -579,7 +642,6 @@ do -- AI_A2A_DISPATCHER -- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Detection#DETECTION_BASE} derived object. -- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop. function AI_A2A_DISPATCHER:ProcessDetected( Detection ) - self:E() local AreaMsg = {} local TaskMsg = {} @@ -606,19 +668,15 @@ do -- AI_A2A_DISPATCHER local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT local DetectedCount = DetectedSet:Count() local DetectedZone = DetectedItem.Zone - self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count() } ) - DetectedSet:Flush() + + self:F( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count() } ) local DetectedID = DetectedItem.ID local A2A_Index = DetectedItem.Index local DetectedItemChanged = DetectedItem.Changed - self:E( { A2A_Index = A2A_Index } ) - - local A2A_Target = self:EvaluateRemoveTask( DetectedItem, A2A_Index ) - self:E( { A2A_Index = A2A_Index, A2A_Target = A2A_Target } ) - DetectedSet:Flush() + self:F( { A2A_Index = A2A_Index, A2A_Target = A2A_Target } ) -- Evaluate A2A_Action if not A2A_Target then diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index ad8c69b67..241a793db 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -226,7 +226,6 @@ end -- @param #SET_BASE self -- @return Core.Base#BASE function SET_BASE:GetFirst() - self:F() local ObjectName = self.Index[1] local FirstObject = self.Set[ObjectName] @@ -238,7 +237,6 @@ end -- @param #SET_BASE self -- @return Core.Base#BASE function SET_BASE:GetLast() - self:F() local ObjectName = self.Index[#self.Index] local LastObject = self.Set[ObjectName] @@ -250,12 +248,9 @@ end -- @param #SET_BASE self -- @return Core.Base#BASE function SET_BASE:GetRandom() - self:F() local RandomItem = self.Set[self.Index[math.random(#self.Index)]] - self:T3( { RandomItem } ) - return RandomItem end diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index d2e44ba63..edab3062a 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -37,6 +37,10 @@ -- -- @module Detection +--BASE:TraceClass("DETECTION_BASE") +--BASE:TraceClass("DETECTION_AREAS") +--BASE:TraceClass("DETECTION_UNITS") +--BASE:TraceClass("DETECTION_TYPES") do -- DETECTION_BASE diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index da203cb54..06c3ce244 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -386,7 +386,7 @@ function CONTROLLABLE:TaskCombo( DCSTasks ) } for TaskID, Task in ipairs( DCSTasks ) do - self:E( Task ) + self:T( Task ) end self:T3( { DCSTaskCombo } ) @@ -585,7 +585,7 @@ function CONTROLLABLE:TaskAttackUnit( AttackUnit, GroupAttack, WeaponExpend, Att } } - self:E( DCSTask ) + self:T3( DCSTask ) return DCSTask end