MOOSE/Moose Development/Moose/Tasking/Task_Capture_Dispatcher.lua
FlightControl 23f92e49dd New TASK CAPTURE DISPATCHER class.
This class allows to send capture tasks to players.
It needs a ZONE_CAPTURE_COALITION class to function.
2019-03-06 22:40:44 +01:00

308 lines
12 KiB
Lua
Raw Blame History

--- **Tasking** - Creates and manages player TASK_ZONE_CAPTURE tasks.
--
-- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human
-- players capture zones in a co-operation effort.
--
-- The dispatcher will implement for you mechanisms to create capture zone tasks:
--
-- * As setup by the mission designer.
-- * Dynamically capture zone tasks.
--
--
--
-- **Specific features:**
--
-- * Creates a task to capture zones and achieve mission goals.
-- * Orchestrate the task flow, so go from Planned to Assigned to Success, Failed or Cancelled.
-- * Co-operation tasking, so a player joins a group of players executing the same task.
--
--
-- **A complete task menu system to allow players to:**
--
-- * Join the task, abort the task.
-- * Mark the location of the zones to capture on the map.
-- * Provide details of the zones.
-- * Route to the zones.
-- * Display the task briefing.
--
--
-- **A complete mission menu system to allow players to:**
--
-- * Join a task, abort the task.
-- * Display task reports.
-- * Display mission statistics.
-- * Mark the task locations on the map.
-- * Provide details of the zones.
-- * Display the mission briefing.
-- * Provide status updates as retrieved from the command center.
-- * Automatically assign a random task as part of a mission.
-- * Manually assign a specific task as part of a mission.
--
--
-- **A settings system, using the settings menu:**
--
-- * Tweak the duration of the display of messages.
-- * Switch between metric and imperial measurement system.
-- * Switch between coordinate formats used in messages: BR, BRA, LL DMS, LL DDM, MGRS.
-- * Various other options.
--
-- ===
--
-- ### Author: **FlightControl**
--
-- ### Contributions:
--
-- ===
--
-- @module Tasking.Task_Zone_Capture_Dispatcher
-- @image Task_Zone_Capture_Dispatcher.JPG
do -- TASK_CAPTURE_DISPATCHER
--- TASK_CAPTURE_DISPATCHER class.
-- @type TASK_CAPTURE_DISPATCHER
-- @extends Tasking.Task_Manager#TASK_MANAGER
-- @field TASK_CAPTURE_DISPATCHER.ZONE ZONE
--- @type TASK_CAPTURE_DISPATCHER.CSAR
-- @field Wrapper.Unit#UNIT PilotUnit
-- @field Tasking.Task#TASK Task
--- Implements the dynamic dispatching of capture zone tasks.
--
-- The **TASK_CAPTURE_DISPATCHER** allows you to setup various tasks for let human
-- players capture zones in a co-operation effort.
--
-- Let's explore **step by step** how to setup the task capture zone dispatcher.
--
-- # 1. Setup a mission environment.
--
-- It is easy, as it works just like any other task setup, so setup a command center and a mission.
--
-- ## 1.1. Create a command center.
--
-- First you need to create a command center using the @{Tasking.CommandCenter#COMMANDCENTER.New}() constructor.
-- The command assumes that you<6F>ve setup a group in the mission editor with the name HQ.
-- This group will act as the command center object.
-- It is a good practice to mark this group as invisible and invulnerable.
--
-- local CommandCenter = COMMANDCENTER
-- :New( GROUP:FindByName( "HQ" ), "HQ" ) -- Create the CommandCenter.
--
-- ## 1.2. Create a mission.
--
-- Tasks work in a **mission**, which groups these tasks to achieve a joint **mission goal**. A command center can **govern multiple missions**.
--
-- Create a new mission, using the @{Tasking.Mission#MISSION.New}() constructor.
--
-- -- Declare the Mission for the Command Center.
-- local Mission = MISSION
-- :New( CommandCenter,
-- "Overlord",
-- "High",
-- "Capture the blue zones.",
-- coalition.side.RED
-- )
--
--
-- # 2. Dispatch a **capture zone** task.
--
-- So, now that we have a command center and a mission, we now create the capture zone task.
-- We create the capture zone task using the @{#TASK_CAPTURE_DISPATCHER.AddCaptureZoneTask}() constructor.
--
-- ## 2.1. Create the capture zones.
--
-- Because a capture zone task will not generate the capture zones, you'll need to create them first.
--
--
-- -- We define here a capture zone; of the type ZONE_CAPTURE_COALITION.
-- -- The zone to be captured has the name Alpha, and was defined in the mission editor as a trigger zone.
-- CaptureZone = ZONE:New( "Alpha" )
-- CaptureZoneCoalitionApha = ZONE_CAPTURE_COALITION:New( CaptureZone, coalition.side.RED )
--
-- ## 2.2. Create a set of player groups.
--
-- What is also needed, is to have a set of @{Core.Group}s defined that contains the clients of the players.
--
-- -- Allocate the player slots, which must be aircraft (airplanes or helicopters), that can be manned by players.
-- -- We use the method FilterPrefixes to filter those player groups that have client slots, as defined in the mission editor.
-- -- In this example, we filter the groups where the name starts with "Blue Player", which captures the blue player slots.
-- local PlayerGroupSet = SET_GROUP:New():FilterPrefixes( "Blue Player" ):FilterStart()
--
-- ## 2.3. Setup the capture zone task.
--
-- First, we need to create a TASK_CAPTURE_DISPATCHER object.
--
-- TaskCaptureZoneDispatcher = TASK_CAPTURE_DISPATCHER:New( Mission, PilotGroupSet )
--
-- So, the variable `TaskCaptureZoneDispatcher` will contain the object of class TASK_CAPTURE_DISPATCHER,
-- which will allow you to dispatch capture zone tasks:
--
-- * for mission `Mission`, as was defined in section 1.2.
-- * for the group set `PilotGroupSet`, as was defined in section 2.2.
--
-- Now that we have `TaskDispatcher` object, we can now **create the TaskCaptureZone**, using the @{#TASK_CAPTURE_DISPATCHER.AddCaptureZoneTask}() method!
--
-- local TaskCaptureZone = TaskCaptureZoneDispatcher:AddCaptureZoneTask(
-- "Capture zone Alpha",
-- CaptureZoneCoalitionAlpha,
-- "Fly to zone Alpha and eliminate all enemy forces to capture it." )
--
-- As a result of this code, the `TaskCaptureZone` (returned) variable will contain an object of @{#TASK_CAPTURE_ZONE}!
-- We pass to the method the title of the task, and the `CaptureZoneCoalitionAlpha`, which is the zone to be captured, as defined in section 2.1!
-- This returned `TaskCaptureZone` object can now be used to setup additional task configurations, or to control this specific task with special events.
--
-- And you're done! As you can see, it is a small bit of work, but the reward is great.
-- And, because all this is done using program interfaces, you can easily build a mission to capture zones yourself!
-- Based on various events happening within your mission, you can use the above methods to create new capture zones,
-- and setup a new capture zone task and assign it to a group of players, while your mission is running!
--
--
--
-- @field #TASK_CAPTURE_DISPATCHER
TASK_CAPTURE_DISPATCHER = {
ClassName = "TASK_CAPTURE_DISPATCHER",
Mission = nil,
Tasks = {},
Zones = {},
ZoneCount = 0,
}
--- TASK_CAPTURE_DISPATCHER constructor.
-- @param #TASK_CAPTURE_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission The mission for which the task dispatching is done.
-- @param Core.Set#SET_GROUP SetGroup The set of groups that can join the tasks within the mission.
-- @return #TASK_CAPTURE_DISPATCHER self
function TASK_CAPTURE_DISPATCHER:New( Mission, SetGroup )
-- Inherits from DETECTION_MANAGER
local self = BASE:Inherit( self, TASK_MANAGER:New( SetGroup ) ) -- #TASK_CAPTURE_DISPATCHER
self.Mission = Mission
self:AddTransition( "Started", "Assign", "Started" )
self:AddTransition( "Started", "ZoneCaptured", "Started" )
self:__StartTasks( 5 )
return self
end
--- Add a capture zone task.
-- @param #TASK_CAPTURE_DISPATCHER self
-- @param #string TaskPrefix (optional) The prefix of the capture zone task.
-- This prefix will be appended with a . + a number of 3 digits.
-- If no TaskPrefix is given, then "Capture" will be used as the prefix.
-- @param Functional.CaptureZoneCoalition#ZONE_CAPTURE_COALITION CaptureZone The zone of the coalition to be captured as the task goal.
-- @param #string Briefing The briefing of the task to be shown to the player.
-- @return Tasking.Task_Capture_Zone#TASK_CAPTURE_ZONE
-- @usage
--
--
function TASK_CAPTURE_DISPATCHER:AddCaptureZoneTask( TaskPrefix, CaptureZone, Briefing )
self.ZoneCount = self.ZoneCount + 1
local TaskName = string.format( ( TaskPrefix or "Capture" ) .. ".%03d", self.ZoneCount )
self.Zones[TaskName] = {}
self.Zones[TaskName].CaptureZone = CaptureZone
self.Zones[TaskName].Briefing = Briefing
self.Zones[TaskName].Task = nil
self.Zones[TaskName].TaskPrefix = TaskPrefix
self:ManageTasks()
return self.Zones[TaskName] and self.Zones[TaskName].Task
end
--- Assigns tasks to the @{Core.Set#SET_GROUP}.
-- @param #TASK_CAPTURE_DISPATCHER self
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
function TASK_CAPTURE_DISPATCHER:ManageTasks()
self:F()
local AreaMsg = {}
local TaskMsg = {}
local ChangeMsg = {}
local Mission = self.Mission
if Mission:IsIDLE() or Mission:IsENGAGED() then
local TaskReport = REPORT:New()
-- Checking the task queue for the dispatcher, and removing any obsolete task!
for TaskIndex, TaskData in pairs( self.Tasks ) do
local Task = TaskData -- Tasking.Task#TASK
if Task:IsStatePlanned() then
-- Here we need to check if the pilot is still existing.
-- local DetectedItem = Detection:GetDetectedItemByIndex( TaskIndex )
-- if not DetectedItem then
-- local TaskText = Task:GetName()
-- for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
-- Mission:GetCommandCenter():MessageToGroup( string.format( "Obsolete A2A task %s for %s removed.", TaskText, Mission:GetShortText() ), TaskGroup )
-- end
-- Task = self:RemoveTask( TaskIndex )
-- end
end
end
-- Now that all obsolete tasks are removed, loop through the Zone tasks.
for TaskName, CaptureZone in pairs( self.Zones ) do
if not CaptureZone.Task then
-- New Transport Task
CaptureZone.Task = TASK_CAPTURE_ZONE:New( Mission, self.SetGroup, TaskName, CaptureZone.CaptureZone, CaptureZone.Briefing )
CaptureZone.Task.TaskPrefix = CaptureZone.TaskPrefix -- We keep the TaskPrefix for further reference!
Mission:AddTask( CaptureZone.Task )
TaskReport:Add( TaskName )
function CaptureZone.Task.OnEnterSuccess( Task, From, Event, To )
self:Success( Task )
end
function CaptureZone.Task.OnEnterCancelled( Task, From, Event, To )
self:Cancelled( Task )
end
function CaptureZone.Task.OnEnterFailed( Task, From, Event, To )
self:Failed( Task )
end
function CaptureZone.Task.OnEnterAborted( Task, From, Event, To )
self:Aborted( Task )
end
-- Now broadcast the onafterCargoPickedUp event to the Task Cargo Dispatcher.
function CaptureZone.Task.OnAfterCaptured( Task, From, Event, To, TaskUnit )
self:Captured( Task, Task.TaskPrefix, TaskUnit )
end
end
end
-- TODO set menus using the HQ coordinator
Mission:GetCommandCenter():SetMenu()
local TaskText = TaskReport:Text(", ")
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if ( not Mission:IsGroupAssigned(TaskGroup) ) and TaskText ~= "" then
Mission:GetCommandCenter():MessageToGroup( string.format( "%s has tasks %s. Subscribe to a task using the radio menu.", Mission:GetShortText(), TaskText ), TaskGroup )
end
end
end
return true
end
end