mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Progress
This commit is contained in:
parent
d120875fa9
commit
ef95cfb1f5
@ -71,7 +71,7 @@ function AI_A2A:New( AIGroup )
|
||||
self:SetControllable( AIGroup )
|
||||
|
||||
self:ManageFuel( .2, 60 )
|
||||
self:ManageDamage( 1 )
|
||||
self:ManageDamage( 0.4 )
|
||||
|
||||
self:SetStartState( "Stopped" )
|
||||
|
||||
|
||||
@ -26,7 +26,7 @@
|
||||
--
|
||||
-- @module AI_A2A_Cap
|
||||
|
||||
BASE:TraceClass("AI_A2A_CAP")
|
||||
--BASE:TraceClass("AI_A2A_CAP")
|
||||
|
||||
--- @type AI_A2A_CAP
|
||||
-- @extends AI.AI_A2A_Patrol#AI_A2A_PATROL
|
||||
|
||||
@ -269,7 +269,7 @@ do -- AI_A2A_DISPATCHER
|
||||
---
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
function AI_A2A_DISPATCHER:ClearDefenderTask( AIGroup )
|
||||
if AIGroup:IsAlive() then
|
||||
if AIGroup:IsAlive() and self.DefenderTasks[AIGroup] then
|
||||
local Target = self.DefenderTasks[AIGroup].Target
|
||||
local Message = "Clearing (" .. self.DefenderTasks[AIGroup].Type .. ") "
|
||||
Message = Message .. AIGroup:GetName()
|
||||
@ -342,8 +342,22 @@ do -- AI_A2A_DISPATCHER
|
||||
DefenderSquadron.Resources = Resources
|
||||
|
||||
self:SetSquadronOverhead( SquadronName, 1 )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Get an item from the Squadron table.
|
||||
-- @param #AI_A2A_DISPATCHER self
|
||||
-- @return #table
|
||||
function AI_A2A_DISPATCHER:GetSquadron( SquadronName )
|
||||
local DefenderSquadron = self.DefenderSquadrons[SquadronName]
|
||||
|
||||
if not DefenderSquadron then
|
||||
error( "Unknown Squadron:" .. SquadronName )
|
||||
end
|
||||
|
||||
return DefenderSquadron
|
||||
end
|
||||
|
||||
|
||||
---
|
||||
@ -361,7 +375,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self.DefenderSquadrons[SquadronName]
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
local Cap = self.DefenderSquadrons[SquadronName].Cap
|
||||
Cap.Name = SquadronName
|
||||
@ -386,7 +400,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self.DefenderSquadrons[SquadronName]
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
local Cap = self.DefenderSquadrons[SquadronName].Cap
|
||||
if Cap then
|
||||
@ -415,7 +429,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self.DefenderSquadrons[SquadronName]
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
local Cap = self.DefenderSquadrons[SquadronName].Cap
|
||||
if Cap then
|
||||
@ -434,7 +448,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self.DefenderSquadrons[SquadronName]
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
|
||||
local Cap = DefenderSquadron.Cap
|
||||
if Cap then
|
||||
@ -501,8 +515,9 @@ do -- AI_A2A_DISPATCHER
|
||||
--
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
function AI_A2A_DISPATCHER:SetSquadronOverhead( SquadronName, Overhead )
|
||||
|
||||
self.Overhead = Overhead
|
||||
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
DefenderSquadron.Overhead = Overhead
|
||||
|
||||
return self
|
||||
end
|
||||
@ -520,7 +535,8 @@ do -- AI_A2A_DISPATCHER
|
||||
-- @return #AI_A2A_DISPATCHER
|
||||
function AI_A2A_DISPATCHER:SetSquadronGrouping( SquadronName, Grouping )
|
||||
|
||||
self.Grouping = Grouping
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
DefenderSquadron.Grouping = Grouping
|
||||
|
||||
return self
|
||||
end
|
||||
@ -602,13 +618,15 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
local AIFriendlies = self:GetAIFriendliesNearBy( DetectedItem )
|
||||
|
||||
for AIName, AIFriendly in pairs( AIFriendlies or {} ) do
|
||||
for FriendlyDistance, AIFriendly in UTILS.spairs( AIFriendlies or {} ) do
|
||||
-- We only allow to ENGAGE targets as long as the Units on both sides are balanced.
|
||||
if DetectedCount > DefenderCount then
|
||||
local Friendly = AIFriendly:GetGroup() -- Wrapper.Group#GROUP
|
||||
if Friendly and Friendly:IsAlive() then
|
||||
-- Ok, so we have a friendly near the potential target.
|
||||
-- Now we need to check if the AIGroup has a Task.
|
||||
self:F( { FriendlyName = Friendly:GetName() } )
|
||||
self:F( { FriendlyDistance = FriendlyDistance } )
|
||||
local DefenderTask = self:GetDefenderTask( Friendly )
|
||||
if DefenderTask then
|
||||
-- The Task should be CAP or INTERCEPT
|
||||
@ -641,13 +659,14 @@ do -- AI_A2A_DISPATCHER
|
||||
self.DefenderSquadrons[SquadronName] = self.DefenderSquadrons[SquadronName] or {}
|
||||
self.DefenderSquadrons[SquadronName].Cap = self.DefenderSquadrons[SquadronName].Cap or {}
|
||||
|
||||
local DefenderSquadron = self.DefenderSquadrons[SquadronName]
|
||||
local DefenderSquadron = self:GetSquadron( SquadronName )
|
||||
local Cap = DefenderSquadron.Cap
|
||||
|
||||
if Cap then
|
||||
|
||||
if self:CanCAP( SquadronName ) then
|
||||
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ]
|
||||
Spawn:InitGrouping( DefenderSquadron.Grouping )
|
||||
local AIGroup = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase )
|
||||
self:F( { AIGroup = AIGroup:GetName() } )
|
||||
|
||||
@ -682,6 +701,13 @@ do -- AI_A2A_DISPATCHER
|
||||
Fsm:__Engage( 1, Target.Set ) -- Engage on the TargetSetUnit
|
||||
|
||||
self:SetDefenderTaskTarget( AIGroup, Target )
|
||||
|
||||
function Fsm:onafterRTB()
|
||||
self:F({"CAP RTB"})
|
||||
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||
local AIGroup = self:GetControllable()
|
||||
Dispatcher:ClearDefenderTask( AIGroup )
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@ -706,7 +732,8 @@ do -- AI_A2A_DISPATCHER
|
||||
DefendersCount = DefendersCount + AIGroup:GetSize()
|
||||
end
|
||||
|
||||
while( DefendersCount < DefendersMissing ) do
|
||||
DefendersCount = DefendersMissing
|
||||
while( DefendersCount > 0 ) do
|
||||
|
||||
for SquadronName, DefenderSquadron in pairs( self.DefenderSquadrons or {} ) do
|
||||
for InterceptID, Intercept in pairs( DefenderSquadron.Intercept or {} ) do
|
||||
@ -724,16 +751,24 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
if ClosestDefenderSquadronName then
|
||||
|
||||
local DefenderSquadron = self.DefenderSquadrons[ClosestDefenderSquadronName]
|
||||
local DefenderSquadron = self:GetSquadron( ClosestDefenderSquadronName )
|
||||
local DefenderOverhead = DefenderSquadron.Overhead
|
||||
local DefenderGrouping = DefenderSquadron.Grouping
|
||||
local DefendersNeeded = math.ceil( DefendersCount * DefenderOverhead )
|
||||
local Intercept = self.DefenderSquadrons[ClosestDefenderSquadronName].Intercept
|
||||
|
||||
local Spawn = DefenderSquadron.Spawn[ math.random( 1, #DefenderSquadron.Spawn ) ]
|
||||
if DefenderGrouping then
|
||||
Spawn:InitGrouping( ( DefenderGrouping < DefendersNeeded ) and DefenderGrouping or DefendersNeeded )
|
||||
else
|
||||
Spawn:InitGrouping()
|
||||
end
|
||||
local AIGroup = Spawn:SpawnAtAirbase( DefenderSquadron.Airbase )
|
||||
self:F( { AIGroup = AIGroup:GetName() } )
|
||||
|
||||
if AIGroup then
|
||||
|
||||
DefendersCount = DefendersCount + AIGroup:GetSize()
|
||||
DefendersCount = DefendersCount - AIGroup:GetSize()
|
||||
|
||||
local Fsm = AI_A2A_INTERCEPT:New( AIGroup, Intercept.MinSpeed, Intercept.MaxSpeed )
|
||||
Fsm:SetDispatcher( self )
|
||||
@ -744,7 +779,7 @@ do -- AI_A2A_DISPATCHER
|
||||
self:SetDefenderTask( AIGroup, "INTERCEPT", Fsm, Target )
|
||||
|
||||
function Fsm:onafterRTB()
|
||||
self:F({"RTB"})
|
||||
self:F({"INTERCEPT RTB"})
|
||||
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
|
||||
local AIGroup = self:GetControllable()
|
||||
Dispatcher:ClearDefenderTask( AIGroup )
|
||||
@ -795,7 +830,7 @@ do -- AI_A2A_DISPATCHER
|
||||
|
||||
-- First, count the active AIGroups Units, targetting the DetectedSet
|
||||
local DefenderCount = self:CountDefendersEngaged( Target )
|
||||
local DefendersMissing = math.ceil( ( AttackerCount - DefenderCount ) * self.Overhead )
|
||||
local DefendersMissing = AttackerCount - DefenderCount
|
||||
|
||||
local Friendlies = self:CountDefendersToBeEngaged( Target, DefenderCount )
|
||||
|
||||
@ -865,7 +900,7 @@ do -- AI_A2A_DISPATCHER
|
||||
local Defender = Defender -- Wrapper.Group#GROUP
|
||||
local Message = string.format( "%s, %s", Defender:GetName(), DefenderTask.Type )
|
||||
if DefenderTask.Target then
|
||||
Message = Message .. " => " .. DefenderTask.Target.Index
|
||||
Message = Message .. " => " .. DefenderTask.Target.Index .. " : " .. DefenderTask.Target.Set:GetObjectNames()
|
||||
end
|
||||
self:F( { Tactical = Message } )
|
||||
end
|
||||
|
||||
@ -21,7 +21,7 @@
|
||||
-- @module AI_A2A_Intercept
|
||||
|
||||
|
||||
BASE:TraceClass("AI_A2A_INTERCEPT")
|
||||
--BASE:TraceClass("AI_A2A_INTERCEPT")
|
||||
|
||||
|
||||
--- @type AI_A2A_INTERCEPT
|
||||
|
||||
@ -598,6 +598,20 @@ function SET_BASE:IsIncludeObject( Object )
|
||||
return true
|
||||
end
|
||||
|
||||
--- Gets a string with all the object names.
|
||||
-- @param #SET_BASE self
|
||||
-- @return #string A string with the names of the objects.
|
||||
function SET_BASE:GetObjectNames()
|
||||
self:F3()
|
||||
|
||||
local ObjectNames = ""
|
||||
for ObjectName, Object in pairs( self.Set ) do
|
||||
ObjectNames = ObjectNames .. ObjectName .. ", "
|
||||
end
|
||||
|
||||
return ObjectNames
|
||||
end
|
||||
|
||||
--- Flushes the current SET_BASE contents in the log ... (for debugging reasons).
|
||||
-- @param #SET_BASE self
|
||||
-- @return #string A string with the names of the objects.
|
||||
|
||||
@ -1167,6 +1167,7 @@ do -- DETECTION_BASE
|
||||
local DetectedItem = ReportGroupData.DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
|
||||
local DetectedSet = ReportGroupData.DetectedItem.Set
|
||||
local DetectedUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
|
||||
local CenterCoord = DetectedUnit:GetCoordinate()
|
||||
local ReportSetGroup = ReportGroupData.ReportSetGroup
|
||||
|
||||
local EnemyCoalition = DetectedUnit:GetCoalition()
|
||||
@ -1181,7 +1182,9 @@ do -- DETECTION_BASE
|
||||
|
||||
if FoundUnitCoalition ~= EnemyCoalition and FoundUnitInReportSetGroup == false then
|
||||
DetectedItem.FriendliesNearBy = DetectedItem.FriendliesNearBy or {}
|
||||
DetectedItem.FriendliesNearBy[FoundUnitName] = UNIT:Find( FoundDCSUnit )
|
||||
local FriendlyUnit = UNIT:Find( FoundDCSUnit )
|
||||
local Distance = CenterCoord:Get2DDistance( FriendlyUnit:GetCoordinate() )
|
||||
DetectedItem.FriendliesNearBy[Distance] = FriendlyUnit
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
@ -37,6 +37,7 @@
|
||||
--
|
||||
-- @module Spawn
|
||||
|
||||
--BASE:TraceClass("SPAWN")
|
||||
|
||||
|
||||
--- SPAWN Class
|
||||
@ -299,6 +300,7 @@ function SPAWN:New( SpawnTemplatePrefix )
|
||||
self.SpawnUnControlled = false
|
||||
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
|
||||
self.DelayOnOff = false -- No intial delay when spawning the first group.
|
||||
self.Grouping = nil -- No grouping
|
||||
|
||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||
else
|
||||
@ -343,6 +345,7 @@ function SPAWN:NewWithAlias( SpawnTemplatePrefix, SpawnAliasPrefix )
|
||||
self.SpawnUnControlled = false
|
||||
self.SpawnInitKeepUnitNames = false -- Overwrite unit names by default with group name.
|
||||
self.DelayOnOff = false -- No intial delay when spawning the first group.
|
||||
self.Grouping = nil
|
||||
|
||||
self.SpawnGroups = {} -- Array containing the descriptions of each Group to be Spawned.
|
||||
else
|
||||
@ -509,6 +512,20 @@ function SPAWN:InitRandomizeTemplate( SpawnTemplatePrefixTable )
|
||||
return self
|
||||
end
|
||||
|
||||
--- When spawning a new group, make the grouping of the units according the InitGrouping setting.
|
||||
-- @param #SPAWN self
|
||||
-- @param #number Grouping Indicates the maximum amount of units in the group.
|
||||
-- @return #SPAWN
|
||||
function SPAWN:InitGrouping( Grouping ) -- R2.2
|
||||
self:F( { self.SpawnTemplatePrefix, Grouping } )
|
||||
|
||||
self.SpawnGrouping = Grouping
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--TODO: Add example.
|
||||
--- This method provides the functionality to randomize the spawning of the Groups at a given list of zones of different types.
|
||||
-- @param #SPAWN self
|
||||
@ -966,7 +983,7 @@ end
|
||||
-- @param #number SpawnIndex (optional) The index which group to spawn within the given zone.
|
||||
-- @return Wrapper.Group#GROUP that was spawned.
|
||||
-- @return #nil Nothing was spawned.
|
||||
function SPAWN:SpawnAtAirbase( Airbase, SpawnIndex )
|
||||
function SPAWN:SpawnAtAirbase( Airbase, SpawnIndex ) -- R2.2
|
||||
self:F( { self.SpawnTemplatePrefix, Airbase, SpawnIndex } )
|
||||
|
||||
local PointVec3 = Airbase:GetPointVec3()
|
||||
@ -1445,7 +1462,7 @@ end
|
||||
-- @param #string SpawnTemplatePrefix
|
||||
-- @param #number SpawnIndex
|
||||
-- @return #SPAWN self
|
||||
function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
|
||||
function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex ) --R2.2
|
||||
self:F( { self.SpawnTemplatePrefix, self.SpawnAliasPrefix } )
|
||||
|
||||
local SpawnTemplate = self:_GetTemplate( SpawnTemplatePrefix )
|
||||
@ -1460,6 +1477,23 @@ function SPAWN:_Prepare( SpawnTemplatePrefix, SpawnIndex )
|
||||
SpawnTemplate.visible = false
|
||||
end
|
||||
|
||||
if self.SpawnGrouping then
|
||||
local UnitAmount = #SpawnTemplate.units
|
||||
self:F( { UnitAmount = UnitAmount, SpawnGrouping = self.SpawnGrouping } )
|
||||
if UnitAmount > self.SpawnGrouping then
|
||||
for UnitID = self.SpawnGrouping + 1, UnitAmount do
|
||||
SpawnTemplate.units[UnitID] = nil
|
||||
end
|
||||
else
|
||||
if UnitAmount < self.SpawnGrouping then
|
||||
for UnitID = UnitAmount + 1, self.SpawnGrouping do
|
||||
SpawnTemplate.units[UnitID] = UTILS.DeepCopy( SpawnTemplate.units[1] )
|
||||
SpawnTemplate.units[UnitID].unitId = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if self.SpawnInitKeepUnitNames == false then
|
||||
for UnitID = 1, #SpawnTemplate.units do
|
||||
SpawnTemplate.units[UnitID].name = string.format( SpawnTemplate.name .. '-%02d', UnitID )
|
||||
|
||||
@ -303,3 +303,27 @@ function UTILS.DoString( s )
|
||||
return false, err
|
||||
end
|
||||
end
|
||||
|
||||
-- Here is a customized version of pairs, which I called spairs because it iterates over the table in a sorted order.
|
||||
function UTILS.spairs( t, order )
|
||||
-- collect the keys
|
||||
local keys = {}
|
||||
for k in pairs(t) do keys[#keys+1] = k end
|
||||
|
||||
-- if order function given, sort by it by passing the table and keys a, b,
|
||||
-- otherwise just sort the keys
|
||||
if order then
|
||||
table.sort(keys, function(a,b) return order(t, a, b) end)
|
||||
else
|
||||
table.sort(keys)
|
||||
end
|
||||
|
||||
-- return the iterator function
|
||||
local i = 0
|
||||
return function()
|
||||
i = i + 1
|
||||
if keys[i] then
|
||||
return keys[i], t[keys[i]]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user