Merge pull request #534 from FlightControl-Master/419-A2A-Tasking

419 a2a tasking
This commit is contained in:
Sven Van de Velde 2017-05-18 21:19:49 +02:00 committed by GitHub
commit eab81a2bf9
10 changed files with 1555 additions and 853 deletions

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1303,19 +1303,52 @@ do -- DETECTION_BASE
return nil
end
do -- Coordinates
--- Get the COORDINATE of a detection item using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
-- @return Core.Point#COORDINATE Coordinate
function DETECTION_BASE:GetDetectedItemCoordinate( Index )
-- If the Zone is set, return the coordinate of the Zone.
local DetectedItemSet = self:GetDetectedSet( Index )
local FirstUnit = DetectedItemSet:GetFirst()
local DetectedZone = self:GetDetectedItemZone( Index )
if DetectedZone then
local Coordinate = DetectedZone:GetCoordinate()
Coordinate:SetHeading(FirstUnit:GetHeading())
return Coordinate
end
-- If no Zone is set, return the coordinate of the first unit in the Set
if FirstUnit then
local Coordinate = FirstUnit:GetCoordinate()
FirstUnit:SetHeading(FirstUnit:GetHeading())
return Coordinate
end
return nil
end
end
do -- Zones
--- Get the @{Zone#ZONE_UNIT} of a detection area using a given numeric index.
-- @param #DETECTION_BASE self
-- @param #number Index
-- @return Core.Zone#ZONE_UNIT DetectedZone
function DETECTION_BASE:GetDetectedZone( Index )
function DETECTION_BASE:GetDetectedItemZone( Index )
local DetectedZone = self.DetectedItems[Index].Zone
if DetectedZone then
return DetectedZone
end
local Detected
return nil
end
@ -1579,7 +1612,7 @@ do -- DETECTION_UNITS
-- @param Index
-- @return #string
function DETECTION_UNITS:DetectedItemReportSummary( Index )
self:F( Index )
self:F( { Index, self.DetectedItems } )
local DetectedItem = self:GetDetectedItem( Index )
local DetectedSet = self:GetDetectedSet( Index )
@ -1977,7 +2010,7 @@ do -- DETECTION_AREAS
local DetectedSet = self:GetDetectedSet( Index )
local ReportSummaryItem
local DetectedZone = self:GetDetectedZone( Index )
local DetectedZone = self:GetDetectedItemZone( Index )
local DetectedItemCoordinate = DetectedZone:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()
@ -2007,7 +2040,7 @@ do -- DETECTION_AREAS
local DetectedSet = self:GetDetectedSet( Index )
local ReportSummaryItem
local DetectedZone = self:GetDetectedZone( Index )
local DetectedZone = self:GetDetectedItemZone( Index )
local DetectedItemCoordinate = DetectedZone:GetCoordinate()
local DetectedItemCoordText = DetectedItemCoordinate:ToString()

View File

@ -825,7 +825,7 @@ end
-- @param #TASK self
function TASK:MenuTaskStatus( TaskGroup )
local ReportText = self:ReportDetails()
local ReportText = self:ReportDetails( TaskGroup )
self:T( ReportText )
self:GetMission():GetCommandCenter():MessageToGroup( ReportText, TaskGroup )
@ -1369,8 +1369,9 @@ end
--- Create a detailed report of the Task.
-- List the Task Status, and the Players assigned to the Task.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #string
function TASK:ReportDetails() --R2.1 fixed report. Now nicely formatted and contains the info required.
function TASK:ReportDetails( TaskGroup ) --R2.1 fixed report. Now nicely formatted and contains the info required.
local Report = REPORT:New():SetIndent( 3 )
@ -1389,16 +1390,27 @@ function TASK:ReportDetails() --R2.1 fixed report. Now nicely formatted and cont
end
local Players = PlayerReport:Text()
local Detection = self.TaskInfo["Detection"] or ""
local Changes = self.TaskInfo["Changes"] or ""
Report:Add( "Task: " .. Name .. " - " .. State .. " - Detailed Report" )
Report:Add( "\n - Players:" )
Report:Add( " - Players:" )
Report:AddIndent( Players )
Report:Add( "\n - Detection:" )
Report:AddIndent( Detection )
Report:Add( "\n - Detection Changes:" )
Report:AddIndent( Changes )
for TaskInfoID, TaskInfo in pairs( self.TaskInfo ) do
local TaskInfoIDText = string.format( " - %s: ", TaskInfoID )
if type(TaskInfo) == "string" then
Report:Add( TaskInfoIDText .. TaskInfo )
elseif type(TaskInfo) == "table" then
if TaskInfoID == "Coordinates" then
local FromCoordinate = TaskGroup:GetUnit(1):GetCoordinate()
Report:Add( TaskInfoIDText )
Report:AddIndent( TaskInfo:ToStringBRAA( FromCoordinate ) .. ", " .. TaskInfo:ToStringAspect( FromCoordinate ) )
Report:AddIndent( TaskInfo:ToStringBULLS( TaskGroup:GetCoalition() ) )
else
end
end
end
return Report:Text()
end

View File

@ -0,0 +1,381 @@
--- **Tasking** - The TASK_A2A models tasks for players in Air to Air engagements.
--
-- ![Banner Image](..\Presentations\TASK_A2A\Dia1.JPG)
--
--
-- # 1) @{Task_A2A#TASK_A2A} class, extends @{Task#TASK}
--
-- The @{#TASK_A2A} class defines Air To Air tasks for a @{Set} of Target Units,
-- based on the tasking capabilities defined in @{Task#TASK}.
-- The TASK_A2A is implemented using a @{Statemachine#FSM_TASK}, and has the following statuses:
--
-- * **None**: Start of the process
-- * **Planned**: The A2A task is planned.
-- * **Assigned**: The A2A task is assigned to a @{Group#GROUP}.
-- * **Success**: The A2A task is successfully completed.
-- * **Failed**: The A2A task has failed. This will happen if the player exists the task early, without communicating a possible cancellation to HQ.
--
-- # 1.1) Set the scoring of achievements in an A2A attack.
--
-- Scoring or penalties can be given in the following circumstances:
--
-- * @{#TASK_A2A.SetScoreOnDestroy}(): Set a score when a target in scope of the A2A attack, has been destroyed.
-- * @{#TASK_A2A.SetScoreOnSuccess}(): Set a score when all the targets in scope of the A2A attack, have been destroyed.
-- * @{#TASK_A2A.SetPenaltyOnFailed}(): Set a penalty when the A2A attack has failed.
--
-- # 2) @{Task_A2A#TASK_INTERCEPT} class, extends @{Task_A2A#TASK_A2A}
--
-- The TASK_A2A_INTERCEPT class defines an INTERCEPT task for a @{Set} of Target Units.
--
-- ====
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
--
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
--
-- @module Task_A2A
do -- TASK_A2A
--- The TASK_A2A class
-- @type TASK_A2A
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK
TASK_A2A = {
ClassName = "TASK_A2A",
}
--- Instantiates a new TASK_A2A.
-- @param #TASK_A2A self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetAttack The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Set#SET_UNIT UnitSetTargets
-- @param #number TargetDistance The distance to Target when the Player is considered to have "arrived" at the engagement range.
-- @param Core.Zone#ZONE_BASE TargetZone The target zone, if known.
-- If the TargetZone parameter is specified, the player will be routed to the center of the zone where all the targets are assumed to be.
-- @return #TASK_A2A self
function TASK_A2A:New( Mission, SetAttack, TaskName, TargetSetUnit, TaskType, TaskBriefing )
local self = BASE:Inherit( self, TASK:New( Mission, SetAttack, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2A
self:F()
self.TargetSetUnit = TargetSetUnit
self.TaskType = TaskType
local Fsm = self:GetUnitProcess()
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "RouteToRendezVous", Rejected = "Reject" } )
Fsm:AddTransition( "Assigned", "RouteToRendezVous", "RoutingToRendezVous" )
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtRendezVous" } )
Fsm:AddProcess ( "RoutingToRendezVous", "RouteToRendezVousZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtRendezVous" } )
Fsm:AddTransition( { "Arrived", "RoutingToRendezVous" }, "ArriveAtRendezVous", "ArrivedAtRendezVous" )
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "Engage", "Engaging" )
Fsm:AddTransition( { "ArrivedAtRendezVous", "HoldingAtRendezVous" }, "HoldAtRendezVous", "HoldingAtRendezVous" )
Fsm:AddProcess ( "Engaging", "Account", ACT_ACCOUNT_DEADS:New( self.TargetSetUnit, self.TaskType ), { Accounted = "Success" } )
Fsm:AddTransition( "Engaging", "RouteToTarget", "Engaging" )
Fsm:AddProcess( "Engaging", "RouteToTargetZone", ACT_ROUTE_ZONE:New(), {} )
Fsm:AddProcess( "Engaging", "RouteToTargetPoint", ACT_ROUTE_POINT:New(), {} )
Fsm:AddTransition( "Engaging", "RouteToTargets", "Engaging" )
Fsm:AddTransition( "Accounted", "DestroyedAll", "Accounted" )
Fsm:AddTransition( "Accounted", "Success", "Success" )
Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
Fsm:AddTransition( "Failed", "Fail", "Failed" )
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_A2A#TASK_A2A Task
function Fsm:onafterRouteToRendezVous( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.RendezVousSetUnit
if Task:GetRendezVousZone( TaskUnit ) then
self:__RouteToRendezVousZone( 0.1 )
else
if Task:GetRendezVousCoordinate( TaskUnit ) then
self:__RouteToRendezVousPoint( 0.1 )
else
self:__ArriveAtRendezVous( 0.1 )
end
end
end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task#TASK_A2A Task
function Fsm:OnAfterArriveAtRendezVous( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.TargetSetUnit
self:__Engage( 0.1 )
end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task#TASK_A2A Task
function Fsm:onafterEngage( TaskUnit, Task )
self:E( { self } )
self:__Account( 0.1 )
self:__RouteToTarget(0.1 )
self:__RouteToTargets( -10 )
end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_A2A#TASK_A2A Task
function Fsm:onafterRouteToTarget( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
-- Determine the first Unit from the self.TargetSetUnit
if Task:GetTargetZone( TaskUnit ) then
self:__RouteToTargetZone( 0.1 )
else
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
local Coordinate = TargetUnit:GetCoordinate()
self:T( { TargetCoordinate = Coordinate, Coordinate:GetX(), Coordinate:GetAlt(), Coordinate:GetZ() } )
Task:SetTargetCoordinate( TargetUnit:GetCoordinate(), TaskUnit )
end
self:__RouteToTargetPoint( 0.1 )
end
end
--- Test
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_A2A#TASK_A2A Task
function Fsm:onafterRouteToTargets( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
local TargetUnit = Task.TargetSetUnit:GetFirst() -- Wrapper.Unit#UNIT
if TargetUnit then
Task:SetTargetCoordinate( TargetUnit:GetCoordinate(), TaskUnit )
end
self:__RouteToTargets( -10 )
end
return self
end
--- @param #TASK_A2A self
function TASK_A2A:GetPlannedMenuText()
return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )"
end
--- @param #TASK_A2A self
-- @param Core.Point#COORDINATE RendezVousCoordinate The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
-- @param #number RendezVousRange The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2A:SetRendezVousCoordinate( RendezVousCoordinate, RendezVousRange, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteRendezVous:SetCoordinate( RendezVousCoordinate )
ActRouteRendezVous:SetRange( RendezVousRange )
end
--- @param #TASK_A2A self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Point#COORDINATE The Coordinate object referencing to the 2D point where the RendezVous point is located on the map.
-- @return #number The RendezVousRange that defines when the player is considered to have arrived at the RendezVous point.
function TASK_A2A:GetRendezVousCoordinate( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
return ActRouteRendezVous:GetCoordinate(), ActRouteRendezVous:GetRange()
end
--- @param #TASK_A2A self
-- @param Core.Zone#ZONE_BASE RendezVousZone The Zone object where the RendezVous is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2A:SetRendezVousZone( RendezVousZone, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
ActRouteRendezVous:SetZone( RendezVousZone )
end
--- @param #TASK_A2A self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Zone#ZONE_BASE The Zone object where the RendezVous is located on the map.
function TASK_A2A:GetRendezVousZone( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteRendezVous = ProcessUnit:GetProcess( "RoutingToRendezVous", "RouteToRendezVousZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
return ActRouteRendezVous:GetZone()
end
--- @param #TASK_A2A self
-- @param Core.Point#COORDINATE TargetCoordinate The Coordinate object where the Target is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2A:SetTargetCoordinate( TargetCoordinate, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
ActRouteTarget:SetCoordinate( TargetCoordinate )
end
--- @param #TASK_A2A self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Point#COORDINATE The Coordinate object where the Target is located on the map.
function TASK_A2A:GetTargetCoordinate( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT
return ActRouteTarget:GetCoordinate()
end
--- @param #TASK_A2A self
-- @param Core.Zone#ZONE_BASE TargetZone The Zone object where the Target is located on the map.
-- @param Wrapper.Unit#UNIT TaskUnit
function TASK_A2A:SetTargetZone( TargetZone, TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
ActRouteTarget:SetZone( TargetZone )
end
--- @param #TASK_A2A self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return Core.Zone#ZONE_BASE The Zone object where the Target is located on the map.
function TASK_A2A:GetTargetZone( TaskUnit )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE
return ActRouteTarget:GetZone()
end
--- Set a score when a target in scope of the A2A attack, has been destroyed .
-- @param #TASK_A2A self
-- @param #string Text The text to display to the player, when the target has been destroyed.
-- @param #number Score The score in points.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_A2A
function TASK_A2A:SetScoreOnDestroy( Text, Score, TaskUnit )
self:F( { Text, Score, TaskUnit } )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
ProcessUnit:AddScoreProcess( "Engaging", "Account", "Account", Text, Score )
return self
end
--- Set a score when all the targets in scope of the A2A attack, have been destroyed.
-- @param #TASK_A2A self
-- @param #string Text The text to display to the player, when all targets hav been destroyed.
-- @param #number Score The score in points.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_A2A
function TASK_A2A:SetScoreOnSuccess( Text, Score, TaskUnit )
self:F( { Text, Score, TaskUnit } )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
ProcessUnit:AddScore( "Success", Text, Score )
return self
end
--- Set a penalty when the A2A attack has failed.
-- @param #TASK_A2A self
-- @param #string Text The text to display to the player, when the A2A attack has failed.
-- @param #number Penalty The penalty in points.
-- @param Wrapper.Unit#UNIT TaskUnit
-- @return #TASK_A2A
function TASK_A2A:SetPenaltyOnFailed( Text, Penalty, TaskUnit )
self:F( { Text, Score, TaskUnit } )
local ProcessUnit = self:GetUnitProcess( TaskUnit )
ProcessUnit:AddScore( "Failed", Text, Penalty )
return self
end
end
do -- TASK_INTERCEPT
--- The TASK_INTERCEPT class
-- @type TASK_INTERCEPT
-- @field Set#SET_UNIT TargetSetUnit
-- @extends Tasking.Task#TASK
TASK_INTERCEPT = {
ClassName = "TASK_INTERCEPT",
}
--- Instantiates a new TASK_INTERCEPT.
-- @param #TASK_INTERCEPT self
-- @param Tasking.Mission#MISSION Mission
-- @param Core.Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @param #string TaskName The name of the Task.
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_INTERCEPT self
function TASK_INTERCEPT:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2A:New( Mission, SetGroup, TaskName, TargetSetUnit, "INTERCEPT", TaskBriefing ) ) -- #TASK_INTERCEPT
self:F()
Mission:AddTask( self )
--TODO: Add BR, Altitude, type of planes...
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Intercept incoming intruders.\n" ..
"Last Known Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end
end

View File

@ -0,0 +1,224 @@
--- **Tasking** - The TASK_A2A_DISPATCHER creates and manages player TASK_A2A tasks based on detected targets.
--
-- ===
--
-- # 1) @{#TASK_A2A_DISPATCHER} class, extends @{#DETECTION_MANAGER}
--
-- The @{#TASK_A2A_DISPATCHER} class implements the dynamic dispatching of tasks upon groups of detected units determined a @{Set} of EWR installation groups.
-- The EWR will detect units, will group them, and will dispatch @{Task}s to groups. Depending on the type of target detected, different tasks will be dispatched.
-- Find a summary below describing for which situation a task type is created:
--
-- * **INTERCEPT Task**: Is created when the target is known, is detected and within a danger zone, and there is no friendly airborne in range.
-- * **SWEEP Task**: Is created when the target is unknown, was detected and the last position is only known, and within a danger zone, and there is no friendly airborne in range.
-- * **ENGAGE Task**: Is created when the target is known, is detected and within a danger zone, and there is a friendly airborne in range, that will receive this task.
--
-- Other task types will follow...
--
-- 3.1) TASK_A2A_DISPATCHER constructor:
-- --------------------------------------
-- The @{#TASK_A2A_DISPATCHER.New}() method creates a new TASK_A2A_DISPATCHER instance.
--
-- ===
--
-- # **API CHANGE HISTORY**
--
-- The underlying change log documents the API changes. Please read this carefully. The following notation is used:
--
-- * **Added** parts are expressed in bold type face.
-- * _Removed_ parts are expressed in italic type face.
--
-- Hereby the change log:
--
-- ===
--
-- # **AUTHORS and CONTRIBUTIONS**
--
-- ### Contributions:
--
-- ### Authors:
--
-- * **FlightControl**: Concept, Design & Programming.
--
-- @module Task_A2A_Dispatcher
do -- TASK_A2A_DISPATCHER
--- TASK_A2A_DISPATCHER class.
-- @type TASK_A2A_DISPATCHER
-- @field Set#SET_GROUP SetGroup The groups to which the FAC will report to.
-- @field Functional.Detection#DETECTION_BASE Detection The DETECTION_BASE object that is used to report the detected objects. The Detection object will only function in RADAR mode!!!
-- @field Tasking.Mission#MISSION Mission
-- @extends Tasking.DetectionManager#DETECTION_MANAGER
TASK_A2A_DISPATCHER = {
ClassName = "TASK_A2A_DISPATCHER",
Mission = nil,
Detection = nil,
Tasks = {},
}
--- TASK_A2A_DISPATCHER constructor.
-- @param #TASK_A2A_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission The mission for which the task dispatching is done.
-- @param Set#SET_GROUP SetGroup The set of groups that can join the tasks within the mission.
-- @param Functional.Detection#DETECTION_BASE Detection The detection results that are used to dynamically assign new tasks to human players.
-- @return #TASK_A2A_DISPATCHER self
function TASK_A2A_DISPATCHER:New( Mission, SetGroup, Detection )
-- Inherits from DETECTION_MANAGER
local self = BASE:Inherit( self, DETECTION_MANAGER:New( SetGroup, Detection ) ) -- #TASK_A2A_DISPATCHER
self.Detection = Detection
self.Mission = Mission
self.Detection:FilterCategories( Unit.Category.AIRPLANE, Unit.Category.HELICOPTER )
self.Detection:InitDetectRadar( true )
self.Detection:SetDetectionInterval( 30 )
self:AddTransition( "Started", "Assign", "Started" )
--- OnAfter Transition Handler for Event Assign.
-- @function [parent=#TASK_A2A_DISPATCHER] OnAfterAssign
-- @param #TASK_A2A_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:__Start( 5 )
return self
end
--- Creates an INTERCEPT task when there are targets for it.
-- @param #TASK_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE.DetectedItem DetectedItem
-- @return Set#SET_UNIT TargetSetUnit: The target set of units.
-- @return #nil If there are no targets to be set.
function TASK_A2A_DISPATCHER:EvaluateINTERCEPT( DetectedItem )
self:F( { DetectedItem.ItemID } )
local DetectedSet = DetectedItem.Set
local DetectedZone = DetectedItem.Zone
-- Put here the intercept logic....
if true then
-- Here we're doing something advanced... We're copying the DetectedSet, but making a new Set only with SEADable Radar units in it.
local TargetSetUnit = SET_UNIT:New()
TargetSetUnit:SetDatabase( DetectedSet )
TargetSetUnit:FilterOnce() -- Filter but don't do any events!!! Elements are added manually upon each detection.
return TargetSetUnit
end
return nil
end
--- Evaluates the removal of the Task from the Mission.
-- Can only occur when the DetectedItem is Changed AND the state of the Task is "Planned".
-- @param #TASK_A2A_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission
-- @param Tasking.Task#TASK Task
-- @param #boolean DetectedItemID
-- @param #boolean DetectedItemChange
-- @return Tasking.Task#TASK
function TASK_A2A_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItemID, DetectedItemChanged )
if Task then
if Task:IsStatePlanned() and DetectedItemChanged == true then
self:E( "Removing Tasking: " .. Task:GetTaskName() )
Mission:RemoveTask( Task )
self.Tasks[DetectedItemID] = nil
end
end
return Task
end
--- Assigns tasks in relation to the detected items to the @{Set#SET_GROUP}.
-- @param #TASK_A2A_DISPATCHER self
-- @param Functional.Detection#DETECTION_BASE Detection The detection created by the @{Detection#DETECTION_BASE} derived object.
-- @return #boolean Return true if you want the task assigning to continue... false will cancel the loop.
function TASK_A2A_DISPATCHER:ProcessDetected( Detection )
self:E()
local AreaMsg = {}
local TaskMsg = {}
local ChangeMsg = {}
local Mission = self.Mission
if Mission:IsIDLE() or Mission:IsENGAGED() then
local TaskReport = REPORT:New()
--- First we need to the detected targets.
for DetectedItemID, DetectedItem in pairs( Detection:GetDetectedItems() ) do
local DetectedItem = DetectedItem -- Functional.Detection#DETECTION_BASE.DetectedItem
local DetectedSet = DetectedItem.Set -- Core.Set#SET_UNIT
local DetectedZone = DetectedItem.Zone
self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
DetectedSet:Flush()
local DetectedID = DetectedItem.ID
local DetectedIndex = DetectedItem.Index
local DetectedItemChanged = DetectedItem.Changed
local Task = self.Tasks[DetectedID]
Task = self:EvaluateRemoveTask( Mission, Task, DetectedID, DetectedItemChanged ) -- Task will be removed if it is planned and changed.
-- Evaluate INTERCEPT
if not Task then
local TargetSetUnit = self:EvaluateINTERCEPT( DetectedItem ) -- Returns a SetUnit if there are targets to be INTERCEPTed...
if TargetSetUnit then
Task = TASK_INTERCEPT:New( Mission, self.SetGroup, string.format( "INTERCEPT.%03d", DetectedID ), TargetSetUnit )
end
if Task then
self.Tasks[DetectedID] = Task
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
Task:SetInfo( "ThreatLevel", "[" .. string.rep( "", DetectedSet:CalculateThreatLevelA2G() ) .. "]" )
local DetectedItemsCount = DetectedSet:Count()
local DetectedItemsTypes = DetectedSet:GetTypeNames()
Task:SetInfo( "Targets", string.format( "%d of %s", DetectedItemsCount, DetectedItemsTypes ) )
Task:SetInfo( "Coordinates", Detection:GetDetectedItemCoordinate( DetectedIndex ) )
Task:SetInfo( "Object", DetectedSet:GetFirst() )
Mission:AddTask( Task )
else
self:E("This should not happen")
end
end
TaskReport:Add( Task:GetName() )
-- OK, so the tasking has been done, now delete the changes reported for the area.
Detection:AcceptChanges( DetectedItem )
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:GetName(), TaskText ), TaskGroup )
end
end
end
return true
end
end

View File

@ -149,6 +149,7 @@ function POSITIONABLE:GetCoordinate()
local PositionableVec3 = self:GetPositionVec3()
local PositionableCoordinate = COORDINATE:NewFromVec3( PositionableVec3 )
PositionableCoordinate:SetHeading( self:GetHeading() )
self:T2( PositionableCoordinate )
return PositionableCoordinate

View File

@ -640,7 +640,7 @@ function UNIT:GetThreatLevel()
"Unarmed",
"Tanker",
"AWACS",
"Transport Helicpter",
"Transport Helicopter",
"UAV",
"Bomber",
"Strategic Bomber",

View File

@ -57,6 +57,8 @@ Tasking/Task.lua
Tasking/DetectionManager.lua
Tasking/Task_A2G_Dispatcher.lua
Tasking/Task_A2G.lua
Tasking/Task_A2A_Dispatcher.lua
Tasking/Task_A2A.lua
Tasking/Task_Cargo.lua
Moose.lua

View File

@ -1,5 +1,5 @@
env.info( '*** MOOSE DYNAMIC INCLUDE START *** ' )
env.info( 'Moose Generation Timestamp: 20170518_2107' )
env.info( 'Moose Generation Timestamp: 20170517_1856' )
local base = _G
@ -74,6 +74,8 @@ __Moose.Include( 'Tasking/Task.lua' )
__Moose.Include( 'Tasking/DetectionManager.lua' )
__Moose.Include( 'Tasking/Task_A2G_Dispatcher.lua' )
__Moose.Include( 'Tasking/Task_A2G.lua' )
__Moose.Include( 'Tasking/Task_A2A_Dispatcher.lua' )
__Moose.Include( 'Tasking/Task_A2A.lua' )
__Moose.Include( 'Tasking/Task_Cargo.lua' )
__Moose.Include( 'Moose.lua' )
BASE:TraceOnOff( true )