mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-08-15 10:47:21 +00:00
Failed is now working. Scoring working on Task level now ...
This commit is contained in:
parent
354a9333c6
commit
f9eb19e0f5
@ -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
|
||||
|
||||
@ -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" )
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 )
|
||||
|
||||
|
||||
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user