mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Merge branch 'master' into funkyfranky
This commit is contained in:
commit
84b4651cd9
@ -391,9 +391,9 @@ function AI_A2A_CAP:onafterEngage( AIGroup, From, Event, To, AttackSetUnit )
|
|||||||
|
|
||||||
self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT
|
self.AttackSetUnit = AttackSetUnit or self.AttackSetUnit -- Core.Set#SET_UNIT
|
||||||
|
|
||||||
local FirstAttackUnit = self.AttackSetUnit:GetFirst()
|
local FirstAttackUnit = self.AttackSetUnit:GetFirst() -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
if FirstAttackUnit then
|
if FirstAttackUnit and FirstAttackUnit:IsAlive() then -- If there is no attacker anymore, stop the engagement.
|
||||||
|
|
||||||
if AIGroup:IsAlive() then
|
if AIGroup:IsAlive() then
|
||||||
|
|
||||||
|
|||||||
@ -1369,14 +1369,14 @@ do -- AI_A2A_DISPATCHER
|
|||||||
---
|
---
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
-- @param Wrapper.Group#GROUP AIGroup
|
-- @param Wrapper.Group#GROUP AIGroup
|
||||||
function AI_A2A_DISPATCHER:SetDefenderTaskTarget( Defender, Target )
|
function AI_A2A_DISPATCHER:SetDefenderTaskTarget( Defender, AttackerDetection )
|
||||||
|
|
||||||
local Message = "(" .. self.DefenderTasks[Defender].Type .. ") "
|
local Message = "(" .. self.DefenderTasks[Defender].Type .. ") "
|
||||||
Message = Message .. Defender:GetName()
|
Message = Message .. Defender:GetName()
|
||||||
Message = Message .. ( Target and ( " target " .. Target.Index .. " [" .. Target.Set:Count() .. "]" ) ) or ""
|
Message = Message .. ( AttackerDetection and ( " target " .. AttackerDetection.Index .. " [" .. AttackerDetection.Set:Count() .. "]" ) ) or ""
|
||||||
self:F( { Target = Message } )
|
self:F( { AttackerDetection = Message } )
|
||||||
if Target then
|
if AttackerDetection then
|
||||||
self.DefenderTasks[Defender].Target = Target
|
self.DefenderTasks[Defender].Target = AttackerDetection
|
||||||
end
|
end
|
||||||
return self
|
return self
|
||||||
end
|
end
|
||||||
@ -2510,20 +2510,20 @@ do -- AI_A2A_DISPATCHER
|
|||||||
|
|
||||||
---
|
---
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_DISPATCHER:CountDefendersEngaged( Target )
|
function AI_A2A_DISPATCHER:CountDefendersEngaged( AttackerDetection )
|
||||||
|
|
||||||
-- First, count the active AIGroups Units, targetting the DetectedSet
|
-- First, count the active AIGroups Units, targetting the DetectedSet
|
||||||
local AIUnitCount = 0
|
local AIUnitCount = 0
|
||||||
|
|
||||||
self:E( "Counting Defenders Engaged for Attacker:" )
|
self:E( "Counting Defenders Engaged for Attacker:" )
|
||||||
local DetectedSet = Target.Set
|
local DetectedSet = AttackerDetection.Set
|
||||||
DetectedSet:Flush()
|
DetectedSet:Flush()
|
||||||
|
|
||||||
local DefenderTasks = self:GetDefenderTasks()
|
local DefenderTasks = self:GetDefenderTasks()
|
||||||
for AIGroup, DefenderTask in pairs( DefenderTasks ) do
|
for AIGroup, DefenderTask in pairs( DefenderTasks ) do
|
||||||
local AIGroup = AIGroup -- Wrapper.Group#GROUP
|
local AIGroup = AIGroup -- Wrapper.Group#GROUP
|
||||||
local DefenderTask = self:GetDefenderTaskTarget( AIGroup )
|
local DefenderTask = self:GetDefenderTaskTarget( AIGroup )
|
||||||
if DefenderTask and DefenderTask.Index == Target.Index then
|
if DefenderTask and DefenderTask.Index == AttackerDetection.Index then
|
||||||
AIUnitCount = AIUnitCount + AIGroup:GetSize()
|
AIUnitCount = AIUnitCount + AIGroup:GetSize()
|
||||||
self:E( "Defender Group Name: " .. AIGroup:GetName() .. ", Size: " .. AIGroup:GetSize() )
|
self:E( "Defender Group Name: " .. AIGroup:GetName() .. ", Size: " .. AIGroup:GetSize() )
|
||||||
end
|
end
|
||||||
@ -2534,18 +2534,18 @@ do -- AI_A2A_DISPATCHER
|
|||||||
|
|
||||||
---
|
---
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_DISPATCHER:CountDefendersToBeEngaged( DetectedItem, DefenderCount )
|
function AI_A2A_DISPATCHER:CountDefendersToBeEngaged( AttackerDetection, DefenderCount )
|
||||||
|
|
||||||
local Friendlies = nil
|
local Friendlies = nil
|
||||||
|
|
||||||
local DetectedSet = DetectedItem.Set
|
local AttackerSet = AttackerDetection.Set
|
||||||
local DetectedCount = DetectedSet:Count()
|
local AttackerCount = AttackerSet:Count()
|
||||||
|
|
||||||
local AIFriendlies = self:GetAIFriendliesNearBy( DetectedItem )
|
local DefenderFriendlies = self:GetAIFriendliesNearBy( AttackerDetection )
|
||||||
|
|
||||||
for FriendlyDistance, AIFriendly in UTILS.spairs( AIFriendlies or {} ) do
|
for FriendlyDistance, AIFriendly in UTILS.spairs( DefenderFriendlies or {} ) do
|
||||||
-- We only allow to ENGAGE targets as long as the Units on both sides are balanced.
|
-- We only allow to ENGAGE targets as long as the Units on both sides are balanced.
|
||||||
if DetectedCount > DefenderCount then
|
if AttackerCount > DefenderCount then
|
||||||
local Friendly = AIFriendly:GetGroup() -- Wrapper.Group#GROUP
|
local Friendly = AIFriendly:GetGroup() -- Wrapper.Group#GROUP
|
||||||
if Friendly and Friendly:IsAlive() then
|
if Friendly and Friendly:IsAlive() then
|
||||||
-- Ok, so we have a friendly near the potential target.
|
-- Ok, so we have a friendly near the potential target.
|
||||||
@ -2554,7 +2554,7 @@ do -- AI_A2A_DISPATCHER
|
|||||||
if DefenderTask then
|
if DefenderTask then
|
||||||
-- The Task should be CAP or GCI
|
-- The Task should be CAP or GCI
|
||||||
if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then
|
if DefenderTask.Type == "CAP" or DefenderTask.Type == "GCI" then
|
||||||
-- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the TargetSet
|
-- If there is no target, then add the AIGroup to the ResultAIGroups for Engagement to the AttackerSet
|
||||||
if DefenderTask.Target == nil then
|
if DefenderTask.Target == nil then
|
||||||
if DefenderTask.Fsm:Is( "Returning" )
|
if DefenderTask.Fsm:Is( "Returning" )
|
||||||
or DefenderTask.Fsm:Is( "Patrolling" ) then
|
or DefenderTask.Fsm:Is( "Patrolling" ) then
|
||||||
@ -2650,16 +2650,16 @@ do -- AI_A2A_DISPATCHER
|
|||||||
|
|
||||||
---
|
---
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, Target, Defenders )
|
function AI_A2A_DISPATCHER:onafterENGAGE( From, Event, To, AttackerDetection, Defenders )
|
||||||
|
|
||||||
if Defenders then
|
if Defenders then
|
||||||
|
|
||||||
for DefenderID, Defender in pairs( Defenders ) do
|
for DefenderID, Defender in pairs( Defenders ) do
|
||||||
|
|
||||||
local Fsm = self:GetDefenderTaskFsm( Defender )
|
local Fsm = self:GetDefenderTaskFsm( Defender )
|
||||||
Fsm:__Engage( 1, Target.Set ) -- Engage on the TargetSetUnit
|
Fsm:__Engage( 1, AttackerDetection.Set ) -- Engage on the TargetSetUnit
|
||||||
|
|
||||||
self:SetDefenderTaskTarget( Defender, Target )
|
self:SetDefenderTaskTarget( Defender, AttackerDetection )
|
||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -2667,164 +2667,169 @@ do -- AI_A2A_DISPATCHER
|
|||||||
|
|
||||||
---
|
---
|
||||||
-- @param #AI_A2A_DISPATCHER self
|
-- @param #AI_A2A_DISPATCHER self
|
||||||
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, DetectedItem, DefendersMissing, Friendlies )
|
function AI_A2A_DISPATCHER:onafterGCI( From, Event, To, AttackerDetection, DefendersMissing, DefenderFriendlies )
|
||||||
|
|
||||||
self:F( { From, Event, To, DetectedItem.Index, DefendersMissing, Friendlies } )
|
self:F( { From, Event, To, AttackerDetection.Index, DefendersMissing, DefenderFriendlies } )
|
||||||
|
|
||||||
local AttackerSet = DetectedItem.Set
|
local AttackerSet = AttackerDetection.Set
|
||||||
local AttackerCount = AttackerSet:Count()
|
local AttackerUnit = AttackerSet:GetFirst()
|
||||||
local DefendersCount = 0
|
|
||||||
|
|
||||||
for DefenderID, AIGroup in pairs( Friendlies or {} ) do
|
if AttackerUnit and AttackerUnit:IsAlive() then
|
||||||
|
local AttackerCount = AttackerSet:Count()
|
||||||
|
local DefenderCount = 0
|
||||||
|
|
||||||
local Fsm = self:GetDefenderTaskFsm( AIGroup )
|
for DefenderID, DefenderGroup in pairs( DefenderFriendlies or {} ) do
|
||||||
Fsm:__Engage( 1, AttackerSet ) -- Engage on the TargetSetUnit
|
|
||||||
|
|
||||||
self:SetDefenderTaskTarget( AIGroup, DetectedItem )
|
local Fsm = self:GetDefenderTaskFsm( DefenderGroup )
|
||||||
|
Fsm:__Engage( 1, AttackerSet ) -- Engage on the TargetSetUnit
|
||||||
|
|
||||||
DefendersCount = DefendersCount + AIGroup:GetSize()
|
self:SetDefenderTaskTarget( DefenderGroup, AttackerDetection )
|
||||||
end
|
|
||||||
|
|
||||||
DefendersCount = DefendersMissing
|
DefenderCount = DefenderCount + DefenderGroup:GetSize()
|
||||||
|
end
|
||||||
|
|
||||||
local ClosestDistance = 0
|
DefenderCount = DefendersMissing
|
||||||
local ClosestDefenderSquadronName = nil
|
|
||||||
|
|
||||||
local BreakLoop = false
|
local ClosestDistance = 0
|
||||||
|
local ClosestDefenderSquadronName = nil
|
||||||
|
|
||||||
while( DefendersCount > 0 and not BreakLoop ) do
|
local BreakLoop = false
|
||||||
self:F( { DefenderSquadrons = self.DefenderSquadrons } )
|
|
||||||
for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do
|
|
||||||
self:F( { GCI = DefenderSquadron.Gci } )
|
|
||||||
for InterceptID, Intercept in pairs( DefenderSquadron.Gci or {} ) do
|
|
||||||
|
|
||||||
self:F( { DefenderSquadron } )
|
while( DefenderCount > 0 and not BreakLoop ) do
|
||||||
local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE
|
self:F( { DefenderSquadrons = self.DefenderSquadrons } )
|
||||||
--local TargetCoord = AttackerSet:GetFirst():GetCoordinate()
|
for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do
|
||||||
local InterceptCoord = DetectedItem.InterceptCoord
|
self:F( { GCI = DefenderSquadron.Gci } )
|
||||||
self:F({InterceptCoord = InterceptCoord})
|
for InterceptID, Intercept in pairs( DefenderSquadron.Gci or {} ) do
|
||||||
if InterceptCoord then
|
|
||||||
local Distance = SpawnCoord:Get2DDistance( InterceptCoord )
|
|
||||||
self:F( { Distance = Distance, InterceptCoord = InterceptCoord } )
|
|
||||||
|
|
||||||
if ClosestDistance == 0 or Distance < ClosestDistance then
|
self:F( { DefenderSquadron } )
|
||||||
|
local SpawnCoord = DefenderSquadron.Airbase:GetCoordinate() -- Core.Point#COORDINATE
|
||||||
|
local AttackerCoord = AttackerUnit:GetCoordinate()
|
||||||
|
local InterceptCoord = AttackerDetection.InterceptCoord
|
||||||
|
self:F({InterceptCoord = InterceptCoord})
|
||||||
|
if InterceptCoord then
|
||||||
|
local InterceptDistance = SpawnCoord:Get2DDistance( InterceptCoord )
|
||||||
|
local AirbaseDistance = SpawnCoord:Get2DDistance( AttackerCoord )
|
||||||
|
self:F( { InterceptDistance = InterceptDistance, AirbaseDistance = AirbaseDistance, InterceptCoord = InterceptCoord } )
|
||||||
|
|
||||||
-- Only intercept if the distance to target is smaller or equal to the GciRadius limit.
|
if ClosestDistance == 0 or InterceptDistance < ClosestDistance then
|
||||||
if Distance <= self.GciRadius then
|
|
||||||
ClosestDistance = Distance
|
-- Only intercept if the distance to target is smaller or equal to the GciRadius limit.
|
||||||
ClosestDefenderSquadronName = SquadronName
|
if AirbaseDistance <= self.GciRadius then
|
||||||
|
ClosestDistance = InterceptDistance
|
||||||
|
ClosestDefenderSquadronName = SquadronName
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if ClosestDefenderSquadronName then
|
if ClosestDefenderSquadronName then
|
||||||
|
|
||||||
local DefenderSquadron = self:CanGCI( ClosestDefenderSquadronName )
|
local DefenderSquadron = self:CanGCI( ClosestDefenderSquadronName )
|
||||||
|
|
||||||
if DefenderSquadron then
|
if DefenderSquadron then
|
||||||
|
|
||||||
local Gci = self.DefenderSquadrons[ClosestDefenderSquadronName].Gci
|
local Gci = self.DefenderSquadrons[ClosestDefenderSquadronName].Gci
|
||||||
|
|
||||||
if Gci then
|
if Gci then
|
||||||
|
|
||||||
local DefenderOverhead = DefenderSquadron.Overhead or self.DefenderDefault.Overhead
|
local DefenderOverhead = DefenderSquadron.Overhead or self.DefenderDefault.Overhead
|
||||||
local DefenderGrouping = DefenderSquadron.Grouping or self.DefenderDefault.Grouping
|
local DefenderGrouping = DefenderSquadron.Grouping or self.DefenderDefault.Grouping
|
||||||
local DefendersNeeded = math.ceil( DefendersCount * DefenderOverhead )
|
local DefendersNeeded = math.ceil( DefenderCount * DefenderOverhead )
|
||||||
|
|
||||||
self:F( { DefaultOverhead = self.DefenderDefault.Overhead, Overhead = DefenderOverhead } )
|
self:F( { DefaultOverhead = self.DefenderDefault.Overhead, Overhead = DefenderOverhead } )
|
||||||
self:F( { DefaultGrouping = self.DefenderDefault.Grouping, Grouping = DefenderGrouping } )
|
self:F( { DefaultGrouping = self.DefenderDefault.Grouping, Grouping = DefenderGrouping } )
|
||||||
self:F( { DefendersCount = DefendersCount, DefendersNeeded = DefendersNeeded } )
|
self:F( { DefendersCount = DefenderCount, DefendersNeeded = DefendersNeeded } )
|
||||||
|
|
||||||
while ( DefendersNeeded > 0 ) do
|
while ( DefendersNeeded > 0 ) do
|
||||||
|
|
||||||
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] -- Functional.Spawn#SPAWN
|
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] -- Functional.Spawn#SPAWN
|
||||||
local DefenderGrouping = ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded
|
local DefenderGrouping = ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded
|
||||||
if DefenderGrouping then
|
if DefenderGrouping then
|
||||||
Spawn:InitGrouping( DefenderGrouping )
|
Spawn:InitGrouping( DefenderGrouping )
|
||||||
else
|
else
|
||||||
Spawn:InitGrouping()
|
Spawn:InitGrouping()
|
||||||
end
|
|
||||||
|
|
||||||
local TakeoffMethod = self:GetSquadronTakeoff( ClosestDefenderSquadronName )
|
|
||||||
local DefenderGCI = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod, DefenderSquadron.TakeoffAltitude or self.DefenderDefault.TakeoffAltitude ) -- Wrapper.Group#GROUP
|
|
||||||
self:F( { GCIDefender = DefenderGCI:GetName() } )
|
|
||||||
|
|
||||||
DefendersNeeded = DefendersNeeded - DefenderGrouping
|
|
||||||
|
|
||||||
self:AddDefenderToSquadron( DefenderSquadron, DefenderGCI, DefenderGrouping )
|
|
||||||
|
|
||||||
if DefenderGCI then
|
|
||||||
|
|
||||||
DefendersCount = DefendersCount - DefenderGrouping
|
|
||||||
|
|
||||||
local Fsm = AI_A2A_GCI:New( DefenderGCI, Gci.EngageMinSpeed, Gci.EngageMaxSpeed )
|
|
||||||
Fsm:SetDispatcher( self )
|
|
||||||
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
|
||||||
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
|
||||||
Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
|
|
||||||
Fsm:SetDisengageRadius( self.DisengageRadius )
|
|
||||||
Fsm:Start()
|
|
||||||
Fsm:__Engage( 2, DetectedItem.Set ) -- Engage on the TargetSetUnit
|
|
||||||
|
|
||||||
|
|
||||||
self:SetDefenderTask( ClosestDefenderSquadronName, DefenderGCI, "GCI", Fsm, DetectedItem )
|
|
||||||
|
|
||||||
|
|
||||||
function Fsm:onafterRTB( Defender, From, Event, To )
|
|
||||||
self:F({"GCI RTB", Defender:GetName()})
|
|
||||||
self:GetParent(self).onafterRTB( self, Defender, From, Event, To )
|
|
||||||
|
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
|
||||||
Dispatcher:ClearDefenderTaskTarget( Defender )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
local TakeoffMethod = self:GetSquadronTakeoff( ClosestDefenderSquadronName )
|
||||||
function Fsm:onafterLostControl( Defender, From, Event, To )
|
local DefenderGCI = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod, DefenderSquadron.TakeoffAltitude or self.DefenderDefault.TakeoffAltitude ) -- Wrapper.Group#GROUP
|
||||||
self:F({"GCI LostControl", Defender:GetName()})
|
self:F( { GCIDefender = DefenderGCI:GetName() } )
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
|
||||||
|
|
||||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
|
DefendersNeeded = DefendersNeeded - DefenderGrouping
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
|
||||||
if Defender:IsAboveRunway() then
|
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
|
||||||
Defender:Destroy()
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
--- @param #AI_A2A_DISPATCHER self
|
self:AddDefenderToSquadron( DefenderSquadron, DefenderGCI, DefenderGrouping )
|
||||||
function Fsm:onafterHome( Defender, From, Event, To, Action )
|
|
||||||
self:F({"GCI Home", Defender:GetName()})
|
|
||||||
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
|
||||||
|
|
||||||
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
if DefenderGCI then
|
||||||
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
|
||||||
|
|
||||||
if Action and Action == "Destroy" then
|
DefenderCount = DefenderCount - DefenderGrouping
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
|
||||||
Defender:Destroy()
|
local Fsm = AI_A2A_GCI:New( DefenderGCI, Gci.EngageMinSpeed, Gci.EngageMaxSpeed )
|
||||||
|
Fsm:SetDispatcher( self )
|
||||||
|
Fsm:SetHomeAirbase( DefenderSquadron.Airbase )
|
||||||
|
Fsm:SetFuelThreshold( DefenderSquadron.FuelThreshold or self.DefenderDefault.FuelThreshold, 60 )
|
||||||
|
Fsm:SetDamageThreshold( self.DefenderDefault.DamageThreshold )
|
||||||
|
Fsm:SetDisengageRadius( self.DisengageRadius )
|
||||||
|
Fsm:Start()
|
||||||
|
Fsm:__Engage( 2, AttackerDetection.Set ) -- Engage on the TargetSetUnit
|
||||||
|
|
||||||
|
|
||||||
|
self:SetDefenderTask( ClosestDefenderSquadronName, DefenderGCI, "GCI", Fsm, AttackerDetection )
|
||||||
|
|
||||||
|
|
||||||
|
function Fsm:onafterRTB( Defender, From, Event, To )
|
||||||
|
self:F({"GCI RTB", Defender:GetName()})
|
||||||
|
self:GetParent(self).onafterRTB( self, Defender, From, Event, To )
|
||||||
|
|
||||||
|
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||||
|
Dispatcher:ClearDefenderTaskTarget( Defender )
|
||||||
end
|
end
|
||||||
|
|
||||||
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
|
--- @param #AI_A2A_DISPATCHER self
|
||||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
function Fsm:onafterLostControl( Defender, From, Event, To )
|
||||||
Defender:Destroy()
|
self:F({"GCI LostControl", Defender:GetName()})
|
||||||
|
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
||||||
|
|
||||||
|
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||||
|
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
||||||
|
if Defender:IsAboveRunway() then
|
||||||
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||||
|
Defender:Destroy()
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
end -- if DefenderGCI then
|
--- @param #AI_A2A_DISPATCHER self
|
||||||
end -- while ( DefendersNeeded > 0 ) do
|
function Fsm:onafterHome( Defender, From, Event, To, Action )
|
||||||
|
self:F({"GCI Home", Defender:GetName()})
|
||||||
|
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
|
||||||
|
|
||||||
|
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||||
|
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
|
||||||
|
|
||||||
|
if Action and Action == "Destroy" then
|
||||||
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||||
|
Defender:Destroy()
|
||||||
|
end
|
||||||
|
|
||||||
|
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
|
||||||
|
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||||
|
Defender:Destroy()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end -- if DefenderGCI then
|
||||||
|
end -- while ( DefendersNeeded > 0 ) do
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- No more resources, try something else.
|
||||||
|
-- Subject for a later enhancement to try to depart from another squadron and disable this one.
|
||||||
|
BreakLoop = true
|
||||||
|
break
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
-- No more resources, try something else.
|
-- There isn't any closest airbase anymore, break the loop.
|
||||||
-- Subject for a later enhancement to try to depart from another squadron and disable this one.
|
|
||||||
BreakLoop = true
|
|
||||||
break
|
break
|
||||||
end
|
end
|
||||||
else
|
end -- if DefenderSquadron then
|
||||||
-- There isn't any closest airbase anymore, break the loop.
|
end -- if AttackerUnit
|
||||||
break
|
|
||||||
end
|
|
||||||
end -- if DefenderSquadron then
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -360,7 +360,7 @@ function AI_A2A_GCI:onafterEngage( AIGroup, From, Event, To, AttackSetUnit )
|
|||||||
|
|
||||||
local FirstAttackUnit = self.AttackSetUnit:GetFirst()
|
local FirstAttackUnit = self.AttackSetUnit:GetFirst()
|
||||||
|
|
||||||
if FirstAttackUnit then
|
if FirstAttackUnit and FirstAttackUnit:IsAlive() then
|
||||||
|
|
||||||
if AIGroup:IsAlive() then
|
if AIGroup:IsAlive() then
|
||||||
|
|
||||||
@ -368,7 +368,6 @@ function AI_A2A_GCI:onafterEngage( AIGroup, From, Event, To, AttackSetUnit )
|
|||||||
|
|
||||||
local CurrentCoord = AIGroup:GetCoordinate()
|
local CurrentCoord = AIGroup:GetCoordinate()
|
||||||
|
|
||||||
|
|
||||||
--- Calculate the target route point.
|
--- Calculate the target route point.
|
||||||
|
|
||||||
local CurrentCoord = AIGroup:GetCoordinate()
|
local CurrentCoord = AIGroup:GetCoordinate()
|
||||||
|
|||||||
@ -990,6 +990,8 @@ do -- DESIGNATE
|
|||||||
function DESIGNATE:onafterLaseOn( From, Event, To, Index, Duration, LaserCode )
|
function DESIGNATE:onafterLaseOn( From, Event, To, Index, Duration, LaserCode )
|
||||||
|
|
||||||
self.Designating[Index] = "Laser"
|
self.Designating[Index] = "Laser"
|
||||||
|
self.LaseStart = timer.getTime()
|
||||||
|
self.LaseDuration = Duration
|
||||||
self:__Lasing( -1, Index, Duration, LaserCode )
|
self:__Lasing( -1, Index, Duration, LaserCode )
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -1038,59 +1040,84 @@ do -- DESIGNATE
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if self.AutoLase or ( not self.AutoLase and ( self.LaseStart + Duration >= timer.getTime() ) ) then
|
||||||
|
|
||||||
TargetSetUnit:ForEachUnitPerThreatLevel( 10, 0,
|
TargetSetUnit:ForEachUnitPerThreatLevel( 10, 0,
|
||||||
--- @param Wrapper.Unit#UNIT SmokeUnit
|
--- @param Wrapper.Unit#UNIT SmokeUnit
|
||||||
function( TargetUnit )
|
function( TargetUnit )
|
||||||
|
|
||||||
self:F( { TargetUnit = TargetUnit:GetName() } )
|
self:F( { TargetUnit = TargetUnit:GetName() } )
|
||||||
|
|
||||||
if MarkingCount < self.MaximumMarkings then
|
if MarkingCount < self.MaximumMarkings then
|
||||||
|
|
||||||
if TargetUnit:IsAlive() then
|
if TargetUnit:IsAlive() then
|
||||||
|
|
||||||
local Recce = self.Recces[TargetUnit]
|
local Recce = self.Recces[TargetUnit]
|
||||||
|
|
||||||
if not Recce then
|
if not Recce then
|
||||||
|
|
||||||
self:E( "Lasing..." )
|
self:E( "Lasing..." )
|
||||||
self.RecceSet:Flush()
|
self.RecceSet:Flush()
|
||||||
|
|
||||||
for RecceGroupID, RecceGroup in pairs( self.RecceSet:GetSet() ) do
|
for RecceGroupID, RecceGroup in pairs( self.RecceSet:GetSet() ) do
|
||||||
for UnitID, UnitData in pairs( RecceGroup:GetUnits() or {} ) do
|
for UnitID, UnitData in pairs( RecceGroup:GetUnits() or {} ) do
|
||||||
|
|
||||||
local RecceUnit = UnitData -- Wrapper.Unit#UNIT
|
local RecceUnit = UnitData -- Wrapper.Unit#UNIT
|
||||||
local RecceUnitDesc = RecceUnit:GetDesc()
|
local RecceUnitDesc = RecceUnit:GetDesc()
|
||||||
--self:F( { RecceUnit = RecceUnit:GetName(), RecceDescription = RecceUnitDesc } )
|
--self:F( { RecceUnit = RecceUnit:GetName(), RecceDescription = RecceUnitDesc } )
|
||||||
|
|
||||||
if RecceUnit:IsLasing() == false then
|
if RecceUnit:IsLasing() == false then
|
||||||
--self:F( { IsDetected = RecceUnit:IsDetected( TargetUnit ), IsLOS = RecceUnit:IsLOS( TargetUnit ) } )
|
--self:F( { IsDetected = RecceUnit:IsDetected( TargetUnit ), IsLOS = RecceUnit:IsLOS( TargetUnit ) } )
|
||||||
|
|
||||||
if RecceUnit:IsDetected( TargetUnit ) and RecceUnit:IsLOS( TargetUnit ) then
|
if RecceUnit:IsDetected( TargetUnit ) and RecceUnit:IsLOS( TargetUnit ) then
|
||||||
|
|
||||||
local LaserCodeIndex = math.random( 1, #self.LaserCodes )
|
local LaserCodeIndex = math.random( 1, #self.LaserCodes )
|
||||||
local LaserCode = self.LaserCodes[LaserCodeIndex]
|
local LaserCode = self.LaserCodes[LaserCodeIndex]
|
||||||
--self:F( { LaserCode = LaserCode, LaserCodeUsed = self.LaserCodesUsed[LaserCode] } )
|
--self:F( { LaserCode = LaserCode, LaserCodeUsed = self.LaserCodesUsed[LaserCode] } )
|
||||||
|
|
||||||
if LaserCodeRequested and LaserCodeRequested ~= LaserCode then
|
if LaserCodeRequested and LaserCodeRequested ~= LaserCode then
|
||||||
LaserCode = LaserCodeRequested
|
LaserCode = LaserCodeRequested
|
||||||
LaserCodeRequested = nil
|
LaserCodeRequested = nil
|
||||||
end
|
|
||||||
|
|
||||||
if not self.LaserCodesUsed[LaserCode] then
|
|
||||||
|
|
||||||
self.LaserCodesUsed[LaserCode] = LaserCodeIndex
|
|
||||||
local Spot = RecceUnit:LaseUnit( TargetUnit, LaserCode, Duration )
|
|
||||||
local AttackSet = self.AttackSet
|
|
||||||
|
|
||||||
function Spot:OnAfterDestroyed( From, Event, To )
|
|
||||||
self:E( "Destroyed Message" )
|
|
||||||
self.Recce:ToSetGroup( "Target " .. TargetUnit:GetTypeName() .. " destroyed. " .. TargetSetUnit:Count() .. " targets left.", 5, AttackSet, self.DesignateName )
|
|
||||||
end
|
end
|
||||||
|
|
||||||
self.Recces[TargetUnit] = RecceUnit
|
if not self.LaserCodesUsed[LaserCode] then
|
||||||
RecceUnit:MessageToSetGroup( "Marking " .. TargetUnit:GetTypeName() .. " with laser " .. RecceUnit:GetSpot().LaserCode .. " for " .. Duration .. "s.", 5, self.AttackSet, self.DesignateName )
|
|
||||||
-- OK. We have assigned for the Recce a TargetUnit. We can exit the function.
|
self.LaserCodesUsed[LaserCode] = LaserCodeIndex
|
||||||
|
local Spot = RecceUnit:LaseUnit( TargetUnit, LaserCode, Duration )
|
||||||
|
local AttackSet = self.AttackSet
|
||||||
|
|
||||||
|
function Spot:OnAfterDestroyed( From, Event, To )
|
||||||
|
self:E( "Destroyed Message" )
|
||||||
|
self.Recce:ToSetGroup( "Target " .. TargetUnit:GetTypeName() .. " destroyed. " .. TargetSetUnit:Count() .. " targets left.", 5, AttackSet, self.DesignateName )
|
||||||
|
end
|
||||||
|
|
||||||
|
self.Recces[TargetUnit] = RecceUnit
|
||||||
|
RecceUnit:MessageToSetGroup( "Marking " .. TargetUnit:GetTypeName() .. " with laser " .. RecceUnit:GetSpot().LaserCode .. " for " .. Duration .. "s.", 5, self.AttackSet, self.DesignateName )
|
||||||
|
-- OK. We have assigned for the Recce a TargetUnit. We can exit the function.
|
||||||
|
MarkingCount = MarkingCount + 1
|
||||||
|
local TargetUnitType = TargetUnit:GetTypeName()
|
||||||
|
if not MarkedTypes[TargetUnitType] then
|
||||||
|
MarkedTypes[TargetUnitType] = true
|
||||||
|
ReportTypes:Add(TargetUnitType)
|
||||||
|
end
|
||||||
|
ReportLaserCodes:Add(RecceUnit.LaserCode)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
--RecceUnit:MessageToSetGroup( "Can't mark " .. TargetUnit:GetTypeName(), 5, self.AttackSet )
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- The Recce is lasing, but the Target is not detected or within LOS. So stop lasing and send a report.
|
||||||
|
|
||||||
|
if not RecceUnit:IsDetected( TargetUnit ) or not RecceUnit:IsLOS( TargetUnit ) then
|
||||||
|
|
||||||
|
local Recce = self.Recces[TargetUnit] -- Wrapper.Unit#UNIT
|
||||||
|
|
||||||
|
if Recce then
|
||||||
|
Recce:LaseOff()
|
||||||
|
Recce:MessageToSetGroup( "Target " .. TargetUnit:GetTypeName() "out of LOS. Cancelling lase!", 5, self.AttackSet, self.DesignateName )
|
||||||
|
end
|
||||||
|
else
|
||||||
MarkingCount = MarkingCount + 1
|
MarkingCount = MarkingCount + 1
|
||||||
local TargetUnitType = TargetUnit:GetTypeName()
|
local TargetUnitType = TargetUnit:GetTypeName()
|
||||||
if not MarkedTypes[TargetUnitType] then
|
if not MarkedTypes[TargetUnitType] then
|
||||||
@ -1098,59 +1125,39 @@ do -- DESIGNATE
|
|||||||
ReportTypes:Add(TargetUnitType)
|
ReportTypes:Add(TargetUnitType)
|
||||||
end
|
end
|
||||||
ReportLaserCodes:Add(RecceUnit.LaserCode)
|
ReportLaserCodes:Add(RecceUnit.LaserCode)
|
||||||
return
|
|
||||||
end
|
end
|
||||||
else
|
|
||||||
--RecceUnit:MessageToSetGroup( "Can't mark " .. TargetUnit:GetTypeName(), 5, self.AttackSet )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
-- The Recce is lasing, but the Target is not detected or within LOS. So stop lasing and send a report.
|
|
||||||
|
|
||||||
if not RecceUnit:IsDetected( TargetUnit ) or not RecceUnit:IsLOS( TargetUnit ) then
|
|
||||||
|
|
||||||
local Recce = self.Recces[TargetUnit] -- Wrapper.Unit#UNIT
|
|
||||||
|
|
||||||
if Recce then
|
|
||||||
Recce:LaseOff()
|
|
||||||
Recce:MessageToSetGroup( "Target " .. TargetUnit:GetTypeName() "out of LOS. Cancelling lase!", 5, self.AttackSet, self.DesignateName )
|
|
||||||
end
|
|
||||||
else
|
|
||||||
MarkingCount = MarkingCount + 1
|
|
||||||
local TargetUnitType = TargetUnit:GetTypeName()
|
|
||||||
if not MarkedTypes[TargetUnitType] then
|
|
||||||
MarkedTypes[TargetUnitType] = true
|
|
||||||
ReportTypes:Add(TargetUnitType)
|
|
||||||
end
|
|
||||||
ReportLaserCodes:Add(RecceUnit.LaserCode)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
else
|
||||||
|
MarkingCount = MarkingCount + 1
|
||||||
|
local TargetUnitType = TargetUnit:GetTypeName()
|
||||||
|
if not MarkedTypes[TargetUnitType] then
|
||||||
|
MarkedTypes[TargetUnitType] = true
|
||||||
|
ReportTypes:Add(TargetUnitType)
|
||||||
|
end
|
||||||
|
ReportLaserCodes:Add(Recce.LaserCode)
|
||||||
|
--Recce:MessageToSetGroup( self.DesignateName .. ": Marking " .. TargetUnit:GetTypeName() .. " with laser " .. Recce.LaserCode .. ".", 5, self.AttackSet )
|
||||||
end
|
end
|
||||||
else
|
|
||||||
MarkingCount = MarkingCount + 1
|
|
||||||
local TargetUnitType = TargetUnit:GetTypeName()
|
|
||||||
if not MarkedTypes[TargetUnitType] then
|
|
||||||
MarkedTypes[TargetUnitType] = true
|
|
||||||
ReportTypes:Add(TargetUnitType)
|
|
||||||
end
|
|
||||||
ReportLaserCodes:Add(Recce.LaserCode)
|
|
||||||
--Recce:MessageToSetGroup( self.DesignateName .. ": Marking " .. TargetUnit:GetTypeName() .. " with laser " .. Recce.LaserCode .. ".", 5, self.AttackSet )
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
)
|
||||||
|
|
||||||
|
local MarkedTypesText = ReportTypes:Text(', ')
|
||||||
|
local MarkedLaserCodesText = ReportLaserCodes:Text(', ')
|
||||||
|
for MarkedType, MarketCount in pairs( MarkedTypes ) do
|
||||||
|
self.CC:GetPositionable():MessageToSetGroup( "Marking " .. MarkingCount .. " x " .. MarkedTypesText .. " with lasers " .. MarkedLaserCodesText .. ".", 5, self.AttackSet, self.DesignateName )
|
||||||
end
|
end
|
||||||
)
|
|
||||||
|
|
||||||
local MarkedTypesText = ReportTypes:Text(', ')
|
self:__Lasing( -30, Index, Duration, LaserCodeRequested )
|
||||||
local MarkedLaserCodesText = ReportLaserCodes:Text(', ')
|
|
||||||
for MarkedType, MarketCount in pairs( MarkedTypes ) do
|
self:SetDesignateMenu()
|
||||||
self.CC:GetPositionable():MessageToSetGroup( "Marking " .. MarkingCount .. " x " .. MarkedTypesText .. " with lasers " .. MarkedLaserCodesText .. ".", 5, self.AttackSet, self.DesignateName )
|
|
||||||
|
else
|
||||||
|
self:__LaseOff( 1 )
|
||||||
end
|
end
|
||||||
|
|
||||||
self:__Lasing( -30, Index, Duration )
|
|
||||||
|
|
||||||
self:SetDesignateMenu()
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user