mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
Merge pull request #152 from FlightControl-Master/Process-Templates
Process templates
This commit is contained in:
commit
20dca5088a
@ -116,9 +116,18 @@ function BASE:New()
|
||||
self.__index = self
|
||||
_ClassID = _ClassID + 1
|
||||
self.ClassID = _ClassID
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function BASE:_Destructor()
|
||||
--self:E("_Destructor")
|
||||
|
||||
self:EventRemoveAll()
|
||||
end
|
||||
|
||||
|
||||
--- This is the worker method to inherit from a parent class.
|
||||
-- @param #BASE self
|
||||
-- @param Child is the Child class that inherits.
|
||||
@ -131,6 +140,22 @@ function BASE:Inherit( Child, Parent )
|
||||
if Child ~= nil then
|
||||
setmetatable( Child, Parent )
|
||||
Child.__index = Child
|
||||
|
||||
local proxy = newproxy(true)
|
||||
local proxyMeta = getmetatable(proxy)
|
||||
|
||||
proxyMeta.__gc = function ()
|
||||
-- env.info("In __gc for " .. Child:GetClassNameAndID() )
|
||||
if Child._Destructor then
|
||||
Child:_Destructor()
|
||||
end
|
||||
end
|
||||
|
||||
-- keep the userdata from newproxy reachable until the object
|
||||
-- table is about to be garbage-collected - then the __gc hook
|
||||
-- will be invoked and the destructor called
|
||||
rawset(Child, '__proxy', proxy)
|
||||
|
||||
end
|
||||
--self:T( 'Inherited from ' .. Parent.ClassName )
|
||||
return Child
|
||||
|
||||
@ -85,9 +85,16 @@ end
|
||||
-- @return #EVENT.Events
|
||||
function EVENT:Init( EventID, EventClass )
|
||||
self:F3( { _EVENTCODES[EventID], EventClass } )
|
||||
if not self.Events[EventID] then
|
||||
|
||||
if not self.Events[EventID] then
|
||||
self.Events[EventID] = {}
|
||||
|
||||
-- Create a WEAK table to ensure that the garbage collector is cleaning the event links when the object usage is cleaned.
|
||||
local Meta = {}
|
||||
setmetatable( self.Events[EventID], Meta )
|
||||
Meta.__mode = "k"
|
||||
end
|
||||
|
||||
if not self.Events[EventID][EventClass] then
|
||||
self.Events[EventID][EventClass] = {}
|
||||
end
|
||||
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
--- STATEMACHINE class
|
||||
-- @type STATEMACHINE
|
||||
-- @extends Base#BASE
|
||||
-- @extends Core.Base#BASE
|
||||
STATEMACHINE = {
|
||||
ClassName = "STATEMACHINE",
|
||||
}
|
||||
@ -34,43 +34,85 @@ function STATEMACHINE:New( options )
|
||||
|
||||
--local self = routines.utils.deepCopy( self ) -- Create a new self instance
|
||||
|
||||
assert(options.events)
|
||||
--assert(options.events)
|
||||
|
||||
--local MT = {}
|
||||
--setmetatable( self, MT )
|
||||
--self.__index = self
|
||||
|
||||
self.options = options
|
||||
self.options.subs = self.options.subs or {}
|
||||
self.current = options.initial or 'none'
|
||||
self.events = {}
|
||||
self.subs = {}
|
||||
self.endstates = {}
|
||||
|
||||
for _, event in ipairs(options.events or {}) do
|
||||
local name = event.name
|
||||
local __name = "__" .. event.name
|
||||
self[name] = self[name] or self:_create_transition(name)
|
||||
self[__name] = self[__name] or self:_delayed_transition(name)
|
||||
self:T( "Added methods: " .. name .. ", " .. __name )
|
||||
self.events[name] = self.events[name] or { map = {} }
|
||||
self:_add_to_map(self.events[name].map, event)
|
||||
for _, event in pairs(options.events or {}) do
|
||||
self:E({ "events", event })
|
||||
self:_eventmap( self.events, event )
|
||||
end
|
||||
|
||||
for name, callback in pairs(options.callbacks or {}) do
|
||||
self:E("callbacks")
|
||||
self[name] = callback
|
||||
end
|
||||
|
||||
for name, sub in pairs( options.subs or {} ) do
|
||||
self:E("sub")
|
||||
self:_submap( self.subs, sub, name )
|
||||
end
|
||||
|
||||
for name, endstate in pairs( options.endstates or {} ) do
|
||||
self:E("endstate")
|
||||
self.endstates[endstate] = endstate
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function STATEMACHINE:SetInitialState( State )
|
||||
self.current = State
|
||||
end
|
||||
|
||||
function STATEMACHINE:AddAction( From, Event, To )
|
||||
|
||||
local event = {}
|
||||
event.from = From
|
||||
event.name = Event
|
||||
event.to = To
|
||||
|
||||
self:E( event )
|
||||
|
||||
self:_eventmap( self.events, event )
|
||||
end
|
||||
|
||||
|
||||
--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task.
|
||||
-- @return Process#PROCESS
|
||||
function STATEMACHINE:AddProcess( From, Event, Process, ReturnEvents )
|
||||
|
||||
local sub = {}
|
||||
sub.FromParent = From
|
||||
sub.EventParent = Event
|
||||
sub.fsm = Process
|
||||
sub.event = "Start"
|
||||
sub.ReturnEvents = ReturnEvents
|
||||
|
||||
self.options.subs[Event] = sub
|
||||
|
||||
self:_submap( self.subs, sub, nil )
|
||||
|
||||
self:AddAction( From, Event, "*" )
|
||||
|
||||
return Process
|
||||
end
|
||||
|
||||
function STATEMACHINE:GetSubs()
|
||||
|
||||
return self.options.subs
|
||||
end
|
||||
|
||||
|
||||
function STATEMACHINE:LoadCallBacks( CallBackTable )
|
||||
|
||||
for name, callback in pairs( CallBackTable or {} ) do
|
||||
@ -79,41 +121,54 @@ function STATEMACHINE:LoadCallBacks( CallBackTable )
|
||||
|
||||
end
|
||||
|
||||
function STATEMACHINE:_eventmap( events, event )
|
||||
|
||||
local name = event.name
|
||||
local __name = "__" .. event.name
|
||||
self[name] = self[name] or self:_create_transition(name)
|
||||
self[__name] = self[__name] or self:_delayed_transition(name)
|
||||
self:T( "Added methods: " .. name .. ", " .. __name )
|
||||
events[name] = self.events[name] or { map = {} }
|
||||
self:_add_to_map( events[name].map, event )
|
||||
|
||||
end
|
||||
|
||||
function STATEMACHINE:_submap( subs, sub, name )
|
||||
self:E( { sub = sub, name = name } )
|
||||
subs[sub.onstateparent] = subs[sub.onstateparent] or {}
|
||||
subs[sub.onstateparent][sub.oneventparent] = subs[sub.onstateparent][sub.oneventparent] or {}
|
||||
local Index = #subs[sub.onstateparent][sub.oneventparent] + 1
|
||||
subs[sub.onstateparent][sub.oneventparent][Index] = {}
|
||||
subs[sub.onstateparent][sub.oneventparent][Index].fsm = sub.fsm
|
||||
subs[sub.onstateparent][sub.oneventparent][Index].event = sub.event
|
||||
subs[sub.onstateparent][sub.oneventparent][Index].returnevents = sub.returnevents -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
|
||||
subs[sub.onstateparent][sub.oneventparent][Index].name = name
|
||||
subs[sub.onstateparent][sub.oneventparent][Index].fsmparent = self
|
||||
subs[sub.FromParent] = subs[sub.FromParent] or {}
|
||||
subs[sub.FromParent][sub.EventParent] = subs[sub.FromParent][sub.EventParent] or {}
|
||||
local Index = #subs[sub.FromParent][sub.EventParent] + 1
|
||||
subs[sub.FromParent][sub.EventParent][Index] = {}
|
||||
subs[sub.FromParent][sub.EventParent][Index].fsm = sub.fsm
|
||||
subs[sub.FromParent][sub.EventParent][Index].event = sub.event
|
||||
subs[sub.FromParent][sub.EventParent][Index].ReturnEvents = sub.ReturnEvents or {} -- these events need to be given to find the correct continue event ... if none given, the processing will stop.
|
||||
subs[sub.FromParent][sub.EventParent][Index].name = name
|
||||
subs[sub.FromParent][sub.EventParent][Index].fsmparent = self
|
||||
end
|
||||
|
||||
|
||||
function STATEMACHINE:_call_handler(handler, params)
|
||||
if handler then
|
||||
return handler( self, unpack(params) )
|
||||
if self[handler] then
|
||||
self:E( "Calling " .. handler )
|
||||
return self[handler]( self, unpack(params) )
|
||||
end
|
||||
end
|
||||
|
||||
function STATEMACHINE._handler( self, EventName, ... )
|
||||
|
||||
self:F( { EventName, ... } )
|
||||
self:E( { EventName, ... } )
|
||||
|
||||
local can, to = self:can(EventName)
|
||||
self:T( { EventName, can, to } )
|
||||
local can, to = self:can( EventName )
|
||||
self:E( { EventName, can, to } )
|
||||
|
||||
local ReturnValues = nil
|
||||
|
||||
if can then
|
||||
local from = self.current
|
||||
local params = { ..., EventName, from, to }
|
||||
local params = { EventName, from, to, ... }
|
||||
|
||||
if self:_call_handler(self["onbefore" .. EventName], params) == false
|
||||
or self:_call_handler(self["onleave" .. from], params) == false then
|
||||
if self:_call_handler("onbefore" .. EventName, params) == false
|
||||
or self:_call_handler("onleave" .. from, params) == false then
|
||||
return false
|
||||
end
|
||||
|
||||
@ -121,11 +176,15 @@ function STATEMACHINE._handler( self, EventName, ... )
|
||||
|
||||
local execute = true
|
||||
|
||||
local subtable = self:_gosub( to, EventName )
|
||||
local subtable = self:_gosub( from, EventName )
|
||||
for _, sub in pairs( subtable ) do
|
||||
--if sub.nextevent then
|
||||
-- self:F2( "nextevent = " .. sub.nextevent )
|
||||
-- self[sub.nextevent]( self )
|
||||
--end
|
||||
self:F2( "calling sub: " .. sub.event )
|
||||
sub.fsm.fsmparent = self
|
||||
sub.fsm.returnevents = sub.returnevents
|
||||
sub.fsm.ReturnEvents = sub.ReturnEvents
|
||||
sub.fsm[sub.event]( sub.fsm )
|
||||
execute = true
|
||||
end
|
||||
@ -133,28 +192,28 @@ function STATEMACHINE._handler( self, EventName, ... )
|
||||
local fsmparent, event = self:_isendstate( to )
|
||||
if fsmparent and event then
|
||||
self:F2( { "end state: ", fsmparent, event } )
|
||||
self:_call_handler(self["onenter" .. to] or self["on" .. to], params)
|
||||
self:_call_handler(self["onafter" .. EventName] or self["on" .. EventName], params)
|
||||
self:_call_handler(self["onstatechange"], params)
|
||||
self:_call_handler("onenter" .. to, params)
|
||||
self:_call_handler("onafter" .. EventName, params)
|
||||
self:_call_handler("onstatechange", params)
|
||||
fsmparent[event]( fsmparent )
|
||||
execute = false
|
||||
end
|
||||
|
||||
if execute then
|
||||
self:T3( { onenter = "onenter" .. to, callback = self["onenter" .. to] } )
|
||||
self:_call_handler(self["onenter" .. to] or self["on" .. to], params)
|
||||
self:_call_handler("onenter" .. to, params)
|
||||
|
||||
self:T3( { On = "OnBefore" .. to, callback = self["OnBefore" .. to] } )
|
||||
if ( self:_call_handler(self["OnBefore" .. to], params ) ~= false ) then
|
||||
if ( self:_call_handler("OnBefore" .. to, params ) ~= false ) then
|
||||
|
||||
self:T3( { onafter = "onafter" .. EventName, callback = self["onafter" .. EventName] } )
|
||||
self:_call_handler(self["onafter" .. EventName] or self["on" .. EventName], params)
|
||||
self:_call_handler("onafter" .. EventName, params)
|
||||
|
||||
self:T3( { On = "OnAfter" .. to, callback = self["OnAfter" .. to] } )
|
||||
ReturnValues = self:_call_handler(self["OnAfter" .. to], params )
|
||||
ReturnValues = self:_call_handler("OnAfter" .. to, params )
|
||||
end
|
||||
|
||||
self:_call_handler(self["onstatechange"], params)
|
||||
self:_call_handler("onstatechange", params)
|
||||
end
|
||||
|
||||
return ReturnValues
|
||||
@ -176,32 +235,30 @@ function STATEMACHINE:_create_transition( EventName )
|
||||
return function( self, ... ) return self._handler( self, EventName , ... ) end
|
||||
end
|
||||
|
||||
function STATEMACHINE:_gosub( parentstate, parentevent )
|
||||
function STATEMACHINE:_gosub( ParentFrom, ParentEvent )
|
||||
local fsmtable = {}
|
||||
if self.subs[parentstate] and self.subs[parentstate][parentevent] then
|
||||
return self.subs[parentstate][parentevent]
|
||||
if self.subs[ParentFrom] and self.subs[ParentFrom][ParentEvent] then
|
||||
self:E( { ParentFrom, ParentEvent, self.subs[ParentFrom] } )
|
||||
return self.subs[ParentFrom][ParentEvent]
|
||||
else
|
||||
return {}
|
||||
end
|
||||
end
|
||||
|
||||
function STATEMACHINE:_isendstate( state )
|
||||
local fsmparent = self.fsmparent
|
||||
if fsmparent and self.endstates[state] then
|
||||
self:E( { state = state, endstates = self.endstates, endstate = self.endstates[state] } )
|
||||
local returnevent = nil
|
||||
local fromstate = fsmparent.current
|
||||
self:E( fromstate )
|
||||
self:E( self.returnevents )
|
||||
for _, eventname in pairs( self.returnevents ) do
|
||||
local event = fsmparent.events[eventname]
|
||||
self:E( event )
|
||||
local to = event and event.map[fromstate] or event.map['*']
|
||||
if to and to == state then
|
||||
return fsmparent, eventname
|
||||
else
|
||||
self:E( { "could not find parent event name for state", fromstate, to } )
|
||||
end
|
||||
function STATEMACHINE:_isendstate( Current )
|
||||
local FSMParent = self.fsmparent
|
||||
if FSMParent and self.endstates[Current] then
|
||||
self:E( { state = Current, endstates = self.endstates, endstate = self.endstates[Current] } )
|
||||
FSMParent.current = Current
|
||||
local ParentFrom = FSMParent.current
|
||||
self:E( ParentFrom )
|
||||
self:E( self.ReturnEvents )
|
||||
local Event = self.ReturnEvents[Current]
|
||||
self:E( { ParentFrom, Event, self.ReturnEvents } )
|
||||
if Event then
|
||||
return FSMParent, Event
|
||||
else
|
||||
self:E( { "Could not find parent event name for state ", ParentFrom } )
|
||||
end
|
||||
end
|
||||
|
||||
@ -209,6 +266,7 @@ function STATEMACHINE:_isendstate( state )
|
||||
end
|
||||
|
||||
function STATEMACHINE:_add_to_map(map, event)
|
||||
self:E( { map, event } )
|
||||
if type(event.from) == 'string' then
|
||||
map[event.from] = event.to
|
||||
else
|
||||
@ -216,6 +274,7 @@ function STATEMACHINE:_add_to_map(map, event)
|
||||
map[from] = event.to
|
||||
end
|
||||
end
|
||||
self:E( { map, event } )
|
||||
end
|
||||
|
||||
function STATEMACHINE:is(state)
|
||||
@ -224,6 +283,7 @@ end
|
||||
|
||||
function STATEMACHINE:can(e)
|
||||
local event = self.events[e]
|
||||
self:E( { self.current, event } )
|
||||
local to = event and event.map[self.current] or event.map['*']
|
||||
return to ~= nil, to
|
||||
end
|
||||
@ -252,45 +312,11 @@ function STATEMACHINE:todot(filename)
|
||||
end
|
||||
|
||||
|
||||
--- STATEMACHINE_TASK class
|
||||
-- @type STATEMACHINE_TASK
|
||||
-- @field Task#TASK_BASE Task
|
||||
-- @extends StateMachine#STATEMACHINE
|
||||
STATEMACHINE_TASK = {
|
||||
ClassName = "STATEMACHINE_TASK",
|
||||
}
|
||||
|
||||
--- Creates a new STATEMACHINE_TASK object.
|
||||
-- @param #STATEMACHINE_TASK self
|
||||
-- @param #table FSMT
|
||||
-- @param Task#TASK_BASE Task
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #STATEMACHINE_TASK
|
||||
function STATEMACHINE_TASK:New( FSMT, Task, TaskUnit )
|
||||
|
||||
local self = BASE:Inherit( self, STATEMACHINE:New( FSMT ) ) -- StateMachine#STATEMACHINE_PROCESS
|
||||
|
||||
self["onstatechange"] = Task.OnStateChange
|
||||
self["onAssigned"] = Task.OnAssigned
|
||||
self["onSuccess"] = Task.OnSuccess
|
||||
self["onFailed"] = Task.OnFailed
|
||||
|
||||
self.Task = Task
|
||||
self.TaskUnit = TaskUnit
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function STATEMACHINE_TASK:_call_handler( handler, params )
|
||||
if handler then
|
||||
return handler( self.Task, self.TaskUnit, unpack( params ) )
|
||||
end
|
||||
end
|
||||
|
||||
--- STATEMACHINE_CONTROLLABLE class
|
||||
-- @type STATEMACHINE_CONTROLLABLE
|
||||
-- @field Controllable#CONTROLLABLE Controllable
|
||||
-- @extends StateMachine#STATEMACHINE
|
||||
-- @extends Core.StateMachine#STATEMACHINE
|
||||
STATEMACHINE_CONTROLLABLE = {
|
||||
ClassName = "STATEMACHINE_CONTROLLABLE",
|
||||
}
|
||||
@ -329,14 +355,16 @@ function STATEMACHINE_CONTROLLABLE:GetControllable()
|
||||
end
|
||||
|
||||
function STATEMACHINE_CONTROLLABLE:_call_handler( handler, params )
|
||||
if handler then
|
||||
return handler( self, self.Controllable, unpack( params ) )
|
||||
if self[handler] then
|
||||
self:E( "Calling " .. handler )
|
||||
return self[handler]( self, self.Controllable, unpack( params ) )
|
||||
end
|
||||
end
|
||||
|
||||
--- STATEMACHINE_PROCESS class
|
||||
-- @type STATEMACHINE_PROCESS
|
||||
-- @field Process#PROCESS Process
|
||||
-- @field Tasking.Task#TASK_BASE Task
|
||||
-- @extends Core.StateMachine#STATEMACHINE_CONTROLLABLE
|
||||
STATEMACHINE_PROCESS = {
|
||||
ClassName = "STATEMACHINE_PROCESS",
|
||||
@ -352,6 +380,92 @@ function STATEMACHINE_PROCESS:New( FSMT )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Sets the task of the process.
|
||||
-- @param #PROCESS self
|
||||
-- @param Tasking.Task#TASK_BASE Task
|
||||
-- @return #PROCESS
|
||||
function STATEMACHINE_PROCESS:SetTask( Task )
|
||||
|
||||
self.Task = Task
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Gets the task of the process.
|
||||
-- @param #PROCESS self
|
||||
-- @return Task#TASK_BASE
|
||||
function STATEMACHINE_PROCESS:GetTask()
|
||||
|
||||
return self.Task
|
||||
end
|
||||
|
||||
--- Gets the mission of the process.
|
||||
-- @param #PROCESS self
|
||||
-- @return Mission#MISSION
|
||||
function STATEMACHINE_PROCESS:GetMission()
|
||||
|
||||
return self.Task.Mission
|
||||
end
|
||||
|
||||
|
||||
--- Assign the process to a @{Unit} and activate the process.
|
||||
-- @param #PROCESS self
|
||||
-- @param Task.Tasking#TASK_BASE Task
|
||||
-- @param Wrapper.Unit#UNIT ProcessUnit
|
||||
-- @return #PROCESS self
|
||||
function STATEMACHINE_PROCESS:Assign( Task, ProcessUnit )
|
||||
self:E( { Task, ProcessUnit } )
|
||||
|
||||
self:SetControllable( ProcessUnit )
|
||||
self:SetTask( Task )
|
||||
|
||||
self.ProcessGroup = ProcessUnit:GetGroup()
|
||||
|
||||
--self:Activate()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function STATEMACHINE_PROCESS:onenterAssigned( ProcessUnit )
|
||||
|
||||
self.Task:Assign()
|
||||
end
|
||||
|
||||
function STATEMACHINE_PROCESS:onenterSuccess( ProcessUnit )
|
||||
|
||||
self.Task:Success()
|
||||
end
|
||||
|
||||
--- STATEMACHINE_TASK class
|
||||
-- @type STATEMACHINE_TASK
|
||||
-- @field Task#TASK_BASE Task
|
||||
-- @extends Core.StateMachine#STATEMACHINE
|
||||
STATEMACHINE_TASK = {
|
||||
ClassName = "STATEMACHINE_TASK",
|
||||
}
|
||||
|
||||
--- Creates a new STATEMACHINE_TASK object.
|
||||
-- @param #STATEMACHINE_TASK self
|
||||
-- @param #table FSMT
|
||||
-- @param Task#TASK_BASE Task
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #STATEMACHINE_TASK
|
||||
function STATEMACHINE_TASK:New( FSMT )
|
||||
|
||||
local self = BASE:Inherit( self, STATEMACHINE_CONTROLLABLE:New( FSMT ) ) -- Core.StateMachine#STATEMACHINE_TASK
|
||||
|
||||
self["onstatechange"] = self.OnStateChange
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function STATEMACHINE_TASK:_call_handler( handler, params )
|
||||
if self[handler] then
|
||||
self:E( "Calling " .. handler )
|
||||
return self[handler]( self, unpack( params ) )
|
||||
end
|
||||
end
|
||||
|
||||
do -- STATEMACHINE_SET
|
||||
|
||||
--- STATEMACHINE_SET class
|
||||
@ -396,8 +510,9 @@ function STATEMACHINE_SET:Get()
|
||||
end
|
||||
|
||||
function STATEMACHINE_SET:_call_handler( handler, params )
|
||||
if handler then
|
||||
return handler( self, self.Set, unpack( params ) )
|
||||
if self[handler] then
|
||||
self:E( "Calling " .. handler )
|
||||
return self[handler]( self, self.Set, unpack( params ) )
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
-- @field Group#GROUP ProcessGroup
|
||||
-- @field Menu#MENU_GROUP MissionMenu
|
||||
-- @field #string ProcessName
|
||||
-- @extends StateMachine#STATEMACHINE_CONTROLLABLE
|
||||
-- @extends Core.StateMachine#STATEMACHINE_CONTROLLABLE
|
||||
PROCESS = {
|
||||
ClassName = "PROCESS",
|
||||
NextEvent = nil,
|
||||
@ -19,7 +19,7 @@ PROCESS = {
|
||||
-- @param Unit#UNIT ProcessUnit (Optional) If provided, it defines the UNIT for which the process is running.
|
||||
-- @return #PROCESS
|
||||
function PROCESS:New( FSMT, ProcessName, ProcessUnit )
|
||||
local self = BASE:Inherit( self, STATEMACHINE_CONTROLLABLE:New( FSMT, ProcessUnit ) )
|
||||
local self = BASE:Inherit( self, STATEMACHINE_PROCESS:New( FSMT, ProcessUnit ) )
|
||||
self:F()
|
||||
|
||||
if ProcessUnit then
|
||||
@ -29,6 +29,7 @@ function PROCESS:New( FSMT, ProcessName, ProcessUnit )
|
||||
--self.MissionMenu = Task.Mission:GetMissionMenu( self.ProcessGroup )
|
||||
self.ProcessName = ProcessName
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
@ -40,74 +41,20 @@ function PROCESS:GetGroup()
|
||||
return self.ProcessGroup
|
||||
end
|
||||
|
||||
--- Sets the task of the process.
|
||||
-- @param #PROCESS self
|
||||
-- @param Tasking.Task#TASK_BASE ProcessTask
|
||||
-- @return #PROCESS
|
||||
function PROCESS:SetTask( ProcessTask )
|
||||
|
||||
self.ProcessTask = ProcessTask
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Gets the task of the process.
|
||||
-- @param #PROCESS self
|
||||
-- @return Task#TASK_BASE
|
||||
function PROCESS:GetTask()
|
||||
|
||||
return self.ProcessTask
|
||||
end
|
||||
|
||||
--- Gets the mission of the process.
|
||||
-- @param #PROCESS self
|
||||
-- @return Mission#MISSION
|
||||
function PROCESS:GetMission()
|
||||
|
||||
return self.ProcessTask.Mission
|
||||
end
|
||||
|
||||
function PROCESS:ProcessStart()
|
||||
|
||||
end
|
||||
|
||||
function PROCESS:ProcessStop()
|
||||
self:E("ProcessStop Base Class")
|
||||
|
||||
self:EventRemoveAll()
|
||||
end
|
||||
|
||||
--- Assign the process to a @{Unit} and activate the process.
|
||||
-- @param #PROCESS self
|
||||
-- @param Unit#UNIT ProcessUnit
|
||||
-- @return #PROCESS self
|
||||
function PROCESS:Assign( ProcessTask, ProcessUnit )
|
||||
|
||||
self:SetControllable( ProcessUnit )
|
||||
self:SetTask( ProcessTask )
|
||||
|
||||
self:ProcessStart()
|
||||
|
||||
self.ProcessGroup = ProcessUnit:GetGroup()
|
||||
--self:Activate()
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds a score for the PROCESS to be achieved.
|
||||
-- @param #PROCESS self
|
||||
-- @param Task#TASK_BASE Task The task for which the process needs to account score.
|
||||
-- @param #string ProcessStatus is the state of the process when the score needs to be given. (See the relevant state descriptions of the process).
|
||||
-- @param #string ScoreText is a text describing the score that is given according the status.
|
||||
-- @param #number Score is a number providing the score of the status.
|
||||
-- @return #PROCESS self
|
||||
function PROCESS:AddScore( Task, ProcessStatus, ScoreText, Score )
|
||||
function PROCESS:AddScore( ProcessStatus, ScoreText, Score )
|
||||
self:F2( { ProcessStatus, ScoreText, Score } )
|
||||
|
||||
self.Scores[ProcessStatus] = self.Scores[ProcessStatus] or {}
|
||||
self.Scores[ProcessStatus].ScoreText = ScoreText
|
||||
self.Scores[ProcessStatus].Score = Score
|
||||
self.Scores[ProcessStatus].Task = Task
|
||||
|
||||
return self
|
||||
end
|
||||
@ -118,17 +65,18 @@ end
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS:OnStateChange( ProcessUnit, Event, From, To )
|
||||
self:E( { self.ProcessName, Event, From, To, ProcessUnit.UnitName } )
|
||||
function PROCESS:onstatechange( ProcessUnit, Event, From, To, Dummy )
|
||||
self:E( { ProcessUnit, Event, From, To, Dummy } )
|
||||
|
||||
if self:IsTrace() then
|
||||
MESSAGE:New( "Process " .. self.ProcessName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll()
|
||||
end
|
||||
|
||||
self:E( self.Scores[To] )
|
||||
-- TODO: This needs to be reworked with a callback functions allocated within Task, and set within the mission script from the Task Objects...
|
||||
if self.Scores[To] then
|
||||
|
||||
local Task = self.Scores[To].Task
|
||||
local Task = self.Task
|
||||
local Scoring = Task:GetScoring()
|
||||
if Scoring then
|
||||
Scoring:_AddMissionTaskScore( Task.Mission, ProcessUnit, self.Scores[To].ScoreText, self.Scores[To].Score )
|
||||
|
||||
@ -275,18 +275,20 @@ function SCORING:_AddMissionTaskScore( Mission, PlayerUnit, Text, Score )
|
||||
local MissionName = Mission:GetName()
|
||||
|
||||
self:F( { Mission:GetName(), PlayerUnit.UnitName, PlayerName, Text, Score } )
|
||||
|
||||
local PlayerData = self.Players[PlayerName]
|
||||
|
||||
if not self.Players[PlayerName].Mission[MissionName] then
|
||||
self.Players[PlayerName].Mission[MissionName] = {}
|
||||
self.Players[PlayerName].Mission[MissionName].ScoreTask = 0
|
||||
self.Players[PlayerName].Mission[MissionName].ScoreMission = 0
|
||||
if not PlayerData.Mission[MissionName] then
|
||||
PlayerData.Mission[MissionName] = {}
|
||||
PlayerData.Mission[MissionName].ScoreTask = 0
|
||||
PlayerData.Mission[MissionName].ScoreMission = 0
|
||||
end
|
||||
|
||||
self:T( PlayerName )
|
||||
self:T( self.Players[PlayerName].Mission[MissionName] )
|
||||
self:T( PlayerData.Mission[MissionName] )
|
||||
|
||||
self.Players[PlayerName].Score = self.Players[PlayerName].Score + Score
|
||||
self.Players[PlayerName].Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
|
||||
PlayerData.Score = self.Players[PlayerName].Score + Score
|
||||
PlayerData.Mission[MissionName].ScoreTask = self.Players[PlayerName].Mission[MissionName].ScoreTask + Score
|
||||
|
||||
MESSAGE:New( "Player '" .. PlayerName .. "' has " .. Text .. " in Mission '" .. MissionName .. "'. " ..
|
||||
Score .. " task score!",
|
||||
@ -306,10 +308,12 @@ function SCORING:_AddMissionScore( Mission, Text, Score )
|
||||
|
||||
local MissionName = Mission:GetName()
|
||||
|
||||
self:F( { Mission, Text, Score } )
|
||||
self:E( { Mission, Text, Score } )
|
||||
self:E( self.Players )
|
||||
|
||||
for PlayerName, PlayerData in pairs( self.Players ) do
|
||||
|
||||
self:E( PlayerData )
|
||||
if PlayerData.Mission[MissionName] then
|
||||
|
||||
PlayerData.Score = PlayerData.Score + Score
|
||||
|
||||
@ -96,10 +96,10 @@ do -- PROCESS_ACCOUNT
|
||||
{ name = 'Report', from = '*', to = 'Report' },
|
||||
{ name = 'Event', from = '*', to = 'Account' },
|
||||
{ name = 'More', from = 'Account', to = 'Wait' },
|
||||
{ name = 'NoMore', from = 'Account', to = 'Success' },
|
||||
{ name = 'NoMore', from = 'Account', to = 'Accounted' },
|
||||
{ name = 'Fail', from = '*', to = 'Failed' },
|
||||
},
|
||||
endstates = { 'Success', 'Failed' }
|
||||
endstates = { 'Accounted', 'Failed' }
|
||||
}
|
||||
|
||||
-- Inherits from BASE
|
||||
@ -124,8 +124,11 @@ do -- PROCESS_ACCOUNT
|
||||
-- @param #string To
|
||||
function PROCESS_ACCOUNT:onafterStart( ProcessUnit, Event, From, To )
|
||||
|
||||
self:EventOnDead( self.EventDead )
|
||||
|
||||
self:__Wait( 1 )
|
||||
end
|
||||
|
||||
|
||||
--- StateMachine callback function
|
||||
-- @param #PROCESS_ACCOUNT self
|
||||
@ -169,6 +172,15 @@ do -- PROCESS_ACCOUNT_DEADS
|
||||
TargetSetUnit = nil,
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new DESTROY process.
|
||||
-- @param #PROCESS_ACCOUNT_DEADS self
|
||||
-- @param Set#SET_UNIT TargetSetUnit
|
||||
-- @param #string TaskName
|
||||
function PROCESS_ACCOUNT_DEADS:Template( TargetSetUnit, TaskName )
|
||||
return { self, arg }
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new DESTROY process.
|
||||
-- @param #PROCESS_ACCOUNT_DEADS self
|
||||
@ -182,12 +194,15 @@ do -- PROCESS_ACCOUNT_DEADS
|
||||
|
||||
self.TargetSetUnit = TargetSetUnit
|
||||
self.TaskName = TaskName
|
||||
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
function PROCESS_ACCOUNT_DEADS:_Destructor()
|
||||
self:E("_Destructor")
|
||||
|
||||
self:RemoveEventsAll()
|
||||
|
||||
function PROCESS_ACCOUNT_DEADS:ProcessStart()
|
||||
self:EventOnDead( self.EventDead )
|
||||
end
|
||||
|
||||
--- Process Events
|
||||
@ -199,6 +214,7 @@ do -- PROCESS_ACCOUNT_DEADS
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_ACCOUNT_DEADS:onenterReport( ProcessUnit, Event, From, To )
|
||||
self:E( { ProcessUnit, Event, From, To } )
|
||||
|
||||
local TaskGroup = ProcessUnit:GetGroup()
|
||||
MESSAGE:New( "Your group with assigned " .. self.TaskName .. " task has " .. self.TargetSetUnit:GetUnitTypesText() .. " targets left to be destroyed.", 5, "HQ" ):ToGroup( TaskGroup )
|
||||
@ -211,7 +227,7 @@ do -- PROCESS_ACCOUNT_DEADS
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_ACCOUNT_DEADS:onenterAccount( ProcessUnit, EventData, Event, From, To )
|
||||
function PROCESS_ACCOUNT_DEADS:onenterAccount( ProcessUnit, Event, From, To, EventData )
|
||||
self:T( { ProcessUnit, EventData, Event, From, To } )
|
||||
|
||||
self:T({self.Controllable})
|
||||
|
||||
@ -134,6 +134,14 @@ do -- PROCESS_ASSIGN_ACCEPT
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new task assignment state machine. The process will accept the task by default, no player intervention accepted.
|
||||
-- @param #PROCESS_ASSIGN_ACCEPT self
|
||||
-- @param #string TaskBriefing
|
||||
function PROCESS_ASSIGN_ACCEPT:Template( TaskBriefing )
|
||||
return { self, { TaskBriefing } }
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new task assignment state machine. The process will accept the task by default, no player intervention accepted.
|
||||
-- @param #PROCESS_ASSIGN_ACCEPT self
|
||||
-- @param #string TaskBriefing
|
||||
|
||||
@ -107,7 +107,7 @@ do -- PROCESS_ROUTE
|
||||
{ name = 'Fail', from = '*', to = 'Failed' },
|
||||
},
|
||||
endstates = {
|
||||
'Arrived', 'Failed', 'Success'
|
||||
'Arrived', 'Failed'
|
||||
},
|
||||
}
|
||||
|
||||
@ -150,10 +150,10 @@ do -- PROCESS_ROUTE
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
function PROCESS_ROUTE:onafterRoute( ProcessUnit, Event, From, To )
|
||||
function PROCESS_ROUTE:onbeforeRoute( ProcessUnit, Event, From, To )
|
||||
|
||||
if ProcessUnit:IsAlive() then
|
||||
local HasArrived = self:HasArrived( ProcessUnit )
|
||||
local HasArrived = self:HasArrived( ProcessUnit ) -- Polymorphic
|
||||
if self.DisplayCount >= self.DisplayInterval then
|
||||
self:T( { HasArrived = HasArrived } )
|
||||
if not HasArrived then
|
||||
@ -165,7 +165,12 @@ do -- PROCESS_ROUTE
|
||||
end
|
||||
|
||||
self:T( { DisplayCount = self.DisplayCount } )
|
||||
self:__Route( 1 )
|
||||
|
||||
if HasArrived then
|
||||
self:__Arrive( 1 )
|
||||
else
|
||||
self:__Route( 1 )
|
||||
end
|
||||
|
||||
return HasArrived -- if false, then the event will not be executed...
|
||||
end
|
||||
@ -189,6 +194,14 @@ do -- PROCESS_ROUTE_ZONE
|
||||
PROCESS_ROUTE_ZONE = {
|
||||
ClassName = "PROCESS_ROUTE_ZONE",
|
||||
}
|
||||
|
||||
|
||||
--- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE.
|
||||
-- @param #PROCESS_ROUTE_ZONE self
|
||||
-- @param Zone#ZONE_BASE TargetZone
|
||||
function PROCESS_ROUTE_ZONE:Template( TargetZone )
|
||||
return { self, arg }
|
||||
end
|
||||
|
||||
|
||||
--- Creates a new routing state machine. The task will route a controllable to a ZONE until the controllable is within that ZONE.
|
||||
@ -206,9 +219,15 @@ do -- PROCESS_ROUTE_ZONE
|
||||
|
||||
--- Method override to check if the controllable has arrived.
|
||||
-- @param #PROCESS_ROUTE self
|
||||
-- @param Controllable#CONTROLLABLE ProcessUnit
|
||||
-- @param Wrapper.Controllable#CONTROLLABLE ProcessUnit
|
||||
-- @return #boolean
|
||||
function PROCESS_ROUTE_ZONE:HasArrived( ProcessUnit )
|
||||
|
||||
if ProcessUnit:IsInZone( self.TargetZone ) then
|
||||
local RouteText = ProcessUnit:GetCallsign() .. ": You have arrived within the zone!"
|
||||
MESSAGE:New( RouteText, self.DisplayTime, self.DisplayCategory ):ToGroup( ProcessUnit:GetGroup() )
|
||||
end
|
||||
|
||||
return ProcessUnit:IsInZone( self.TargetZone )
|
||||
end
|
||||
|
||||
|
||||
@ -144,13 +144,20 @@ do -- PROCESS_SMOKE_TARGETS_ZONE
|
||||
ClassName = "PROCESS_SMOKE_TARGETS_ZONE",
|
||||
}
|
||||
|
||||
function PROCESS_SMOKE_TARGETS_ZONE:ProcessStop()
|
||||
self:E("ProcessStop Detailed")
|
||||
function PROCESS_SMOKE_TARGETS_ZONE:_Destructor()
|
||||
self:E("_Destructor")
|
||||
|
||||
self.Menu:Remove()
|
||||
|
||||
self:EventRemoveAll()
|
||||
end
|
||||
|
||||
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
|
||||
-- @param #PROCESS_SMOKE_TARGETS_ZONE self
|
||||
-- @param Set#SET_UNIT TargetSetUnit
|
||||
-- @param Zone#ZONE_BASE TargetZone
|
||||
function PROCESS_SMOKE_TARGETS_ZONE:Template( TargetSetUnit, TargetZone )
|
||||
return { self, arg }
|
||||
end
|
||||
|
||||
--- Creates a new target smoking state machine. The process will request from the menu if it accepts the task, if not, the unit is removed from the simulator.
|
||||
-- @param #PROCESS_SMOKE_TARGETS_ZONE self
|
||||
|
||||
@ -9,8 +9,8 @@
|
||||
-- * @{#TASK_BASE.AssignToGroup}():Assign a task to a group (of players).
|
||||
-- * @{#TASK_BASE.AddProcess}():Add a @{Process} to a task.
|
||||
-- * @{#TASK_BASE.RemoveProcesses}():Remove a running @{Process} from a running task.
|
||||
-- * @{#TASK_BASE.AddStateMachine}():Add a @{StateMachine} to a task.
|
||||
-- * @{#TASK_BASE.RemoveStateMachines}():Remove @{StateMachine}s from a task.
|
||||
-- * @{#TASK_BASE.SetStateMachine}():Set a @{StateMachine} to a task.
|
||||
-- * @{#TASK_BASE.RemoveStateMachine}():Remove @{StateMachine} from a task.
|
||||
-- * @{#TASK_BASE.HasStateMachine}():Enquire if the task has a @{StateMachine}
|
||||
-- * @{#TASK_BASE.AssignToUnit}(): Assign a task to a unit. (Needs to be implemented in the derived classes from @{#TASK_BASE}.
|
||||
-- * @{#TASK_BASE.UnAssignFromUnit}(): Unassign the task from a unit.
|
||||
@ -69,22 +69,29 @@ TASK_BASE = {
|
||||
|
||||
--- Instantiates a new TASK_BASE. Should never be used. Interface Class.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Mission#MISSION The mission wherein the Task is registered.
|
||||
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
|
||||
-- @param Mission#MISSION Mission The mission wherein the Task is registered.
|
||||
-- @param Set#SET_GROUP SetGroupAssign The set of groups for which the Task can be assigned.
|
||||
-- @param #string TaskName The name of the Task
|
||||
-- @param #string TaskType The type of the Task
|
||||
-- @param #string TaskCategory The category of the Task (A2G, A2A, Transport, ... )
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, TaskCategory )
|
||||
function TASK_BASE:New( Mission, SetGroupAssign, TaskName, TaskType, TaskCategory )
|
||||
|
||||
|
||||
local self = BASE:Inherit( self, STATEMACHINE_TASK:New( {} ) )
|
||||
|
||||
self:SetInitialState( "Planned" )
|
||||
self:AddAction( "Planned", "Assign", "Assigned" )
|
||||
self:AddAction( "Assigned", "Success", "Success" )
|
||||
self:AddAction( "*", "Fail", "Failed" )
|
||||
|
||||
local self = BASE:Inherit( self, BASE:New() )
|
||||
self:E( "New TASK " .. TaskName )
|
||||
|
||||
self.Processes = {}
|
||||
self.Fsm = {}
|
||||
|
||||
self.Mission = Mission
|
||||
self.SetGroup = SetGroup
|
||||
self.SetGroup = SetGroupAssign
|
||||
|
||||
self:SetCategory( TaskCategory )
|
||||
self:SetType( TaskType )
|
||||
@ -92,6 +99,9 @@ function TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, TaskCategory )
|
||||
self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences ..
|
||||
|
||||
self.TaskBriefing = "You are assigned to the task: " .. self.TaskName .. "."
|
||||
|
||||
self.FsmTemplate = self.FsmTemplate or STATEMACHINE_PROCESS:New( {} )
|
||||
self.FsmTemplate:SetTask( self )
|
||||
|
||||
return self
|
||||
end
|
||||
@ -109,6 +119,10 @@ function TASK_BASE:CleanUp()
|
||||
return nil
|
||||
end
|
||||
|
||||
function TASK_BASE:GetFsmTemplate()
|
||||
|
||||
return self.FsmTemplate
|
||||
end
|
||||
|
||||
--- Assign the @{Task}to a @{Group}.
|
||||
-- @param #TASK_BASE self
|
||||
@ -128,6 +142,7 @@ function TASK_BASE:AssignToGroup( TaskGroup )
|
||||
for UnitID, UnitData in pairs( TaskUnits ) do
|
||||
local TaskUnit = UnitData -- Unit#UNIT
|
||||
local PlayerName = TaskUnit:GetPlayerName()
|
||||
self:E(PlayerName)
|
||||
if PlayerName ~= nil or PlayerName ~= "" then
|
||||
self:AssignToUnit( TaskUnit )
|
||||
end
|
||||
@ -136,6 +151,66 @@ function TASK_BASE:AssignToGroup( TaskGroup )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Assign the @{Task} to an alive @{Unit}.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:AssignToUnit( TaskUnit )
|
||||
self:F( TaskUnit:GetName() )
|
||||
|
||||
-- Copy the FsmTemplate, which is not assigned to a Unit.
|
||||
-- Assign the FsmTemplate to the TaskUnit.
|
||||
local FsmTemplate = self:GetFsmTemplate()
|
||||
local FsmUnit = UTILS.DeepCopy( FsmTemplate )
|
||||
FsmUnit:Assign( self, TaskUnit )
|
||||
|
||||
-- Assign each FsmSub in FsmUnit to the TaskUnit.
|
||||
-- (This is not done during the copy).
|
||||
self:E(FsmUnit:GetSubs())
|
||||
for FsmSubID, FsmSub in pairs( FsmUnit:GetSubs() ) do
|
||||
self:E( { "Sub ID", FsmSub.fsm:GetClassNameAndID(), FsmSubID } )
|
||||
FsmSub.fsm:Assign( self, TaskUnit )
|
||||
end
|
||||
|
||||
|
||||
-- for TransitionID, TransitionTemplate in ipairs( self.TransitionTemplates ) do
|
||||
-- self:E( TransitionTemplate )
|
||||
-- FSM:AddTransition( TransitionTemplate.From, TransitionTemplate.Event, TransitionTemplate.To )
|
||||
-- end
|
||||
|
||||
-- Copy each ProcessTemplate for the TaskUnit that is alive, as set as a template at the Parent.
|
||||
-- Each Process will start From a state, upon a fired Event.
|
||||
-- Upon finalization of the Process, the ReturnEvents contain for which Return state which Event of the Parent needs to be fired.
|
||||
-- The Return state of the Process is transferred to the Parent.
|
||||
-- for ProcessID, ProcessTemplate in ipairs( self.ProcessTemplates ) do
|
||||
-- FSM:AddProcess( ProcessTemplate.From, ProcessTemplate.Event, Process, ProcessTemplate.ReturnEvents )
|
||||
-- self:E( { "Process ID", Process:GetClassNameAndID() } )
|
||||
-- Process:Assign( self, TaskUnit )
|
||||
-- end
|
||||
|
||||
FsmUnit:SetInitialState( "Planned" )
|
||||
FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow.
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- UnAssign the @{Task} from an alive @{Unit}.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:UnAssignFromUnit( TaskUnitName )
|
||||
self:F( TaskUnitName )
|
||||
|
||||
if self:HasStateMachine( TaskUnitName ) == true then
|
||||
self:E("RemoveStateMachines")
|
||||
self:RemoveStateMachine( TaskUnitName )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
|
||||
--- Send the briefng message of the @{Task} to the assigned @{Group}s.
|
||||
-- @param #TASK_BASE self
|
||||
function TASK_BASE:SendBriefingToAssignedGroups()
|
||||
@ -186,33 +261,6 @@ function TASK_BASE:IsAssignedToGroup( TaskGroup )
|
||||
return false
|
||||
end
|
||||
|
||||
--- Assign the @{Task} to an alive @{Unit}.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:AssignToUnit( TaskUnit )
|
||||
self:F( TaskUnit:GetName() )
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
--- UnAssign the @{Task} from an alive @{Unit}.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:UnAssignFromUnit( TaskUnitName )
|
||||
self:F( TaskUnitName )
|
||||
|
||||
if self:HasStateMachine( TaskUnitName ) == true then
|
||||
self:E("RemoveStateMachines")
|
||||
self:RemoveStateMachines( TaskUnitName )
|
||||
self:E("RemoveProcesses")
|
||||
self:RemoveProcesses( TaskUnitName )
|
||||
end
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
--- Set the menu options of the @{Task} to all the groups in the SetGroup.
|
||||
-- @param #TASK_BASE self
|
||||
-- @return #TASK_BASE self
|
||||
@ -406,31 +454,6 @@ function TASK_BASE:GetTaskName()
|
||||
end
|
||||
|
||||
|
||||
--- This is the key worker function for the class. Instantiate a new Process based on the ProcessName to @{Task} and assign it to the ProcessUnit.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT ProcessUnit The unit to which the process should be assigned.
|
||||
-- @param #string ProcessName The name of the Process.
|
||||
-- @return Process#PROCESS The Process that was added.
|
||||
function TASK_BASE:AssignProcess( ProcessUnit, ProcessName )
|
||||
self:F( { ProcessName } )
|
||||
local ProcessUnitName = ProcessUnit:GetName()
|
||||
|
||||
-- Create the Process instance base on the ProcessClasses collection assigned to the Task
|
||||
local ProcessTemplate, ProcessArguments
|
||||
ProcessTemplate = self:GetProcessTemplate( ProcessName )
|
||||
|
||||
self:E( "Deepcopy" )
|
||||
-- This statement copies the process template assigned to the task and creates a new process.
|
||||
local Process = UTILS.DeepCopy( ProcessTemplate ) -- Fsm.Process#PROCESS
|
||||
Process:Assign( self, ProcessUnit )
|
||||
|
||||
self.Processes = self.Processes or {}
|
||||
self.Processes[ProcessUnitName] = self.Processes[ProcessUnitName] or {}
|
||||
|
||||
self.Processes[ProcessUnitName][ProcessName] = Process
|
||||
|
||||
return Process
|
||||
end
|
||||
|
||||
|
||||
--- Get the default or currently assigned @{Process} template with key ProcessName.
|
||||
@ -445,35 +468,6 @@ function TASK_BASE:GetProcessTemplate( ProcessName )
|
||||
end
|
||||
|
||||
|
||||
--- Set the default @{Process} template with key ProcessName providing the ProcessClass and the process object when it is assigned to a @{Controllable} by the task.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param #string ProcessName
|
||||
-- @param Process#PROCESS ProcessTemplate
|
||||
-- @return Process#PROCESS
|
||||
function TASK_BASE:SetProcessTemplate( ProcessName, ProcessTemplate )
|
||||
|
||||
self.ProcessClasses[ProcessName] = ProcessTemplate
|
||||
|
||||
return ProcessTemplate
|
||||
end
|
||||
|
||||
|
||||
--- Remove Processes from @{Task} with key @{Unit}
|
||||
-- @param #TASK_BASE self
|
||||
-- @param #string TaskUnitName
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:RemoveProcesses( TaskUnitName )
|
||||
self:E( TaskUnitName )
|
||||
|
||||
for ProcessID, ProcessData in pairs( self.Processes[TaskUnitName] ) do
|
||||
local Process = ProcessData -- Process.Process#PROCESS
|
||||
Process:ProcessStop()
|
||||
Process = nil
|
||||
self.Processes[TaskUnitName][ProcessID] = nil
|
||||
self:E( self.Processes[TaskUnitName][ProcessID] )
|
||||
end
|
||||
self.Processes[TaskUnitName] = nil
|
||||
end
|
||||
|
||||
--- Fail processes from @{Task} with key @{Unit}
|
||||
-- @param #TASK_BASE self
|
||||
@ -491,10 +485,10 @@ end
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:AddStateMachine( TaskUnit, Fsm )
|
||||
function TASK_BASE:SetStateMachine( TaskUnit, Fsm )
|
||||
local TaskUnitName = TaskUnit:GetName()
|
||||
self.Fsm[TaskUnitName] = self.Fsm[TaskUnitName] or {}
|
||||
self.Fsm[TaskUnitName][#self.Fsm[TaskUnitName]+1] = Fsm
|
||||
self.Fsm[TaskUnitName] = Fsm
|
||||
|
||||
return Fsm
|
||||
end
|
||||
|
||||
@ -502,14 +496,10 @@ end
|
||||
-- @param #TASK_BASE self
|
||||
-- @param #string TaskUnitName
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:RemoveStateMachines( TaskUnitName )
|
||||
function TASK_BASE:RemoveStateMachine( TaskUnitName )
|
||||
|
||||
for _, Fsm in pairs( self.Fsm[TaskUnitName] ) do
|
||||
Fsm = nil
|
||||
self.Fsm[TaskUnitName][_] = nil
|
||||
self:E( self.Fsm[TaskUnitName][_] )
|
||||
end
|
||||
self.Fsm[TaskUnitName] = nil
|
||||
collectgarbage()
|
||||
end
|
||||
|
||||
--- Checks if there is a FiniteStateMachine assigned to @{Unit} for @{Task}
|
||||
@ -609,7 +599,7 @@ end
|
||||
|
||||
--- Gets the Scoring of the task
|
||||
-- @param #TASK_BASE self
|
||||
-- @return Scoring#SCORING Scoring
|
||||
-- @return Functional.Scoring#SCORING Scoring
|
||||
function TASK_BASE:GetScoring()
|
||||
return self.Mission:GetScoring()
|
||||
end
|
||||
@ -785,7 +775,7 @@ end
|
||||
-- @param #string ScoreText is a text describing the score that is given according the status.
|
||||
-- @param #number Score is a number providing the score of the status.
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:AddScore( TaskStatus, ScoreText, Score )
|
||||
function TASK_BASE:AddScoreTask( TaskStatus, ScoreText, Score )
|
||||
self:F2( { TaskStatus, ScoreText, Score } )
|
||||
|
||||
self.Scores[TaskStatus] = self.Scores[TaskStatus] or {}
|
||||
@ -794,26 +784,35 @@ function TASK_BASE:AddScore( TaskStatus, ScoreText, Score )
|
||||
return self
|
||||
end
|
||||
|
||||
--- Adds a score for the TASK to be achieved.
|
||||
-- @param #TASK_BASE self
|
||||
-- @param #string TaskStatus is the status of the TASK when the score needs to be given.
|
||||
-- @param #string ScoreText is a text describing the score that is given according the status.
|
||||
-- @param #number Score is a number providing the score of the status.
|
||||
-- @return #TASK_BASE self
|
||||
function TASK_BASE:AddScoreProcess( Event, State, ScoreText, Score )
|
||||
self:F2( { State, ScoreText, Score } )
|
||||
|
||||
|
||||
self:E( self:GetFsmTemplate():GetSubs()[Event].fsm )
|
||||
local Process = self:GetFsmTemplate():GetSubs()[Event].fsm
|
||||
|
||||
Process:AddScore( State, ScoreText, Score )
|
||||
|
||||
return self
|
||||
end
|
||||
|
||||
|
||||
--- StateMachine callback function for a TASK
|
||||
-- @param #TASK_BASE self
|
||||
-- @param Unit#UNIT TaskUnit
|
||||
-- @param StateMachine#STATEMACHINE_TASK Fsm
|
||||
-- @param #string Event
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Event#EVENTDATA Event
|
||||
function TASK_BASE:OnAssigned( TaskUnit, Fsm, Event, From, To )
|
||||
function TASK_BASE:onenterAssigned( Fsm, Event, From, To )
|
||||
|
||||
self:E("Assigned")
|
||||
|
||||
local TaskGroup = TaskUnit:GetGroup()
|
||||
|
||||
TaskGroup:Message( self.TaskBriefing, 20 )
|
||||
|
||||
self:RemoveMenuForGroup( TaskGroup )
|
||||
self:SetAssignedMenuForGroup( TaskGroup )
|
||||
|
||||
end
|
||||
|
||||
|
||||
@ -825,19 +824,9 @@ end
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Event#EVENTDATA Event
|
||||
function TASK_BASE:OnSuccess( TaskUnit, Fsm, Event, From, To )
|
||||
function TASK_BASE:onenterSuccess( TaskUnit, Fsm, Event, From, To )
|
||||
|
||||
self:E("Success")
|
||||
|
||||
self:UnAssignFromGroups()
|
||||
self:RemoveMenu()
|
||||
|
||||
local TaskGroup = TaskUnit:GetGroup()
|
||||
|
||||
self:StateSuccess()
|
||||
|
||||
-- The task has become successful, the event catchers can be cleaned.
|
||||
self:EventRemoveAll()
|
||||
end
|
||||
|
||||
--- StateMachine callback function for a TASK
|
||||
@ -869,17 +858,18 @@ end
|
||||
-- @param #string From
|
||||
-- @param #string To
|
||||
-- @param Event#EVENTDATA Event
|
||||
function TASK_BASE:OnStateChange( TaskUnit, Fsm, Event, From, To )
|
||||
function TASK_BASE:onstatechange( Event, From, To )
|
||||
|
||||
if self:IsTrace() then
|
||||
MESSAGE:New( "Task " .. self.TaskName .. " : " .. Event .. " changed to state " .. To, 15 ):ToAll()
|
||||
end
|
||||
|
||||
self:E( { Event, From, To } )
|
||||
self:SetState( self, "State", To )
|
||||
self:E( { Event, From, To, self:IsTrace() } )
|
||||
self:E( self.Scores )
|
||||
|
||||
if self.Scores[To] then
|
||||
local Scoring = self:GetScoring()
|
||||
self:E( Scoring )
|
||||
if Scoring then
|
||||
Scoring:_AddMissionScore( self.Mission, self.Scores[To].ScoreText, self.Scores[To].Score )
|
||||
end
|
||||
|
||||
@ -67,8 +67,7 @@ do -- TASK_SEAD
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
--- Assign the @{Task} to a @{Unit}.
|
||||
-- @param #TASK_SEAD self
|
||||
@ -85,7 +84,7 @@ do -- TASK_SEAD
|
||||
local FSMT = {
|
||||
initial = 'None',
|
||||
events = {
|
||||
{ name = 'Next', from = 'None', to = 'Planned' },
|
||||
{ name = 'Start', from = 'None', to = 'Planned' },
|
||||
{ name = 'Next', from = 'Planned', to = 'Assigned' },
|
||||
{ name = 'Reject', from = 'Planned', to = 'Rejected' },
|
||||
{ name = 'Next', from = 'Assigned', to = 'Success' },
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
|
||||
env.info( "Lua Version = " .. _VERSION )
|
||||
|
||||
local Mission = MISSION:New( 'SEAD Targets', "Strategic", "SEAD the enemy", coalition.side.RED )
|
||||
local Scoring = SCORING:New( "SEAD" )
|
||||
|
||||
@ -9,23 +11,32 @@ local TargetSet = SET_UNIT:New():FilterPrefixes( "US Hawk SR" ):FilterOnce()
|
||||
|
||||
local TargetZone = ZONE:New( "Target Zone" )
|
||||
|
||||
local TaskSEAD = TASK_SEAD
|
||||
:New( Mission, SEADSet, "SEAD Radars", TargetSet, TargetZone )
|
||||
local TaskSEAD = TASK_BASE:New( Mission, SEADSet, "SEAD Radars", "A2G", "SEAD" ) -- Tasking.Task#TASK_BASE
|
||||
--:New( Mission, SEADSet, "SEAD Radars", TargetSet, TargetZone )
|
||||
|
||||
TaskSEAD:AddScore( "Success", "Destroyed all target radars", 250 )
|
||||
TaskSEAD:AddScore( "Failed", "Failed to destroy all target radars", -100 )
|
||||
local FsmSEAD = TaskSEAD:GetFsmTemplate()
|
||||
|
||||
local AssignProcess = TaskSEAD:SetProcessTemplate( "ASSIGN", PROCESS_ASSIGN_MENU_ACCEPT:New( "SEAD", "Hello World" ) )
|
||||
AssignProcess:AddScore( TaskSEAD, "Assign", "You are assigned to the task", 10 )
|
||||
FsmSEAD:AddProcess( "Planned", "Accept", PROCESS_ASSIGN_ACCEPT:New( "SEAD the Area" ), { Assigned = "Route", Rejected = "Eject" } )
|
||||
FsmSEAD:AddProcess( "Assigned", "Route", PROCESS_ROUTE_ZONE:New( TargetZone, 3000 ), { Arrived = "Update" } )
|
||||
FsmSEAD:AddAction ( "Rejected", "Eject", "Planned" )
|
||||
FsmSEAD:AddAction ( "Arrived", "Update", "Updated" )
|
||||
FsmSEAD:AddProcess( "Updated", "Account", PROCESS_ACCOUNT_DEADS:New( TargetSet, "SEAD" ), { Accounted = "Success" } )
|
||||
FsmSEAD:AddProcess( "Updated", "Smoke", PROCESS_SMOKE_TARGETS_ZONE:New( TargetSet, TargetZone ) )
|
||||
FsmSEAD:AddAction ( "Accounted", "Success", "Success" )
|
||||
FsmSEAD:AddAction ( "Failed", "Fail", "Failed" )
|
||||
|
||||
local AccountProcess = TaskSEAD:SetProcessTemplate( "ACCOUNT", PROCESS_ACCOUNT_DEADS:New( TargetSet, "SEAD" ) )
|
||||
AccountProcess:AddScore( TaskSEAD, "Account", "destroyed a radar", 25 )
|
||||
AccountProcess:AddScore( TaskSEAD, "Failed", "failed to destroy a radar", -100 )
|
||||
TaskSEAD:AddScoreTask( "Success", "Destroyed all target radars", 250 )
|
||||
TaskSEAD:AddScoreTask( "Failed", "Failed to destroy all target radars", -100 )
|
||||
TaskSEAD:AddScoreProcess( "Account", "Account", "destroyed a radar", 25 )
|
||||
TaskSEAD:AddScoreProcess( "Account", "Fail", "failed to destroy a radar", -100 )
|
||||
|
||||
--local SmokeProcess = TaskSEAD:SetProcessTemplate( "SMOKE", PROCESS_SMOKE_TARGETS_ZONE:New( TargetSet, TargetZone ) )
|
||||
--SmokeProcess:SetAttackGroup( GROUP:FindByName( "SmokeGroup" ), "Watchdog" )
|
||||
--SmokeProcess:AddScore( TaskSEAD, "Account", "destroyed a radar", 25 )
|
||||
--SmokeProcess:AddScore( TaskSEAD, "Failed", "failed to destroy a radar", -100 )
|
||||
function FsmSEAD:onenterUpdated( TaskUnit )
|
||||
self:E( { self } )
|
||||
self:Account()
|
||||
self:Smoke()
|
||||
end
|
||||
|
||||
-- Needs to be checked, should not be necessary ...
|
||||
TaskSEAD:AssignToGroup( SEADSet:Get( "Test SEAD" ) )
|
||||
|
||||
Mission:AddTask( TaskSEAD )
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user