This commit is contained in:
FlightControl 2017-02-18 19:51:20 +01:00
parent 5c090b108c
commit f9708de598
16 changed files with 318 additions and 137 deletions

View File

@ -175,7 +175,7 @@ do -- ACT_ASSIGN_ACCEPT
self:Message( "You are assigned to the task " .. self.Task:GetName() ) self:Message( "You are assigned to the task " .. self.Task:GetName() )
self.Task:Assign() self.Task:Assign( ProcessUnit, self.Task )
end end
end -- ACT_ASSIGN_ACCEPT end -- ACT_ASSIGN_ACCEPT

View File

@ -125,6 +125,17 @@ do -- ACT_ASSIST
self.MenuSmokeRed = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Red smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Red } ) self.MenuSmokeRed = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop Red smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.Red } )
self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } ) self.MenuSmokeWhite = MENU_GROUP_COMMAND:New( ProcessGroup, "Drop White smoke on targets", self.Menu, MenuSmoke, { self = self, SmokeColor = SMOKECOLOR.White } )
end end
--- StateMachine callback function
-- @param #ACT_ASSIST self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ASSIST:onafterStop( ProcessUnit, From, Event, To )
self.Menu:Remove() -- When stopped, remove the menus
end
end end

View File

@ -177,6 +177,89 @@ do -- ACT_ROUTE
end -- ACT_ROUTE end -- ACT_ROUTE
do -- ACT_ROUTE_POINT
--- ACT_ROUTE_POINT class
-- @type ACT_ROUTE_POINT
-- @field Tasking.Task#TASK TASK
-- @extends #ACT_ROUTE
ACT_ROUTE_POINT = {
ClassName = "ACT_ROUTE_POINT",
}
--- Creates a new routing state machine.
-- The task will route a controllable to a TargetPointVec2 until the controllable is within the TargetDistance.
-- @param #ACT_ROUTE_POINT self
-- @param Core.Point#POINT_VEC2 The PointVec2 to Target.
-- @param #number TargetDistance The Distance to Target.
-- @param Core.Zone#ZONE_BASE TargetZone
function ACT_ROUTE_POINT:New( TargetPointVec2, TargetDistance )
local self = BASE:Inherit( self, ACT_ROUTE:New() ) -- #ACT_ROUTE_POINT
self.TargetPointVec2 = TargetPointVec2
self.TargetDistance = TargetDistance
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
return self
end
function ACT_ROUTE_POINT:Init( FsmRoute )
self.TargetPointVec2 = FsmRoute.TargetPointVec2
self.TargetDistance = FsmRoute.TargetDistance
self.DisplayInterval = 30
self.DisplayCount = 30
self.DisplayMessage = true
self.DisplayTime = 10 -- 10 seconds is the default
end
--- Set PointVec2
-- @param #ACT_ROUTE_POINT self
-- @param Core.Point#POINT_VEC2 TargetPointVec2 The PointVec2 to Target.
function ACT_ROUTE_POINT:SetTargetPointVec2( TargetPointVec2 )
self.TargetPointVec2 = TargetPointVec2
end
--- Method override to check if the controllable has arrived.
-- @param #ACT_ROUTE_POINT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @return #boolean
function ACT_ROUTE_POINT:onfuncHasArrived( ProcessUnit )
local Distance = self.TargetPointVec2:Get2DDistance( ProcessUnit:GetPointVec2() )
if Distance <= self.TargetDistance then
local RouteText = "You have arrived within engagement range."
self:Message( RouteText )
return true
end
return false
end
--- Task Events
--- StateMachine callback function
-- @param #ACT_ROUTE_POINT self
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
-- @param #string Event
-- @param #string From
-- @param #string To
function ACT_ROUTE_POINT:onenterReporting( ProcessUnit, From, Event, To )
local TaskUnitPointVec2 = ProcessUnit:GetPointVec2()
local RouteText = "Route to " .. TaskUnitPointVec2:GetBRText( self.TargetPointVec2 ) .. " km to target."
self:Message( RouteText )
end
end -- ACT_ROUTE_POINT
do -- ACT_ROUTE_ZONE do -- ACT_ROUTE_ZONE

View File

@ -869,6 +869,27 @@ do -- FSM_PROCESS
function FSM_PROCESS:Init( FsmProcess ) function FSM_PROCESS:Init( FsmProcess )
self:T( "No Initialisation" ) self:T( "No Initialisation" )
end end
function FSM_PROCESS:_call_handler( handler, params, EventName )
local ErrorHandler = function( errmsg )
env.info( "Error in FSM_PROCESS call handler:" .. errmsg )
if debug ~= nil then
env.info( debug.traceback() )
end
return errmsg
end
if self[handler] then
self:F3( "Calling " .. handler )
self._EventSchedules[EventName] = nil
local Result, Value = xpcall( function() return self[handler]( self, self.Controllable, self.Task, unpack( params ) ) end, ErrorHandler )
return Value
--return self[handler]( self, self.Controllable, unpack( params ) )
end
end
--- Creates a new FSM_PROCESS object based on this FSM_PROCESS. --- Creates a new FSM_PROCESS object based on this FSM_PROCESS.
-- @param #FSM_PROCESS self -- @param #FSM_PROCESS self
@ -893,7 +914,7 @@ do -- FSM_PROCESS
-- Copy Processes -- Copy Processes
for ProcessID, Process in pairs( self:GetProcesses() ) do for ProcessID, Process in pairs( self:GetProcesses() ) do
self:T( { Process} ) self:E( { Process} )
local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents ) local FsmProcess = NewFsm:AddProcess( Process.From, Process.Event, Process.fsm:Copy( Controllable, Task ), Process.ReturnEvents )
end end

View File

@ -240,6 +240,7 @@ SET_BASE = {
Filter = {}, Filter = {},
Set = {}, Set = {},
List = {}, List = {},
Index = {},
} }
--- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names. --- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
@ -258,10 +259,14 @@ function SET_BASE:New( Database )
self.YieldInterval = 10 self.YieldInterval = 10
self.TimeInterval = 0.001 self.TimeInterval = 0.001
self.Set = {}
self.List = {} self.List = {}
self.List.__index = self.List self.List.__index = self.List
self.List = setmetatable( { Count = 0 }, self.List ) self.List = setmetatable( { Count = 0 }, self.List )
self.Index = {}
self.CallScheduler = SCHEDULER:New( self ) self.CallScheduler = SCHEDULER:New( self )
self:SetEventPriority( 2 ) self:SetEventPriority( 2 )
@ -313,6 +318,8 @@ function SET_BASE:Add( ObjectName, Object )
self.Set[ObjectName] = t._ self.Set[ObjectName] = t._
table.insert( self.Index, ObjectName )
end end
--- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index. --- Adds a @{Base#BASE} object in the @{Set#SET_BASE}, using the Object Name as the index.
@ -364,7 +371,15 @@ function SET_BASE:Remove( ObjectName )
t._prev = nil t._prev = nil
self.List.Count = self.List.Count - 1 self.List.Count = self.List.Count - 1
for Index, Key in ipairs( self.Index ) do
if Key == ObjectName then
table.remove( self.Index, Index )
break
end
end
self.Set[ObjectName] = nil self.Set[ObjectName] = nil
end end
end end
@ -406,13 +421,26 @@ function SET_BASE:GetLast()
return t return t
end end
--- Gets a random object from the @{Set#SET_BASE} and derived classes.
-- @param #SET_BASE self
-- @return Core.Base#BASE
function SET_BASE:GetRandom()
self:F()
local RandomItem = self.Set[self.Index[math.random(#self.Index)]]
self:T3( { RandomItem } )
return RandomItem
end
--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes. --- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes.
-- @param #SET_BASE self -- @param #SET_BASE self
-- @return #number Count -- @return #number Count
function SET_BASE:Count() function SET_BASE:Count()
return self.List.Count return #self.Index
end end

View File

@ -2,7 +2,6 @@
-- --
-- === -- ===
-- --
--
-- # 1) @{#DETECTION_BASE} class, extends @{Fsm#FSM} -- # 1) @{#DETECTION_BASE} class, extends @{Fsm#FSM}
-- --
-- The @{#DETECTION_BASE} class defines the core functions to administer detected objects. -- The @{#DETECTION_BASE} class defines the core functions to administer detected objects.
@ -473,16 +472,20 @@ do -- DETECTION_BASE
-- @param #string Event The Event string. -- @param #string Event The Event string.
-- @param #string To The To State string. -- @param #string To The To State string.
function DETECTION_BASE:onafterDetect(From,Event,To) function DETECTION_BASE:onafterDetect(From,Event,To)
self:F( {From,Event,To}) self:E( {From,Event,To})
local DetectDelay = 0.01 local DetectDelay = 0.1
self.DetectionCount = 0 self.DetectionCount = 0
self.DetectionRun = 0 self.DetectionRun = 0
self:UnIdentifyAllDetectedObjects() -- Resets the DetectedObjectsIdentified table self:UnIdentifyAllDetectedObjects() -- Resets the DetectedObjectsIdentified table
self.DetectionSetGroup:Flush()
for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do for DetectionGroupID, DetectionGroupData in pairs( self.DetectionSetGroup:GetSet() ) do
self:E( {DetectionGroupData})
self:__DetectionGroup( DetectDelay, DetectionGroupData ) -- Process each detection asynchronously. self:__DetectionGroup( DetectDelay, DetectionGroupData ) -- Process each detection asynchronously.
self.DetectionCount = self.DetectionCount + 1 self.DetectionCount = self.DetectionCount + 1
DetectDelay = DetectDelay + 0.1
end end
end end
@ -492,21 +495,17 @@ do -- DETECTION_BASE
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param Wrapper.Group#GROUP DetectionGroup -- @param Wrapper.Group#GROUP DetectionGroup
function DETECTION_BASE:onafterDetectionGroup( From, Event, To, DetectionGroup ) function DETECTION_BASE:onafterDetectionGroup( From, Event, To, DetectionGroup )
self:F( {From,Event,To}) self:E( {From,Event,To})
self:__Detect( self.DetectionInterval )
self.DetectionRun = self.DetectionRun + 1 self.DetectionRun = self.DetectionRun + 1
self:UnIdentifyAllDetectedObjects() -- Resets the DetectedObjectsIdentified table
local HasDetectedObjects = false local HasDetectedObjects = false
if DetectionGroup:IsAlive() then if DetectionGroup:IsAlive() then
local DetectionGroupName = DetectionGroup:GetName() local DetectionGroupName = DetectionGroup:GetName()
local DetectionGroupObjects = {} local DetectedUnits = {}
local DetectedTargets = DetectionGroup:GetDetectedTargets( local DetectedTargets = DetectionGroup:GetDetectedTargets(
self.DetectVisual, self.DetectVisual,
@ -537,7 +536,7 @@ do -- DETECTION_BASE
( DetectedObjectVec3.z - DetectionGroupVec3.z )^2 ( DetectedObjectVec3.z - DetectionGroupVec3.z )^2
) ^ 0.5 / 1000 ) ^ 0.5 / 1000
self:T2( { DetectionGroupName, DetectedObjectName, Distance } ) self:T( { DetectionGroupName, DetectedObjectName, Distance } )
-- Calculate Acceptance -- Calculate Acceptance
@ -614,6 +613,8 @@ do -- DETECTION_BASE
end end
if DetectionAccepted then if DetectionAccepted then
HasDetectedObjects = true
if not self.DetectedObjects[DetectedObjectName] then if not self.DetectedObjects[DetectedObjectName] then
self.DetectedObjects[DetectedObjectName] = {} self.DetectedObjects[DetectedObjectName] = {}
@ -623,7 +624,9 @@ do -- DETECTION_BASE
self.DetectedObjects[DetectedObjectName].Type = Detection.type self.DetectedObjects[DetectedObjectName].Type = Detection.type
self.DetectedObjects[DetectedObjectName].Distance = Distance self.DetectedObjects[DetectedObjectName].Distance = Distance
DetectionGroupObjects[DetectedObjectName] = DetectedObject local DetectedUnit = UNIT:FindByName( DetectedObjectName )
DetectedUnits[DetectedObjectName] = DetectedUnit
else else
-- if beyond the DetectionRange then nullify... -- if beyond the DetectionRange then nullify...
if self.DetectedObjects[DetectedObjectName] then if self.DetectedObjects[DetectedObjectName] then
@ -636,13 +639,14 @@ do -- DETECTION_BASE
end end
if HasDetectedObjects then if HasDetectedObjects then
self:__Detected( 0.1, DetectionGroupObjects ) self:__Detected( 0.1, DetectedUnits )
end end
end end
if self.DetectionRun == self.DetectionCount then if self.DetectionCount > 0 and self.DetectionRun == self.DetectionCount then
self:CreateDetectionSets() self:__Detect( self.DetectionInterval )
--self:CreateDetectionSets()
end end
end end
@ -896,11 +900,14 @@ do -- DETECTION_BASE
--- Adds a new DetectedItem to the DetectedItems list. --- Adds a new DetectedItem to the DetectedItems list.
-- The DetectedItem is a table and contains a SET_UNIT in the field Set. -- The DetectedItem is a table and contains a SET_UNIT in the field Set.
-- @param #DETECTION_BASE self -- @param #DETECTION_BASE self
-- @param Core.Set#SET_UNIT Set (optional) The Set of Units to be added.
-- @param Core.Zone#ZONE_UNIT Zone (optional) The Zone to be added where the Units are located.
-- @return #DETECTION_BASE.DetectedItem -- @return #DETECTION_BASE.DetectedItem
function DETECTION_BASE:AddDetectedItem() function DETECTION_BASE:AddDetectedItem( Set, Zone )
local DetectedItem = {} local DetectedItem = {}
DetectedItem.Set = SET_UNIT:New() DetectedItem.Set = Set or SET_UNIT:New()
DetectedItem.Zone = Zone
table.insert( self.DetectedItems, DetectedItem ) table.insert( self.DetectedItems, DetectedItem )
@ -962,6 +969,24 @@ do -- DETECTION_BASE
return nil return nil
end end
do -- Zones
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
-- @return Core.Zone#ZONE_UNIT DetectedZone
function DETECTION_BASE:GetDetectedZone( Index )
local DetectedZone = self.DetectedItems[Index].Zone
if DetectedZone then
return DetectedZone
end
return nil
end
end
--- Report summary of a detected item using a given numeric index. --- Report summary of a detected item using a given numeric index.
@ -1057,7 +1082,7 @@ do -- DETECTION_UNITS
for DetectedUnitName, DetectedObjectData in pairs( self.DetectedObjects ) do for DetectedUnitName, DetectedObjectData in pairs( self.DetectedObjects ) do
self:E( { "Detected Unit #", DetectedUnitName } ) self:T( { "Detected Unit #", DetectedUnitName } )
local DetectedUnit = UNIT:FindByName( DetectedUnitName ) -- Wrapper.Unit#UNIT local DetectedUnit = UNIT:FindByName( DetectedUnitName ) -- Wrapper.Unit#UNIT
@ -1091,10 +1116,8 @@ do -- DETECTION_UNITS
local DetectedItemUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT local DetectedItemUnit = DetectedSet:GetFirst() -- Wrapper.Unit#UNIT
self:E( DetectedItemUnit )
if DetectedItemUnit then if DetectedItemUnit then
self:E(DetectedItemUnit) self:T(DetectedItemUnit)
local UnitCategoryName = DetectedItemUnit:GetCategoryName() local UnitCategoryName = DetectedItemUnit:GetCategoryName()
local UnitCategoryType = DetectedItemUnit:GetTypeName() local UnitCategoryType = DetectedItemUnit:GetTypeName()
@ -1244,7 +1267,7 @@ do -- DETECTION_TYPES
for DetectedUnitName, DetectedObjectData in pairs( self.DetectedObjects ) do for DetectedUnitName, DetectedObjectData in pairs( self.DetectedObjects ) do
self:E( { "Detected Unit #", DetectedUnitName } ) self:T( { "Detected Unit #", DetectedUnitName } )
local DetectedUnit = UNIT:FindByName( DetectedUnitName ) -- Wrapper.Unit#UNIT local DetectedUnit = UNIT:FindByName( DetectedUnitName ) -- Wrapper.Unit#UNIT
@ -1361,34 +1384,18 @@ do -- DETECTION_AREAS
-- @return #DETECTION_AREAS.DetectedItem DetectedItem -- @return #DETECTION_AREAS.DetectedItem DetectedItem
function DETECTION_AREAS:AddDetectedItem( Set, Zone ) function DETECTION_AREAS:AddDetectedItem( Set, Zone )
self:F( { Set, Zone } ) self:F( { Set, Zone } )
-- local Detected = self:GetDetectedItems()
local DetectedItem = {} local DetectedItem = self:GetParent( self ).AddDetectedItem( self, Set, Zone )
DetectedItem.Set = Set
DetectedItem.Zone = Zone
DetectedItem.Removed = false DetectedItem.Removed = false
DetectedItem.AreaID = #self.DetectedItems+1 DetectedItem.AreaID = #self.DetectedItems+1
self:E( { #self.DetectedItems, DetectedItem } ) self:T( { #self.DetectedItems, DetectedItem } )
table.insert( self.DetectedItems, DetectedItem )
return DetectedItem return DetectedItem
end end
--- Remove a detected @{#DETECTION_AREAS.DetectedItem} with a given Index.
-- @param #DETECTION_AREAS self
-- @param #number Index The DetectedItemIndex of the DetectedItems list are to be removed.
-- @return #nil
function DETECTION_AREAS:RemoveDetectedItem( DetectedItemIndex )
local DetectedItems = self:GetDetectedItems()
local DetectedCount = self:GetDetectedItemsCount()
local DetectedArea = self:GetDetectedItem( Index )
DetectedArea[Index] = nil
return nil
end
--- Report summary of a detected item using a given numeric index. --- Report summary of a detected item using a given numeric index.
-- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS self
-- @param Index -- @param Index
@ -1419,20 +1426,6 @@ do -- DETECTION_AREAS
return nil return nil
end end
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index.
-- @param #DETECTION_AREAS self
-- @param #number Index
-- @return Core.Zone#ZONE_UNIT DetectedZone
function DETECTION_AREAS:GetDetectedZone( Index )
local DetectedZone = self.DetectedItems[Index].Zone
if DetectedZone then
return DetectedZone
end
return nil
end
--- Background worker function to determine if there are friendlies nearby ... --- Background worker function to determine if there are friendlies nearby ...
-- @param #DETECTION_AREAS self -- @param #DETECTION_AREAS self
-- @param Wrapper.Unit#UNIT ReportUnit -- @param Wrapper.Unit#UNIT ReportUnit

View File

@ -182,7 +182,6 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New() self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
Mission:AddTask( self )
return self return self
end end

View File

@ -36,38 +36,109 @@ do -- TASK_SEAD
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned. -- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task. -- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets -- @param Set#SET_UNIT UnitSetTargets
-- @param Core.Zone#ZONE_BASE TargetZone -- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_SEAD self -- @return #TASK_SEAD self
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetDistance )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, "SEAD" ) ) -- Tasking.Task_SEAD#TASK_SEAD local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, "SEAD" ) ) -- Tasking.Task#TASK_SEAD
self:F() self:F()
self.TargetSetUnit = TargetSetUnit self.TargetSetUnit = TargetSetUnit
self.TargetZone = TargetZone self.TargetDistance = TargetDistance
Mission:AddTask( self )
local Fsm = self:GetUnitProcess() local Fsm = self:GetUnitProcess()
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "Route", Rejected = "Eject" } )
Fsm:AddProcess ( "Assigned", "Route", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Update" } )
Fsm:AddTransition( "Rejected", "Eject", "Planned" )
Fsm:AddTransition( "Arrived", "Update", "Updated" )
Fsm:AddProcess ( "Updated", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "SEAD" ), { Accounted = "Success" } )
Fsm:AddProcess ( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
Fsm:AddTransition( "Accounted", "Success", "Success" )
Fsm:AddTransition( "Failed", "Fail", "Failed" )
function Fsm:onenterUpdated( TaskUnit )
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "Route", Rejected = "Reject" } )
Fsm:AddTransition( "Assigned", "Route", "Routing" )
Fsm:AddProcess ( "Routing", "RouteToPoint", ACT_ROUTE_POINT:New( self.TargetPointVec2, self.TargetDistance ), { Arrived = "Arrive" } )
Fsm:AddProcess ( "Routing", "RouteToZone", ACT_ROUTE_ZONE:New( self.TargetZone ), { Arrived = "Arrive" } )
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
Fsm:AddTransition( "Arrived", "Arrive", "Accounting" )
Fsm:AddProcess ( "Accounting", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, "SEAD" ), { Accounted = "Success" } )
Fsm:AddProcess ( "Accounting", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( self.TargetSetUnit, self.TargetZone ) )
Fsm:AddTransition( "Accounting", "CheckRange", "Accounting" )
Fsm:AddTransition( "Accounting", "InRange", "Accounting" )
Fsm:AddTransition( "Accounting", "NotInRange", "Assigned" )
Fsm:AddTransition( "Accounting", "Success", "Success" )
Fsm:AddTransition( "Failed", "Fail", "Failed" )
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task#TASK_SEAD Task
function Fsm:onenterRouting( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.TargetSetUnit
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
self:E( { TargetZone = Task.TargetZone } )
if Task.TargetZone then
self:__RouteToZone( 0.1 )
else
local TargetPointVec2 = TargetUnit:GetPointVec2()
local RoutePointProcess = self:GetProcess( "Routing", "RouteToPoint" )
RoutePointProcess:SetTargetPointVec2( TargetPointVec2 )
self:__RouteToPoint( 0.1 )
end
end
end
function Fsm:onenterAccounting( TaskUnit, Task )
self:E( { self } ) self:E( { self } )
self:Account() self:Account()
self:Smoke() self:Smoke()
self:__CheckRange( -5 )
end
--- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
function Fsm:onafterCheckRange( TaskUnit, Task )
self:E( "CheckRange" )
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
local PointVec2 = TargetUnit:GetPointVec2()
local Distance = PointVec2:Get2DDistance( TaskUnit:GetPointVec2() )
if Distance > Task.TargetDistance then
self:NotInRange()
else
self:InRange()
end
end
end
function Fsm:onafterNotInRange( TaskUnit )
self:E( "Not In Range" )
-- Stop accounting etc. and go back to routing.
local FsmAccount = self:GetProcess( "Accounting", "Account" )
local FsmSmoke = self:GetProcess( "Accounting", "Smoke" )
FsmAccount:Stop() -- Stop the Accounting
FsmSmoke:Stop() -- Stop the Smoking
self:__Route( 1 )
end end
function Fsm:onafterInRange( TaskUnit )
self:E( "In Range" )
self:__CheckRange( -5 )
end
return self return self
end
end
--- @param #TASK_SEAD self --- @param #TASK_SEAD self
function TASK_SEAD:GetPlannedMenuText() function TASK_SEAD:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end end
--- @param #TASK_SEAD self
function TASK_SEAD:SetTargetZone( TargetZone )
self.TargetZone = TargetZone
end
end end

View File

@ -1,3 +1,10 @@
2017-02-17
- Added ACT_ROUTE_POINT
-- Routes a controllable to a point with a defined distance.
-- Upon arrived within the engagement distance, an arrival text is shown.
2016-12-06 2016-12-06
- Renamed the documentation references following the structure of the files. - Renamed the documentation references following the structure of the files.

View File

@ -1,5 +1,5 @@
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170213_1411' ) env.info( 'Moose Generation Timestamp: 20170217_1332' )
local base = _G local base = _G

View File

@ -1,5 +1,5 @@
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' ) env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170213_1411' ) env.info( 'Moose Generation Timestamp: 20170217_1332' )
local base = _G local base = _G

View File

@ -37,9 +37,11 @@ function RecceDetection:OnAfterDetect(From,Event,To)
local DetectionReport = RecceDetection:DetectedReportDetailed() local DetectionReport = RecceDetection:DetectedReportDetailed()
CC:MessageToAll( DetectionReport, 15, "" ) CC:GetPositionable():MessageToAll( DetectionReport, 15, "" )
end end
local ArtilleryTime = {}
local ArtilleryAim = 180
--- OnAfter Transition Handler for Event Detect. --- OnAfter Transition Handler for Event Detect.
-- @param Functional.Detection#DETECTION_UNITS self -- @param Functional.Detection#DETECTION_UNITS self
@ -48,14 +50,21 @@ end
-- @param #string To The To State string. -- @param #string To The To State string.
-- @param Wrapper.Unit#UNIT DetectedUnits -- @param Wrapper.Unit#UNIT DetectedUnits
function RecceDetection:OnAfterDetected( From, Event, To, DetectedUnits ) function RecceDetection:OnAfterDetected( From, Event, To, DetectedUnits )
self:E( { From, Event, To, DetectedUnits } )
local ArtilleryArray = ArtillerySetGroup:GetSet()
local ArtilleryArrayCount = ArtillerySetGroup:Count()
for DetectedUnitID, DetectedUnit in pairs( DetectedUnits ) do for DetectedUnitID, DetectedUnit in pairs( DetectedUnits ) do
local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT local DetectedUnit = DetectedUnit -- Wrapper.Unit#UNIT
local Artillery = ArtilleryArray[ math.random( 1, ArtilleryArrayCount ) ] -- Wrapper.Group#GROUP local Artillery = ArtillerySetGroup:GetRandom() -- Wrapper.Group#GROUP
local Task = Artillery:TaskFireAtPoint( DetectedUnit:GetVec2(), 500, 2 ) -- Fire 2 rockets to the target point.
Artillery:SetTask( Task, 0.5 ) if ArtilleryTime[Artillery] and ArtilleryTime[Artillery] <= timer.getTime() - ArtilleryAim then
ArtilleryTime[Artillery] = nil
end
if not ArtilleryTime[Artillery] then
local Task = Artillery:TaskFireAtPoint( DetectedUnit:GetVec2(), 500, 4 ) -- Fire 2 rockets to the target point.
Artillery:SetTask( Task, 0.5 )
ArtilleryTime[Artillery] = timer.getTime()
end
end end
end end

View File

@ -104,11 +104,12 @@ local TargetZone = ZONE:New( "Target Zone" )
-- 2. The set of groups of planes that pilots can join. -- 2. The set of groups of planes that pilots can join.
-- 3. The name of the Task... This can be any name, and will be provided when the Pilot joins the task. -- 3. The name of the Task... This can be any name, and will be provided when the Pilot joins the task.
-- 4. A type of the Task. When Tasks are in state Planned, then a menu can be provided that group the task based on this given type. -- 4. A type of the Task. When Tasks are in state Planned, then a menu can be provided that group the task based on this given type.
local SEADTask = TASK:New( local SEADTask = TASK_SEAD:New(
Mission, Mission,
SEADSet, SEADSet,
"SEAD Radars Vector 1", "SEAD Radars Vector 1",
"SEAD" ) -- Tasking.Task#TASK TargetSet,
15000 ) -- Tasking.Task#TASK_SEAD
-- This is now an important part of the Task process definition. -- This is now an important part of the Task process definition.
-- Each TASK contains a "Process Template". -- Each TASK contains a "Process Template".
@ -122,56 +123,14 @@ local SEADTask = TASK:New(
local SEADProcess = SEADTask:GetUnitProcess() -- #SEADProcess local SEADProcess = SEADTask:GetUnitProcess() -- #SEADProcess
-- Adding a new sub-process to the Task Template. SEADProcess:AddScoreProcess( "Accounting", "Account", "Account", "destroyed a radar", 25 )
-- At first, the task needs to be accepted by a pilot. SEADProcess:AddScoreProcess( "Accounting", "Account", "Failed", "failed to destroy a radar", -10 )
-- We use for this the SUB-PROCESS ACT_ASSIGN_ACCEPT.
-- The method on the FsmSEAD AddProcess accepts the following parameters:
-- 1. State From "Planned". When the Fsm is in state "Planned", allow the event "Accept".
-- 2. Event "Accept". This event can be triggered through FsmSEAD:Accept() or FsmSEAD:__Accept( 1 ). See documentation on state machines.
-- 3. The PROCESS derived class. In this case, we use the ACT_ASSIGN_ACCEPT to accept the task and provide a briefing. So, when the event "Accept" is fired, this process is executed.
-- 4. A table with the "return" states of the ACT_ASSIGN_ACCEPT process. This table indicates that for a certain return state, a further event needs to be called.
-- 4.1 When the return state is Assigned, fire the event in the Task FsmSEAD:Route()
-- 4.2 When the return state is Rejected, fire the event in the Task FsmSEAD:Eject()
-- All other AddProcess calls are working in a similar manner.
SEADProcess:AddProcess( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( "SEAD the Area" ), { Assigned = "Route", Rejected = "Eject" } ) -- FSM SUB for type SEADProcess.
SEADProcess:AddProcess( "Assigned", "Route", ACT_ROUTE_ZONE:New( TargetZone ), { Arrived = "Update" } ) -- FSM SUB for type SEADProcess.
-- Adding a new Action...
-- Actions define also the flow of the Task, but the actions will need to be programmed within your script.
-- See the state machine explanation for further details.
-- The AddTransition received a couple of parameters:
-- 1. State From "Rejected". When the FsmSEAD is in state "Rejected", the event "Eject" can be fired.
-- 2. Event "Eject". This event can be triggered synchronously through FsmSEAD:Eject() or asynchronously through FsmSEAD:__Eject(secs).
-- 3. State To "Planned". After the event has been fired, the FsmSEAD will transition to Planned.
SEADProcess:AddTransition( "Rejected", "Eject", "Planned" )
SEADProcess:AddTransition( "Arrived", "Update", "Updated" )
SEADProcess:AddProcess( "Updated", "Account", ACT_ACCOUNT_DEADS:New( TargetSet, "SEAD" ), { Accounted = "Success" } )
SEADProcess:AddProcess( "Updated", "Smoke", ACT_ASSIST_SMOKE_TARGETS_ZONE:New( TargetSet, TargetZone ) )
SEADProcess:AddTransition( "Accounted", "Success", "Success" )
SEADProcess:AddTransition( "*", "Fail", "Failed" )
SEADProcess:AddScoreProcess( "Updated", "Account", "Account", "destroyed a radar", 25 )
SEADProcess:AddScoreProcess( "Updated", "Account", "Failed", "failed to destroy a radar", -10 )
-- Now we will set the SCORING. Scoring is set using the TaskSEAD object. -- Now we will set the SCORING. Scoring is set using the TaskSEAD object.
-- Scores can be set on the status of the Task, and on Process level. -- Scores can be set on the status of the Task, and on Process level.
SEADProcess:AddScore( "Success", "Destroyed all target radars", 250 ) SEADProcess:AddScore( "Success", "Destroyed all target radars", 250 )
SEADProcess:AddScore( "Failed", "Failed to destroy all target radars", -100 ) SEADProcess:AddScore( "Failed", "Failed to destroy all target radars", -100 )
function SEADProcess:OnEnterUpdated( Controllable, From, Event, To )
self:E( { self } )
self:Account()
self:Smoke()
end
-- Here we handle the PlayerAborted event, which is fired when a Player leaves the unit while being assigned to the Task. -- Here we handle the PlayerAborted event, which is fired when a Player leaves the unit while being assigned to the Task.
-- Within the event handler, which is passed the PlayerUnit and PlayerName parameter, -- Within the event handler, which is passed the PlayerUnit and PlayerName parameter,
-- we check if the SEADTask has still AlivePlayers assigned to the Task. -- we check if the SEADTask has still AlivePlayers assigned to the Task.
@ -184,14 +143,14 @@ function SEADTask:OnEnterPlayerCrashed( PlayerUnit, PlayerName )
end end
local TaskSEAD2 = TASK:New( Mission, SEADSet, "SEAD Radars Vector 2", "SEAD" ) -- Tasking.Task#TASK --local TaskSEAD2 = TASK:New( Mission, SEADSet, "SEAD Radars Vector 2", "SEAD" ) -- Tasking.Task#TASK
TaskSEAD2:SetUnitProcess( SEADTask:GetUnitProcess():Copy() ) --TaskSEAD2:SetUnitProcess( SEADTask:GetUnitProcess():Copy() )
Mission:AddTask( TaskSEAD2 ) --Mission:AddTask( TaskSEAD2 )
--
Mission:RemoveTask( SEADTask ) --Mission:RemoveTask( SEADTask )
--
SEADTask = nil --SEADTask = nil
SEADProcess = nil --SEADProcess = nil
collectgarbage() collectgarbage()