From f9eb19e0f51622d2f86c8e1347fd1b885712ab55 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Tue, 29 Nov 2016 10:40:01 +0100 Subject: [PATCH] Failed is now working. Scoring working on Task level now ... --- Moose Development/Moose/Core/Event.lua | 2 +- Moose Development/Moose/Core/StateMachine.lua | 6 ++ Moose Development/Moose/Tasking/Task.lua | 75 +++------------ Moose Development/Moose/Tasking/Task_A2G.lua | 2 +- Moose Development/Moose/Tasking/Task_SEAD.lua | 2 +- .../Moose_Test_Task_SEAD.lua | 90 +++++++++++++++--- .../Moose_Test_Task_SEAD.miz | Bin 26045 -> 27918 bytes 7 files changed, 100 insertions(+), 77 deletions(-) diff --git a/Moose Development/Moose/Core/Event.lua b/Moose Development/Moose/Core/Event.lua index a64e5a64b..180b892d0 100644 --- a/Moose Development/Moose/Core/Event.lua +++ b/Moose Development/Moose/Core/Event.lua @@ -737,7 +737,7 @@ function EVENT:onEvent( Event ) Event.WeaponName = Event.Weapon:getTypeName() --Event.WeaponTgtDCSUnit = Event.Weapon:getTarget() end - self:E( { _EVENTCODES[Event.id], Event.initiator, Event.IniDCSUnitName, Event.target, Event.TgtDCSUnitName, Event.weapon, Event.WeaponName } ) + self:E( { _EVENTCODES[Event.id], Event, Event.IniDCSUnitName, Event.TgtDCSUnitName } ) -- Okay, we got the event from DCS. Now loop the self.Events[] table for the received Event.id, and for each EventData registered, check if a function needs to be called. for EventClass, EventData in pairs( self.Events[Event.id] ) do diff --git a/Moose Development/Moose/Core/StateMachine.lua b/Moose Development/Moose/Core/StateMachine.lua index 132144b7b..ecbf176f8 100644 --- a/Moose Development/Moose/Core/StateMachine.lua +++ b/Moose Development/Moose/Core/StateMachine.lua @@ -451,6 +451,12 @@ function STATEMACHINE_PROCESS:onenterAssigned( ProcessUnit ) self.Task:Assign() end +function STATEMACHINE_PROCESS:onenterFailed( ProcessUnit ) + self:E( "Failed" ) + + self.Task:Fail() +end + function STATEMACHINE_PROCESS:onenterSuccess( ProcessUnit ) self:E( "Success" ) diff --git a/Moose Development/Moose/Tasking/Task.lua b/Moose Development/Moose/Tasking/Task.lua index dd0d5826e..9d7245a8b 100644 --- a/Moose Development/Moose/Tasking/Task.lua +++ b/Moose Development/Moose/Tasking/Task.lua @@ -53,7 +53,7 @@ -- @type TASK_BASE -- @field Scheduler#SCHEDULER TaskScheduler -- @field Mission#MISSION Mission --- @field StateMachine#STATEMACHINE Fsm +-- @field Core.StateMachine#STATEMACHINE_PROCESS FsmTemplate -- @field Set#SET_GROUP SetGroup The Set of Groups assigned to the Task -- @extends Core.StateMachine#STATEMACHINE_TASK TASK_BASE = { @@ -65,6 +65,7 @@ TASK_BASE = { Scores = {}, Menu = {}, SetGroup = nil, + FsmTemplate = nil, } --- Instantiates a new TASK_BASE. Should never be used. Interface Class. @@ -73,12 +74,11 @@ TASK_BASE = { -- @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, SetGroupAssign, TaskName, TaskType, TaskCategory ) +function TASK_BASE:New( Mission, SetGroupAssign, TaskName, TaskType ) - local self = BASE:Inherit( self, STATEMACHINE_TASK:New( {} ) ) + local self = BASE:Inherit( self, STATEMACHINE_TASK:New( {} ) ) -- Core.StateMachine#STATEMACHINE_TASK self:SetInitialState( "Planned" ) self:AddAction( "Planned", "Assign", "Assigned" ) @@ -93,7 +93,6 @@ function TASK_BASE:New( Mission, SetGroupAssign, TaskName, TaskType, TaskCategor self.Mission = Mission self.SetGroup = SetGroupAssign - self:SetCategory( TaskCategory ) self:SetType( TaskType ) self:SetName( TaskName ) self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences .. @@ -118,19 +117,6 @@ function TASK_BASE:GetGroups() return self.SetGroup end ---- Cleans all references of a TASK_BASE. --- @param #TASK_BASE self --- @return #nil -function TASK_BASE:CleanUp() - - _EVENTDISPATCHER:OnPlayerLeaveRemove( self ) - _EVENTDISPATCHER:OnDeadRemove( self ) - _EVENTDISPATCHER:OnCrashRemove( self ) - _EVENTDISPATCHER:OnPilotDeadRemove( self ) - - return nil -end - function TASK_BASE:GetFsmTemplate() return self.FsmTemplate @@ -183,7 +169,7 @@ function TASK_BASE:AssignToUnit( TaskUnit ) -- 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 ) + local FsmUnit = UTILS.DeepCopy( FsmTemplate ) -- Core.StateMachine#STATEMACHINE_PROCESS FsmUnit:Assign( self, TaskUnit ) -- Assign each FsmSub in FsmUnit to the TaskUnit. @@ -192,28 +178,15 @@ function TASK_BASE:AssignToUnit( TaskUnit ) for FsmSubID, FsmSub in pairs( FsmUnit:GetSubs() ) do self:E( { "Sub ID", FsmSub.fsm:GetClassNameAndID(), FsmSubID } ) FsmSub.fsm:Assign( self, TaskUnit ) - --FsmSub.fsm:_SetDestructor() - - - --FsmSub.fsm = nil - --collectgarbage() 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 + -- Set the events + FsmUnit:EventOnPilotDead( + --- @param Core.Event#EVENTDATA EventData + function( self, EventData ) + self:__Fail( 1 ) + end + ) FsmUnit:SetInitialState( "Planned" ) FsmUnit:Accept() -- Each Task needs to start with an Accept event to start the flow. @@ -552,16 +525,15 @@ function TASK_BASE:GetScoring() end ---- Gets the Task Index, which is a combination of the Task category, the Task type, the Task name. +--- Gets the Task Index, which is a combination of the Task type, the Task name. -- @param #TASK_BASE self -- @return #string The Task ID function TASK_BASE:GetTaskIndex() - local TaskCategory = self:GetCategory() local TaskType = self:GetType() local TaskName = self:GetName() - return TaskCategory .. "." ..TaskType .. "." .. TaskName + return TaskType .. "." .. TaskName end --- Sets the Name of the Task @@ -592,20 +564,6 @@ function TASK_BASE:GetType() return self.TaskType end ---- Sets the Category of the Task --- @param #TASK_BASE self --- @param #string TaskCategory -function TASK_BASE:SetCategory( TaskCategory ) - self.TaskCategory = TaskCategory -end - ---- Gets the Category of the Task --- @param #TASK_BASE self --- @return #string TaskCategory -function TASK_BASE:GetCategory() - return self.TaskCategory -end - --- Sets the ID of the Task -- @param #TASK_BASE self -- @param #string TaskID @@ -810,14 +768,11 @@ 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:IsTrace() } ) - self:E( self.Scores ) if self.Scores[To] then local Scoring = self:GetScoring() - self:E( Scoring ) if Scoring then + self:E( { self.Scores[To].ScoreText, self.Scores[To].Score } ) Scoring:_AddMissionScore( self.Mission, self.Scores[To].ScoreText, self.Scores[To].Score ) end end diff --git a/Moose Development/Moose/Tasking/Task_A2G.lua b/Moose Development/Moose/Tasking/Task_A2G.lua index 066d19b5c..4ecfdffab 100644 --- a/Moose Development/Moose/Tasking/Task_A2G.lua +++ b/Moose Development/Moose/Tasking/Task_A2G.lua @@ -38,7 +38,7 @@ do -- TASK_A2G -- @param Zone#ZONE_BASE TargetZone -- @return #TASK_A2G self function TASK_A2G:New( Mission, SetGroup, TaskName, TaskType, TargetSetUnit, TargetZone, FACUnit ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, TaskType, "A2G" ) ) + local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, TaskType ) ) self:F() self.TargetSetUnit = TargetSetUnit diff --git a/Moose Development/Moose/Tasking/Task_SEAD.lua b/Moose Development/Moose/Tasking/Task_SEAD.lua index 89fe1ae45..4242f17aa 100644 --- a/Moose Development/Moose/Tasking/Task_SEAD.lua +++ b/Moose Development/Moose/Tasking/Task_SEAD.lua @@ -39,7 +39,7 @@ do -- TASK_SEAD -- @param Zone#ZONE_BASE TargetZone -- @return #TASK_SEAD self function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TargetZone ) - local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "SEAD", "A2G" ) ) -- Tasking.Task_SEAD#TASK_SEAD + local self = BASE:Inherit( self, TASK_BASE:New( Mission, SetGroup, TaskName, "SEAD" ) ) -- Tasking.Task_SEAD#TASK_SEAD self:F() self.TargetSetUnit = TargetSetUnit diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua index 5e715d2ca..9b785f21b 100644 --- a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua +++ b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.lua @@ -1,41 +1,103 @@ +-- This test mission is a test bed for the TASKING framework. +-- It creates an head quarters (HQ), which contains one mission with one task to be accomplished. +-- When the pilot joins the plane, it will need to accept the task using the HQ menu. +-- Once the task is accepted, the group of the pilot will be assigned to the task. +-- The pilot will need to fly to the attack zone and elimitate all targets reported. +-- A smoking system is available that the pilot can use the acquire targets. +-- Once all targets are elimitated, the task is finished, and the mission is set to complete. +-- If the pilot crashes during flying, the task will fail, and the mission is set to failed. -env.info( "Lua Version = " .. _VERSION ) - --- Test Garbage control of one declared PROCESS. -do - local Process = PROCESS_ASSIGN_ACCEPT:New( "SEAD the Area" ) -end - -collectgarbage() - +-- Create the HQ object. local HQ = COMMANDCENTER:New( GROUP:FindByName( "HQ" ) ) -local Mission = MISSION:New( HQ, 'SEAD Targets', "Strategic", "SEAD the enemy", coalition.side.RED ) +-- MOOSE contains a MISSION class. Use the MISSION class to setup missions, containing tasks to be executed. +-- Create the Mission object, and attach the Mission to the HQ object. +-- The Mission accepts 4 parameters: +-- 1. The HQ object +-- 2. The name of the Mission +-- 3. The type of Mission, this can be any word like "Strategic", "Tactical", "Urgent", "Optional", "Secondary"... +-- 4. The briefing of the Mission. This briefing is shown when the pilot joins a Task within the Mission. +local Mission = MISSION:New( HQ, 'SEAD Targets', "Strategic", "SEAD the enemy" ) + + +-- MOOSE contains a SCORING class. Use the SCORING class to account the scores of achievements made by the pilots. +-- The scoring system is a standalone object, so here the Scoring object is created. local Scoring = SCORING:New( "SEAD" ) +-- The Scoring object is attached to the Mission object. +-- By doing this, now the Mission can set at defined states in tasks ( and in processes within the tasks ) scoring values, and a text. See later. Mission:AddScoring( Scoring ) +-- Define the set of group of planes that can be assigned to the Mission object. local SEADSet = SET_GROUP:New():FilterPrefixes( "Test SEAD"):FilterStart() + +-- Define the set of units that are the targets. +-- Note that I use FilterOnce, which means that the set will be defined only once, +-- and will not be continuously updated! local TargetSet = SET_UNIT:New():FilterPrefixes( "US Hawk SR" ):FilterOnce() +-- Define the zone to where the pilot needs to navigate. local TargetZone = ZONE:New( "Target Zone" ) -local TaskSEAD = TASK_BASE:New( Mission, SEADSet, "SEAD Radars", "A2G", "SEAD" ) -- Tasking.Task#TASK_BASE - --:New( Mission, SEADSet, "SEAD Radars", TargetSet, TargetZone ) - +-- MOOSE contains a TASK_BASE class. Use the TASK class to define a new Task object and attach it to a Mission object. +-- Here we define a new TaskSEAD object, and attach it to the Mission object. +-- ( The TASK_BASE class is the base class for ALL derived Task templates. +-- Task templates are TASK classes that quickly setup a Task scenario with given parameters. ) +-- +-- The TASK_BASE class is thus the primary task, and a task scenario will need to be provided to the TaskSEAD of the states and events that form the task. +-- TASK_BASE gets a couple of parameters: +-- 1. The Mission for which the Task needs to be achieved. +-- 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. +-- 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 TaskSEAD = TASK_BASE:New( Mission, SEADSet, "SEAD Radars", "SEAD" ) -- Tasking.Task#TASK_BASE + +-- This is now an important part of the Task process definition. +-- Each TASK contains a "Process Template". +-- You need to define this process Template by added Actions and Processes, otherwise, the task won't do anything. +-- This call retrieves the Finite State Machine template of the Task. +-- This template WILL NEVER DIRECTLY BE EXECUTED. +-- But, when a Pilot joins a UNIT as defined within the SEADSet, the TaskSEAD will COPY the FsmSEAD to a NEW INTERNAL OBJECT and assign the COPIED FsmSEAD to the UNIT of the player. +-- There can be many copied FsmSEAD objects internally active within TaskSEAD, for each pilot that joined the Task one is instantiated. +-- The reason why this is done, is that each unit as a role within the Task, and can have different status. +-- Therefore, the FsmSEAD is a TEMPLATE PROCESS of the TASK, and must be designed as a UNIT with a player is executing that PROCESS. local FsmSEAD = TaskSEAD:GetFsmTemplate() +-- Adding a new sub-process to the Task Template. +-- At first, the task needs to be accepted by a pilot. +-- We use for this the SUB-PROCESS PROCESS_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 PROCESS_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 PROCESS_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. FsmSEAD:AddProcess( "Planned", "Accept", PROCESS_ASSIGN_ACCEPT:New( "SEAD the Area" ), { Assigned = "Route", Rejected = "Eject" } ) + +-- Same, adding a process. FsmSEAD:AddProcess( "Assigned", "Route", PROCESS_ROUTE_ZONE:New( TargetZone, 3000 ), { Arrived = "Update" } ) + +-- 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 AddAction 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. 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" ) +FsmSEAD:AddAction ( "*", "Fail", "Failed" ) +-- 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. 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 ) diff --git a/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz b/Moose Test Missions/Moose_Test_Tasking/Moose_Test_Task_SEAD/Moose_Test_Task_SEAD.miz index 709d26d82501cce6d7eb769aedaa5b44080ee741..0f5cd8705851e84741d15a56a5b9b8812625047d 100644 GIT binary patch delta 12987 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 delta 11107 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