diff --git a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua index e0484ee64..498c7a574 100644 --- a/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_A2G_Dispatcher.lua @@ -3511,7 +3511,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender Birth", Defender:GetName()}) --self:GetParent(self).onafterBirth( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) @@ -3525,7 +3525,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender PatrolRoute", Defender:GetName()}) self:GetParent(self).onafterPatrolRoute( self, Defender, From, Event, To, AttackSetUnit ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) if Squadron then @@ -3539,7 +3539,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender RTB", Defender:GetName()}) self:GetParent(self).onafterRTB( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " returning." ) @@ -3552,7 +3552,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender LostControl", Defender:GetName()}) self:GetParent(self).onafterHome( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " lost control." ) @@ -3567,7 +3567,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender Home", Defender:GetName()}) self:GetParent(self).onafterHome( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " landing." ) @@ -3619,7 +3619,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender Birth", Defender:GetName()}) --self:GetParent(self).onafterBirth( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) local DefenderTarget = Dispatcher:GetDefenderTaskTarget( Defender ) @@ -3636,7 +3636,7 @@ do -- AI_A2G_DISPATCHER self:F({"Engage Route", Defender:GetName()}) self:GetParent(self).onafterEngageRoute( self, Defender, From, Event, To, AttackSetUnit ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) @@ -3652,7 +3652,7 @@ do -- AI_A2G_DISPATCHER self:F({"Engage Route", Defender:GetName()}) --self:GetParent(self).onafterBirth( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) local FirstUnit = AttackSetUnit:GetFirst() @@ -3666,7 +3666,7 @@ do -- AI_A2G_DISPATCHER function Fsm:onafterRTB( Defender, From, Event, To ) self:F({"Defender RTB", Defender:GetName()}) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " RTB." ) @@ -3681,7 +3681,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender LostControl", Defender:GetName()}) self:GetParent(self).onafterHome( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = Fsm:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " lost control." ) @@ -3697,7 +3697,7 @@ do -- AI_A2G_DISPATCHER self:F({"Defender Home", Defender:GetName()}) self:GetParent(self).onafterHome( self, Defender, From, Event, To ) - local DefenderName = Defender:GetName() + local DefenderName = Defender:GetCallsign() local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) Dispatcher:MessageToPlayers( "Squadron " .. Squadron.Name .. ", " .. DefenderName .. " landing." ) @@ -4056,6 +4056,7 @@ do -- AI_A2G_DISPATCHER local TaskReport = REPORT:New() + local DefenseTotal = 0 for DefenderGroup, DefenderTask in pairs( self:GetDefenderTasks() ) do local DefenderGroup = DefenderGroup -- Wrapper.Group#GROUP @@ -4089,12 +4090,15 @@ do -- AI_A2G_DISPATCHER end end +-- for DefenderGroup, DefenderTask in pairs( self:GetDefenderTasks() ) do +-- DefenseTotal = DefenseTotal + 1 +-- end + local Report = REPORT:New( "\nTactical Overview" ) local DefenderGroupCount = 0 local DefendersTotal = 0 - local DefenseTotal = 0 -- Now that all obsolete tasks are removed, loop through the detected targets. --for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do @@ -4149,7 +4153,10 @@ do -- AI_A2G_DISPATCHER end end - if EngageCoordinate and ( ( self.DefenseLimit and DefenseTotal < self.DefenseLimit ) or true ) then + -- There needs to be an EngageCoordinate. + -- If self.DefenseLimit is set (thus limit the amount of defenses to one zone), then only start a new defense if the maximum has not been reached. + -- If self.DefenseLimit has not been set, there is an unlimited amount of zones to be defended. + if ( EngageCoordinate and ( self.DefenseLimit and DefenseTotal < self.DefenseLimit ) or not self.DefenseLimit ) then do local DefendersTotal, DefendersEngaged, DefendersMissing, Friendlies = self:Evaluate_SEAD( DetectedItem ) -- Returns a SET_UNIT with the SEAD targets to be engaged... if DefendersMissing > 0 then diff --git a/Moose Development/Moose/AI/AI_Escort.lua b/Moose Development/Moose/AI/AI_Escort.lua index 254af3768..c7e9645f7 100644 --- a/Moose Development/Moose/AI/AI_Escort.lua +++ b/Moose Development/Moose/AI/AI_Escort.lua @@ -224,7 +224,6 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) self.PlayerGroup = self.FollowUnit:GetGroup() -- Wrapper.Group#GROUP self.EscortName = EscortName - self.EscortGroupSet = EscortGroupSet self.EscortGroupSet:SetSomeIteratorLimit( 8 ) @@ -266,7 +265,9 @@ function AI_ESCORT:New( EscortUnit, EscortGroupSet, EscortName, EscortBriefing ) end end ) - + + self:SetFlightReportType( self.__Enum.ReportType.All ) + return self end @@ -293,6 +294,7 @@ function AI_ESCORT:_InitFlightMenus() self:SetFlightMenuROT() self:SetFlightMenuTargets() + self:SetFlightMenuReportType() end @@ -357,6 +359,8 @@ function AI_ESCORT:onafterStart( EscortGroupSet ) self.Detection:InitDetectOptical( true ) self.Detection:InitDetectRadar( true ) self.Detection:InitDetectRWR( true ) + + self.Detection:SetAcceptRange( 100000 ) self.Detection:__Start( 30 ) @@ -1115,20 +1119,57 @@ function AI_ESCORT:MenuSmoke( MenuTextFormat ) return self 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() + local FlightMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", self.FlightMenu ) + + -- Report Targets + local FlightMenuReportTargetsNow = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets now!", FlightMenuReportTargets, AI_ESCORT._FlightReportNearbyTargetsNow, self ) + local FlightMenuReportTargetsOn = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets on", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportNearbyTargets, self, true ) + local FlightMenuReportTargetsOff = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets off", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportNearbyTargets, self, false ) + + -- Attack Targets + 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 - local FlightMenuReportTargets = MENU_GROUP:New( self.PlayerGroup, "Report targets", self.FlightMenu ) - - -- Report Targets - local FlightMenuReportTargetsNow = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets now!", FlightMenuReportTargets, AI_ESCORT._FlightReportNearbyTargetsNow, self ) - local FlightMenuReportTargetsOn = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets on", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportNearbyTargets, self, true ) - local FlightMenuReportTargetsOff = MENU_GROUP_COMMAND:New( self.PlayerGroup, "Report targets off", FlightMenuReportTargets, AI_ESCORT._FlightSwitchReportNearbyTargets, self, false ) - - -- Attack Targets - local FlightMenuAttackNearbyTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", self.FlightMenu ) - MenuTargets.FlightReportTargetsScheduler = SCHEDULER:New( self, self._FlightReportTargetsScheduler, {}, MenuTargets.Interval, MenuTargets.Interval ) end @@ -1542,22 +1583,6 @@ function AI_ESCORT:_FlightReportNearbyTargetsNow() 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 ) @@ -1565,13 +1590,65 @@ function AI_ESCORT:_FlightSwitchReportNearbyTargets( ReportTargets ) --- @param Core.Group#GROUP EscortGroup function( EscortGroup ) if EscortGroup:IsAir() then - self:_SwitchReportNearbyTargets( EscortGroup, ReportTargets ) + self:_EscortSwitchReportNearbyTargets( EscortGroup, ReportTargets ) 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 ) @@ -1706,7 +1783,12 @@ function AI_ESCORT:_AttackTarget( EscortGroup, DetectedItem ) end - EscortGroup:MessageTypeToGroup( "Engaging Target!", MESSAGE.Type.Information, self.PlayerGroup ) + local DetectedTargetsReport = REPORT:New( "Engaging target:\n" ) + local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, self.PlayerGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) + local ReportSummary = DetectedItemReportSummary:Text(", ") + DetectedTargetsReport:AddIndent( ReportSummary, "-" ) + + EscortGroup:MessageTypeToGroup( DetectedTargetsReport:Text(), MESSAGE.Type.Information, self.PlayerGroup ) end @@ -1724,6 +1806,41 @@ function AI_ESCORT:_FlightAttackTarget( DetectedItem ) end +function AI_ESCORT:_FlightAttackNearestTarget( TargetType ) + + self.Detection:Detect() + self:_FlightReportTargetsScheduler() + + local EscortGroup = self.EscortGroupSet:GetFirst() + 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 ) + else + EscortGroup:MessageTypeToGroup( "Nothing to attack!", MESSAGE.Type.Information, self.PlayerGroup ) + end + +end + + --- --- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP EscortGroup The escort group that will attack the detected item. @@ -1884,6 +2001,17 @@ function AI_ESCORT:_ResumeScheduler( EscortGroup ) 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. -- @param #AI_ESCORT self -- @param Wrapper.Group#GROUP EscortGroup @@ -1910,40 +2038,56 @@ function AI_ESCORT:_ReportTargetsScheduler( EscortGroup, Report ) local EscortMenuAttackTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", EscortGroup.EscortMenu ) local DetectedTargets = false - for DetectedItemIndex, DetectedItem in pairs( DetectedItems ) do - DetectedTargets = true + + 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 DetectedMenu = self.Detection:DetectedItemReportMenu( DetectedItem, EscortGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ):Text("\n") - - local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, EscortGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) - local ReportSummary = DetectedItemReportSummary:Text(", ") - DetectedTargetsReport:AddIndent( ReportSummary, "-" ) + local DetectedItemSet = self.Detection:GetDetectedItemSet( DetectedItem ) - if EscortGroup:IsAir() then + local HasGround = DetectedItemSet:HasGroundUnits() > 0 + local HasGroundRadar = HasGround and DetectedItemSet:HasRadar() > 0 + local HasAir = DetectedItemSet:HasAirUnits() > 0 + + local FlightReportType = self:GetFlightReportType() + - MENU_GROUP_COMMAND:New( self.PlayerGroup, - DetectedMenu, - EscortMenuAttackTargets, - AI_ESCORT._AttackTarget, - self, - EscortGroup, - DetectedItem - ):SetTag( "Escort" ):SetTime( TimeUpdate ) - else - if self.EscortMenuTargetAssistance then - local MenuTargetAssistance = MENU_GROUP:New( self.PlayerGroup, EscortGroupName, EscortGroup.EscortMenuTargetAssistance ) + 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 + + local DetectedMenu = self.Detection:DetectedItemReportMenu( DetectedItem, EscortGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ):Text("\n") + + local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, EscortGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) + local ReportSummary = DetectedItemReportSummary:Text(", ") + DetectedTargetsReport:AddIndent( ReportSummary, "-" ) + + if EscortGroup:IsAir() then + MENU_GROUP_COMMAND:New( self.PlayerGroup, DetectedMenu, - MenuTargetAssistance, - AI_ESCORT._AssistTarget, + EscortMenuAttackTargets, + AI_ESCORT._AttackTarget, self, EscortGroup, DetectedItem - ) + ):SetTag( "Escort" ):SetTime( TimeUpdate ) + else + if self.EscortMenuTargetAssistance then + local MenuTargetAssistance = MENU_GROUP:New( self.PlayerGroup, EscortGroupName, EscortGroup.EscortMenuTargetAssistance ) + MENU_GROUP_COMMAND:New( self.PlayerGroup, + DetectedMenu, + MenuTargetAssistance, + AI_ESCORT._AssistTarget, + self, + EscortGroup, + DetectedItem + ) + end end - end - end EscortMenuAttackTargets:RemoveSubMenus( TimeUpdate, "Escort" ) @@ -1975,43 +2119,53 @@ function AI_ESCORT:_FlightReportTargetsScheduler() if EscortGroup and ( self.PlayerUnit:IsAlive() and EscortGroup:IsAlive() ) then - local ClientGroup = self.PlayerGroup - local TimeUpdate = timer.getTime() - local DetectedItems = self.Detection:GetDetectedItems() local DetectedTargets = false local ClientEscortTargets = self.Detection - local FlightMenuAttackTargets = MENU_GROUP:New( self.PlayerGroup, "Attack targets", self.FlightMenu ) - - 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 self:F("FlightReportTargetScheduler Targets") - - DetectedTargets = true -- There are detected targets, when the content of the for loop is executed. We use it to display a message. + local DetectedItemSet = self.Detection:GetDetectedItemSet( DetectedItem ) - local DetectedItemReportMenu = self.Detection:DetectedItemReportMenu( DetectedItem, ClientGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) - local ReportMenuText = DetectedItemReportMenu:Text(", ") + local HasGround = DetectedItemSet:HasGroundUnits() > 0 + local HasGroundRadar = HasGround and DetectedItemSet:HasRadar() > 0 + local HasAir = DetectedItemSet:HasAirUnits() > 0 - MENU_GROUP_COMMAND:New( self.PlayerGroup, - ReportMenuText, - FlightMenuAttackTargets, - AI_ESCORT._FlightAttackTarget, - self, - DetectedItem - ):SetTag( "Flight" ):SetTime( TimeUpdate ) + local FlightReportType = self:GetFlightReportType() + - local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, ClientGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) - local ReportSummary = DetectedItemReportSummary:Text(", ") - DetectedTargetsReport:AddIndent( ReportSummary, "-" ) + 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. + + local DetectedItemReportMenu = self.Detection:DetectedItemReportMenu( DetectedItem, self.PlayerGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) + local ReportMenuText = DetectedItemReportMenu:Text(", ") + + MENU_GROUP_COMMAND:New( self.PlayerGroup, + ReportMenuText, + self.FlightMenuAttack, + AI_ESCORT._FlightAttackTarget, + self, + DetectedItem + ):SetTag( "Flight" ):SetTime( TimeUpdate ) + + local DetectedItemReportSummary = self.Detection:DetectedItemReportSummary( DetectedItem, self.PlayerGroup, _DATABASE:GetPlayerSettings( self.PlayerUnit:GetPlayerName() ) ) + local ReportSummary = DetectedItemReportSummary:Text(", ") + DetectedTargetsReport:AddIndent( ReportSummary, "-" ) + end end - FlightMenuAttackTargets:RemoveSubMenus( TimeUpdate, "Flight" ) + self.FlightMenuAttack:RemoveSubMenus( TimeUpdate, "Flight" ) if DetectedTargets then EscortGroup:MessageTypeToGroup( DetectedTargetsReport:Text( "\n" ), MESSAGE.Type.Information, self.PlayerGroup ) diff --git a/Moose Development/Moose/AI/AI_Formation.lua b/Moose Development/Moose/AI/AI_Formation.lua index 21482e930..2ecca0958 100644 --- a/Moose Development/Moose/AI/AI_Formation.lua +++ b/Moose Development/Moose/AI/AI_Formation.lua @@ -147,6 +147,17 @@ AI_FORMATION.__Enum.Mode = { 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", +} diff --git a/Moose Development/Moose/Core/Menu.lua b/Moose Development/Moose/Core/Menu.lua index fa7ab6a72..e968b9350 100644 --- a/Moose Development/Moose/Core/Menu.lua +++ b/Moose Development/Moose/Core/Menu.lua @@ -238,7 +238,7 @@ do -- MENU_BASE self.Path = ( self.ParentMenu and "@" .. table.concat( self.MenuParentPath or {}, "@" ) or "" ) .. "@" .. self.MenuText self.Menus = {} self.MenuCount = 0 - self.MenuTime = timer.getTime() + self.MenuStamp = timer.getTime() self.MenuRemoveParent = false if self.ParentMenu then @@ -285,13 +285,31 @@ do -- MENU_BASE function MENU_BASE:GetMenu( MenuText ) return self.Menus[MenuText] 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. -- @param #MENU_BASE self - -- @param MenuTime + -- @param MenuStamp -- @return #MENU_BASE - function MENU_BASE:SetTime( MenuTime ) - self.MenuTime = MenuTime + function MENU_BASE:SetTime( MenuStamp ) + self.MenuStamp = MenuStamp return self end @@ -443,7 +461,7 @@ do -- MENU_MISSION --- Removes the main menu and the sub menus recursively of this MENU_MISSION. -- @param #MENU_MISSION self -- @return #nil - function MENU_MISSION:Remove( MenuTime, MenuTag ) + function MENU_MISSION:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareMission() local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) @@ -451,7 +469,7 @@ do -- MENU_MISSION if MissionMenu == self then 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 self:F( { Text = self.MenuText, Path = self.MenuPath } ) if self.MenuPath ~= nil then @@ -537,7 +555,7 @@ do -- MENU_MISSION_COMMAND local MissionMenu = MENU_INDEX:HasMissionMenu( Path ) 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 self:F( { Text = self.MenuText, Path = self.MenuPath } ) 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. -- @param #MENU_COALITION self -- @return #nil - function MENU_COALITION:Remove( MenuTime, MenuTag ) + function MENU_COALITION:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareCoalition( self.Coalition ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) @@ -674,7 +692,7 @@ do -- MENU_COALITION if CoalitionMenu == self then 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 self:F( { Coalition = self.Coalition, Text = self.MenuText, Path = self.MenuPath } ) if self.MenuPath ~= nil then @@ -758,14 +776,14 @@ do -- MENU_COALITION_COMMAND --- Removes a radio command item for a coalition -- @param #MENU_COALITION_COMMAND self -- @return #nil - function MENU_COALITION_COMMAND:Remove( MenuTime, MenuTag ) + function MENU_COALITION_COMMAND:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareCoalition( self.Coalition ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local CoalitionMenu = MENU_INDEX:HasCoalitionMenu( self.Coalition, Path ) 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 self:F( { Coalition = self.Coalition, Text = self.MenuText, Path = self.MenuPath } ) if self.MenuPath ~= nil then @@ -907,13 +925,13 @@ do --- Removes the sub menus recursively of this MENU_GROUP. -- @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. -- @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 - Menu:Remove( MenuTime, MenuTag ) + Menu:Remove( MenuStamp, MenuTag ) end self.Menus = nil @@ -923,18 +941,18 @@ do --- Removes the main menu and sub menus recursively of this MENU_GROUP. -- @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. -- @return #nil - function MENU_GROUP:Remove( MenuTime, MenuTag ) + function MENU_GROUP:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareGroup( self.Group ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) if GroupMenu == self then - self:RemoveSubMenus( MenuTime, MenuTag ) - if not MenuTime or self.MenuTime ~= MenuTime then + self:RemoveSubMenus( MenuStamp, MenuTag ) + if not MenuStamp or self.MenuStamp ~= MenuStamp then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if self.MenuPath ~= nil then self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) @@ -1014,17 +1032,17 @@ do --- Removes a menu structure for a group. -- @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. -- @return #nil - function MENU_GROUP_COMMAND:Remove( MenuTime, MenuTag ) + function MENU_GROUP_COMMAND:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareGroup( self.Group ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) 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 self.MenuPath ~= nil then 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. -- @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. -- @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 - Menu:Remove( MenuTime, MenuTag ) + Menu:Remove( MenuStamp, MenuTag ) end self.Menus = nil @@ -1152,18 +1170,18 @@ do --- Removes the main menu and sub menus recursively of this MENU_GROUP. -- @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. -- @return #nil - function MENU_GROUP_DELAYED:Remove( MenuTime, MenuTag ) + function MENU_GROUP_DELAYED:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareGroup( self.Group ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) if GroupMenu == self then - self:RemoveSubMenus( MenuTime, MenuTag ) - if not MenuTime or self.MenuTime ~= MenuTime then + self:RemoveSubMenus( MenuStamp, MenuTag ) + if not MenuStamp or self.MenuStamp ~= MenuStamp then if ( not MenuTag ) or ( MenuTag and self.MenuTag and MenuTag == self.MenuTag ) then if self.MenuPath ~= nil then self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) @@ -1263,17 +1281,17 @@ do --- Removes a menu structure for a group. -- @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. -- @return #nil - function MENU_GROUP_COMMAND_DELAYED:Remove( MenuTime, MenuTag ) + function MENU_GROUP_COMMAND_DELAYED:Remove( MenuStamp, MenuTag ) MENU_INDEX:PrepareGroup( self.Group ) local Path = MENU_INDEX:ParentPath( self.ParentMenu, self.MenuText ) local GroupMenu = MENU_INDEX:HasGroupMenu( self.Group, Path ) 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 self.MenuPath ~= nil then self:F( { Group = self.GroupID, Text = self.MenuText, Path = self.MenuPath } ) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index a2e7fe2bc..a3805d9b6 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -1819,7 +1819,7 @@ do -- COORDINATE --- Returns if a Coordinate is in a certain Radius of this Coordinate in 2D plane using the X and Z axis. -- @param #COORDINATE self - -- @param #COORDINATE ToCoordinate The coordinate that will be tested if it is in the radius of this coordinate. + -- @param #COORDINATE Coordinate The coordinate that will be tested if it is in the radius of this coordinate. -- @param #number Radius The radius of the circle on the 2D plane around this coordinate. -- @return #boolean true if in the Radius. function COORDINATE:IsInRadius( Coordinate, Radius ) @@ -2065,31 +2065,32 @@ do -- COORDINATE -- @return #string The coordinate Text in the configured coordinate system. 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 ModeA2A = false - self:E('A2A false') + local ModeA2A = nil if Task then - self:E('Task ' .. Task.ClassName ) if Task:IsInstanceOf( TASK_A2A ) then ModeA2A = true - self:E('A2A true') else if Task:IsInstanceOf( TASK_A2G ) then ModeA2A = false else if Task:IsInstanceOf( TASK_CARGO ) then ModeA2A = false - else - ModeA2A = false end + if Task:IsInstanceOf( TASK_CAPTURE_ZONE ) then + ModeA2A = false + end end end - else - local IsAir = Controllable and Controllable:IsAirPlane() or false + end + + + if ModeA2A == nil then + local IsAir = Controllable and ( Controllable:IsAirPlane() or Controllable:IsHelicopter() ) or false if IsAir then ModeA2A = true else diff --git a/Moose Development/Moose/Core/Set.lua b/Moose Development/Moose/Core/Set.lua index 23b148ad3..8834dcb0b 100644 --- a/Moose Development/Moose/Core/Set.lua +++ b/Moose Development/Moose/Core/Set.lua @@ -2624,6 +2624,23 @@ do -- SET_UNIT return GroundUnitCount 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. -- @param #SET_UNIT self -- @return #number The amount of ground targets in the Set. diff --git a/Moose Development/Moose/Functional/Detection.lua b/Moose Development/Moose/Functional/Detection.lua index d711ad9b6..ac3f2923e 100644 --- a/Moose Development/Moose/Functional/Detection.lua +++ b/Moose Development/Moose/Functional/Detection.lua @@ -562,18 +562,38 @@ do -- DETECTION_BASE end -- Count alive(!) groups only. Solves issue #1173 https://github.com/FlightControl-Master/MOOSE/issues/1173 - self.DetectionCount = self.DetectionSet:CountAlive() + self.DetectionCount = self:CountAliveRecce() - self.DetectionSet:ForEachGroupAlive( + local DetectionInterval = self.DetectionCount / ( self.RefreshTimeInterval - 1 ) + + self:ForEachAliveRecce( function( DetectionGroup ) self:__Detection( DetectDelay, DetectionGroup, DetectionTimeStamp ) -- Process each detection asynchronously. - DetectDelay = DetectDelay + 1 + DetectDelay = DetectDelay + DetectionInterval end ) self:__Detect( -self.RefreshTimeInterval ) end + + --- @param #DETECTION_BASE self + -- @param #number The amount of alive recce. + function DETECTION_BASE:CountAliveRecce() + + return self.DetectionSet:CountAlive() + + end + + --- @param #DETECTION_BASE self + function DETECTION_BASE:ForEachAliveRecce( IteratorFunction, ... ) + self:F2( arg ) + + self.DetectionSet:ForEachGroupAlive( IteratorFunction, arg ) + + return self + end + --- @param #DETECTION_BASE self -- @param #string From The From State string. @@ -1412,14 +1432,14 @@ do -- DETECTION_BASE world.searchObjects( Object.Category.UNIT, SphereSearch, FindNearByFriendlies, TargetData ) DetectedItem.PlayersNearBy = nil - local DetectionZone = ZONE_UNIT:New( "DetectionPlayers", DetectedUnit, self.FriendliesRange ) _DATABASE:ForEachPlayer( --- @param Wrapper.Unit#UNIT PlayerUnit function( PlayerUnitName ) local PlayerUnit = UNIT:FindByName( PlayerUnitName ) - if PlayerUnit and PlayerUnit:IsInZone(DetectionZone) then + if PlayerUnit and PlayerUnit:GetCoordinate():IsInRadius( DetectedUnitCoord, self.FriendliesRange ) then + --if PlayerUnit and PlayerUnit:IsInZone(DetectionZone) then local PlayerUnitCategory = PlayerUnit:GetDesc().category @@ -2560,9 +2580,17 @@ do -- DETECTION_AREAS local DetectedSet = self:GetDetectedItemSet( DetectedItem ) local ReportSummaryItem - local DetectedZone = self:GetDetectedItemZone( DetectedItem ) - local DetectedItemCoordinate = DetectedZone:GetCoordinate() - local DetectedItemCoordText = DetectedItemCoordinate:ToString( AttackGroup, Settings ) + --local DetectedZone = self:GetDetectedItemZone( DetectedItem ) + local DetectedItemCoordinate = self:GetDetectedItemCoordinate( DetectedItem ) + 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 DetectedItemsCount = DetectedSet:Count() diff --git a/Moose Development/Moose/Functional/DetectionZones.lua b/Moose Development/Moose/Functional/DetectionZones.lua index c44ef9efe..a64710a15 100644 --- a/Moose Development/Moose/Functional/DetectionZones.lua +++ b/Moose Development/Moose/Functional/DetectionZones.lua @@ -44,15 +44,15 @@ do -- DETECTION_ZONES --- DETECTION_ZONES constructor. -- @param #DETECTION_ZONES self - -- @param Core.Set#SET_ZONE_RADIUS DetectionSetZone The @{Set} of ZONE_RADIUS. + -- @param Core.Set#SET_ZONE DetectionSetZone The @{Set} of ZONE_RADIUS. -- @param DCS#Coalition.side DetectionCoalition The coalition of the detection. -- @return #DETECTION_ZONES function DETECTION_ZONES:New( DetectionSetZone, DetectionCoalition ) -- Inherits from DETECTION_BASE - local self = BASE:Inherit( self, DETECTION_BASE:New( DetectionSetZone ) ) + local self = BASE:Inherit( self, DETECTION_BASE:New( DetectionSetZone ) ) -- #DETECTION_ZONES - self.DetectionSetZone = DetectionSetZone + self.DetectionSetZone = DetectionSetZone -- Core.Set#SET_ZONE self.DetectionCoalition = DetectionCoalition self._SmokeDetectedUnits = false @@ -64,6 +64,22 @@ do -- DETECTION_ZONES return self end + --- @param #DETECTION_ZONES self + -- @param #number The amount of alive recce. + function DETECTION_ZONES:CountAliveRecce() + + return self.DetectionSetZone:Count() + + end + + --- @param #DETECTION_ZONES self + function DETECTION_ZONES:ForEachAliveRecce( IteratorFunction, ... ) + self:F2( arg ) + + self.DetectionSetZone:ForEachZone( IteratorFunction, arg ) + + return self + end --- Report summary of a detected item using a given numeric index. -- @param #DETECTION_ZONES self @@ -379,7 +395,7 @@ do -- DETECTION_ZONES self:__DetectedItem( 0.1, DetectedItem ) end end - self:__Detect( self.RefreshTimeInterval ) + self:__Detect( -self.RefreshTimeInterval ) end end @@ -396,7 +412,5 @@ do -- DETECTION_ZONES return IsDetected end - - end \ No newline at end of file diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 3b322abac..d23d00070 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -2798,9 +2798,31 @@ function CONTROLLABLE:GetDetectedTargets( DetectVisual, DetectOptical, DetectRad 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 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 } ) - 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 return nil @@ -3447,3 +3469,20 @@ function CONTROLLABLE:IsAirPlane() return nil 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 + diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 7f5bdd17f..db8283a64 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -63,7 +63,7 @@ POSITIONABLE.__.Cargo = {} -- @param #string PositionableName The POSITIONABLE name -- @return #POSITIONABLE self function POSITIONABLE:New( PositionableName ) - local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) ) + local self = BASE:Inherit( self, IDENTIFIABLE:New( PositionableName ) ) -- #POSITIONABLE self.PositionableName = PositionableName return self