AI_PATROL:
- Target unit is nil. Issue #1234
DETECTION:
- ReportFriendliesNearBy ForEachPlayer added nil check.
CONTROLLABLE:
- Added IsHelicopter()
- Added OptionRestrictBurner()
AI_A2A_Cap
- AtteckUnit not nil check.
AI_A2A_Dispatcher:
- DefenderGroup not nil and alive check #1228
AI_A2A_GCICAP:
- AttackCoordinate nil check
This commit is contained in:
Frank 2019-11-25 11:50:07 +01:00
parent 60042e14dc
commit 169c5a674c
5 changed files with 160 additions and 88 deletions

View File

@ -200,8 +200,7 @@ function AI_A2A_CAP:CreateAttackUnitTasks( AttackSetUnit, DefenderGroup, EngageA
for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do for AttackUnitID, AttackUnit in pairs( self.AttackSetUnit:GetSet() ) do
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } ) if AttackUnit and AttackUnit:IsAlive() and AttackUnit:IsAir() then
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition() -- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
-- Maybe the detected set also contains -- Maybe the detected set also contains
self:T( { "Attacking Task:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } ) self:T( { "Attacking Task:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )

View File

@ -3231,65 +3231,73 @@ do -- AI_A2A_DISPATCHER
self:SetDefenderTask( SquadronName, DefenderCAP, "CAP", AI_A2A_Fsm ) self:SetDefenderTask( SquadronName, DefenderCAP, "CAP", AI_A2A_Fsm )
function AI_A2A_Fsm:onafterTakeoff( DefenderGroup, From, Event, To ) function AI_A2A_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
self:F({"CAP Takeoff", DefenderGroup:GetName()}) -- Issue GetCallsign() returns nil, see https://github.com/FlightControl-Master/MOOSE/issues/1228
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To ) if DefenderGroup and DefenderGroup:IsAlive() then
self:F({"CAP Takeoff", DefenderGroup:GetName()})
local DefenderName = DefenderGroup:GetCallsign() --self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
local Dispatcher = AI_A2A_Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup ) local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = AI_A2A_Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
if Squadron then local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " Wheels up.", DefenderGroup )
AI_A2A_Fsm:__Patrol( 2 ) -- Start Patrolling if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " Wheels up.", DefenderGroup )
AI_A2A_Fsm:__Patrol( 2 ) -- Start Patrolling
end
end end
end end
function AI_A2A_Fsm:onafterPatrolRoute( DefenderGroup, From, Event, To ) function AI_A2A_Fsm:onafterPatrolRoute( DefenderGroup, From, Event, To )
self:F({"CAP PatrolRoute", DefenderGroup:GetName()}) if DefenderGroup and DefenderGroup:IsAlive() then
self:GetParent(self).onafterPatrolRoute( self, DefenderGroup, From, Event, To ) self:F({"CAP PatrolRoute", DefenderGroup:GetName()})
self:GetParent(self).onafterPatrolRoute( self, DefenderGroup, From, Event, To )
local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER local DefenderName = DefenderGroup:GetCallsign()
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup ) local Dispatcher = self:GetDispatcher() -- #AI_A2G_DISPATCHER
if Squadron then local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", patrolling.", DefenderGroup ) if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", patrolling.", DefenderGroup )
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end end
function AI_A2A_Fsm:onafterRTB( DefenderGroup, From, Event, To ) function AI_A2A_Fsm:onafterRTB( DefenderGroup, From, Event, To )
if DefenderGroup and DefenderGroup:IsAlive() then
self:F({"CAP RTB", DefenderGroup:GetName()}) self:F({"CAP RTB", DefenderGroup:GetName()})
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To ) self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
local DefenderName = DefenderGroup:GetCallsign() local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup ) local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup ) Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end end
--- @param #AI_A2A_DISPATCHER self --- @param #AI_A2A_DISPATCHER self
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action ) function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
self:F({"CAP Home", Defender:GetName()}) if Defender and Defender:IsAlive() then
self:GetParent(self).onafterHome( self, Defender, From, Event, To ) self:F({"CAP Home", Defender:GetName()})
self:GetParent(self).onafterHome( self, Defender, From, Event, To )
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( Defender ) local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( Defender )
if Action and Action == "Destroy" then
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender ) if Action and Action == "Destroy" then
Defender:Destroy() Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
end Defender:Destroy()
end
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender ) if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
Defender:Destroy() Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
Dispatcher:ParkDefender( Squadron ) Defender:Destroy()
Dispatcher:ParkDefender( Squadron )
end
end end
end end
end end
@ -3636,22 +3644,31 @@ do -- AI_A2A_DISPATCHER
--- Assigns A2G AI Tasks in relation to the detected items. --- Assigns A2G AI Tasks in relation to the detected items.
-- @param #AI_A2G_DISPATCHER self -- @param #AI_A2G_DISPATCHER self
function AI_A2A_DISPATCHER:Order( DetectedItem ) function AI_A2A_DISPATCHER:Order( DetectedItem )
local AttackCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem )
local detection=self.Detection -- Functional.Detection#DETECTION_AREAS
local ShortestDistance = 999999999 local ShortestDistance = 999999999
-- Get coordinate (or nil).
local AttackCoordinate = detection:GetDetectedItemCoordinate( DetectedItem )
-- Issue https://github.com/FlightControl-Master/MOOSE/issues/1232
if AttackCoordinate then
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
self:I( { DefenderSquadron = DefenderSquadron.Name } )
local Airbase = DefenderSquadron.Airbase
local AirbaseCoordinate = Airbase:GetCoordinate()
local EvaluateDistance = AttackCoordinate:Get2DDistance( AirbaseCoordinate )
if EvaluateDistance <= ShortestDistance then self:I( { DefenderSquadron = DefenderSquadron.Name } )
ShortestDistance = EvaluateDistance
local Airbase = DefenderSquadron.Airbase
local AirbaseCoordinate = Airbase:GetCoordinate()
local EvaluateDistance = AttackCoordinate:Get2DDistance( AirbaseCoordinate )
if EvaluateDistance <= ShortestDistance then
ShortestDistance = EvaluateDistance
end
end end
end end
return ShortestDistance return ShortestDistance
@ -3660,6 +3677,7 @@ do -- AI_A2A_DISPATCHER
--- Shows the tactical display. --- Shows the tactical display.
-- @param #AI_A2A_DISPATCHER self -- @param #AI_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Functional.Detection#DETECTION_BASE} derived object.
function AI_A2A_DISPATCHER:ShowTacticalDisplay( Detection ) function AI_A2A_DISPATCHER:ShowTacticalDisplay( Detection )
local AreaMsg = {} local AreaMsg = {}

View File

@ -667,21 +667,27 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then if TargetObject and TargetObject:isExist() and TargetObject.id_ < 50000000 then
local TargetUnit = UNIT:Find( TargetObject ) local TargetUnit = UNIT:Find( TargetObject )
local TargetUnitName = TargetUnit:GetName()
if self.DetectionZone then -- Check that target is alive due to issue https://github.com/FlightControl-Master/MOOSE/issues/1234
if TargetUnit:IsInZone( self.DetectionZone ) then if TargetUnit and TargetUnit:IsAlive() then
self:T( {"Detected ", TargetUnit } )
local TargetUnitName = TargetUnit:GetName()
if self.DetectionZone then
if TargetUnit:IsInZone( self.DetectionZone ) then
self:T( {"Detected ", TargetUnit } )
if self.DetectedUnits[TargetUnit] == nil then
self.DetectedUnits[TargetUnit] = true
end
Detected = true
end
else
if self.DetectedUnits[TargetUnit] == nil then if self.DetectedUnits[TargetUnit] == nil then
self.DetectedUnits[TargetUnit] = true self.DetectedUnits[TargetUnit] = true
end end
Detected = true Detected = true
end end
else
if self.DetectedUnits[TargetUnit] == nil then
self.DetectedUnits[TargetUnit] = true
end
Detected = true
end end
end end
end end

View File

@ -1438,27 +1438,31 @@ do -- DETECTION_BASE
function( PlayerUnitName ) function( PlayerUnitName )
local PlayerUnit = UNIT:FindByName( PlayerUnitName ) local PlayerUnit = UNIT:FindByName( PlayerUnitName )
if PlayerUnit and PlayerUnit:GetCoordinate():IsInRadius( DetectedUnitCoord, self.FriendliesRange ) then -- Fix for issue https://github.com/FlightControl-Master/MOOSE/issues/1225
--if PlayerUnit and PlayerUnit:IsInZone(DetectionZone) then if PlayerUnit and PlayerUnit:IsAlive() then
local coord=PlayerUnit:GetCoordinate()
if coord and coord:IsInRadius( DetectedUnitCoord, self.FriendliesRange ) then
local PlayerUnitCategory = PlayerUnit:GetDesc().category local PlayerUnitCategory = PlayerUnit:GetDesc().category
if ( not self.FriendliesCategory ) or ( self.FriendliesCategory and ( self.FriendliesCategory == PlayerUnitCategory ) ) then
local PlayerUnitName = PlayerUnit:GetName()
DetectedItem.PlayersNearBy = DetectedItem.PlayersNearBy or {} if ( not self.FriendliesCategory ) or ( self.FriendliesCategory and ( self.FriendliesCategory == PlayerUnitCategory ) ) then
DetectedItem.PlayersNearBy[PlayerUnitName] = PlayerUnit
local PlayerUnitName = PlayerUnit:GetName()
-- Friendlies are sorted per unit category.
DetectedItem.FriendliesNearBy = DetectedItem.FriendliesNearBy or {} DetectedItem.PlayersNearBy = DetectedItem.PlayersNearBy or {}
DetectedItem.FriendliesNearBy[PlayerUnitCategory] = DetectedItem.FriendliesNearBy[PlayerUnitCategory] or {} DetectedItem.PlayersNearBy[PlayerUnitName] = PlayerUnit
DetectedItem.FriendliesNearBy[PlayerUnitCategory][PlayerUnitName] = PlayerUnit
-- Friendlies are sorted per unit category.
local Distance = DetectedUnitCoord:Get2DDistance( PlayerUnit:GetCoordinate() ) DetectedItem.FriendliesNearBy = DetectedItem.FriendliesNearBy or {}
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {} DetectedItem.FriendliesNearBy[PlayerUnitCategory] = DetectedItem.FriendliesNearBy[PlayerUnitCategory] or {}
DetectedItem.FriendliesDistance[Distance] = PlayerUnit DetectedItem.FriendliesNearBy[PlayerUnitCategory][PlayerUnitName] = PlayerUnit
local Distance = DetectedUnitCoord:Get2DDistance( PlayerUnit:GetCoordinate() )
DetectedItem.FriendliesDistance = DetectedItem.FriendliesDistance or {}
DetectedItem.FriendliesDistance[Distance] = PlayerUnit
end
end end
end end
end end

View File

@ -3480,3 +3480,48 @@ 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
--- Sets Controllable Option for Restriction of Afterburner.
-- @param #CONTROLLABLE self
-- @param #boolean RestrictBurner If true, restrict burner. If false or nil, allow (unrestrict) burner.
function CONTROLLABLE:OptionRestrictBurner(RestrictBurner)
self:F2({self.ControllableName})
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local Controller = self:_GetController()
if Controller then
-- Issue https://github.com/FlightControl-Master/MOOSE/issues/1216
if RestrictBurner == true then
if self:IsAir() then
Controller:setOption(16, true)
end
else
if self:IsAir() then
Controller:setOption(16, false)
end
end
end
end
end