- Implemented attack nearest target.

- Implemented attack nearest ground target.
- Implemented attack nearest air target.
- Report all targets.
- Report only ground targets.
- Report only ground targets with radar.
- Report only air targets.
- Sort targest from nearest to furthest.
- Improved menu system.
- Improved detection of ground targets and air targets and reporting.
- Added the task TASK_CAPTURE as part of the reporting framework.
- Improved the detection of targets. Now targets with specific detection methods are correctly detected. f.e. disabling DLINK will now work correctly!

All these fixes are great improvements to the AI_ESCORT framework!
This commit is contained in:
FlightControl 2019-08-10 15:42:00 +02:00
commit 5f9880f17d
7 changed files with 355 additions and 118 deletions

View File

@ -224,7 +224,6 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
self.PlayerGroup = self.FollowUnit:GetGroup() -- Wrapper.Group#GROUP self.PlayerGroup = self.FollowUnit:GetGroup() -- Wrapper.Group#GROUP
self.EscortName = EscortName self.EscortName = EscortName
self.EscortGroupSet = EscortGroupSet self.EscortGroupSet = EscortGroupSet
self.EscortGroupSet:SetSomeIteratorLimit( 8 ) self.EscortGroupSet:SetSomeIteratorLimit( 8 )
@ -267,6 +266,8 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing )
end end
) )
self:SetFlightReportType( self.__Enum.ReportType.All )
return self return self
end end
@ -293,6 +294,7 @@ function AI_ESCORT:_InitFlightMenus()
self:SetFlightMenuROT() self:SetFlightMenuROT()
self:SetFlightMenuTargets() self:SetFlightMenuTargets()
self:SetFlightMenuReportType()
end end
@ -358,6 +360,8 @@ function AI_ESCORT:onafterStart( EscortGroupSet )
self.Detection:InitDetectRadar( true ) self.Detection:InitDetectRadar( true )
self.Detection:InitDetectRWR( true ) self.Detection:InitDetectRWR( true )
self.Detection:SetAcceptRange( 100000 )
self.Detection:__Start( 30 ) self.Detection:__Start( 30 )
self.MainMenu = MENU_GROUP:New( self.PlayerGroup, self.EscortName ) self.MainMenu = MENU_GROUP:New( self.PlayerGroup, self.EscortName )
@ -1115,10 +1119,43 @@ function AI_ESCORT:MenuSmoke( MenuTextFormat )
return self return self
end end
function AI_ESCORT:SetFlightMenuReportType()
local FlightMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", self.FlightMenu )
local MenuStamp = FlightMenuReportTargets:GetStamp()
local FlightReportType = self:GetFlightReportType()
if FlightReportType ~= self.__Enum.ReportType.All then
local FlightMenuReportTargetsAll = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report all targets", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportTypeAll, self )
:SetTag( "ReportType" )
:SetStamp( MenuStamp )
end
if FlightReportType == self.__Enum.ReportType.All or FlightReportType ~= self.__Enum.ReportType.Airborne then
local FlightMenuReportTargetsAirborne = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report airborne targets", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportTypeAirborne, self )
:SetTag( "ReportType" )
:SetStamp( MenuStamp )
end
if FlightReportType == self.__Enum.ReportType.All or FlightReportType ~= self.__Enum.ReportType.GroundRadar then
local FlightMenuReportTargetsGroundRadar = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report gound radar targets", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportTypeGroundRadar, self )
:SetTag( "ReportType" )
:SetStamp( MenuStamp )
end
if FlightReportType == self.__Enum.ReportType.All or FlightReportType ~= self.__Enum.ReportType.Ground then
local FlightMenuReportTargetsGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report ground targets", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportTypeGround, self )
:SetTag( "ReportType" )
:SetStamp( MenuStamp )
end
FlightMenuReportTargets:RemoveSubMenus( MenuStamp, "ReportType" )
end
function AI_ESCORT:SetFlightMenuTargets() function AI_ESCORT:SetFlightMenuTargets()
for _, MenuTargets in pairs( self.Menu.Targets) do
local FlightMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", self.FlightMenu ) local FlightMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", self.FlightMenu )
-- Report Targets -- Report Targets
@ -1127,8 +1164,12 @@ function AI_ESCORT:SetFlightMenuTargets()
local FlightMenuReportTargetsOff = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets off", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportNearbyTargets, self, false ) local FlightMenuReportTargetsOff = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets off", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportNearbyTargets, self, false )
-- Attack Targets -- Attack Targets
local FlightMenuAttackNearbyTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", self.FlightMenu ) self.FlightMenuAttack = MENU_GROUP:New( self.PlayerGroup, "Attack targets", self.FlightMenu )
local FlightMenuAttackNearby = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self ):SetTag( "Attack" )
local FlightMenuAttackNearbyAir = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest airborne targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Air ):SetTag( "Attack" )
local FlightMenuAttackNearbyGround = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Attack nearest ground targets", self.FlightMenuAttack, AI_ESCORT._FlightAttackNearestTarget, self, self.__Enum.ReportType.Ground ):SetTag( "Attack" )
for _, MenuTargets in pairs( self.Menu.Targets) do
MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval ) MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval )
end end
@ -1542,22 +1583,6 @@ function AI_ESCORT:_FlightReportNearbyTargetsNow()
end end
function AI_ESCORT:_SwitchReportNearbyTargets( EscortGroup, ReportTargets )
local EscortUnit = self.PlayerUnit
self.ReportTargets = ReportTargets
if self.ReportTargets then
if not EscortGroup.ReportTargetsScheduler then
EscortGroup.ReportTargetsScheduler:Schedule( self, self._ReportTargetsScheduler, {}, 1, 30 )
end
else
routines.removeFunction( EscortGroup.ReportTargetsScheduler )
EscortGroup.ReportTargetsScheduler = nil
end
end
function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets ) function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets )
@ -1565,13 +1590,65 @@ function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets )
--- @param Core.Group#GROUP EscortGroup --- @param Core.Group#GROUP EscortGroup
function( EscortGroup ) function( EscortGroup )
if EscortGroup:IsAir() then if EscortGroup:IsAir() then
self:_SwitchReportNearbyTargets( EscortGroup, ReportTargets ) self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets )
end end
end end
) )
end end
function AI_ESCORT:SetFlightReportType( ReportType )
self.FlightReportType = ReportType
end
function AI_ESCORT:GetFlightReportType()
return self.FlightReportType
end
function AI_ESCORT:_FlightSwitchReportTypeAll()
self:SetFlightReportType( self.__Enum.ReportType.All )
self:SetFlightMenuReportType()
local EscortGroup = self.EscortGroupSet:GetFirst()
EscortGroup:MessageTypeToGroup( "Reporting all targets.", MESSAGE.Type.Information, self.PlayerGroup )
end
function AI_ESCORT:_FlightSwitchReportTypeAirborne()
self:SetFlightReportType( self.__Enum.ReportType.Airborne )
self:SetFlightMenuReportType()
local EscortGroup = self.EscortGroupSet:GetFirst()
EscortGroup:MessageTypeToGroup( "Reporting airborne targets.", MESSAGE.Type.Information, self.PlayerGroup )
end
function AI_ESCORT:_FlightSwitchReportTypeGroundRadar()
self:SetFlightReportType( self.__Enum.ReportType.Ground )
self:SetFlightMenuReportType()
local EscortGroup = self.EscortGroupSet:GetFirst()
EscortGroup:MessageTypeToGroup( "Reporting ground radar targets.", MESSAGE.Type.Information, self.PlayerGroup )
end
function AI_ESCORT:_FlightSwitchReportTypeGround()
self:SetFlightReportType( self.__Enum.ReportType.Ground )
self:SetFlightMenuReportType()
local EscortGroup = self.EscortGroupSet:GetFirst()
EscortGroup:MessageTypeToGroup( "Reporting ground targets.", MESSAGE.Type.Information, self.PlayerGroup )
end
function AI_ESCORT:_ScanTargets( ScanDuration ) function AI_ESCORT:_ScanTargets( ScanDuration )
@ -1724,6 +1801,35 @@ function AI_ESCORT:_FlightAttackTarget( DetectedItem )
end end
function AI_ESCORT:_FlightAttackNearestTarget( TargetType )
local AttackDetectedItem = nil
local DetectedItems = self.Detection:GetDetectedItems()
for DetectedItemIndex, DetectedItem in UTILS.spairs( DetectedItems, function( t, a, b ) return self:Distance( self.PlayerUnit, t[a] ) < self:Distance( self.PlayerUnit, t[b] ) end ) do
local DetectedItemSet = self.Detection:GetDetectedItemSet( DetectedItem )
local HasGround = DetectedItemSet:HasGroundUnits() > 0
local HasAir = DetectedItemSet:HasAirUnits() > 0
local FlightReportType = self:GetFlightReportType()
if ( TargetType and TargetType == self.__Enum.ReportType.Ground and HasGround ) or
( TargetType and TargetType == self.__Enum.ReportType.Air and HasAir ) or
( TargetType == nil ) then
AttackDetectedItem = DetectedItem
break
end
end
if AttackDetectedItem then
self:_FlightAttackTarget( AttackDetectedItem )
end
end
--- ---
--- @param #AI_ESCORT self --- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item. -- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item.
@ -1884,6 +1990,17 @@ function AI_ESCORT:_ResumeScheduler( EscortGroup )
end end
--- Measure distance between coordinate player and coordinate detected item.
-- @param #AI_ESCORT self
function AI_ESCORT:Distance( PlayerUnit, DetectedItem )
local DetectedCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem )
local PlayerCoordinate = PlayerUnit:GetCoordinate()
return DetectedCoordinate:Get3DDistance( PlayerCoordinate )
end
--- Report Targets Scheduler. --- Report Targets Scheduler.
-- @param #AI_ESCORT self -- @param #AI_ESCORT self
-- @param Wrapper.Group#GROUP EscortGroup -- @param Wrapper.Group#GROUP EscortGroup
@ -1910,7 +2027,24 @@ function AI_ESCORT:_ReportTargetsScheduler( EscortGroup, Report )
local EscortMenuAttackTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", EscortGroup.EscortMenu ) local EscortMenuAttackTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", EscortGroup.EscortMenu )
local DetectedTargets = false local DetectedTargets = false
for DetectedItemIndex, DetectedItem in pairs( DetectedItems ) do
for DetectedItemIndex, DetectedItem in UTILS.spairs( DetectedItems, function( t, a, b ) return self:Distance( self.PlayerUnit, t[a] ) < self:Distance( self.PlayerUnit, t[b] ) end ) do
--for DetectedItemIndex, DetectedItem in pairs( DetectedItems ) do
local DetectedItemSet = self.Detection:GetDetectedItemSet( DetectedItem )
local HasGround = DetectedItemSet:HasGroundUnits() > 0
local HasGroundRadar = HasGround and DetectedItemSet:HasRadar() > 0
local HasAir = DetectedItemSet:HasAirUnits() > 0
local FlightReportType = self:GetFlightReportType()
if ( FlightReportType == self.__Enum.ReportType.All ) or
( FlightReportType == self.__Enum.ReportType.Airborne and HasAir ) or
( FlightReportType == self.__Enum.ReportType.Ground and HasGround ) or
( FlightReportType == self.__Enum.ReportType.GroundRadar and HasGroundRadar ) then
DetectedTargets = true DetectedTargets = true
local DetectedMenu = self.Detection:DetectedItemReportMenu( DetectedItem, EscortGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ):Text("\n") local DetectedMenu = self.Detection:DetectedItemReportMenu( DetectedItem, EscortGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ):Text("\n")
@ -1941,9 +2075,8 @@ function AI_ESCORT:_ReportTargetsScheduler( EscortGroup, Report )
DetectedItem DetectedItem
) )
end end
end end
end
end end
EscortMenuAttackTargets:RemoveSubMenus( TimeUpdate, "Escort" ) EscortMenuAttackTargets:RemoveSubMenus( TimeUpdate, "Escort" )
@ -1975,43 +2108,53 @@ function AI_ESCORT:_FlightReportTargetsScheduler()
if EscortGroup and ( self.PlayerUnit:IsAlive() and EscortGroup:IsAlive() ) then if EscortGroup and ( self.PlayerUnit:IsAlive() and EscortGroup:IsAlive() ) then
local ClientGroup = self.PlayerGroup
local TimeUpdate = timer.getTime() local TimeUpdate = timer.getTime()
local DetectedItems = self.Detection:GetDetectedItems() local DetectedItems = self.Detection:GetDetectedItems()
local DetectedTargets = false local DetectedTargets = false
local ClientEscortTargets = self.Detection local ClientEscortTargets = self.Detection
local FlightMenuAttackTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", self.FlightMenu ) for DetectedItemIndex, DetectedItem in UTILS.spairs( DetectedItems, function( t, a, b ) return self:Distance( self.PlayerUnit, t[a] ) < self:Distance( self.PlayerUnit, t[b] ) end ) do
for DetectedItemIndex, DetectedItem in pairs( DetectedItems ) do
self:F("FlightReportTargetScheduler Targets") self:F("FlightReportTargetScheduler Targets")
local DetectedItemSet = self.Detection:GetDetectedItemSet( DetectedItem )
local HasGround = DetectedItemSet:HasGroundUnits() > 0
local HasGroundRadar = HasGround and DetectedItemSet:HasRadar() > 0
local HasAir = DetectedItemSet:HasAirUnits() > 0
local FlightReportType = self:GetFlightReportType()
if ( FlightReportType == self.__Enum.ReportType.All ) or
( FlightReportType == self.__Enum.ReportType.Airborne and HasAir ) or
( FlightReportType == self.__Enum.ReportType.Ground and HasGround ) or
( FlightReportType == self.__Enum.ReportType.GroundRadar and HasGroundRadar ) then
DetectedTargets = true -- There are detected targets, when the content of the for loop is executed. We use it to display a message. DetectedTargets = true -- There are detected targets, when the content of the for loop is executed. We use it to display a message.
local DetectedItemReportMenu = self.Detection:DetectedItemReportMenu( DetectedItem, ClientGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) local DetectedItemReportMenu = self.Detection:DetectedItemReportMenu( DetectedItem, self.PlayerGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) )
local ReportMenuText = DetectedItemReportMenu:Text(", ") local ReportMenuText = DetectedItemReportMenu:Text(", ")
MENU_GROUP_COMMAND:New( self.PlayerGroup, MENU_GROUP_COMMAND:New( self.PlayerGroup,
ReportMenuText, ReportMenuText,
FlightMenuAttackTargets, self.FlightMenuAttack,
AI_ESCORT._FlightAttackTarget, AI_ESCORT._FlightAttackTarget,
self, self,
DetectedItem DetectedItem
):SetTag( "Flight" ):SetTime( TimeUpdate ) ):SetTag( "Flight" ):SetTime( TimeUpdate )
local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, ClientGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, self.PlayerGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) )
local ReportSummary = DetectedItemReportSummary:Text(", ") local ReportSummary = DetectedItemReportSummary:Text(", ")
DetectedTargetsReport:AddIndent( ReportSummary, "-" ) DetectedTargetsReport:AddIndent( ReportSummary, "-" )
end end
end
FlightMenuAttackTargets:RemoveSubMenus( TimeUpdate, "Flight" ) self.FlightMenuAttack:RemoveSubMenus( TimeUpdate, "Flight" )
if DetectedTargets then if DetectedTargets then
EscortGroup:MessageTypeToGroup( DetectedTargetsReport:Text( "\n" ), MESSAGE.Type.Information, self.PlayerGroup ) EscortGroup:MessageTypeToGroup( DetectedTargetsReport:Text( "\n" ), MESSAGE.Type.Information, self.PlayerGroup )

View File

@ -147,6 +147,17 @@ AI_FORMATION.__Enum.Mode = {
Reconnaissance = "R", Reconnaissance = "R",
} }
--- @type AI_FORMATION.__Enum.ReportType
-- @field #number All
-- @field #number Airborne
-- @field #number GroundRadar
-- @field #number Ground
AI_FORMATION.__Enum.ReportType = {
Airborne = "*",
Airborne = "A",
GroundRadar = "R",
Ground = "G",
}

View File

@ -238,7 +238,7 @@ do -- MENU_BASE
self.Path = ( self.ParentMenu and "@" .. table.concat( self.MenuParentPath or {}, "@" ) or "" ) .. "@" .. self.MenuText self.Path = ( self.ParentMenu and "@" .. table.concat( self.MenuParentPath or {}, "@" ) or "" ) .. "@" .. self.MenuText
self.Menus = {} self.Menus = {}
self.MenuCount = 0 self.MenuCount = 0
self.MenuTime = timer.getTime() self.MenuStamp = timer.getTime()
self.MenuRemoveParent = false self.MenuRemoveParent = false
if self.ParentMenu then if self.ParentMenu then
@ -286,12 +286,30 @@ do -- MENU_BASE
return self.Menus[MenuText] return self.Menus[MenuText]
end end
--- Sets a menu stamp for later prevention of menu removal.
-- @param #MENU_BASE self
-- @param MenuStamp
-- @return #MENU_BASE
function MENU_BASE:SetStamp( MenuStamp )
self.MenuStamp = MenuStamp
return self
end
--- Gets a menu stamp for later prevention of menu removal.
-- @param #MENU_BASE self
-- @return MenuStamp
function MENU_BASE:GetStamp()
return timer.getTime()
end
--- Sets a time stamp for later prevention of menu removal. --- Sets a time stamp for later prevention of menu removal.
-- @param #MENU_BASE self -- @param #MENU_BASE self
-- @param MenuTime -- @param MenuStamp
-- @return #MENU_BASE -- @return #MENU_BASE
function MENU_BASE:SetTime( MenuTime ) function MENU_BASE:SetTime( MenuStamp )
self.MenuTime = MenuTime self.MenuStamp = MenuStamp
return self return self
end end
@ -443,7 +461,7 @@ do -- MENU_MISSION
--- Removes the main menu and the sub menus recursively of this MENU_MISSION. --- Removes the main menu and the sub menus recursively of this MENU_MISSION.
-- @param #MENU_MISSION self -- @param #MENU_MISSION self
-- @return #nil -- @return #nil
function MENU_MISSION:Remove( MenuTime, MenuTag ) function MENU_MISSION:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareMission() MENU_INDEX:PrepareMission()
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
@ -451,7 +469,7 @@ do -- MENU_MISSION
if MissionMenu == self then if MissionMenu == self then
self:RemoveSubMenus() self:RemoveSubMenus()
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Text = self.MenuText, Path = self.MenuPath } ) self:F( { Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
@ -537,7 +555,7 @@ do -- MENU_MISSION_COMMAND
local MissionMenu = MENU_INDEX:HasMissionMenu( Path ) local MissionMenu = MENU_INDEX:HasMissionMenu( Path )
if MissionMenu == self then if MissionMenu == self then
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Text = self.MenuText, Path = self.MenuPath } ) self:F( { Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
@ -666,7 +684,7 @@ do -- MENU_COALITION
--- Removes the main menu and the sub menus recursively of this MENU_COALITION. --- Removes the main menu and the sub menus recursively of this MENU_COALITION.
-- @param #MENU_COALITION self -- @param #MENU_COALITION self
-- @return #nil -- @return #nil
function MENU_COALITION:Remove( MenuTime, MenuTag ) function MENU_COALITION:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareCoalition( self.Coalition ) MENU_INDEX:PrepareCoalition( self.Coalition )
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
@ -674,7 +692,7 @@ do -- MENU_COALITION
if CoalitionMenu == self then if CoalitionMenu == self then
self:RemoveSubMenus() self:RemoveSubMenus()
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Coalition = self.Coalition, Text = self.MenuText, Path = self.MenuPath } ) self:F( { Coalition = self.Coalition, Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
@ -758,14 +776,14 @@ do -- MENU_COALITION_COMMAND
--- Removes a radio command item for a coalition --- Removes a radio command item for a coalition
-- @param #MENU_COALITION_COMMAND self -- @param #MENU_COALITION_COMMAND self
-- @return #nil -- @return #nil
function MENU_COALITION_COMMAND:Remove( MenuTime, MenuTag ) function MENU_COALITION_COMMAND:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareCoalition( self.Coalition ) MENU_INDEX:PrepareCoalition( self.Coalition )
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
local CoalitionMenu = MENU_INDEX:HasCoalitionMenu( self.Coalition, Path ) local CoalitionMenu = MENU_INDEX:HasCoalitionMenu( self.Coalition, Path )
if CoalitionMenu == self then if CoalitionMenu == self then
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
self:F( { Coalition = self.Coalition, Text = self.MenuText, Path = self.MenuPath } ) self:F( { Coalition = self.Coalition, Text = self.MenuText, Path = self.MenuPath } )
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
@ -907,13 +925,13 @@ do
--- Removes the sub menus recursively of this MENU_GROUP. --- Removes the sub menus recursively of this MENU_GROUP.
-- @param #MENU_GROUP self -- @param #MENU_GROUP self
-- @param MenuTime -- @param MenuStamp
-- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set. -- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set.
-- @return #MENU_GROUP self -- @return #MENU_GROUP self
function MENU_GROUP:RemoveSubMenus( MenuTime, MenuTag ) function MENU_GROUP:RemoveSubMenus( MenuStamp, MenuTag )
for MenuText, Menu in pairs( self.Menus or {} ) do for MenuText, Menu in pairs( self.Menus or {} ) do
Menu:Remove( MenuTime, MenuTag ) Menu:Remove( MenuStamp, MenuTag )
end end
self.Menus = nil self.Menus = nil
@ -923,18 +941,18 @@ do
--- Removes the main menu and sub menus recursively of this MENU_GROUP. --- Removes the main menu and sub menus recursively of this MENU_GROUP.
-- @param #MENU_GROUP self -- @param #MENU_GROUP self
-- @param MenuTime -- @param MenuStamp
-- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set. -- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set.
-- @return #nil -- @return #nil
function MENU_GROUP:Remove( MenuTime, MenuTag ) function MENU_GROUP:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareGroup( self.Group ) MENU_INDEX:PrepareGroup( self.Group )
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path )
if GroupMenu == self then if GroupMenu == self then
self:RemoveSubMenus( MenuTime, MenuTag ) self:RemoveSubMenus( MenuStamp, MenuTag )
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
@ -1014,17 +1032,17 @@ do
--- Removes a menu structure for a group. --- Removes a menu structure for a group.
-- @param #MENU_GROUP_COMMAND self -- @param #MENU_GROUP_COMMAND self
-- @param MenuTime -- @param MenuStamp
-- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set. -- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set.
-- @return #nil -- @return #nil
function MENU_GROUP_COMMAND:Remove( MenuTime, MenuTag ) function MENU_GROUP_COMMAND:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareGroup( self.Group ) MENU_INDEX:PrepareGroup( self.Group )
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path )
if GroupMenu == self then if GroupMenu == self then
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
@ -1136,13 +1154,13 @@ do
--- Removes the sub menus recursively of this MENU_GROUP_DELAYED. --- Removes the sub menus recursively of this MENU_GROUP_DELAYED.
-- @param #MENU_GROUP_DELAYED self -- @param #MENU_GROUP_DELAYED self
-- @param MenuTime -- @param MenuStamp
-- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set. -- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set.
-- @return #MENU_GROUP_DELAYED self -- @return #MENU_GROUP_DELAYED self
function MENU_GROUP_DELAYED:RemoveSubMenus( MenuTime, MenuTag ) function MENU_GROUP_DELAYED:RemoveSubMenus( MenuStamp, MenuTag )
for MenuText, Menu in pairs( self.Menus or {} ) do for MenuText, Menu in pairs( self.Menus or {} ) do
Menu:Remove( MenuTime, MenuTag ) Menu:Remove( MenuStamp, MenuTag )
end end
self.Menus = nil self.Menus = nil
@ -1152,18 +1170,18 @@ do
--- Removes the main menu and sub menus recursively of this MENU_GROUP. --- Removes the main menu and sub menus recursively of this MENU_GROUP.
-- @param #MENU_GROUP_DELAYED self -- @param #MENU_GROUP_DELAYED self
-- @param MenuTime -- @param MenuStamp
-- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set. -- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set.
-- @return #nil -- @return #nil
function MENU_GROUP_DELAYED:Remove( MenuTime, MenuTag ) function MENU_GROUP_DELAYED:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareGroup( self.Group ) MENU_INDEX:PrepareGroup( self.Group )
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path )
if GroupMenu == self then if GroupMenu == self then
self:RemoveSubMenus( MenuTime, MenuTag ) self:RemoveSubMenus( MenuStamp, MenuTag )
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )
@ -1263,17 +1281,17 @@ do
--- Removes a menu structure for a group. --- Removes a menu structure for a group.
-- @param #MENU_GROUP_COMMAND_DELAYED self -- @param #MENU_GROUP_COMMAND_DELAYED self
-- @param MenuTime -- @param MenuStamp
-- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set. -- @param MenuTag A Tag or Key to filter the menus to be refreshed with the Tag set.
-- @return #nil -- @return #nil
function MENU_GROUP_COMMAND_DELAYED:Remove( MenuTime, MenuTag ) function MENU_GROUP_COMMAND_DELAYED:Remove( MenuStamp, MenuTag )
MENU_INDEX:PrepareGroup( self.Group ) MENU_INDEX:PrepareGroup( self.Group )
local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText )
local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path )
if GroupMenu == self then if GroupMenu == self then
if not MenuTime or self.MenuTime ~= MenuTime then if not MenuStamp or self.MenuStamp ~= MenuStamp then
if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then
if self.MenuPath ~= nil then if self.MenuPath ~= nil then
self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } )

View File

@ -2065,31 +2065,32 @@ do -- COORDINATE
-- @return #string The coordinate Text in the configured coordinate system. -- @return #string The coordinate Text in the configured coordinate system.
function COORDINATE:ToString( Controllable, Settings, Task ) function COORDINATE:ToString( Controllable, Settings, Task )
self:F2( { Controllable = Controllable and Controllable:GetName() } ) self:E( { Controllable = Controllable and Controllable:GetName() } )
local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS local Settings = Settings or ( Controllable and _DATABASE:GetPlayerSettings( Controllable:GetPlayerName() ) ) or _SETTINGS
local ModeA2A = false local ModeA2A = nil
self:E('A2A false')
if Task then if Task then
self:E('Task ' .. Task.ClassName )
if Task:IsInstanceOf( TASK_A2A ) then if Task:IsInstanceOf( TASK_A2A ) then
ModeA2A = true ModeA2A = true
self:E('A2A true')
else else
if Task:IsInstanceOf( TASK_A2G ) then if Task:IsInstanceOf( TASK_A2G ) then
ModeA2A = false ModeA2A = false
else else
if Task:IsInstanceOf( TASK_CARGO ) then if Task:IsInstanceOf( TASK_CARGO ) then
ModeA2A = false ModeA2A = false
else end
if Task:IsInstanceOf( TASK_CAPTURE_ZONE ) then
ModeA2A = false ModeA2A = false
end end
end end
end end
else end
local IsAir = Controllable and Controllable:IsAirPlane() or false
if ModeA2A == nil then
local IsAir = Controllable and ( Controllable:IsAirPlane() or Controllable:IsHelicopter() ) or false
if IsAir then if IsAir then
ModeA2A = true ModeA2A = true
else else

View File

@ -2624,6 +2624,23 @@ do -- SET_UNIT
return GroundUnitCount return GroundUnitCount
end end
--- Returns if the @{Set} has air targets.
-- @param #SET_UNIT self
-- @return #number The amount of air targets in the Set.
function SET_UNIT:HasAirUnits()
self:F2()
local AirUnitCount = 0
for UnitID, UnitData in pairs( self:GetSet() ) do
local UnitTest = UnitData -- Wrapper.Unit#UNIT
if UnitTest:IsAir() then
AirUnitCount = AirUnitCount + 1
end
end
return AirUnitCount
end
--- Returns if the @{Set} has friendly ground units. --- Returns if the @{Set} has friendly ground units.
-- @param #SET_UNIT self -- @param #SET_UNIT self
-- @return #number The amount of ground targets in the Set. -- @return #number The amount of ground targets in the Set.

View File

@ -2560,9 +2560,17 @@ do -- DETECTION_AREAS
local DetectedSet = self:GetDetectedItemSet( DetectedItem ) local DetectedSet = self:GetDetectedItemSet( DetectedItem )
local ReportSummaryItem local ReportSummaryItem
local DetectedZone = self:GetDetectedItemZone( DetectedItem ) --local DetectedZone = self:GetDetectedItemZone( DetectedItem )
local DetectedItemCoordinate = DetectedZone:GetCoordinate() local DetectedItemCoordinate = self:GetDetectedItemCoordinate( DetectedItem )
local DetectedItemCoordText = DetectedItemCoordinate:ToString( AttackGroup, Settings ) local DetectedAir = DetectedSet:HasAirUnits()
local DetectedAltitude = self:GetDetectedItemCoordinate( DetectedItem )
local DetectedItemCoordText = ""
if DetectedAir > 0 then
DetectedItemCoordText = DetectedItemCoordinate:ToStringA2A( AttackGroup, Settings )
else
DetectedItemCoordText = DetectedItemCoordinate:ToStringA2G( AttackGroup, Settings )
end
local ThreatLevelA2G = self:GetDetectedItemThreatLevel( DetectedItem ) local ThreatLevelA2G = self:GetDetectedItemThreatLevel( DetectedItem )
local DetectedItemsCount = DetectedSet:Count() local DetectedItemsCount = DetectedSet:Count()

View File

@ -2798,9 +2798,31 @@ function CONTROLLABLE:GetDetectedTargets( DetectVisual, DetectOptical, DetectRad
local DetectionRWR = ( DetectRWR and DetectRWR == true ) and Controller.Detection.RWR or nil local DetectionRWR = ( DetectRWR and DetectRWR == true ) and Controller.Detection.RWR or nil
local DetectionDLINK = ( DetectDLINK and DetectDLINK == true ) and Controller.Detection.DLINK or nil local DetectionDLINK = ( DetectDLINK and DetectDLINK == true ) and Controller.Detection.DLINK or nil
local Params = {}
if DetectionVisual then
Params[#Params+1] = DetectionVisual
end
if DetectionOptical then
Params[#Params+1] = DetectionOptical
end
if DetectionRadar then
Params[#Params+1] = DetectionRadar
end
if DetectionIRST then
Params[#Params+1] = DetectionIRST
end
if DetectionRWR then
Params[#Params+1] = DetectionRWR
end
if DetectionDLINK then
Params[#Params+1] = DetectionDLINK
end
self:T2( { DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK } ) self:T2( { DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK } )
return self:_GetController():getDetectedTargets( DetectionVisual, DetectionOptical, DetectionRadar, DetectionIRST, DetectionRWR, DetectionDLINK ) return self:_GetController():getDetectedTargets( Params[1], Params[2], Params[3], Params[4], Params[5], Params[6] )
end end
return nil return nil
@ -3447,3 +3469,20 @@ function CONTROLLABLE:IsAirPlane()
return nil return nil
end end
--- Returns if the Controllable contains Helicopters.
-- @param #CONTROLLABLE self
-- @return #boolean true if Controllable contains Helicopters.
function CONTROLLABLE:IsHelicopter()
self:F2()
local DCSObject = self:GetDCSObject()
if DCSObject then
local Category = DCSObject:getDesc().category
return Category == Unit.Category.HELICOPTER
end
return nil
end