mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
369606f0f1 | ||
|
|
8d4ce5e486 | ||
|
|
dd242bc1fe | ||
|
|
34d73af8bf | ||
|
|
604255bfba | ||
|
|
cfc0367c55 | ||
|
|
f4a89d62e3 | ||
|
|
a36e39205b | ||
|
|
3789674666 | ||
|
|
a22774b278 | ||
|
|
81bb8dd65f | ||
|
|
9d3796b605 | ||
|
|
3e3dfc83aa | ||
|
|
e062db9411 | ||
|
|
023eae825d | ||
|
|
1a4baeafb6 | ||
|
|
b754972490 | ||
|
|
0c36e4e40d | ||
|
|
1f97495fdd | ||
|
|
c164c0f9e3 | ||
|
|
f0b5ec1025 | ||
|
|
b72ea2d02c | ||
|
|
238fcf1176 | ||
|
|
c354fecc6d | ||
|
|
4434d1da21 | ||
|
|
17ffc7cef9 | ||
|
|
006fd25e56 | ||
|
|
f2eafe0302 | ||
|
|
52069cc1d0 | ||
|
|
d9374f0389 | ||
|
|
19520f9688 | ||
|
|
1eda5af7df | ||
|
|
2ea8487e04 | ||
|
|
b0885ada00 | ||
|
|
1c6c0c4d81 | ||
|
|
3011b0ac8e | ||
|
|
e4334cccb3 | ||
|
|
645ca570a8 | ||
|
|
fd30da2f95 | ||
|
|
b378ad2885 | ||
|
|
9c45031a33 | ||
|
|
e4606b4d05 | ||
|
|
07e690caf0 | ||
|
|
223de9d1aa | ||
|
|
7d7c521bce | ||
|
|
baaee9f92e | ||
|
|
3a9be7a890 |
@@ -438,13 +438,14 @@ function AI_A2A:onafterStatus()
|
||||
RTB = false
|
||||
end
|
||||
end
|
||||
|
||||
if self:Is( "Fuel" ) or self:Is( "Damaged" ) or self:Is( "LostControl" ) then
|
||||
if DistanceFromHomeBase < 5000 then
|
||||
self:E( self.Controllable:GetName() .. " is too far from home base, RTB!" )
|
||||
self:Home( "Destroy" )
|
||||
end
|
||||
end
|
||||
|
||||
-- I think this code is not requirement anymore after release 2.5.
|
||||
-- if self:Is( "Fuel" ) or self:Is( "Damaged" ) or self:Is( "LostControl" ) then
|
||||
-- if DistanceFromHomeBase < 5000 then
|
||||
-- self:E( self.Controllable:GetName() .. " is near the home base, RTB!" )
|
||||
-- self:Home( "Destroy" )
|
||||
-- end
|
||||
-- end
|
||||
|
||||
|
||||
if not self:Is( "Fuel" ) and not self:Is( "Home" ) then
|
||||
@@ -481,9 +482,12 @@ function AI_A2A:onafterStatus()
|
||||
end
|
||||
|
||||
-- Check if planes went RTB and are out of control.
|
||||
-- We only check if planes are out of control, when they are in duty.
|
||||
if self.Controllable:HasTask() == false then
|
||||
if not self:Is( "Started" ) and
|
||||
not self:Is( "Stopped" ) and
|
||||
not self:Is( "Fuel" ) and
|
||||
not self:Is( "Damaged" ) and
|
||||
not self:Is( "Home" ) then
|
||||
if self.IdleCount >= 2 then
|
||||
if Damage ~= InitialLife then
|
||||
@@ -503,8 +507,11 @@ function AI_A2A:onafterStatus()
|
||||
if RTB == true then
|
||||
self:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
if not self:Is("Home") then
|
||||
self:__Status( 10 )
|
||||
end
|
||||
|
||||
self:__Status( 10 )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -635,7 +642,7 @@ end
|
||||
--- @param Wrapper.Group#GROUP AIGroup
|
||||
function AI_A2A.Resume( AIGroup, Fsm )
|
||||
|
||||
AIGroup:F( { "AI_A2A.Resume:", AIGroup:GetName() } )
|
||||
AIGroup:I( { "AI_A2A.Resume:", AIGroup:GetName() } )
|
||||
if AIGroup:IsAlive() then
|
||||
Fsm:__RTB( 0.5 )
|
||||
end
|
||||
|
||||
@@ -476,13 +476,12 @@ function AI_A2A_CAP:OnEventDead( EventData )
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AICap
|
||||
function AI_A2A_CAP.Resume( AICap )
|
||||
function AI_A2A_CAP.Resume( AICap, Fsm )
|
||||
|
||||
AICap:F( { "AI_A2A_CAP.Resume:", AICap:GetName() } )
|
||||
AICap:I( { "AI_A2A_CAP.Resume:", AICap:GetName() } )
|
||||
if AICap:IsAlive() then
|
||||
local _AI_A2A = AICap:GetState( AICap, "AI_A2A" ) -- #AI_A2A
|
||||
_AI_A2A:__Reset( 1 )
|
||||
_AI_A2A:__Route( 5 )
|
||||
Fsm:__Reset( 1 )
|
||||
Fsm:__Route( 5 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1013,12 +1013,48 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
self:SetTacticalDisplay( false )
|
||||
|
||||
self.DefenderCAPIndex = 0
|
||||
|
||||
self:__Start( 5 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A_DISPATCHER self
|
||||
function AI_A2A_DISPATCHER:onafterStart( From, Event, To )
|
||||
|
||||
self:GetParent( self, AI_A2A_DISPATCHER ).onafterStart( self, From, Event, To )
|
||||
|
||||
-- Spawn the resources.
|
||||
for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
|
||||
DefenderSquadron.Resource = {}
|
||||
if DefenderSquadron.ResourceCount then
|
||||
for Resource = 1, DefenderSquadron.ResourceCount do
|
||||
self:ParkDefender( DefenderSquadron )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A_DISPATCHER self
|
||||
function AI_A2A_DISPATCHER:ParkDefender( DefenderSquadron )
|
||||
local TemplateID = math.random( 1, #DefenderSquadron.Spawn )
|
||||
local Spawn = DefenderSquadron.Spawn[ TemplateID ] -- Core.Spawn#SPAWN
|
||||
Spawn:InitGrouping( 1 )
|
||||
local SpawnGroup
|
||||
if self:IsSquadronVisible( DefenderSquadron.Name ) then
|
||||
SpawnGroup = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, SPAWN.Takeoff.Cold )
|
||||
local GroupName = SpawnGroup:GetName()
|
||||
DefenderSquadron.Resources = DefenderSquadron.Resources or {}
|
||||
DefenderSquadron.Resources[TemplateID] = DefenderSquadron.Resources[TemplateID] or {}
|
||||
DefenderSquadron.Resources[TemplateID][GroupName] = {}
|
||||
DefenderSquadron.Resources[TemplateID][GroupName] = SpawnGroup
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
--- @param #AI_A2A_DISPATCHER self
|
||||
-- @param Core.Event#EVENTDATA EventData
|
||||
function AI_A2A_DISPATCHER:OnEventBaseCaptured( EventData )
|
||||
@@ -1030,7 +1066,7 @@ do -- AI_A2A_DISPATCHER
|
||||
-- Now search for all squadrons located at the airbase, and sanatize them.
|
||||
for SquadronName, Squadron in pairs( self.DefenderSquadrons ) do
|
||||
if Squadron.AirbaseName == AirbaseName then
|
||||
Squadron.Resources = -999 -- The base has been captured, and the resources are eliminated. No more spawning.
|
||||
Squadron.ResourceCount = -999 -- The base has been captured, and the resources are eliminated. No more spawning.
|
||||
Squadron.Captured = true
|
||||
self:I( "Squadron " .. SquadronName .. " captured." )
|
||||
end
|
||||
@@ -1059,6 +1095,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||
end
|
||||
DefenderUnit:Destroy()
|
||||
self:ParkDefender( Squadron, Defender )
|
||||
return
|
||||
end
|
||||
if DefenderUnit:GetLife() ~= DefenderUnit:GetLife0() then
|
||||
@@ -1085,6 +1122,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||
end
|
||||
DefenderUnit:Destroy()
|
||||
self:ParkDefender( Squadron, Defender )
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1474,7 +1512,7 @@ do -- AI_A2A_DISPATCHER
|
||||
-- Just remember that your template (groups late activated) need to start with the prefix you have specified in your code.
|
||||
-- If you have only one prefix name for a squadron, you don't need to use the `{ }`, otherwise you need to use the brackets.
|
||||
--
|
||||
-- @param #number Resources (optional) A number that specifies how many resources are in stock of the squadron. If not specified, the squadron will have infinite resources available.
|
||||
-- @param #number ResourceCount (optional) A number that specifies how many resources are in stock of the squadron. If not specified, the squadron will have infinite resources available.
|
||||
--
|
||||
-- @usage
|
||||
-- -- Now Setup the A2A dispatcher, and initialize it using the Detection object.
|
||||
@@ -1497,13 +1535,13 @@ do -- AI_A2A_DISPATCHER
|
||||
--
|
||||
-- @usage
|
||||
-- -- This is an example like the previous, but now with infinite resources.
|
||||
-- -- The Resources parameter is not given in the SetSquadron method.
|
||||
-- -- The ResourceCount parameter is not given in the SetSquadron method.
|
||||
-- A2ADispatcher:SetSquadron( "104th", "Batumi", "Mig-29" )
|
||||
-- A2ADispatcher:SetSquadron( "23th", "Batumi", "Su-27" )
|
||||
--
|
||||
--
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
function AI_A2A_DISPATCHER:SetSquadron( SquadronName, AirbaseName, TemplatePrefixes, Resources )
|
||||
function AI_A2A_DISPATCHER:SetSquadron( SquadronName, AirbaseName, TemplatePrefixes, ResourceCount )
|
||||
|
||||
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
@@ -1528,11 +1566,11 @@ do -- AI_A2A_DISPATCHER
|
||||
DefenderSquadron.Spawn[#DefenderSquadron.Spawn+1] = self.DefenderSpawns[SpawnTemplate]
|
||||
end
|
||||
end
|
||||
DefenderSquadron.Resources = Resources
|
||||
DefenderSquadron.ResourceCount = ResourceCount
|
||||
DefenderSquadron.TemplatePrefixes = TemplatePrefixes
|
||||
DefenderSquadron.Captured = false -- Not captured. This flag will be set to true, when the airbase where the squadron is located, is captured.
|
||||
|
||||
self:F( { Squadron = {SquadronName, AirbaseName, TemplatePrefixes, Resources } } )
|
||||
self:F( { Squadron = {SquadronName, AirbaseName, TemplatePrefixes, ResourceCount } } )
|
||||
|
||||
return self
|
||||
end
|
||||
@@ -1551,6 +1589,54 @@ do -- AI_A2A_DISPATCHER
|
||||
end
|
||||
|
||||
|
||||
--- Set the Squadron visible before startup of the dispatcher.
|
||||
-- All planes will be spawned as uncontrolled on the parking spot.
|
||||
-- They will lock the parking spot.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
-- @usage
|
||||
--
|
||||
-- -- Set the Squadron visible before startup of dispatcher.
|
||||
-- A2ADispatcher:SetSquadronVisible( "Mineralnye" )
|
||||
--
|
||||
function AI_A2A_DISPATCHER:SetSquadronVisible( SquadronName )
|
||||
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
DefenderSquadron.Uncontrolled = true
|
||||
|
||||
for SpawnTemplate, DefenderSpawn in pairs( self.DefenderSpawns ) do
|
||||
DefenderSpawn:InitUnControlled()
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
--- Check if the Squadron is visible before startup of the dispatcher.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
-- @return #bool true if visible.
|
||||
-- @usage
|
||||
--
|
||||
-- -- Set the Squadron visible before startup of dispatcher.
|
||||
-- local IsVisible = A2ADispatcher:IsSquadronVisible( "Mineralnye" )
|
||||
--
|
||||
function AI_A2A_DISPATCHER:IsSquadronVisible( SquadronName )
|
||||
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
if DefenderSquadron then
|
||||
return DefenderSquadron.Uncontrolled == true
|
||||
end
|
||||
|
||||
return nil
|
||||
|
||||
end
|
||||
|
||||
--- Set a CAP for a Squadron.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @param #string SquadronName The squadron name.
|
||||
@@ -1699,7 +1785,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
if DefenderSquadron.Captured == false then -- We can only spawn new CAP if the base has not been captured.
|
||||
|
||||
if ( not DefenderSquadron.Resources ) or ( DefenderSquadron.Resources and DefenderSquadron.Resources > 0 ) then -- And, if there are sufficient resources.
|
||||
if ( not DefenderSquadron.ResourceCount ) or ( DefenderSquadron.ResourceCount and DefenderSquadron.ResourceCount > 0 ) then -- And, if there are sufficient resources.
|
||||
|
||||
local Cap = DefenderSquadron.Cap
|
||||
if Cap then
|
||||
@@ -1732,7 +1818,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
if DefenderSquadron.Captured == false then -- We can only spawn new CAP if the base has not been captured.
|
||||
|
||||
if ( not DefenderSquadron.Resources ) or ( DefenderSquadron.Resources and DefenderSquadron.Resources > 0 ) then -- And, if there are sufficient resources.
|
||||
if ( not DefenderSquadron.ResourceCount ) or ( DefenderSquadron.ResourceCount and DefenderSquadron.ResourceCount > 0 ) then -- And, if there are sufficient resources.
|
||||
local Gci = DefenderSquadron.Gci
|
||||
if Gci then
|
||||
return DefenderSquadron
|
||||
@@ -2490,21 +2576,21 @@ do -- AI_A2A_DISPATCHER
|
||||
self.Defenders = self.Defenders or {}
|
||||
local DefenderName = Defender:GetName()
|
||||
self.Defenders[ DefenderName ] = Squadron
|
||||
if Squadron.Resources then
|
||||
Squadron.Resources = Squadron.Resources - Size
|
||||
if Squadron.ResourceCount then
|
||||
Squadron.ResourceCount = Squadron.ResourceCount - Size
|
||||
end
|
||||
self:F( { DefenderName = DefenderName, SquadronResources = Squadron.Resources } )
|
||||
self:F( { DefenderName = DefenderName, SquadronResourceCount = Squadron.ResourceCount } )
|
||||
end
|
||||
|
||||
--- @param #AI_A2A_DISPATCHER self
|
||||
function AI_A2A_DISPATCHER:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||
self.Defenders = self.Defenders or {}
|
||||
local DefenderName = Defender:GetName()
|
||||
if Squadron.Resources then
|
||||
Squadron.Resources = Squadron.Resources + Defender:GetSize()
|
||||
if Squadron.ResourceCount then
|
||||
Squadron.ResourceCount = Squadron.ResourceCount + Defender:GetSize()
|
||||
end
|
||||
self.Defenders[ DefenderName ] = nil
|
||||
self:F( { DefenderName = DefenderName, SquadronResources = Squadron.Resources } )
|
||||
self:F( { DefenderName = DefenderName, SquadronResourceCount = Squadron.ResourceCount } )
|
||||
end
|
||||
|
||||
function AI_A2A_DISPATCHER:GetSquadronFromDefender( Defender )
|
||||
@@ -2646,7 +2732,80 @@ do -- AI_A2A_DISPATCHER
|
||||
return Friendlies
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
function AI_A2A_DISPATCHER:ResourceActivate( DefenderSquadron, DefendersNeeded )
|
||||
|
||||
local SquadronName = DefenderSquadron.Name
|
||||
DefendersNeeded = DefendersNeeded or 4
|
||||
local DefenderGrouping = DefenderSquadron.Grouping or self.DefenderDefault.Grouping
|
||||
DefenderGrouping = ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded
|
||||
|
||||
if self:IsSquadronVisible( SquadronName ) then
|
||||
|
||||
-- Here we CAP the new planes.
|
||||
-- The Resources table is filled in advance.
|
||||
local TemplateID = math.random( 1, #DefenderSquadron.Spawn ) -- Choose the template.
|
||||
|
||||
-- We determine the grouping based on the parameters set.
|
||||
self:F( { DefenderGrouping = DefenderGrouping } )
|
||||
|
||||
-- New we will form the group to spawn in.
|
||||
-- We search for the first free resource matching the template.
|
||||
local DefenderUnitIndex = 1
|
||||
local DefenderCAPTemplate = nil
|
||||
local DefenderName = nil
|
||||
for GroupName, DefenderGroup in pairs( DefenderSquadron.Resources[TemplateID] or {} ) do
|
||||
self:F( { GroupName = GroupName } )
|
||||
local DefenderTemplate = _DATABASE:GetGroupTemplate( GroupName )
|
||||
if DefenderUnitIndex == 1 then
|
||||
DefenderCAPTemplate = UTILS.DeepCopy( DefenderTemplate )
|
||||
self.DefenderCAPIndex = self.DefenderCAPIndex + 1
|
||||
DefenderCAPTemplate.name = SquadronName .. "#" .. self.DefenderCAPIndex .. "#" .. GroupName
|
||||
DefenderName = DefenderCAPTemplate.name
|
||||
else
|
||||
-- Add the unit in the template to the DefenderCAPTemplate.
|
||||
local DefenderUnitTemplate = DefenderTemplate.units[1]
|
||||
DefenderCAPTemplate.units[DefenderUnitIndex] = DefenderUnitTemplate
|
||||
end
|
||||
DefenderUnitIndex = DefenderUnitIndex + 1
|
||||
DefenderSquadron.Resources[TemplateID][GroupName] = nil
|
||||
if DefenderUnitIndex > DefenderGrouping then
|
||||
break
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
if DefenderCAPTemplate then
|
||||
local TakeoffMethod = self:GetSquadronTakeoff( SquadronName )
|
||||
local SpawnGroup = GROUP:Register( DefenderName )
|
||||
DefenderCAPTemplate.lateActivation = nil
|
||||
DefenderCAPTemplate.uncontrolled = nil
|
||||
local Takeoff = self:GetSquadronTakeoff( SquadronName )
|
||||
DefenderCAPTemplate.route.points[1].type = GROUPTEMPLATE.Takeoff[Takeoff][1] -- type
|
||||
DefenderCAPTemplate.route.points[1].action = GROUPTEMPLATE.Takeoff[Takeoff][2] -- action
|
||||
local Defender = _DATABASE:Spawn( DefenderCAPTemplate )
|
||||
|
||||
self:AddDefenderToSquadron( DefenderSquadron, Defender, DefenderGrouping )
|
||||
return Defender, DefenderGrouping
|
||||
end
|
||||
else
|
||||
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] -- Core.Spawn#SPAWN
|
||||
if DefenderGrouping then
|
||||
Spawn:InitGrouping( DefenderGrouping )
|
||||
else
|
||||
Spawn:InitGrouping()
|
||||
end
|
||||
|
||||
local TakeoffMethod = self:GetSquadronTakeoff( SquadronName )
|
||||
local Defender = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod, DefenderSquadron.TakeoffAltitude or self.DefenderDefault.TakeoffAltitude ) -- Wrapper.Group#GROUP
|
||||
self:AddDefenderToSquadron( DefenderSquadron, Defender, DefenderGrouping )
|
||||
return Defender, DefenderGrouping
|
||||
end
|
||||
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
---
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
@@ -2663,15 +2822,9 @@ do -- AI_A2A_DISPATCHER
|
||||
local Cap = DefenderSquadron.Cap
|
||||
|
||||
if Cap then
|
||||
|
||||
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] -- Core.Spawn#SPAWN
|
||||
local DefenderGrouping = DefenderSquadron.Grouping or self.DefenderDefault.Grouping
|
||||
Spawn:InitGrouping( DefenderGrouping )
|
||||
|
||||
local TakeoffMethod = self:GetSquadronTakeoff( SquadronName )
|
||||
local DefenderCAP = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase, TakeoffMethod, DefenderSquadron.TakeoffAltitude or self.DefenderDefault.TakeoffAltitude )
|
||||
self:AddDefenderToSquadron( DefenderSquadron, DefenderCAP, DefenderGrouping )
|
||||
|
||||
local DefenderCAP, DefenderGrouping = self:ResourceActivate( DefenderSquadron )
|
||||
|
||||
if DefenderCAP then
|
||||
|
||||
local Fsm = AI_A2A_CAP:New( DefenderCAP, Cap.Zone, Cap.FloorAltitude, Cap.CeilingAltitude, Cap.PatrolMinSpeed, Cap.PatrolMaxSpeed, Cap.EngageMinSpeed, Cap.EngageMaxSpeed, Cap.AltType )
|
||||
@@ -2686,7 +2839,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self:SetDefenderTask( SquadronName, DefenderCAP, "CAP", Fsm )
|
||||
|
||||
function Fsm:onafterTakeoff( Defender, From, Event, To )
|
||||
self:F({"GCI Birth", Defender:GetName()})
|
||||
self:F({"CAP Birth", Defender:GetName()})
|
||||
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
|
||||
|
||||
local Dispatcher = Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||
@@ -2720,9 +2873,9 @@ do -- AI_A2A_DISPATCHER
|
||||
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
|
||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||
Defender:Destroy()
|
||||
self:ParkDefender( Squadron, Defender )
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -2828,31 +2981,19 @@ do -- AI_A2A_DISPATCHER
|
||||
self:F( { Grouping = DefenderGrouping, SquadronGrouping = DefenderSquadron.Grouping, DefaultGrouping = self.DefenderDefault.Grouping } )
|
||||
self:F( { DefendersCount = DefenderCount, DefendersNeeded = DefendersNeeded } )
|
||||
|
||||
-- DefenderSquadron.Resources can have the value nil, which expresses unlimited resources.
|
||||
-- DefendersNeeded cannot exceed DefenderSquadron.Resources!
|
||||
if DefenderSquadron.Resources and DefendersNeeded > DefenderSquadron.Resources then
|
||||
DefendersNeeded = DefenderSquadron.Resources
|
||||
-- DefenderSquadron.ResourceCount can have the value nil, which expresses unlimited resources.
|
||||
-- DefendersNeeded cannot exceed DefenderSquadron.ResourceCount!
|
||||
if DefenderSquadron.ResourceCount and DefendersNeeded > DefenderSquadron.ResourceCount then
|
||||
DefendersNeeded = DefenderSquadron.ResourceCount
|
||||
BreakLoop = true
|
||||
end
|
||||
|
||||
while ( DefendersNeeded > 0 ) do
|
||||
|
||||
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ] -- Core.Spawn#SPAWN
|
||||
local DefenderGrouping = ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded
|
||||
if DefenderGrouping then
|
||||
Spawn:InitGrouping( DefenderGrouping )
|
||||
else
|
||||
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() } )
|
||||
local DefenderGCI, DefenderGrouping = self:ResourceActivate( DefenderSquadron, DefendersNeeded )
|
||||
|
||||
DefendersNeeded = DefendersNeeded - DefenderGrouping
|
||||
|
||||
self:AddDefenderToSquadron( DefenderSquadron, DefenderGCI, DefenderGrouping )
|
||||
|
||||
if DefenderGCI then
|
||||
|
||||
DefenderCount = DefenderCount - DefenderGrouping / DefenderOverhead
|
||||
@@ -2919,6 +3060,7 @@ do -- AI_A2A_DISPATCHER
|
||||
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
|
||||
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
|
||||
Defender:Destroy()
|
||||
self:ParkDefender( Squadron, Defender )
|
||||
end
|
||||
end
|
||||
end -- if DefenderGCI then
|
||||
@@ -3500,7 +3642,7 @@ do
|
||||
-- For airplanes, 6000 (6km) is recommended, and is also the default value of this parameter.
|
||||
-- @param #number EngageRadius The radius in meters wherein detected airplanes will be engaged by airborne defenders without a task.
|
||||
-- @param #number GciRadius The radius in meters wherein detected airplanes will GCI.
|
||||
-- @param #number Resources The amount of resources that will be allocated to each squadron.
|
||||
-- @param #number ResourceCount The amount of resources that will be allocated to each squadron.
|
||||
-- @return #AI_A2A_GCICAP
|
||||
-- @usage
|
||||
--
|
||||
@@ -3575,7 +3717,7 @@ do
|
||||
--
|
||||
-- A2ADispatcher = AI_A2A_GCICAP:New( { "DF CCCP" }, { "SQ CCCP" }, nil, nil, nil, nil, nil, 30 )
|
||||
--
|
||||
function AI_A2A_GCICAP:New( EWRPrefixes, TemplatePrefixes, CapPrefixes, CapLimit, GroupingRadius, EngageRadius, GciRadius, Resources )
|
||||
function AI_A2A_GCICAP:New( EWRPrefixes, TemplatePrefixes, CapPrefixes, CapLimit, GroupingRadius, EngageRadius, GciRadius, ResourceCount )
|
||||
|
||||
local EWRSetGroup = SET_GROUP:New()
|
||||
EWRSetGroup:FilterPrefixes( EWRPrefixes )
|
||||
@@ -3629,7 +3771,7 @@ do
|
||||
end
|
||||
end
|
||||
if Templates then
|
||||
self:SetSquadron( AirbaseName, AirbaseName, Templates, Resources )
|
||||
self:SetSquadron( AirbaseName, AirbaseName, Templates, ResourceCount )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3706,7 +3848,7 @@ do
|
||||
-- For airplanes, 6000 (6km) is recommended, and is also the default value of this parameter.
|
||||
-- @param #number EngageRadius The radius in meters wherein detected airplanes will be engaged by airborne defenders without a task.
|
||||
-- @param #number GciRadius The radius in meters wherein detected airplanes will GCI.
|
||||
-- @param #number Resources The amount of resources that will be allocated to each squadron.
|
||||
-- @param #number ResourceCount The amount of resources that will be allocated to each squadron.
|
||||
-- @return #AI_A2A_GCICAP
|
||||
-- @usage
|
||||
--
|
||||
@@ -3790,9 +3932,9 @@ do
|
||||
--
|
||||
-- A2ADispatcher = AI_A2A_GCICAP:NewWithBorder( { "DF CCCP" }, { "SQ CCCP" }, "Border", nil, nil, nil, nil, nil, 30 )
|
||||
--
|
||||
function AI_A2A_GCICAP:NewWithBorder( EWRPrefixes, TemplatePrefixes, BorderPrefix, CapPrefixes, CapLimit, GroupingRadius, EngageRadius, GciRadius, Resources )
|
||||
function AI_A2A_GCICAP:NewWithBorder( EWRPrefixes, TemplatePrefixes, BorderPrefix, CapPrefixes, CapLimit, GroupingRadius, EngageRadius, GciRadius, ResourceCount )
|
||||
|
||||
local self = AI_A2A_GCICAP:New( EWRPrefixes, TemplatePrefixes, CapPrefixes, CapLimit, GroupingRadius, EngageRadius, GciRadius, Resources )
|
||||
local self = AI_A2A_GCICAP:New( EWRPrefixes, TemplatePrefixes, CapPrefixes, CapLimit, GroupingRadius, EngageRadius, GciRadius, ResourceCount )
|
||||
|
||||
if BorderPrefix then
|
||||
self:SetBorderZone( ZONE_POLYGON:New( BorderPrefix, GROUP:FindByName( BorderPrefix ) ) )
|
||||
|
||||
@@ -351,13 +351,12 @@ function AI_A2A_PATROL:onafterRoute( AIPatrol, From, Event, To )
|
||||
end
|
||||
|
||||
--- @param Wrapper.Group#GROUP AIPatrol
|
||||
function AI_A2A_PATROL.Resume( AIPatrol )
|
||||
function AI_A2A_PATROL.Resume( AIPatrol, Fsm )
|
||||
|
||||
AIPatrol:F( { "AI_A2A_PATROL.Resume:", AIPatrol:GetName() } )
|
||||
AIPatrol:I( { "AI_A2A_PATROL.Resume:", AIPatrol:GetName() } )
|
||||
if AIPatrol:IsAlive() then
|
||||
local _AI_A2A = AIPatrol:GetState( AIPatrol, "AI_A2A" ) -- AI.AI_A2A#AI_A2A
|
||||
_AI_A2A:__Reset( 1 )
|
||||
_AI_A2A:__Route( 5 )
|
||||
Fsm:__Reset( 1 )
|
||||
Fsm:__Route( 5 )
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -899,7 +899,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
|
||||
|
||||
for CarrierGroupName, Carrier in pairs( self.SetCarrier:GetSet() ) do
|
||||
local Carrier = Carrier -- Wrapper.Group#GROUP
|
||||
if Carrier:IsAlive() == true then
|
||||
if Carrier:IsAlive() ~= nil then
|
||||
local AI_Cargo = self.AI_Cargo[Carrier]
|
||||
if not AI_Cargo then
|
||||
|
||||
|
||||
@@ -1702,7 +1702,7 @@ function SPAWN:SpawnAtAirbase( SpawnAirbase, Takeoff, TakeoffAltitude, TerminalT
|
||||
-- When spawned in the air, we need to generate a Takeoff Event.
|
||||
if Takeoff == GROUP.Takeoff.Air then
|
||||
for UnitID, UnitSpawned in pairs( GroupSpawned:GetUnits() ) do
|
||||
SCHEDULER:New( nil, BASE.CreateEventTakeoff, { GroupSpawned, timer.getTime(), UnitSpawned:GetDCSObject() } , 1 )
|
||||
SCHEDULER:New( nil, BASE.CreateEventTakeoff, { GroupSpawned, timer.getTime(), UnitSpawned:GetDCSObject() } , 5 )
|
||||
end
|
||||
end
|
||||
|
||||
@@ -2005,10 +2005,10 @@ end
|
||||
function SPAWN:InitUnControlled( UnControlled )
|
||||
self:F2( { self.SpawnTemplatePrefix, UnControlled } )
|
||||
|
||||
self.SpawnUnControlled = UnControlled
|
||||
self.SpawnUnControlled = UnControlled or true
|
||||
|
||||
for SpawnGroupID = 1, self.SpawnMaxGroups do
|
||||
self.SpawnGroups[SpawnGroupID].UnControlled = UnControlled
|
||||
self.SpawnGroups[SpawnGroupID].UnControlled = self.SpawnUnControlled
|
||||
end
|
||||
|
||||
return self
|
||||
|
||||
@@ -474,7 +474,7 @@ do -- DESIGNATE
|
||||
self.Designating = {}
|
||||
self:SetDesignateName()
|
||||
|
||||
self.LaseDuration = 60
|
||||
self:SetLaseDuration() -- Default is 120 seconds.
|
||||
|
||||
self:SetFlashStatusMenu( false )
|
||||
self:SetFlashDetectionMessages( true )
|
||||
@@ -677,6 +677,14 @@ do -- DESIGNATE
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the lase duration for designations.
|
||||
-- @param #DESIGNATE self
|
||||
-- @param #number LaseDuration The time in seconds a lase will continue to hold on target. The default is 120 seconds.
|
||||
-- @return #DESIGNATE
|
||||
function DESIGNATE:SetLaseDuration( LaseDuration )
|
||||
self.LaseDuration = LaseDuration or 120
|
||||
return self
|
||||
end
|
||||
|
||||
--- Generate an array of possible laser codes.
|
||||
-- Each new lase will select a code from this table.
|
||||
@@ -1000,9 +1008,9 @@ do -- DESIGNATE
|
||||
if string.find( Designating, "L", 1, true ) == nil then
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Search other target", DetectedMenu, self.MenuForget, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
for LaserCode, MenuText in pairs( self.MenuLaserCodes ) do
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, string.format( MenuText, LaserCode ), DetectedMenu, self.MenuLaseCode, self, DesignateIndex, 60, LaserCode ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, string.format( MenuText, LaserCode ), DetectedMenu, self.MenuLaseCode, self, DesignateIndex, self.LaseDuration, LaserCode ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Lase with random laser code(s)", DetectedMenu, self.MenuLaseOn, self, DesignateIndex, 60 ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Lase with random laser code(s)", DetectedMenu, self.MenuLaseOn, self, DesignateIndex, self.LaseDuration ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
else
|
||||
MENU_GROUP_COMMAND_DELAYED:New( AttackGroup, "Stop lasing", DetectedMenu, self.MenuLaseOff, self, DesignateIndex ):SetTime( MenuTime ):SetTag( self.DesignateName )
|
||||
end
|
||||
@@ -1160,10 +1168,10 @@ do -- DESIGNATE
|
||||
|
||||
if string.find( self.Designating[Index], "L", 1, true ) == nil then
|
||||
self.Designating[Index] = self.Designating[Index] .. "L"
|
||||
self.LaseStart = timer.getTime()
|
||||
self.LaseDuration = Duration
|
||||
self:Lasing( Index, Duration, LaserCode )
|
||||
end
|
||||
self.LaseStart = timer.getTime()
|
||||
self.LaseDuration = Duration
|
||||
self:Lasing( Index, Duration, LaserCode )
|
||||
end
|
||||
|
||||
|
||||
@@ -1322,7 +1330,7 @@ do -- DESIGNATE
|
||||
local MarkedLaserCodesText = ReportLaserCodes:Text(', ')
|
||||
self.CC:GetPositionable():MessageToSetGroup( "Marking " .. MarkingCount .. " x " .. MarkedTypesText .. ", code " .. MarkedLaserCodesText .. ".", 5, self.AttackSet, self.DesignateName )
|
||||
|
||||
self:__Lasing( -30, Index, Duration, LaserCodeRequested )
|
||||
self:__Lasing( -self.LaseDuration, Index, Duration, LaserCodeRequested )
|
||||
|
||||
self:SetDesignateMenu()
|
||||
|
||||
|
||||
@@ -2136,7 +2136,7 @@ do -- Route methods
|
||||
local canroad=false
|
||||
|
||||
-- Check if a valid path on road could be found.
|
||||
if PathOnRoad then
|
||||
if PathOnRoad and LengthDirect > 2000 then -- if the length of the movement is less than 1 km, drive directly.
|
||||
-- Check whether the road is very long compared to direct path.
|
||||
if LongRoad and Shortcut then
|
||||
|
||||
|
||||
Reference in New Issue
Block a user