diff --git a/Moose Development/Moose/Set.lua b/Moose Development/Moose/Set.lua index 628d57b75..bd8a9c97d 100644 --- a/Moose Development/Moose/Set.lua +++ b/Moose Development/Moose/Set.lua @@ -228,6 +228,7 @@ SET_BASE = { ClassName = "SET_BASE", Set = {}, + List = {}, } --- Creates a new SET_BASE object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names. @@ -246,6 +247,10 @@ function SET_BASE:New( Database ) self.YieldInterval = 10 self.TimeInterval = 0.001 + self.List = {} + self.List.__index = self.List + self.List = setmetatable( { Count = 0 }, self.List ) + return self end @@ -275,18 +280,72 @@ end -- @param Base#BASE Object -- @return Base#BASE The added BASE Object. function SET_BASE:Add( ObjectName, Object ) + self:E( ObjectName ) - self.Set[ObjectName] = Object + local t = { _ = Object } + + if self.List.last then + self.List.last._next = t + t._prev = self.List.last + self.List.last = t + else + -- this is the first node + self.List.first = t + self.List.last = t + end + + self.List.Count = self.List.Count + 1 + + self.Set[ObjectName] = t + end --- Removes a @{Base#BASE} object from the @{Set#SET_BASE} and derived classes, based on the Object Name. -- @param #SET_BASE self -- @param #string ObjectName function SET_BASE:Remove( ObjectName ) + self:E( ObjectName ) - self.Set[ObjectName] = nil + local t = self.Set[ObjectName] + + if t then + if t._next then + if t._prev then + t._next._prev = t._prev + t._prev._next = t._next + else + -- this was the first node + t._next._prev = nil + self.List._first = t._next + end + elseif t._prev then + -- this was the last node + t._prev._next = nil + self.List._last = t._prev + else + -- this was the only node + self.List._first = nil + self.List._last = nil + end + + t._next = nil + t._prev = nil + self.List.Count = self.List.Count - 1 + + self.Set[ObjectName] = nil + end + end +--- Retrieves the amount of objects in the @{Set#SET_BASE} and derived classes. +-- @param #SET_BASE self +-- @return #number Count +function SET_BASE:Count() + + return self.List.Count +end + + --- Define the SET iterator **"yield interval"** and the **"time interval"**. -- @param #SET_BASE self -- @param #number YieldInterval Sets the frequency when the iterator loop will yield after the number of objects processed. The default frequency is 10 objects processed. @@ -454,7 +513,8 @@ function SET_BASE:ForEach( IteratorFunction, arg, Set, Function, FunctionArgumen local function CoRoutine() local Count = 0 - for ObjectID, Object in pairs( Set ) do + for ObjectID, ObjectData in pairs( Set ) do + local Object = ObjectData._ self:T3( Object ) if Function then if Function( unpack( FunctionArguments ), Object ) == true then diff --git a/Moose Development/Moose/StateMachine.lua b/Moose Development/Moose/StateMachine.lua index 0d4df8852..ad370fbea 100644 --- a/Moose Development/Moose/StateMachine.lua +++ b/Moose Development/Moose/StateMachine.lua @@ -1,6 +1,3 @@ -local machine = {} -machine.__index = machine - --- This module contains the STATEMACHINE class. -- -- === @@ -23,42 +20,42 @@ STATEMACHINE = { --- Creates a new STATEMACHINE object. -- @param #STATEMACHINE self -- @return #STATEMACHINE -function STATEMACHINE:New(options) +function STATEMACHINE:New( options ) local self = routines.utils.deepCopy( self ) -- Create a new self instance assert(options.events) - local FiniteStateMachine = {} - setmetatable( FiniteStateMachine, self ) + local MT = {} + setmetatable( self, MT ) self.__index = self - FiniteStateMachine.options = options - FiniteStateMachine.current = options.initial or 'none' - FiniteStateMachine.events = {} + self.options = options + self.current = options.initial or 'none' + self.events = {} for _, event in ipairs(options.events or {}) do local name = event.name - FiniteStateMachine[name] = FiniteStateMachine[name] or self:create_transition(name) - FiniteStateMachine.events[name] = FiniteStateMachine.events[name] or { map = {} } - self:add_to_map(FiniteStateMachine.events[name].map, event) + self[name] = self[name] or self:_create_transition(name) + self.events[name] = self.events[name] or { map = {} } + self:_add_to_map(self.events[name].map, event) end for name, callback in pairs(options.callbacks or {}) do - FiniteStateMachine[name] = callback + self[name] = callback end - return FiniteStateMachine + return self end -function STATEMACHINE:call_handler(handler, params) +function STATEMACHINE:_call_handler(handler, params) if handler then return handler(unpack(params)) end end -function STATEMACHINE:create_transition(name) +function STATEMACHINE:_create_transition(name) return function(self, ...) local can, to = self:can(name) @@ -66,16 +63,16 @@ function STATEMACHINE:create_transition(name) local from = self.current local params = { self, name, from, to, ... } - if self:call_handler(self["onbefore" .. name], params) == false - or self:call_handler(self["onleave" .. from], params) == false then + if self:_call_handler(self["onbefore" .. name], params) == false + or self:_call_handler(self["onleave" .. from], params) == false then return false end self.current = to - self:call_handler(self["onenter" .. to] or self["on" .. to], params) - self:call_handler(self["onafter" .. name] or self["on" .. name], params) - self:call_handler(self["onstatechange"], params) + self:_call_handler(self["onenter" .. to] or self["on" .. to], params) + self:_call_handler(self["onafter" .. name] or self["on" .. name], params) + self:_call_handler(self["onstatechange"], params) return true end @@ -84,7 +81,7 @@ function STATEMACHINE:create_transition(name) end end -function STATEMACHINE:add_to_map(map, event) +function STATEMACHINE:_add_to_map(map, event) if type(event.from) == 'string' then map[event.from] = event.to else @@ -126,3 +123,33 @@ function STATEMACHINE:todot(filename) dotfile:write('}\n') dotfile:close() end + +--- STATEMACHINE_TASK class +-- @type STATEMACHINE_TASK +-- @field Task2#TASK2 Task +-- @extends StateMachine#STATEMACHINE +STATEMACHINE_TASK = { + ClassName = "STATEMACHINE_TASK", +} + +--- Creates a new STATEMACHINE_TASK object. +-- @param #STATEMACHINE_TASK self +-- @return #STATEMACHINE_TASK +function STATEMACHINE_TASK:New( Task, options ) + + local FsmT = routines.utils.deepCopy( self ) -- Create a new self instance + local Parent = STATEMACHINE:New(options) + + setmetatable( FsmT, Parent ) + FsmT.__index = FsmT + + FsmT.Task = Task + + return FsmT +end + +function STATEMACHINE_TASK:_call_handler( handler, params ) + if handler then + return handler( self.Task, unpack( params ) ) + end +end diff --git a/Moose Development/Moose/Task2.lua b/Moose Development/Moose/Task2.lua index 50aa64249..9c7ef825c 100644 --- a/Moose Development/Moose/Task2.lua +++ b/Moose Development/Moose/Task2.lua @@ -24,14 +24,14 @@ end --- @param #TASK2 self function TASK2:Schedule() - self.TaskScheduler = SCHEDULER:New( self.StateMachine, self.StateMachine.Assign, { self, self.Client }, 1) + self.TaskScheduler = SCHEDULER:New( self.Fsm, self.Fsm.Assign, { self, self.Client }, 1) end --- @param #TASK2 self function TASK2:NextEvent( NextEvent, ... ) self:E( NextEvent ) - self.TaskScheduler = SCHEDULER:New( self.StateMachine, NextEvent, { self, self.Client }, 1 ) + self.TaskScheduler = SCHEDULER:New( self.Fsm, NextEvent, { self, self.Client, unpack( arg ) }, 1 ) end diff --git a/Moose Development/Moose/TaskSead.lua b/Moose Development/Moose/TaskSead.lua index 249a79c3f..d281f6ec6 100644 --- a/Moose Development/Moose/TaskSead.lua +++ b/Moose Development/Moose/TaskSead.lua @@ -4,103 +4,166 @@ --- TASK2_SEAD class -- @type TASK2_SEAD +-- @field Client#CLIENT Client +-- @field Set#SET_UNIT TargetSet -- @extends Task2#TASK2 TASK2_SEAD = { ClassName = "TASK2_SEAD", - StateMachine = {}, + Fsm = {}, + TargetSet = nil, } +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function TASK2_SEAD:OnAssign( Fsm, Event, From, To ) + self:E( { Event, From, To, self.Client.ClientName} ) -function TASK2_SEAD:New( Client ) + self.Client:Message( "Assigned", 15 ) + self:NextEvent( Fsm.Await ) +end + +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function TASK2_SEAD:OnAwait( Fsm, Event, From, To ) + self:E( { Event, From, To, self.Client.ClientName} ) + + self.Client:Message( "Waiting", 15 ) + self:NextEvent( Fsm.Await ) +end + +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function TASK2_SEAD:OnHitTarget( Fsm, Event, From, To, TargetUnit ) + + self.Client:Message( "Hit Target", 15 ) + if self.TargetSet:Count() > 0 then + self:NextEvent( Fsm.MoreTargets ) + else + self:NextEvent( Fsm.Destroyed ) + end +end + +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function TASK2_SEAD:OnMoreTargets( Fsm, Event, From, To ) + + self.Client:Message( "More Targets", 15 ) + +end + +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +-- @param Unit#UNIT KilledUnit +function TASK2_SEAD:OnKilled( Fsm, Event, From, To, KilledUnit ) + + if KilledUnit:GetName() == self.Client:GetName() then + self.Client:Message( "Player got killed", 15 ) + self:NextEvent( Fsm.Restart ) + end + +end + +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function TASK2_SEAD:OnRestart( Fsm, Event, From, To ) + + self.Client:Message( "Restart SEAD Task", 15 ) + +end + +--- StateMachine callback function for a TASK2 +-- @param #TASK2_SEAD self +-- @param StateMachine#STATEMACHINE_TASK Fsm +-- @param #string Event +-- @param #string From +-- @param #string To +function TASK2_SEAD:OnDestroyed( Fsm, Event, From, To ) + + self.Client:Message( "Destroyed", 15 ) + +end + +function TASK2_SEAD:New( Client, TargetSet ) -- Inherits from BASE local self = BASE:Inherit( self, TASK2:New( Client ) ) -- #TASK2_SEAD + + self.TargetSet = TargetSet - - --- @param #TASK2_SEAD self - -- @param #string Event - -- @param #string From - -- @param #string To - -- @param Client#CLIENT Client - local function OnAssign( self, Event, From, To, Task, Client ) - Task:E( { Event, From, To, Client.ClientName} ) - - Client:Message( "Assigned", 15 ) - Task:NextEvent( self.Await ) - end - - --- @param #string Event - -- @param #string From - -- @param #string To - local function OnAwait( self, Event, From, To, Task, Client ) - Task:E( { Event, From, To, Client.ClientName} ) - - Client:Message( "Waiting", 15 ) - Task:NextEvent( self.Await ) - end - - --- @param #string Event - -- @param #string From - -- @param #string To - local function OnHitTarget( self, Event, From, To ) - - end - - --- @param #string Event - -- @param #string From - -- @param #string To - local function OnMoreTargets( self, Event, From, To ) - - end - - local function OnKilled( self, Event, From, To ) - - end - - local function OnFailed( self, Event, From, To ) - - end - - local function OnDestroyed( self, Event, From, To ) - - end - - self.StateMachine = STATEMACHINE:New( { + self.Fsm = STATEMACHINE_TASK:New( self, { initial = 'Unassigned', events = { { name = 'Assign', from = 'Unassigned', to = 'Assigned' }, { name = 'Await', from = 'Assigned', to = 'Waiting' }, - { name = 'Await', from = 'Waiting', to = 'Waiting' }, - { name = 'HitTarget', from = 'Waiting', to = 'Destroyed' }, - { name = 'MoreTargets', from = 'Destroyed', to = 'Waiting' }, - { name = 'Killed', from = 'Waiting', to = 'Killed' }, - { name = 'Failed', from = 'Killed', to = 'Unassigned' }, - { name = 'Destroyed', from = 'Destroyed', to = 'Finished' } + { name = 'HitTarget', from = 'Waiting', to = 'Destroy' }, + { name = 'MoreTargets', from = 'Destroy', to = 'Waiting' }, + { name = 'Destroyed', from = 'Destroy', to = 'Success' }, + { name = 'Killed', from = 'Assigned', to = 'Failed' }, + { name = 'Killed', from = 'Waiting', to = 'Failed' }, + { name = 'Killed', from = 'Destroy', to = 'Failed' }, + { name = 'Restart', from = 'Failed', to = 'Unassigned' } }, callbacks = { - onAssign = OnAssign, - onAwait = OnAwait, - onHitTarget = OnHitTarget, - onMoreTargets = OnMoreTargets, - onKilled = OnKilled, - onFailed = OnFailed, - onDestroyed = OnDestroyed, + onAssign = self.OnAssign, + onAwait = self.OnAwait, + onHitTarget = self.OnHitTarget, + onMoreTargets = self.OnMoreTargets, + onDestroyed = self.OnDestroyed, + onKilled = self.OnKilled, + onRestart = self.OnRestart, } } ) - _EVENTDISPATCHER:OnHit( self.OnHit, self ) + _EVENTDISPATCHER:OnHit( self.EventHit, self ) + _EVENTDISPATCHER:OnDead( self.EventKilled, self ) + _EVENTDISPATCHER:OnCrash( self.EventKilled, self ) self:Schedule() end + + --- @param #TASK2_SEAD self -- @param Event#EVENTDATA Event -function TASK2_SEAD:OnHit( Event ) +function TASK2_SEAD:EventHit( Event ) if Event.IniUnit then - self:NextEvent( self.StateMachine.OnHitTarget ) + self:NextEvent( self.Fsm.HitTarget, Event.IniUnit ) + end +end + +--- @param #TASK2_SEAD self +-- @param Event#EVENTDATA Event +function TASK2_SEAD:EventKilled( Event ) + + if Event.IniUnit then + self:NextEvent( self.Fsm.Killed, Event.IniUnit ) end end diff --git a/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.lua b/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.lua index f69a08e67..84c5197fb 100644 --- a/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.lua +++ b/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.lua @@ -1,4 +1,5 @@ local Client = CLIENT:FindByName( "Test SEAD" ) +local TargetSet = SET_UNIT:New():FilterPrefixes( "US Hawk SR" ):FilterStart() -local Task_SEAD = TASK2_SEAD:New( Client ) +local Task_SEAD = TASK2_SEAD:New( Client, TargetSet ) diff --git a/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz b/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz index 859ba5ae1..a7ef2ec34 100644 Binary files a/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz and b/Moose Test Missions/Moose_Test_TASK_SEAD/Moose_Test_TASK_SEAD.miz differ diff --git a/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation - Old - kopie.pptx b/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation - Old - kopie.pptx new file mode 100644 index 000000000..bd2e557cd Binary files /dev/null and b/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation - Old - kopie.pptx differ diff --git a/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation.pptx b/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation.pptx index 0807da80a..889058b07 100644 Binary files a/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation.pptx and b/Moose Training/Presentations/DCS World - MOOSE - Detection - Part 1 - Explanation.pptx differ