Fixed AI_CAP

-- ROE fine tuned.
-- Detection events cross firing and exploding...
-- Crash, Ejected, PilotDead is detected, makes the FSM stop.
-- FSM bug fixed. There was an issue with the onbefore and onleave
events returning false, which did not stop the transition! Fixed now.
-- Event calling can return errors, and these must be logged correctly
-> xpcall implemented.
-- Added help from moose club members as a reference in the
documentation. -> delta99 en whisper.
-- ...
This commit is contained in:
FlightControl
2017-01-19 19:51:37 +01:00
parent b52dd7cf57
commit 15fdb0fd45
83 changed files with 613 additions and 326 deletions

View File

@@ -1,5 +1,5 @@
env.info( '*** MOOSE STATIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170117_1202' )
env.info( 'Moose Generation Timestamp: 20170119_1944' )
local base = _G
Include = {}
@@ -4878,6 +4878,16 @@ end
-- @param #EVENTDATA Event
function EVENT:onEvent( Event )
local ErrorHandler = function( errmsg )
env.info( "Error in SCHEDULER function:" .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
if self and self.Events and self.Events[Event.id] then
if Event.initiator and Event.initiator:getCategory() == Object.Category.UNIT then
Event.IniDCSUnit = Event.initiator
@@ -4919,14 +4929,16 @@ function EVENT:onEvent( Event )
-- If the EventData is for a UNIT, the call directly the EventClass EventFunction for that UNIT.
if Event.IniDCSUnitName and EventData.IniUnit and EventData.IniUnit[Event.IniDCSUnitName] then
self:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID(), ", Unit ", Event.IniUnitName } )
EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event )
local Result, Value = xpcall( function() return EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event ) end, ErrorHandler )
--EventData.IniUnit[Event.IniDCSUnitName].EventFunction( EventData.IniUnit[Event.IniDCSUnitName].EventClass, Event )
else
-- If the EventData is not bound to a specific unit, then call the EventClass EventFunction.
-- Note that here the EventFunction will need to implement and determine the logic for the relevant source- or target unit, or weapon.
if Event.IniDCSUnit and not EventData.IniUnit then
if EventClass == EventData.EventClass then
self:T( { "Calling EventFunction for Class ", EventClass:GetClassNameAndID() } )
EventData.EventFunction( EventData.EventClass, Event )
local Result, Value = xpcall( function() return EventData.EventFunction( EventData.EventClass, Event ) end, ErrorHandler )
--EventData.EventFunction( EventData.EventClass, Event )
end
end
end
@@ -11243,7 +11255,8 @@ do -- FSM
function FSM:_call_handler(handler, params)
if self[handler] then
self:E( "Calling " .. handler )
return self[handler]( self, unpack(params) )
local Value = self[handler]( self, unpack(params) )
return Value
end
end
@@ -11265,10 +11278,11 @@ do -- FSM
self:E( "FSM Transition:" .. self.current .. " --> " .. EventName .. " --> " .. to )
end
if self:_call_handler("onbefore" .. EventName, params) == false
or self:_call_handler("OnBefore" .. EventName, params) == false
or self:_call_handler("onleave" .. from, params) == false
or self:_call_handler("OnLeave" .. from, params) == false then
if ( self:_call_handler("onbefore" .. EventName, params) == false )
or ( self:_call_handler("OnBefore" .. EventName, params) == false )
or ( self:_call_handler("onleave" .. from, params) == false )
or ( self:_call_handler("OnLeave" .. from, params) == false ) then
self:E( "Cancel Transition" )
return false
end
@@ -11460,7 +11474,8 @@ do -- FSM_CONTROLLABLE
if self[handler] then
self:F3( "Calling " .. handler )
return xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler )
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, unpack( params ) ) end, ErrorHandler )
return Value
--return self[handler]( self, self.Controllable, unpack( params ) )
end
end
@@ -13483,8 +13498,8 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount )
}
if AmmoCount then
DCSTask.params.expendQty = AmmoCount
DCSTask.params.expendQtyEnabled = true
DCSTask.params.expendQty = AmmoCount
DCSTask.params.expendQtyEnabled = true
end
self:T3( { DCSTask } )
@@ -24679,7 +24694,7 @@ end
--
-- ![Process](..\Presentations\AI_Patrol\Dia3.JPG)
--
-- The AI_PATROL_ZONE is assigned a @(Group) and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
-- The AI_PATROL_ZONE is assigned a @{Group} and this must be done before the AI_PATROL_ZONE process can be started using the **Start** event.
--
-- ![Process](..\Presentations\AI_Patrol\Dia4.JPG)
--
@@ -25070,6 +25085,10 @@ function AI_PATROL_ZONE:New( PatrolZone, PatrolFloorAltitude, PatrolCeilingAltit
self:AddTransition( "*", "Reset", "Patrolling" ) -- FSM_CONTROLLABLE Transition for type #AI_PATROL_ZONE.
self:AddTransition( "*", "Eject", "Ejected" )
self:AddTransition( "*", "Crash", "Crashed" )
self:AddTransition( "*", "PilotDead", "PilotDead" )
return self
end
@@ -25111,7 +25130,7 @@ end
function AI_PATROL_ZONE:SetDetectionOn()
self:F2()
self.DetectUnits = true
self.DetectOn = true
end
--- Set the detection off. The AI will NOT detect for targets.
@@ -25121,7 +25140,35 @@ end
function AI_PATROL_ZONE:SetDetectionOff()
self:F2()
self.DetectUnits = false
self.DetectOn = false
end
--- Set the status checking off.
-- @param #AI_PATROL_ZONE self
-- @return #AI_PATROL_ZONE self
function AI_PATROL_ZONE:SetStatusOff()
self:F2()
self.CheckStatus = false
end
--- Activate the detection. The AI will detect for targets if the Detection is switched On.
-- @param #AI_PATROL_ZONE self
-- @return #AI_PATROL_ZONE self
function AI_PATROL_ZONE:SetDetectionActivated()
self:F2()
self.DetectActivated = true
self:__Detect( self.DetectInterval )
end
--- Deactivate the detection. The AI will NOT detect for targets.
-- @param #AI_PATROL_ZONE self
-- @return #AI_PATROL_ZONE self
function AI_PATROL_ZONE:SetDetectionDeactivated()
self:F2()
self.DetectActivated = false
end
--- Set the interval in seconds between each detection executed by the AI.
@@ -25164,7 +25211,7 @@ end
function AI_PATROL_ZONE:GetDetectedUnits()
self:F2()
return self.DetectedUnits
return self.DetectedUnits
end
@@ -25212,13 +25259,18 @@ end
function AI_PATROL_ZONE:onafterStart( Controllable, From, Event, To )
self:F2()
self:__Route( 5 ) -- Route to the patrol point. The asynchronous trigger is important, because a spawned group and units takes at least one second to come live.
self:__Status( 30 ) -- Check status status every 30 seconds.
self:__Detect( self.DetectInterval ) -- Detect for new targets every 30 seconds.
self:__Route( 1 ) -- Route to the patrol point. The asynchronous trigger is important, because a spawned group and units takes at least one second to come live.
self:__Status( 60 ) -- Check status status every 30 seconds.
self:SetDetectionActivated()
self:EventOnPilotDead( self.OnPilotDead )
self:EventOnCrash( self.OnCrash )
self:EventOnEjection( self.OnEjection )
Controllable:OptionROEHoldFire()
Controllable:OptionROTVertical()
self.Controllable:OnReSpawn(
function( PatrolGroup )
self:E( "ReSpawn" )
@@ -25234,7 +25286,7 @@ end
--- @param Wrapper.Controllable#CONTROLLABLE Controllable
function AI_PATROL_ZONE:onbeforeDetect( Controllable, From, Event, To )
return self.DetectUnits
return self.DetectOn and self.DetectActivated
end
--- @param #AI_PATROL_ZONE self
@@ -25265,11 +25317,12 @@ function AI_PATROL_ZONE:onafterDetect( Controllable, From, Event, To )
end
end
self:__Detect( self.DetectInterval )
if Detected == true then
self:__Detected( 1 )
self:__Detected( 1.5 )
end
self:__Detect( self.DetectInterval )
end
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
@@ -25425,7 +25478,7 @@ function AI_PATROL_ZONE:onafterStatus()
if RTB == true then
self:RTB()
else
self:__Status( 30 ) -- Execute the Patrol event after 30 seconds.
self:__Status( 60 ) -- Execute the Patrol event after 30 seconds.
end
end
end
@@ -25467,6 +25520,40 @@ function AI_PATROL_ZONE:onafterRTB()
end
end
--- @param #AI_PATROL_ZONE self
function AI_PATROL_ZONE:onafterDead()
self:SetDetectionOff()
self:SetStatusOff()
end
--- @param #AI_PATROL_ZONE self
-- @param Core.Event#EVENTDATA EventData
function AI_PATROL_ZONE:OnCrash( EventData )
if self.Controllable:IsAlive() and EventData.IniDCSGroupName == self.Controllable:GetName() then
self:__Crash( 1, EventData )
end
end
--- @param #AI_PATROL_ZONE self
-- @param Core.Event#EVENTDATA EventData
function AI_PATROL_ZONE:OnEjection( EventData )
if self.Controllable:IsAlive() and EventData.IniDCSGroupName == self.Controllable:GetName() then
self:__Eject( 1, EventData )
end
end
--- @param #AI_PATROL_ZONE self
-- @param Core.Event#EVENTDATA EventData
function AI_PATROL_ZONE:OnPilotDead( EventData )
if self.Controllable:IsAlive() and EventData.IniDCSGroupName == self.Controllable:GetName() then
self:__PilotDead( 1, EventData )
end
end
--- Single-Player:**Yes** / Mulit-Player:**Yes** / AI:**Yes** / Human:**No** / Types:**Air** -- **Provide Close Air Support to friendly ground troops.**
--
-- ![Banner Image](..\Presentations\AI_Cas\Dia1.JPG)
@@ -25483,7 +25570,7 @@ end
--
-- ![HoldAndEngage](..\Presentations\AI_Cas\Dia3.JPG)
--
-- The AI_CAS_ZONE is assigned a @(Group) and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
-- The AI_CAS_ZONE is assigned a @{Group} and this must be done before the AI_CAS_ZONE process can be started through the **Start** event.
--
-- ![Start Event](..\Presentations\AI_Cas\Dia4.JPG)
--
@@ -25591,7 +25678,7 @@ end
-- @type AI_CAS_ZONE
-- @field Wrapper.Controllable#CONTROLLABLE AIControllable The @{Controllable} patrolling.
-- @field Core.Zone#ZONE_BASE TargetZone The @{Zone} where the patrol needs to be executed.
-- @extends AI.AI_Patrol#AI_CAS_ZONE
-- @extends AI.AI_Patrol#AI_PATROL_ZONE
AI_CAS_ZONE = {
ClassName = "AI_CAS_ZONE",
}
@@ -25803,24 +25890,10 @@ end
-- @param #string To The To State string.
function AI_CAS_ZONE:onafterStart( Controllable, From, Event, To )
self:Route()
self:__Status( 30 ) -- Check status status every 30 seconds.
self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
-- Call the parent Start event handler
self:GetParent(self).onafterStart( self, Controllable, From, Event, To )
self:EventOnDead( self.OnDead )
Controllable:OptionROEHoldFire()
Controllable:OptionROTVertical()
self.Controllable:OnReSpawn(
function( PatrolGroup )
self:E( "ReSpawn" )
self:__Reset()
self:__Route( 5 )
end
)
end
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
@@ -25853,8 +25926,6 @@ function AI_CAS_ZONE:onafterEngage( Controllable, From, Event, To )
if Controllable:IsAlive() then
self:Detect( self.EngageZone )
local EngageRoute = {}
--- Calculate the current route point.
@@ -25985,7 +26056,7 @@ end
-- @param #string To The To State string.
function AI_CAS_ZONE:onafterAccomplish( Controllable, From, Event, To )
self.Accomplished = true
self.DetectUnits = false
self:SetDetectionOff()
end
--- @param #AI_CAS_ZONE self
@@ -26013,7 +26084,7 @@ end
--
-- ![Process](..\Presentations\AI_Cap\Dia3.JPG)
--
-- The AI_CAP_ZONE is assigned a @(Group) and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
-- The AI_CAP_ZONE is assigned a @{Group} and this must be done before the AI_CAP_ZONE process can be started using the **Start** event.
--
-- ![Process](..\Presentations\AI_Cap\Dia4.JPG)
--
@@ -26104,7 +26175,9 @@ end
-- * **[Quax](https://forums.eagle.ru/member.php?u=90530)**: Concept, Advice & Testing.
-- * **[Pikey](https://forums.eagle.ru/member.php?u=62835)**: Concept, Advice & Testing.
-- * **[Gunterlund](http://forums.eagle.ru:8080/member.php?u=75036)**: Test case revision.
--
-- * **[Whisper](http://forums.eagle.ru/member.php?u=3829): Testing.
-- * **[Delta99](https://forums.eagle.ru/member.php?u=125166): Testing.
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
@@ -26337,23 +26410,9 @@ end
-- @param #string To The To State string.
function AI_CAP_ZONE:onafterStart( Controllable, From, Event, To )
-- Call the parent Start event handler
self:GetParent(self).onafterStart( self, Controllable, From, Event, To )
self:Route()
self:__Status( 30 ) -- Check status status every 30 seconds.
self:__Detect( self.DetectInterval ) -- Detect for new targets every DetectInterval in the EngageZone.
self:EventOnDead( self.OnDead )
Controllable:OptionROEOpenFire()
self.Controllable:OnReSpawn(
function( PatrolGroup )
self:E( "ReSpawn" )
self:__Reset()
self:__Route( 5 )
end
)
end
--- @param Wrapper.Controllable#CONTROLLABLE AIControllable
@@ -26415,8 +26474,6 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
if Controllable:IsAlive() then
self:Detect( self.EngageZone )
local EngageRoute = {}
--- Calculate the current route point.
@@ -26467,7 +26524,7 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
for DetectedUnitID, DetectedUnit in pairs( self.DetectedUnits ) do
local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
self:T( DetectedUnit )
self:T( { DetectedUnit, DetectedUnit:IsAlive(), DetectedUnit:IsAir() } )
if DetectedUnit:IsAlive() and DetectedUnit:IsAir() then
if self.EngageZone then
if DetectedUnit:IsInZone( self.EngageZone ) then
@@ -26495,8 +26552,9 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
if #AttackTasks == 0 then
self:E("No targets found -> Going back to Patrolling")
self:Accomplish()
self:Route()
self:__Accomplish( 1 )
self:__Route( 1 )
self:SetDetectionActivated()
else
EngageRoute[1].task = Controllable:TaskCombo( AttackTasks )
@@ -26504,10 +26562,11 @@ function AI_CAP_ZONE:onafterEngage( Controllable, From, Event, To )
self.Controllable:SetState( self.Controllable, "EngageZone", self )
self.Controllable:WayPointFunction( #EngageRoute, 1, "_NewEngageCapRoute" )
self:SetDetectionDeactivated()
end
--- NOW ROUTE THE GROUP!
--- NOW ROUTE THE GROUP!
self.Controllable:WayPointExecute( 1, 2 )
end
@@ -26535,17 +26594,7 @@ end
-- @param #string To The To State string.
function AI_CAP_ZONE:onafterAccomplish( Controllable, From, Event, To )
self.Accomplished = true
self.DetectUnits = false
end
--- @param #AI_CAP_ZONE self
-- @param Core.Event#EVENTDATA EventData
function AI_CAP_ZONE:OnDead( EventData )
self:T( { "EventDead", EventData } )
if EventData.IniDCSUnit then
self:__Destroy( 1, EventData )
end
self:SetDetectionOff()
end