--- **Tasking** - Creates and manages player TASK_CARGO tasks. -- -- The **TASK_CARGO_DISPATCHER** allows you to setup various tasks for let human -- players transport cargo as part of a task. -- -- The cargo dispatcher will implement for you mechanisms to create cargo transportation tasks: -- -- * As setup by the mission designer. -- * Dynamically create CSAR missions (when a pilot is downed as part of a downed plane). -- * Dynamically spawn new cargo and create cargo taskings! -- -- -- -- **Specific features:** -- -- * Creates a task to transport @{Cargo.Cargo} to and between deployment zones. -- * Derived from the TASK_CARGO class, which is derived from the TASK class. -- * 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 task location on the map. -- * Provide details of the target. -- * Route to the cargo. -- * Route to the deploy zones. -- * Load/Unload cargo. -- * Board/Unboard cargo. -- * Slingload cargo. -- * 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 targets. -- * 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. -- * Different settings modes for A2G and A2A operations. -- * Various other options. -- -- === -- -- ### Author: **FlightControl** -- -- ### Contributions: -- -- === -- -- @module Tasking.Task_Cargo_Dispatcher -- @image Task_Cargo_Dispatcher.JPG do -- TASK_CARGO_DISPATCHER --- TASK_CARGO_DISPATCHER class. -- @type TASK_CARGO_DISPATCHER -- @extends Tasking.Task_Manager#TASK_MANAGER -- @field TASK_CARGO_DISPATCHER.CSAR CSAR --- @type TASK_CARGO_DISPATCHER.CSAR -- @field Wrapper.Unit#UNIT PilotUnit -- @field Tasking.Task#TASK Task --- Implements the dynamic dispatching of cargo tasks. -- -- The **TASK_CARGO_DISPATCHER** allows you to setup various tasks for let human -- players transport cargo as part of a task. -- -- There are currently **two types of tasks** that can be constructed: -- -- * A **normal cargo transport** task, which tasks humans to transport cargo from a location towards a deploy zone. -- * A **CSAR** cargo transport task. CSAR tasks are **automatically generated** when a friendly (AI) plane is downed and the friendly pilot ejects... -- You as a player (the helo pilot) can go out in the battlefield, fly behind enemy lines, and rescue the pilot (back to a deploy zone). -- -- Let's explore **step by step** how to setup the task cargo 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. -- -- local CommandCenter = COMMANDCENTER -- :New( HQ, "Lima" ) -- 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", -- "Transport the cargo.", -- coalition.side.RED -- ) -- -- -- # 2. Dispatch a **transport cargo** task. -- -- So, now that we have a command center and a mission, we now create the transport task. -- We create the transport task using the @{#TASK_CARGO_DISPATCHER.AddTransportTask}() constructor. -- -- ## 2.1. Create the cargo in the mission. -- -- Because a transport task will not generate the cargo itself, you'll need to create it first. -- -- -- Here we define the "cargo set", which is a collection of cargo objects. -- -- The cargo set will be the input for the cargo transportation task. -- -- So a transportation object is handling a cargo set, which is automatically updated when new cargo is added/deleted. -- local WorkmaterialsCargoSet = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart() -- -- -- Now we add cargo into the battle scene. -- local PilotGroup = GROUP:FindByName( "Engineers" ) -- -- -- CARGO_GROUP can be used to setup cargo with a GROUP object underneath. -- -- We name the type of this group "Workmaterials", so that this cargo group will be included within the WorkmaterialsCargoSet. -- -- Note that the name of the cargo is "Engineer Team 1". -- local CargoGroup = CARGO_GROUP:New( PilotGroup, "Workmaterials", "Engineer Team 1", 500 ) -- -- What is also needed, is to have a set of @{Core.Group}s defined that contains the clients of the players. -- -- -- Allocate the Transport, which are the helicopters to retrieve the pilot, that can be manned by players. -- -- The name of these helicopter groups containing one client begins with "Transport", as modelled within the mission editor. -- local PilotGroupSet = SET_GROUP:New():FilterPrefixes( "Transport" ):FilterStart() -- -- ## 2.2. Setup the cargo transport task. -- -- First, we need to create a TASK_CARGO_DISPATCHER object. -- -- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, PilotGroupSet ) -- -- So, the variable `TaskDispatcher` will contain the object of class TASK_CARGO_DISPATCHER, which will allow you to dispatch cargo transport tasks: -- -- * for mission `Mission`. -- * for the group set `PilotGroupSet`. -- -- Now that we have `TaskDispatcher` object, we can now **create the TransportTask**, using the @{#TASK_CARGO_DISPATCHER.AddTransportTask}() method! -- -- local TransportTask = TaskDispatcher:AddTransportTask( -- "Transport workmaterials", -- WorkmaterialsCargoSet, -- "Transport the workers, engineers and the equipment near the Workplace." ) -- -- As a result of this code, the `TransportTask` (returned) variable will contain an object of @{#TASK_CARGO_TRANSPORT}! -- We pass to the method the title of the task, and the `WorkmaterialsCargoSet`, which is the set of cargo groups to be transported! -- This object can also be used to setup additional things, or to control this specific task with special actions. -- -- And you're done! As you can see, it is a bit of work, but the reward is great. -- And, because all this is done using program interfaces, you can build a mission with a **dynamic cargo transport task mechanism** yourself! -- Based on events happening within your mission, you can use the above methods to create new cargo, and setup a new task for cargo transportation to a group of players! -- -- -- # 3. Dispatch CSAR tasks. -- -- CSAR tasks can be dynamically created when a friendly pilot ejects, or can be created manually. -- We'll explore both options. -- -- ## 3.1. CSAR task dynamic creation. -- -- Because there is an "event" in a running simulation that creates CSAR tasks, the method @{#TASK_CARGO_DISPATCHER.StartCSARTasks}() will create automatically: -- -- 1. a new downed pilot at the location where the plane was shot -- 2. declare that pilot as cargo -- 3. creates a CSAR task automatically to retrieve that pilot -- 4. requires deploy zones to be specified where to transport the downed pilot to, in order to complete that task. -- -- You create a CSAR task dynamically in a very easy way: -- -- TaskDispatcher:StartCSARTasks( -- "CSAR", -- { ZONE_UNIT:New( "Hospital", STATIC:FindByName( "Hospital" ), 100 ) }, -- "One of our pilots has ejected. Go out to Search and Rescue our pilot!\n" .. -- "Use the radio menu to let the command center assist you with the CSAR tasking." -- ) -- -- The method @{#TASK_CARGO_DISPATCHER.StopCSARTasks}() will automatically stop with the creation of CSAR tasks when friendly pilots eject. -- -- **Remarks:** -- -- * the ZONE_UNIT can also be a ZONE, or a ZONE_POLYGON object, or any other ZONE_ object! -- * you can declare the array of zones in another variable, or course! -- -- -- ## 3.2. CSAR task manual creation. -- -- We create the CSAR task using the @{#TASK_CARGO_DISPATCHER.AddCSARTask}() constructor. -- -- The method will create a new CSAR task, and will generate the pilots cargo itself, at the specified coordinate. -- -- What is first needed, is to have a set of @{Core.Group}s defined that contains the clients of the players. -- -- -- Allocate the Transport, which are the helicopter to retrieve the pilot, that can be manned by players. -- local GroupSet = SET_GROUP:New():FilterPrefixes( "Transport" ):FilterStart() -- -- We need to create a TASK_CARGO_DISPATCHER object. -- -- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, GroupSet ) -- -- So, the variable `TaskDispatcher` will contain the object of class TASK_CARGO_DISPATCHER, which will allow you to dispatch cargo CSAR tasks: -- -- * for mission `Mission`. -- * for the group of players (pilots) captured within the `GroupSet` (those groups with a name starting with `"Transport"`). -- -- Now that we have a PilotsCargoSet and a GroupSet, we can now create the CSAR task manually. -- -- -- Declare the CSAR task. -- local CSARTask = TaskDispatcher:AddCSARTask( -- "CSAR Task", -- Coordinate, -- 270, -- "Bring the pilot back!" -- ) -- -- As a result of this code, the `CSARTask` (returned) variable will contain an object of @{#TASK_CARGO_CSAR}! -- We pass to the method the title of the task, and the `WorkmaterialsCargoSet`, which is the set of cargo groups to be transported! -- This object can also be used to setup additional things, or to control this specific task with special actions. -- Note that when you declare a CSAR task manually, you'll still need to specify a deployment zone! -- -- # 4. Setup the deploy zone(s). -- -- The task cargo dispatcher also foresees methods to setup the deployment zones to where the cargo needs to be transported! -- -- There are two levels on which deployment zones can be configured: -- -- * Default deploy zones: The TASK_CARGO_DISPATCHER object can have default deployment zones, which will apply over all tasks active in the task dispatcher. -- * Task specific deploy zones: The TASK_CARGO_DISPATCHER object can have specific deployment zones which apply to a specific task only! -- -- Note that for Task specific deployment zones, there are separate deployment zone creation methods per task type! -- -- ## 4.1. Setup default deploy zones. -- -- Use the @{#TASK_CARGO_DISPATCHER.SetDefaultDeployZone}() to setup one deployment zone, and @{#TASK_CARGO_DISPATCHER.SetDefaultDeployZones}() to setup multiple default deployment zones in one call. -- -- ## 4.2. Setup task specific deploy zones for a **transport task**. -- -- Use the @{#TASK_CARGO_DISPATCHER.SetTransportDeployZone}() to setup one deployment zone, and @{#TASK_CARGO_DISPATCHER.SetTransportDeployZones}() to setup multiple default deployment zones in one call. -- -- ## 4.3. Setup task specific deploy zones for a **CSAR task**. -- -- Use the @{#TASK_CARGO_DISPATCHER.SetCSARDeployZone}() to setup one deployment zone, and @{#TASK_CARGO_DISPATCHER.SetCSARDeployZones}() to setup multiple default deployment zones in one call. -- -- -- -- @field #TASK_CARGO_DISPATCHER TASK_CARGO_DISPATCHER = { ClassName = "TASK_CARGO_DISPATCHER", Mission = nil, Tasks = {}, CSAR = {}, CSARSpawned = 0, Transport = {}, TransportCount = 0, } --- TASK_CARGO_DISPATCHER constructor. -- @param #TASK_CARGO_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_CARGO_DISPATCHER self function TASK_CARGO_DISPATCHER:New( Mission, SetGroup ) -- Inherits from DETECTION_MANAGER local self = BASE:Inherit( self, TASK_MANAGER:New( SetGroup ) ) -- #TASK_CARGO_DISPATCHER self.Mission = Mission self:AddTransition( "Started", "Assign", "Started" ) --- OnAfter Transition Handler for Event Assign. -- @function [parent=#TASK_CARGO_DISPATCHER] OnAfterAssign -- @param #TASK_CARGO_DISPATCHER self -- @param #string From The From State string. -- @param #string Event The Event string. -- @param #string To The To State string. -- @param Tasking.Task_A2A#TASK_A2A Task -- @param Wrapper.Unit#UNIT TaskUnit -- @param #string PlayerName self:SetCSARRadius() self:__StartTasks( 5 ) -- For CSAR missions, we process the event when a pilot ejects. self:HandleEvent( EVENTS.Ejection ) return self end --- Handle the event when a pilot ejects. -- @param #TASK_CARGO_DISPATCHER self -- @param Core.Event#EVENTDATA EventData function TASK_CARGO_DISPATCHER:OnEventEjection( EventData ) self:F( { EventData = EventData } ) if self.CSARTasks == true then local CSARCoordinate = EventData.IniUnit:GetCoordinate() local CSARCoalition = EventData.IniUnit:GetCoalition() local CSARCountry = EventData.IniUnit:GetCountry() local CSARHeading = EventData.IniUnit:GetHeading() -- Only add a CSAR task if the coalition of the mission is equal to the coalition of the ejected unit. if CSARCoalition == self.Mission:GetCommandCenter():GetCoalition() then local CSARTaskName = self:AddCSARTask( self.CSARTaskName, CSARCoordinate, CSARHeading, CSARCountry, self.CSARBriefing ) self:SetCSARDeployZones( CSARTaskName, self.CSARDeployZones ) end end return self end --- Define one default deploy zone for all the cargo tasks. -- @param #TASK_CARGO_DISPATCHER self -- @param DefaultDeployZone A default deploy zone. -- @return #TASK_CARGO_DISPATCHER function TASK_CARGO_DISPATCHER:SetDefaultDeployZone( DefaultDeployZone ) self.DefaultDeployZones = { DefaultDeployZone } return self end --- Define the deploy zones for all the cargo tasks. -- @param #TASK_CARGO_DISPATCHER self -- @param DefaultDeployZones A list of the deploy zones. -- @return #TASK_CARGO_DISPATCHER -- function TASK_CARGO_DISPATCHER:SetDefaultDeployZones( DefaultDeployZones ) self.DefaultDeployZones = DefaultDeployZones return self end --- Start the generation of CSAR tasks to retrieve a downed pilots. -- You need to specify a task briefing, a task name, default deployment zone(s). -- This method can only be used once! -- @param #TASK_CARGO_DISPATCHER self -- @param #string CSARTaskName The CSAR task name. -- @param #string CSARDeployZones The zones to where the CSAR deployment should be directed. -- @param #string CSARBriefing The briefing of the CSAR tasks. -- @return #TASK_CARGO_DISPATCHER function TASK_CARGO_DISPATCHER:StartCSARTasks( CSARTaskName, CSARDeployZones, CSARBriefing) if not self.CSARTasks then self.CSARTasks = true self.CSARTaskName = CSARTaskName self.CSARDeployZones = CSARDeployZones self.CSARBriefing = CSARBriefing else error( "TASK_CARGO_DISPATCHER: The generation of CSAR tasks has already started." ) end return self end --- Stop the generation of CSAR tasks to retrieve a downed pilots. -- @param #TASK_CARGO_DISPATCHER self -- @return #TASK_CARGO_DISPATCHER function TASK_CARGO_DISPATCHER:StopCSARTasks() if self.CSARTasks then self.CSARTasks = nil self.CSARTaskName = nil self.CSARDeployZones = nil self.CSARBriefing = nil else error( "TASK_CARGO_DISPATCHER: The generation of CSAR tasks was not yet started." ) end return self end --- Add a CSAR task to retrieve a downed pilot. -- You need to specify a coordinate from where the pilot will be spawned to be rescued. -- @param #TASK_CARGO_DISPATCHER self -- @param #string CSARTaskPrefix (optional) The prefix of the CSAR task. -- @param Core.Point#COORDINATE CSARCoordinate The coordinate where a downed pilot will be spawned. -- @param #number CSARHeading The heading of the pilot in degrees. -- @param DCSCountry#Country CSARCountry The country ID of the pilot that will be spawned. -- @param #string CSARBriefing The briefing of the CSAR task. -- @return #string The CSAR Task Name as a string. The Task Name is the main key and is shown in the task list of the Mission Tasking menu. -- @usage -- -- -- Add a CSAR task to rescue a downed pilot from within a coordinate. -- local Coordinate = PlaneUnit:GetPointVec2() -- TaskA2ADispatcher:AddCSARTask( "CSAR Task", Coordinate ) -- -- -- Add a CSAR task to rescue a downed pilot from within a coordinate of country RUSSIA, which is pointing to the west (270°). -- local Coordinate = PlaneUnit:GetPointVec2() -- TaskA2ADispatcher:AddCSARTask( "CSAR Task", Coordinate, 270, Country.RUSSIA ) -- function TASK_CARGO_DISPATCHER:AddCSARTask( CSARTaskPrefix, CSARCoordinate, CSARHeading, CSARCountry, CSARBriefing ) local CSARCoalition = self.Mission:GetCommandCenter():GetCoalition() CSARHeading = CSARHeading or 0 CSARCountry = CSARCountry or self.Mission:GetCommandCenter():GetCountry() self.CSARSpawned = self.CSARSpawned + 1 local CSARTaskName = string.format( ( CSARTaskPrefix or "CSAR" ) .. ".%03d", self.CSARSpawned ) -- Create the CSAR Pilot SPAWN object. -- Let us create the Template for the replacement Pilot :-) local Template = { ["visible"] = false, ["hidden"] = false, ["task"] = "Ground Nothing", ["name"] = string.format( "CSAR Pilot#%03d", self.CSARSpawned ), ["x"] = CSARCoordinate.x, ["y"] = CSARCoordinate.z, ["units"] = { [1] = { ["type"] = ( CSARCoalition == coalition.side.BLUE ) and "Soldier M4" or "Infantry AK", ["name"] = string.format( "CSAR Pilot#%03d-01", self.CSARSpawned ), ["skill"] = "Excellent", ["playerCanDrive"] = false, ["x"] = CSARCoordinate.x, ["y"] = CSARCoordinate.z, ["heading"] = CSARHeading, }, -- end of [1] }, -- end of ["units"] } local CSARGroup = GROUP:NewTemplate( Template, CSARCoalition, Group.Category.GROUND, CSARCountry ) self.CSAR[CSARTaskName] = {} self.CSAR[CSARTaskName].PilotGroup = CSARGroup self.CSAR[CSARTaskName].Briefing = CSARBriefing self.CSAR[CSARTaskName].Task = nil return CSARTaskName end --- Define the radius to when a CSAR task will be generated for any downed pilot within range of the nearest CSAR airbase. -- @param #TASK_CARGO_DISPATCHER self -- @param #number CSARRadius (Optional, Default = 50000) The radius in meters to decide whether a CSAR needs to be created. -- @return #TASK_CARGO_DISPATCHER -- @usage -- -- -- Set 20km as the radius to CSAR any downed pilot within range of the nearest CSAR airbase. -- TaskA2ADispatcher:SetEngageRadius( 20000 ) -- -- -- Set 50km as the radius to to CSAR any downed pilot within range of the nearest CSAR airbase. -- TaskA2ADispatcher:SetEngageRadius() -- 50000 is the default value. -- function TASK_CARGO_DISPATCHER:SetCSARRadius( CSARRadius ) self.CSARRadius = CSARRadius or 50000 return self end --- Define one deploy zone for the CSAR tasks. -- @param #TASK_CARGO_DISPATCHER self -- @param #string CSARTaskName (optional) The name of the CSAR task. -- @param CSARDeployZone A CSAR deploy zone. -- @return #TASK_CARGO_DISPATCHER function TASK_CARGO_DISPATCHER:SetCSARDeployZone( CSARTaskName, CSARDeployZone ) if CSARTaskName then self.CSAR[CSARTaskName].DeployZones = { CSARDeployZone } end return self end --- Define the deploy zones for the CSAR tasks. -- @param #TASK_CARGO_DISPATCHER self -- @param #string CSARTaskName (optional) The name of the CSAR task. -- @param CSARDeployZones A list of the CSAR deploy zones. -- @return #TASK_CARGO_DISPATCHER -- function TASK_CARGO_DISPATCHER:SetCSARDeployZones( CSARTaskName, CSARDeployZones ) if CSARTaskName and self.CSAR[CSARTaskName] then self.CSAR[CSARTaskName].DeployZones = CSARDeployZones end return self end --- Add a Transport task to transport cargo from fixed locations to a deployment zone. -- @param #TASK_CARGO_DISPATCHER self -- @param #string TaskPrefix (optional) The prefix of the transport task. -- This prefix will be appended with a . + a number of 3 digits. -- If no TaskPrefix is given, then "Transport" will be used as the prefix. -- @param Core.SetCargo#SET_CARGO SetCargo The SetCargo to be transported. -- @param #string Briefing The briefing of the task transport to be shown to the player. -- @return Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT -- @usage -- -- -- Add a Transport task to transport cargo of different types to a Transport Deployment Zone. -- TaskDispatcher = TASK_CARGO_DISPATCHER:New( Mission, TransportGroups ) -- -- local CargoSetWorkmaterials = SET_CARGO:New():FilterTypes( "Workmaterials" ):FilterStart() -- local EngineerCargoGroup = CARGO_GROUP:New( GROUP:FindByName( "Engineers" ), "Workmaterials", "Engineers", 250 ) -- local ConcreteCargo = CARGO_SLINGLOAD:New( STATIC:FindByName( "Concrete" ), "Workmaterials", "Concrete", 150, 50 ) -- local CrateCargo = CARGO_CRATE:New( STATIC:FindByName( "Crate" ), "Workmaterials", "Crate", 150, 50 ) -- local EnginesCargo = CARGO_CRATE:New( STATIC:FindByName( "Engines" ), "Workmaterials", "Engines", 150, 50 ) -- local MetalCargo = CARGO_CRATE:New( STATIC:FindByName( "Metal" ), "Workmaterials", "Metal", 150, 50 ) -- -- -- Here we add the task. We name the task "Build a Workplace". -- -- We provide the CargoSetWorkmaterials, and a briefing as the 2nd and 3rd parameter. -- -- The :AddTransportTask() returns a Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT object, which we keep as a reference for further actions. -- -- The WorkplaceTask holds the created and returned Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT object. -- local WorkplaceTask = TaskDispatcher:AddTransportTask( "Build a Workplace", CargoSetWorkmaterials, "Transport the workers, engineers and the equipment near the Workplace." ) -- -- -- Here we set a TransportDeployZone. We use the WorkplaceTask as the reference, and provide a ZONE object. -- TaskDispatcher:SetTransportDeployZone( WorkplaceTask, ZONE:New( "Workplace" ) ) -- function TASK_CARGO_DISPATCHER:AddTransportTask( TaskName, SetCargo, Briefing ) self.TransportCount = self.TransportCount + 1 local TaskName = string.format( ( TaskName or "Transport" ) .. ".%03d", self.TransportCount ) self.Transport[TaskName] = {} self.Transport[TaskName].SetCargo = SetCargo self.Transport[TaskName].Briefing = Briefing self.Transport[TaskName].Task = nil self:ManageTasks() return self.Transport[TaskName] and self.Transport[TaskName].Task end --- Define one deploy zone for the Transport tasks. -- @param #TASK_CARGO_DISPATCHER self -- @param Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT Task The name of the Transport task. -- @param TransportDeployZone A Transport deploy zone. -- @return #TASK_CARGO_DISPATCHER -- @usage -- -- function TASK_CARGO_DISPATCHER:SetTransportDeployZone( Task, TransportDeployZone ) if self.Transport[Task.TaskName] then self.Transport[Task.TaskName].DeployZones = { TransportDeployZone } else error( "Task does not exist" ) end self:ManageTasks() return self end --- Define the deploy zones for the Transport tasks. -- @param #TASK_CARGO_DISPATCHER self -- @param Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT Task The name of the Transport task. -- @param TransportDeployZones A list of the Transport deploy zones. -- @return #TASK_CARGO_DISPATCHER -- function TASK_CARGO_DISPATCHER:SetTransportDeployZones( Task, TransportDeployZones ) if self.Transport[Task.TaskName] then self.Transport[Task.TaskName].DeployZones = TransportDeployZones else error( "Task does not exist" ) end self:ManageTasks() return self end --- Evaluates of a CSAR task needs to be started. -- @param #TASK_CARGO_DISPATCHER self -- @return Core.Set#SET_CARGO The SetCargo to be rescued. -- @return #nil If there is no CSAR task required. function TASK_CARGO_DISPATCHER:EvaluateCSAR( CSARUnit ) local CSARCargo = CARGO_GROUP:New( CSARUnit, "Pilot", CSARUnit:GetName(), 80, 1500, 10 ) local SetCargo = SET_CARGO:New() SetCargo:AddCargosByName( CSARUnit:GetName() ) SetCargo:Flush(self) return SetCargo end --- Assigns tasks to the @{Core.Set#SET_GROUP}. -- @param #TASK_CARGO_DISPATCHER self -- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop. function TASK_CARGO_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 CSAR pilots. for CSARName, CSAR in pairs( self.CSAR ) do if not CSAR.Task then -- New CSAR Task local SetCargo = self:EvaluateCSAR( CSAR.PilotGroup ) CSAR.Task = TASK_CARGO_CSAR:New( Mission, self.SetGroup, CSARName, SetCargo, CSAR.Briefing ) Mission:AddTask( CSAR.Task ) TaskReport:Add( CSARName ) if CSAR.DeployZones then CSAR.Task:SetDeployZones( CSAR.DeployZones or {} ) else CSAR.Task:SetDeployZones( self.DefaultDeployZones or {} ) end end end -- Now that all obsolete tasks are removed, loop through the Transport tasks. for TransportName, Transport in pairs( self.Transport ) do if not Transport.Task then -- New Transport Task Transport.Task = TASK_CARGO_TRANSPORT:New( Mission, self.SetGroup, TransportName, Transport.SetCargo, Transport.Briefing ) Mission:AddTask( Transport.Task ) TaskReport:Add( TransportName ) function Transport.Task.OnEnterSuccess( Task, From, Event, To ) self:Success( Task ) end function Transport.Task.onenterCancelled( Task, From, Event, To ) self:Cancelled( Task ) end function Transport.Task.onenterFailed( Task, From, Event, To ) self:Failed( Task ) end function Transport.Task.onenterAborted( Task, From, Event, To ) self:Aborted( Task ) end end if Transport.DeployZones then Transport.Task:SetDeployZones( Transport.DeployZones or {} ) else Transport.Task:SetDeployZones( self.DefaultDeployZones or {} ) 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