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

@ -12,7 +12,7 @@
--
-- ![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)
--
@ -103,7 +103,9 @@
-- * **[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.
@ -336,23 +338,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
@ -414,8 +402,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.
@ -466,7 +452,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
@ -494,8 +480,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 )
@ -503,10 +490,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
@ -534,17 +522,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

View File

@ -14,7 +14,7 @@
--
-- ![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)
--
@ -122,7 +122,7 @@
-- @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",
}
@ -334,24 +334,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
@ -384,8 +370,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.
@ -516,7 +500,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

View File

@ -11,7 +11,7 @@
--
-- ![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)
--
@ -402,6 +402,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
@ -443,7 +447,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.
@ -453,7 +457,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.
@ -496,7 +528,7 @@ end
function AI_PATROL_ZONE:GetDetectedUnits()
self:F2()
return self.DetectedUnits
return self.DetectedUnits
end
@ -544,13 +576,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" )
@ -566,7 +603,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
@ -597,11 +634,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
@ -757,7 +795,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
@ -799,3 +837,37 @@ 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

View File

@ -717,6 +717,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
@ -758,14 +768,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

View File

@ -529,7 +529,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
@ -551,10 +552,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
@ -746,7 +748,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

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
@ -12549,7 +12564,7 @@ end
-- * @{#CONTROLLABLE.TaskEmbarkToTransport}: (GROUND) Embark to a Transport landed at a location.
-- * @{#CONTROLLABLE.TaskEscort}: (AIR) Escort another airborne controllable.
-- * @{#CONTROLLABLE.TaskFAC_AttackControllable}: (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction.
-- * @{#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire at a VEC2 point until ammunition is finished.
-- * @{#CONTROLLABLE.TaskFireAtPoint}: (GROUND) Fire some or all ammunition at a VEC2 point.
-- * @{#CONTROLLABLE.TaskFollow}: (AIR) Following another airborne controllable.
-- * @{#CONTROLLABLE.TaskHold}: (GROUND) Hold ground controllable from moving.
-- * @{#CONTROLLABLE.TaskHoldPosition}: (AIR) Hold position at the current position of the first unit of the controllable.
@ -13457,15 +13472,18 @@ end
-- @param #CONTROLLABLE self
-- @param Dcs.DCSTypes#Vec2 Vec2 The point to fire at.
-- @param Dcs.DCSTypes#Distance Radius The radius of the zone to deploy the fire at.
-- @param #number AmmoCount (optional) Quantity of ammunition to expand (omit to fire until ammunition is depleted).
-- @return Dcs.DCSTasking.Task#Task The DCS task structure.
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius )
self:F2( { self.ControllableName, Vec2, Radius } )
function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius, AmmoCount )
self:F2( { self.ControllableName, Vec2, Radius, AmmoCount } )
-- FireAtPoint = {
-- id = 'FireAtPoint',
-- params = {
-- point = Vec2,
-- radius = Distance,
-- expendQty = number,
-- expendQtyEnabled = boolean,
-- }
-- }
@ -13474,8 +13492,15 @@ function CONTROLLABLE:TaskFireAtPoint( Vec2, Radius )
params = {
point = Vec2,
radius = Radius,
expendQty = 100, -- dummy value
expendQtyEnabled = false,
}
}
if AmmoCount then
DCSTask.params.expendQty = AmmoCount
DCSTask.params.expendQtyEnabled = true
end
self:T3( { DCSTask } )
return DCSTask
@ -24669,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)
--
@ -25060,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
@ -25101,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.
@ -25111,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.
@ -25154,7 +25211,7 @@ end
function AI_PATROL_ZONE:GetDetectedUnits()
self:F2()
return self.DetectedUnits
return self.DetectedUnits
end
@ -25202,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" )
@ -25224,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
@ -25255,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
@ -25415,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
@ -25457,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)
@ -25473,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)
--
@ -25581,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",
}
@ -25793,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
@ -25843,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.
@ -25975,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
@ -26003,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)
--
@ -26094,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.
@ -26327,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
@ -26405,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.
@ -26457,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
@ -26485,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 )
@ -26494,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
@ -26525,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

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

View File

@ -86,7 +86,7 @@ and automatically engage any airborne enemies that are within a certain range or
<p><img src="..\Presentations\AI_Cap\Dia3.JPG" alt="Process"/></p>
<p>The AI<em>CAP</em>ZONE is assigned a @(Group) and this must be done before the AI<em>CAP</em>ZONE process can be started using the <strong>Start</strong> event.</p>
<p>The AI<em>CAP</em>ZONE is assigned a <a href="Group.html">Group</a> and this must be done before the AI<em>CAP</em>ZONE process can be started using the <strong>Start</strong> event.</p>
<p><img src="..\Presentations\AI_Cap\Dia4.JPG" alt="Process"/></p>
@ -186,6 +186,8 @@ Use the method <a href="AI.AI_Cap.html##(AI_CAP_ZONE).SetEngageZone">AI.AI<em>Ca
<li><strong><a href="https://forums.eagle.ru/member.php?u=90530">Quax</a></strong>: Concept, Advice &amp; Testing.</li>
<li><strong><a href="https://forums.eagle.ru/member.php?u=62835">Pikey</a></strong>: Concept, Advice &amp; Testing.</li>
<li><strong><a href="http://forums.eagle.ru:8080/member.php?u=75036">Gunterlund</a></strong>: Test case revision.</li>
<li>**<a href="http://forums.eagle.ru/member.php?u=3829">Whisper</a>: Testing.</li>
<li>**<a href="https://forums.eagle.ru/member.php?u=125166">Delta99</a>: Testing. </li>
</ul>
<h3>Authors:</h3>
@ -246,12 +248,6 @@ Use the method <a href="AI.AI_Cap.html##(AI_CAP_ZONE).SetEngageZone">AI.AI<em>Ca
<td class="name" nowrap="nowrap"><a href="##(AI_CAP_ZONE).Destroy">AI_CAP_ZONE:Destroy()</a></td>
<td class="summary">
<p>Synchronous Event Trigger for Event Destroy.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAP_ZONE).DetectUnits">AI_CAP_ZONE.DetectUnits</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -348,12 +344,6 @@ Use the method <a href="AI.AI_Cap.html##(AI_CAP_ZONE).SetEngageZone">AI.AI<em>Ca
<td class="name" nowrap="nowrap"><a href="##(AI_CAP_ZONE).OnBeforeFired">AI_CAP_ZONE:OnBeforeFired(Controllable, From, Event, To)</a></td>
<td class="summary">
<p>OnBefore Transition Handler for Event Fired.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAP_ZONE).OnDead">AI_CAP_ZONE:OnDead(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -576,20 +566,6 @@ Use the method <a href="AI.AI_Cap.html##(AI_CAP_ZONE).SetEngageZone">AI.AI<em>Ca
<p>Synchronous Event Trigger for Event Destroy.</p>
</dd>
</dl>
<dl class="function">
<dt>
<em>#boolean</em>
<a id="#(AI_CAP_ZONE).DetectUnits" >
<strong>AI_CAP_ZONE.DetectUnits</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
@ -1139,27 +1115,6 @@ Return false to cancel Transition.</p>
<dl class="function">
<dt>
<a id="#(AI_CAP_ZONE).OnDead" >
<strong>AI_CAP_ZONE:OnDead(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_CAP_ZONE).OnEnterEngaging" >
<strong>AI_CAP_ZONE:OnEnterEngaging(Controllable, From, Event, To)</strong>
</a>

View File

@ -88,7 +88,7 @@ The AI<em>CAS</em>ZONE runs a process. It holds an AI in a Patrol Zone and when
<p><img src="..\Presentations\AI_Cas\Dia3.JPG" alt="HoldAndEngage"/></p>
<p>The AI<em>CAS</em>ZONE is assigned a @(Group) and this must be done before the AI<em>CAS</em>ZONE process can be started through the <strong>Start</strong> event.</p>
<p>The AI<em>CAS</em>ZONE is assigned a <a href="Group.html">Group</a> and this must be done before the AI<em>CAS</em>ZONE process can be started through the <strong>Start</strong> event.</p>
<p><img src="..\Presentations\AI_Cas\Dia4.JPG" alt="Start Event"/></p>
@ -255,12 +255,6 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).Destroy">AI_CAS_ZONE:Destroy()</a></td>
<td class="summary">
<p>Synchronous Event Trigger for Event Destroy.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_CAS_ZONE).DetectUnits">AI_CAS_ZONE.DetectUnits</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -561,20 +555,6 @@ It can be notified to go RTB through the <strong>RTB</strong> event.</p>
<p>Synchronous Event Trigger for Event Destroy.</p>
</dd>
</dl>
<dl class="function">
<dt>
<em>#boolean</em>
<a id="#(AI_CAS_ZONE).DetectUnits" >
<strong>AI_CAS_ZONE.DetectUnits</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">

View File

@ -85,7 +85,7 @@
<p><img src="..\Presentations\AI_Patrol\Dia3.JPG" alt="Process"/></p>
<p>The AI<em>PATROL</em>ZONE is assigned a @(Group) and this must be done before the AI<em>PATROL</em>ZONE process can be started using the <strong>Start</strong> event.</p>
<p>The AI<em>PATROL</em>ZONE is assigned a <a href="Group.html">Group</a> and this must be done before the AI<em>PATROL</em>ZONE process can be started using the <strong>Start</strong> event.</p>
<p><img src="..\Presentations\AI_Patrol\Dia4.JPG" alt="Process"/></p>
@ -276,6 +276,12 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).Detect">AI_PATROL_ZONE:Detect()</a></td>
<td class="summary">
<p>Synchronous Event Trigger for Event Detect.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).DetectActivated">AI_PATROL_ZONE.DetectActivated</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -285,7 +291,7 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).DetectUnits">AI_PATROL_ZONE.DetectUnits</a></td>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).DetectOn">AI_PATROL_ZONE.DetectOn</a></td>
<td class="summary">
</td>
@ -402,6 +408,18 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).OnBeforeStatus">AI_PATROL_ZONE:OnBeforeStatus(Controllable, From, Event, To)</a></td>
<td class="summary">
<p>OnBefore Transition Handler for Event Status.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).OnCrash">AI_PATROL_ZONE:OnCrash(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).OnEjection">AI_PATROL_ZONE:OnEjection(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -426,6 +444,12 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).OnLeaveReturning">AI_PATROL_ZONE:OnLeaveReturning(Controllable, From, Event, To)</a></td>
<td class="summary">
<p>OnLeave Transition Handler for State Returning.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).OnPilotDead">AI_PATROL_ZONE:OnPilotDead(EventData)</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -504,6 +528,18 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).SetAltitude">AI_PATROL_ZONE:SetAltitude(PatrolFloorAltitude, PatrolCeilingAltitude)</a></td>
<td class="summary">
<p>Sets the floor and ceiling altitude of the patrol.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).SetDetectionActivated">AI_PATROL_ZONE:SetDetectionActivated()</a></td>
<td class="summary">
<p>Activate the detection.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).SetDetectionDeactivated">AI_PATROL_ZONE:SetDetectionDeactivated()</a></td>
<td class="summary">
<p>Deactivate the detection.</p>
</td>
</tr>
<tr>
@ -534,6 +570,12 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).SetSpeed">AI_PATROL_ZONE:SetSpeed(PatrolMinSpeed, PatrolMaxSpeed)</a></td>
<td class="summary">
<p>Sets (modifies) the minimum and maximum speed of the patrol.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).SetStatusOff">AI_PATROL_ZONE:SetStatusOff()</a></td>
<td class="summary">
<p>Set the status checking off.</p>
</td>
</tr>
<tr>
@ -588,6 +630,12 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).__Status">AI_PATROL_ZONE:__Status(Delay)</a></td>
<td class="summary">
<p>Asynchronous Event Trigger for Event Status.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(AI_PATROL_ZONE).onafterDead">AI_PATROL_ZONE:onafterDead()</a></td>
<td class="summary">
</td>
</tr>
<tr>
@ -723,6 +771,20 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<p>Synchronous Event Trigger for Event Detect.</p>
</dd>
</dl>
<dl class="function">
<dt>
<em>#boolean</em>
<a id="#(AI_PATROL_ZONE).DetectActivated" >
<strong>AI_PATROL_ZONE.DetectActivated</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">
@ -743,8 +805,8 @@ Use the method <a href="##(AI_PATROL_ZONE).ManageDamage">AI<em>PATROL</em>ZONE.M
<dt>
<em>#boolean</em>
<a id="#(AI_PATROL_ZONE).DetectUnits" >
<strong>AI_PATROL_ZONE.DetectUnits</strong>
<a id="#(AI_PATROL_ZONE).DetectOn" >
<strong>AI_PATROL_ZONE.DetectOn</strong>
</a>
</dt>
<dd>
@ -1461,6 +1523,48 @@ Return false to cancel Transition.</p>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).OnCrash" >
<strong>AI_PATROL_ZONE:OnCrash(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).OnEjection" >
<strong>AI_PATROL_ZONE:OnEjection(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).OnEnterPatrolling" >
<strong>AI_PATROL_ZONE:OnEnterPatrolling(Controllable, From, Event, To)</strong>
</a>
@ -1626,6 +1730,27 @@ The To State string.</p>
<p><em>#boolean:</em>
Return false to cancel Transition.</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).OnPilotDead" >
<strong>AI_PATROL_ZONE:OnPilotDead(EventData)</strong>
</a>
</dt>
<dd>
<h3>Parameter</h3>
<ul>
<li>
<p><code><em><a href="Core.Event.html##(EVENTDATA)">Core.Event#EVENTDATA</a> EventData </em></code>: </p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
@ -1830,6 +1955,48 @@ self</p>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).SetDetectionActivated" >
<strong>AI_PATROL_ZONE:SetDetectionActivated()</strong>
</a>
</dt>
<dd>
<p>Activate the detection.</p>
<p>The AI will detect for targets if the Detection is switched On.</p>
<h3>Return value</h3>
<p><em><a href="##(AI_PATROL_ZONE)">#AI<em>PATROL</em>ZONE</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).SetDetectionDeactivated" >
<strong>AI_PATROL_ZONE:SetDetectionDeactivated()</strong>
</a>
</dt>
<dd>
<p>Deactivate the detection.</p>
<p>The AI will NOT detect for targets.</p>
<h3>Return value</h3>
<p><em><a href="##(AI_PATROL_ZONE)">#AI<em>PATROL</em>ZONE</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).SetDetectionInterval" >
<strong>AI_PATROL_ZONE:SetDetectionInterval(Seconds)</strong>
</a>
@ -1966,6 +2133,24 @@ self</p>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).SetStatusOff" >
<strong>AI_PATROL_ZONE:SetStatusOff()</strong>
</a>
</dt>
<dd>
<p>Set the status checking off.</p>
<h3>Return value</h3>
<p><em><a href="##(AI_PATROL_ZONE)">#AI<em>PATROL</em>ZONE</a>:</em>
self</p>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).Start" >
<strong>AI_PATROL_ZONE:Start()</strong>
</a>
@ -2147,6 +2332,19 @@ The delay in seconds.</p>
</li>
</ul>
</dd>
</dl>
<dl class="function">
<dt>
<a id="#(AI_PATROL_ZONE).onafterDead" >
<strong>AI_PATROL_ZONE:onafterDead()</strong>
</a>
</dt>
<dd>
</dd>
</dl>
<dl class="function">

View File

@ -115,7 +115,7 @@ This is different from the EnRoute tasks, where the targets of the task need to
<li><a href="##(CONTROLLABLE).TaskEmbarkToTransport">CONTROLLABLE.TaskEmbarkToTransport</a>: (GROUND) Embark to a Transport landed at a location.</li>
<li><a href="##(CONTROLLABLE).TaskEscort">CONTROLLABLE.TaskEscort</a>: (AIR) Escort another airborne controllable. </li>
<li><a href="##(CONTROLLABLE).TaskFAC_AttackControllable">CONTROLLABLE.TaskFAC_AttackControllable</a>: (AIR + GROUND) The task makes the controllable/unit a FAC and orders the FAC to control the target (enemy ground controllable) destruction.</li>
<li><a href="##(CONTROLLABLE).TaskFireAtPoint">CONTROLLABLE.TaskFireAtPoint</a>: (GROUND) Fire at a VEC2 point until ammunition is finished.</li>
<li><a href="##(CONTROLLABLE).TaskFireAtPoint">CONTROLLABLE.TaskFireAtPoint</a>: (GROUND) Fire some or all ammunition at a VEC2 point.</li>
<li><a href="##(CONTROLLABLE).TaskFollow">CONTROLLABLE.TaskFollow</a>: (AIR) Following another airborne controllable.</li>
<li><a href="##(CONTROLLABLE).TaskHold">CONTROLLABLE.TaskHold</a>: (GROUND) Hold ground controllable from moving.</li>
<li><a href="##(CONTROLLABLE).TaskHoldPosition">CONTROLLABLE.TaskHoldPosition</a>: (AIR) Hold position at the current position of the first unit of the controllable.</li>
@ -568,7 +568,7 @@ A speed can be given in km/h.</p>
</td>
</tr>
<tr>
<td class="name" nowrap="nowrap"><a href="##(CONTROLLABLE).TaskFireAtPoint">CONTROLLABLE:TaskFireAtPoint(Vec2, Radius)</a></td>
<td class="name" nowrap="nowrap"><a href="##(CONTROLLABLE).TaskFireAtPoint">CONTROLLABLE:TaskFireAtPoint(Vec2, Radius, AmmoCount)</a></td>
<td class="summary">
<p>(GROUND) Fire at a VEC2 point until ammunition is finished.</p>
</td>
@ -2504,7 +2504,7 @@ The DCS task structure.</p>
<dt>
<a id="#(CONTROLLABLE).TaskFireAtPoint" >
<strong>CONTROLLABLE:TaskFireAtPoint(Vec2, Radius)</strong>
<strong>CONTROLLABLE:TaskFireAtPoint(Vec2, Radius, AmmoCount)</strong>
</a>
</dt>
<dd>
@ -2524,6 +2524,12 @@ The point to fire at.</p>
<p><code><em><a href="Dcs.DCSTypes.html##(Distance)">Dcs.DCSTypes#Distance</a> Radius </em></code>:
The radius of the zone to deploy the fire at.</p>
</li>
<li>
<p><code><em>#number AmmoCount </em></code>:
(optional) Quantity of ammunition to expand (omit to fire until ammunition is depleted).</p>
</li>
</ul>
<h3>Return value</h3>

View File

@ -2491,7 +2491,7 @@ Spawn_BE_KA50 = SPAWN:New( 'BE KA-50@RAMP-Ground Defense' ):Schedule( 600, 0.5 )
<p> Flag that indicates if all the Groups of the SpawnGroup need to be visible when Spawned.</p>
<p> When the first Spawn executes, all the Groups need to be made visible before start.</p>
</dd>
</dl>

View File

@ -193,15 +193,6 @@ For example, for the SEAD Task, the task action flow combines the actions ASSIGN
* [ACT_ASSIST](Documentation/Assist.html): Mechanisms to assist players executing a task. For example, acquire targets through smoking them.
# MOOSE Tutorials and Examples
You can download [test missions](https://github.com/FlightControl-Master/MOOSE/tree/master/Test%20Missions) to have examples and learn the syntax and usage of the MOOSE classes.
There are [Video Tutorials](https://www.youtube.com/channel/UCjrA9j5LQoWsG4SpS8i79Qg) on my YOUTUBE channel on which you can learn some coding aspects with mission execution demos, as well as some of the tooling and internal mechanisms within MOOSE.
In the triggers section, there is a flag (9999) that will decide how MOOSE will be loaded. When flag 9999 is set, MOOSE will be dynamically loaded. When flag 9999 is off, MOOSE will be loaded embedded. Note that when loaded embedded, **your mission must include the last Moose_Embedded.lua file**. So, ensure that the last file is included in the DO SCRIPT section when MOOSE got an update!
# Credits
Note that the framework is based on code i've written myself, but some of it is also based on code that i've seen as great scripting code and ideas, and which i've revised. I see this framework evolving towards a broader public, and the ownership may dissapear (or parts of it). Consider this code public domain. Therefore a list of credits to all who have or are contributing (this list will increase over time): Grimes, Prof_Hilactic, xcom, the 476 virtual squadron team, ...
@ -223,8 +214,8 @@ Working together with James has resulted in the creation of the AIBALANCER class
**Stuka (Danny)**
Working together with Danny has resulted in the MISSILETRAINER class. Stuka has shared his ideas and together we made a design. Together with the 476 virtual team, we tested this CLASS, and got much positive feedback!
**Mechanic (G<EFBFBD>bor)**
Worked together with G<EFBFBD>bor to create the concept of the DETECTION and FAC classes. Mechanic shared his ideas and concepts to group detected targets into sets within detection zones... Will continue to work with G<>bor to workout the DETECTION and FAC classes.
**Mechanic (Gabor)**
Worked together with Gabor to create the concept of the DETECTION and FAC classes. Mechanic shared his ideas and concepts to group detected targets into sets within detection zones... Will continue to work with G<>bor to workout the DETECTION and FAC classes.
**Shadoh**
Interacted on the eagle dynamics forum to build the FOLLOW class to build large WWII airplane formations.