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
local AttackUnit = AttackUnit -- Wrapper.Unit#UNIT
self:T( { "Attacking Unit:", AttackUnit:GetName(), AttackUnit:IsAlive(), AttackUnit:IsAir() } )
if AttackUnit:IsAlive() and AttackUnit:IsAir() then
if AttackUnit and AttackUnit:IsAlive() and AttackUnit:IsAir() then
-- TODO: Add coalition check? Only attack units of if AttackUnit:GetCoalition()~=AICap:GetCoalition()
-- Maybe the detected set also contains
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 )
function AI_A2A_Fsm:onafterTakeoff( DefenderGroup, From, Event, To )
self:F({"CAP Takeoff", DefenderGroup:GetName()})
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = AI_A2A_Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " Wheels up.", DefenderGroup )
AI_A2A_Fsm:__Patrol( 2 ) -- Start Patrolling
-- Issue GetCallsign() returns nil, see https://github.com/FlightControl-Master/MOOSE/issues/1228
if DefenderGroup and DefenderGroup:IsAlive() then
self:F({"CAP Takeoff", DefenderGroup:GetName()})
--self:GetParent(self).onafterBirth( self, Defender, From, Event, To )
local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = AI_A2A_Fsm:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " Wheels up.", DefenderGroup )
AI_A2A_Fsm:__Patrol( 2 ) -- Start Patrolling
end
end
end
function AI_A2A_Fsm:onafterPatrolRoute( 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 Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", patrolling.", DefenderGroup )
if DefenderGroup and DefenderGroup:IsAlive() then
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 Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. ", patrolling.", DefenderGroup )
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end
function AI_A2A_Fsm:onafterRTB( DefenderGroup, From, Event, To )
self:F({"CAP RTB", DefenderGroup:GetName()})
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
if DefenderGroup and DefenderGroup:IsAlive() then
self:F({"CAP RTB", DefenderGroup:GetName()})
self:GetParent(self).onafterRTB( self, DefenderGroup, From, Event, To )
local DefenderName = DefenderGroup:GetCallsign()
local Dispatcher = self:GetDispatcher() -- #AI_A2A_DISPATCHER
local Squadron = Dispatcher:GetSquadronFromDefender( DefenderGroup )
if Squadron then
Dispatcher:MessageToPlayers( Squadron, DefenderName .. " returning to base.", DefenderGroup )
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end
Dispatcher:ClearDefenderTaskTarget( DefenderGroup )
end
--- @param #AI_A2A_DISPATCHER self
function AI_A2A_Fsm:onafterHome( Defender, From, Event, To, Action )
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 )
if Action and Action == "Destroy" then
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
Defender:Destroy()
end
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
Defender:Destroy()
Dispatcher:ParkDefender( Squadron )
if Defender and Defender:IsAlive() then
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 )
if Action and Action == "Destroy" then
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
Defender:Destroy()
end
if Dispatcher:GetSquadronLanding( Squadron.Name ) == AI_A2A_DISPATCHER.Landing.NearAirbase then
Dispatcher:RemoveDefenderFromSquadron( Squadron, Defender )
Defender:Destroy()
Dispatcher:ParkDefender( Squadron )
end
end
end
end
@ -3636,22 +3644,31 @@ do -- AI_A2A_DISPATCHER
--- Assigns A2G AI Tasks in relation to the detected items.
-- @param #AI_A2G_DISPATCHER self
function AI_A2A_DISPATCHER:Order( DetectedItem )
local AttackCoordinate = self.Detection:GetDetectedItemCoordinate( DetectedItem )
local detection=self.Detection -- Functional.Detection#DETECTION_AREAS
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
self:I( { DefenderSquadron = DefenderSquadron.Name } )
local Airbase = DefenderSquadron.Airbase
local AirbaseCoordinate = Airbase:GetCoordinate()
local EvaluateDistance = AttackCoordinate:Get2DDistance( AirbaseCoordinate )
for DefenderSquadronName, DefenderSquadron in pairs( self.DefenderSquadrons ) do
if EvaluateDistance <= ShortestDistance then
ShortestDistance = EvaluateDistance
self:I( { DefenderSquadron = DefenderSquadron.Name } )
local Airbase = DefenderSquadron.Airbase
local AirbaseCoordinate = Airbase:GetCoordinate()
local EvaluateDistance = AttackCoordinate:Get2DDistance( AirbaseCoordinate )
if EvaluateDistance <= ShortestDistance then
ShortestDistance = EvaluateDistance
end
end
end
return ShortestDistance
@ -3660,6 +3677,7 @@ do -- AI_A2A_DISPATCHER
--- Shows the tactical display.
-- @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 )
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
local TargetUnit = UNIT:Find( TargetObject )
local TargetUnitName = TargetUnit:GetName()
if self.DetectionZone then
if TargetUnit:IsInZone( self.DetectionZone ) then
self:T( {"Detected ", TargetUnit } )
-- Check that target is alive due to issue https://github.com/FlightControl-Master/MOOSE/issues/1234
if TargetUnit and TargetUnit:IsAlive() then
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
self.DetectedUnits[TargetUnit] = true
end
Detected = true
Detected = true
end
else
if self.DetectedUnits[TargetUnit] == nil then
self.DetectedUnits[TargetUnit] = true
end
Detected = true
end
end
end

View File

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

View File

@ -3480,3 +3480,48 @@ 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
--- 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