From 2e2aabdcc9697fe9682e09930ee4842b2479aeb3 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Sun, 2 Apr 2017 08:04:43 +0200 Subject: [PATCH] Progress --- Moose Development/Moose/AI/AI_Cargo.lua | 25 ++- Moose Development/Moose/Core/Zone.lua | 112 ++++++---- .../Moose/Tasking/Task_CARGO.lua | 202 ++++++++++++++---- ...- A2G Task Dispatching DETECTION_AREAS.lua | 35 --- .../TSK-100 - Cargo Pickup.lua | 35 --- .../TSK-100 - Cargo Pickup.miz | Bin 28460 -> 0 bytes 6 files changed, 255 insertions(+), 154 deletions(-) delete mode 100644 Moose Test Missions/TAD - Task Dispatching/TAD-100 - A2G Task Dispatching DETECTION_AREAS/TAD-100 - A2G Task Dispatching DETECTION_AREAS.lua delete mode 100644 Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.lua delete mode 100644 Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.miz diff --git a/Moose Development/Moose/AI/AI_Cargo.lua b/Moose Development/Moose/AI/AI_Cargo.lua index 2e6f0d6ab..9b05de6c0 100644 --- a/Moose Development/Moose/AI/AI_Cargo.lua +++ b/Moose Development/Moose/AI/AI_Cargo.lua @@ -302,7 +302,12 @@ end function AI_CARGO:IsInRadius( PointVec2 ) self:F( { PointVec2 } ) - local Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) + local Distance = 0 + if self:IsLoaded() then + Distance = PointVec2:DistanceFromPointVec2( self.CargoCarrier:GetPointVec2() ) + else + Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() ) + end self:T( Distance ) if Distance <= self.ReportRadius then @@ -313,6 +318,24 @@ function AI_CARGO:IsInRadius( PointVec2 ) end +--- Check if Cargo is the given @{Zone}. +-- @param #AI_CARGO self +-- @param Core.Zone#ZONE_BASE Zone +-- @return #boolean **true** if cargo is in the Zone, **false** if cargo is not in the Zone. +function AI_CARGO:IsInZone( Zone ) + self:F( { Zone } ) + + if self:IsLoaded() then + return Zone:IsPointVec2InZone( self.CargoCarrier:GetPointVec2() ) + else + return Zone:IsPointVec2InZone( self.CargoObject:GetPointVec2() ) + end + + return nil + +end + + --- Check if CargoCarrier is near the Cargo to be Loaded. -- @param #AI_CARGO self -- @param Core.Point#POINT_VEC2 PointVec2 diff --git a/Moose Development/Moose/Core/Zone.lua b/Moose Development/Moose/Core/Zone.lua index 432a360a7..d7c00ae39 100644 --- a/Moose Development/Moose/Core/Zone.lua +++ b/Moose Development/Moose/Core/Zone.lua @@ -73,41 +73,41 @@ -- @extends Core.Base#BASE ---- # 1) ZONE_BASE class, extends @{Base#BASE} +--- # ZONE_BASE class, extends @{Base#BASE} -- -- This class is an abstract BASE class for derived classes, and is not meant to be instantiated. -- --- ## 1.1) Each zone has a name: +-- ## Each zone has a name: -- -- * @{#ZONE_BASE.GetName}(): Returns the name of the zone. -- --- ## 1.2) Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}: +-- ## Each zone implements two polymorphic functions defined in @{Zone#ZONE_BASE}: -- -- * @{#ZONE_BASE.IsVec2InZone}(): Returns if a Vec2 is within the zone. -- * @{#ZONE_BASE.IsVec3InZone}(): Returns if a Vec3 is within the zone. -- --- ## 1.3) A zone has a probability factor that can be set to randomize a selection between zones: +-- ## A zone has a probability factor that can be set to randomize a selection between zones: -- -- * @{#ZONE_BASE.SetRandomizeProbability}(): Set the randomization probability of a zone to be selected, taking a value between 0 and 1 ( 0 = 0%, 1 = 100% ) -- * @{#ZONE_BASE.GetRandomizeProbability}(): Get the randomization probability of a zone to be selected, passing a value between 0 and 1 ( 0 = 0%, 1 = 100% ) -- * @{#ZONE_BASE.GetZoneMaybe}(): Get the zone taking into account the randomization probability. nil is returned if this zone is not a candidate. -- --- ## 1.4) A zone manages Vectors: +-- ## A zone manages Vectors: -- -- * @{#ZONE_BASE.GetVec2}(): Returns the @{DCSTypes#Vec2} coordinate of the zone. -- * @{#ZONE_BASE.GetRandomVec2}(): Define a random @{DCSTypes#Vec2} within the zone. -- --- ## 1.5) A zone has a bounding square: +-- ## A zone has a bounding square: -- -- * @{#ZONE_BASE.GetBoundingSquare}(): Get the outer most bounding square of the zone. -- --- ## 1.6) A zone can be marked: +-- ## A zone can be marked: -- -- * @{#ZONE_BASE.SmokeZone}(): Smokes the zone boundaries in a color. -- * @{#ZONE_BASE.FlareZone}(): Flares the zone boundaries in a color. -- --- === -- @field #ZONE_BASE ZONE_BASE +-- ZONE_BASE = { ClassName = "ZONE_BASE", ZoneName = "", @@ -144,20 +144,21 @@ function ZONE_BASE:GetName() return self.ZoneName end ---- Returns if a location is within the zone. + +--- Returns if a Vec2 is within the zone. -- @param #ZONE_BASE self --- @param Dcs.DCSTypes#Vec2 Vec2 The location to test. --- @return #boolean true if the location is within the zone. +-- @param Dcs.DCSTypes#Vec2 Vec2 The Vec2 to test. +-- @return #boolean true if the Vec2 is within the zone. function ZONE_BASE:IsVec2InZone( Vec2 ) self:F2( Vec2 ) return false end ---- Returns if a point is within the zone. +--- Returns if a Vec3 is within the zone. -- @param #ZONE_BASE self -- @param Dcs.DCSTypes#Vec3 Vec3 The point to test. --- @return #boolean true if the point is within the zone. +-- @return #boolean true if the Vec3 is within the zone. function ZONE_BASE:IsVec3InZone( Vec3 ) self:F2( Vec3 ) @@ -166,6 +167,31 @@ function ZONE_BASE:IsVec3InZone( Vec3 ) return InZone end +--- Returns if a PointVec2 is within the zone. +-- @param #ZONE_BASE self +-- @param Core.Point#POINT_VEC2 PointVec2 The PointVec2 to test. +-- @return #boolean true if the PointVec2 is within the zone. +function ZONE_BASE:IsPointVec2InZone( PointVec2 ) + self:F2( PointVec2 ) + + local InZone = self:IsVec2InZone( PointVec2:GetVec2() ) + + return InZone +end + +--- Returns if a PointVec3 is within the zone. +-- @param #ZONE_BASE self +-- @param Core.Point#POINT_VEC3 PointVec3 The PointVec3 to test. +-- @return #boolean true if the PointVec3 is within the zone. +function ZONE_BASE:IsPointVec3InZone( PointVec3 ) + self:F2( PointVec3 ) + + local InZone = self:IsPointVec2InZone( PointVec3 ) + + return InZone +end + + --- Returns the @{DCSTypes#Vec2} coordinate of the zone. -- @param #ZONE_BASE self -- @return #nil. @@ -310,29 +336,29 @@ end -- @type ZONE_RADIUS -- @field Dcs.DCSTypes#Vec2 Vec2 The current location of the zone. -- @field Dcs.DCSTypes#Distance Radius The radius of the zone. --- @extends Core.Zone#ZONE_BASE +-- @extends #ZONE_BASE ---- # 2) @{Zone#ZONE_RADIUS} class, extends @{Zone#ZONE_BASE} +--- # ZONE_RADIUS class, extends @{Zone#ZONE_BASE} -- -- The ZONE_RADIUS class defined by a zone name, a location and a radius. -- This class implements the inherited functions from Core.Zone#ZONE_BASE taking into account the own zone format and properties. -- --- ## 2.1) @{Zone#ZONE_RADIUS} constructor +-- ## ZONE_RADIUS constructor -- -- * @{#ZONE_RADIUS.New}(): Constructor. -- --- ## 2.2) Manage the radius of the zone +-- ## Manage the radius of the zone -- -- * @{#ZONE_RADIUS.SetRadius}(): Sets the radius of the zone. -- * @{#ZONE_RADIUS.GetRadius}(): Returns the radius of the zone. -- --- ## 2.3) Manage the location of the zone +-- ## Manage the location of the zone -- -- * @{#ZONE_RADIUS.SetVec2}(): Sets the @{DCSTypes#Vec2} of the zone. -- * @{#ZONE_RADIUS.GetVec2}(): Returns the @{DCSTypes#Vec2} of the zone. -- * @{#ZONE_RADIUS.GetVec3}(): Returns the @{DCSTypes#Vec3} of the zone, taking an additional height parameter. -- --- ## 2.4) Zone point randomization +-- ## Zone point randomization -- -- Various functions exist to find random points within the zone. -- @@ -340,8 +366,6 @@ end -- * @{#ZONE_RADIUS.GetRandomPointVec2}(): Gets a @{Point#POINT_VEC2} object representing a random 2D point in the zone. -- * @{#ZONE_RADIUS.GetRandomPointVec3}(): Gets a @{Point#POINT_VEC3} object representing a random 3D point in the zone. Note that the height of the point is at landheight. -- --- === --- -- @field #ZONE_RADIUS ZONE_RADIUS -- ZONE_RADIUS = { @@ -615,17 +639,15 @@ end --- @type ZONE --- @extends Core.Zone#ZONE_RADIUS +--- @type ZONE +-- @extends #ZONE_RADIUS ---- # 3) ZONE class, extends @{Zone#ZONE_RADIUS} +--- # ZONE class, extends @{Zone#ZONE_RADIUS} -- -- The ZONE class, defined by the zone name as defined within the Mission Editor. -- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- --- === --- -- @field #ZONE ZONE -- ZONE = { @@ -655,18 +677,15 @@ function ZONE:New( ZoneName ) end ---- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. --- @type ZONE_UNIT +--- @type ZONE_UNIT -- @field Wrapper.Unit#UNIT ZoneUNIT -- @extends Core.Zone#ZONE_RADIUS ---- # 4) #ZONE_UNIT class, extends @{Zone#ZONE_RADIUS} +--- # ZONE_UNIT class, extends @{Zone#ZONE_RADIUS} -- -- The ZONE_UNIT class defined by a zone around a @{Unit#UNIT} with a radius. -- This class implements the inherited functions from @{#ZONE_RADIUS} taking into account the own zone format and properties. -- --- === --- -- @field #ZONE_UNIT ZONE_UNIT -- ZONE_UNIT = { @@ -751,16 +770,14 @@ end --- @type ZONE_GROUP -- @field Wrapper.Group#GROUP ZoneGROUP --- @extends Core.Zone#ZONE_RADIUS +-- @extends #ZONE_RADIUS ---- # 5) #ZONE_GROUP class, extends @{Zone#ZONE_RADIUS} +--- # ZONE_GROUP class, extends @{Zone#ZONE_RADIUS} -- -- The ZONE_GROUP class defines by a zone around a @{Group#GROUP} with a radius. The current leader of the group defines the center of the zone. -- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties. -- --- === --- -- @field #ZONE_GROUP ZONE_GROUP -- ZONE_GROUP = { @@ -818,16 +835,16 @@ end --- @type ZONE_POLYGON_BASE -- @field #ZONE_POLYGON_BASE.ListVec2 Polygon The polygon defined by an array of @{DCSTypes#Vec2}. --- @extends Core.Zone#ZONE_BASE +-- @extends #ZONE_BASE ---- # 6) ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE} +--- # ZONE_POLYGON_BASE class, extends @{Zone#ZONE_BASE} -- -- The ZONE_POLYGON_BASE class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. -- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties. -- This class is an abstract BASE class for derived classes, and is not meant to be instantiated. -- --- ## 6.1) Zone point randomization +-- ## Zone point randomization -- -- Various functions exist to find random points within the zone. -- @@ -835,8 +852,6 @@ end -- * @{#ZONE_POLYGON_BASE.GetRandomPointVec2}(): Return a @{Point#POINT_VEC2} object representing a random 2D point within the zone. -- * @{#ZONE_POLYGON_BASE.GetRandomPointVec3}(): Return a @{Point#POINT_VEC3} object representing a random 3D point at landheight within the zone. -- --- === --- -- @field #ZONE_POLYGON_BASE ZONE_POLYGON_BASE -- ZONE_POLYGON_BASE = { @@ -870,6 +885,17 @@ function ZONE_POLYGON_BASE:New( ZoneName, PointsArray ) return self end +--- Returns the center location of the polygon. +-- @param #ZONE_GROUP self +-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Group} location. +function ZONE_POLYGON_BASE:GetVec2() + self:F( self.ZoneName ) + + local Bounds = self:GetBoundingSquare() + + return { x = ( Bounds.x2 + Bounds.x1 ) / 2, y = ( Bounds.y2 + Bounds.y1 ) / 2 } +end + --- Flush polygon coordinates as a table in DCS.log. -- @param #ZONE_POLYGON_BASE self -- @return #ZONE_POLYGON_BASE self @@ -1073,16 +1099,14 @@ end --- @type ZONE_POLYGON --- @extends Core.Zone#ZONE_POLYGON_BASE +-- @extends #ZONE_POLYGON_BASE ---- # 7) ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE} +--- # ZONE_POLYGON class, extends @{Zone#ZONE_POLYGON_BASE} -- -- The ZONE_POLYGON class defined by a sequence of @{Group#GROUP} waypoints within the Mission Editor, forming a polygon. -- This class implements the inherited functions from @{Zone#ZONE_RADIUS} taking into account the own zone format and properties. -- --- === --- -- @field #ZONE_POLYGON ZONE_POLYGON -- ZONE_POLYGON = { diff --git a/Moose Development/Moose/Tasking/Task_CARGO.lua b/Moose Development/Moose/Tasking/Task_CARGO.lua index d44a8a920..e234438c2 100644 --- a/Moose Development/Moose/Tasking/Task_CARGO.lua +++ b/Moose Development/Moose/Tasking/Task_CARGO.lua @@ -75,6 +75,8 @@ do -- TASK_CARGO self.SetCargo = SetCargo self.TaskType = TaskType + + self.DeployZones = {} -- setmetatable( {}, { __mode = "v" } ) -- weak table on value Mission:AddTask( self ) @@ -83,14 +85,14 @@ do -- TASK_CARGO Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "SelectAction", Rejected = "Reject" } ) - Fsm:AddTransition( { "Assigned", "Landed", "Boarded", "Deployed" } , "SelectAction", "WaitingForCommand" ) + Fsm:AddTransition( "*", "SelectAction", "WaitingForCommand" ) Fsm:AddTransition( "WaitingForCommand", "RouteToPickup", "RoutingToPickup" ) Fsm:AddProcess ( "RoutingToPickup", "RouteToPickupPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtPickup" } ) Fsm:AddTransition( "Arrived", "ArriveAtPickup", "ArrivedAtPickup" ) Fsm:AddTransition( "WaitingForCommand", "RouteToDeploy", "RoutingToDeploy" ) - Fsm:AddProcess ( "RoutingToDeploy", "RouteToDeployPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtDeploy" } ) + Fsm:AddProcess ( "RoutingToDeploy", "RouteToDeployZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtDeploy" } ) Fsm:AddTransition( "ArrivedAtDeploy", "ArriveAtDeploy", "ArrivedAtDeploy" ) Fsm:AddTransition( { "ArrivedAtPickup", "ArrivedAtDeploy" }, "Land", "Landing" ) @@ -146,14 +148,27 @@ do -- TASK_CARGO end if Cargo:IsLoaded() then - MENU_GROUP_COMMAND:New( - TaskUnit:GetGroup(), - "Deploy cargo " .. Cargo.Name, - TaskUnit.Menu, - self.MenuBoardCargo, - self, - Cargo - ) + for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do + if Cargo:IsInZone( DeployZone ) then + MENU_GROUP_COMMAND:New( + TaskUnit:GetGroup(), + "Deploy cargo " .. Cargo.Name, + TaskUnit.Menu, + self.MenuUnBoardCargo, + self, + Cargo + ) + else + MENU_GROUP_COMMAND:New( + TaskUnit:GetGroup(), + "Route to deploy zone " .. DeployZoneName, + TaskUnit.Menu, + self.MenuRouteToDeploy, + self, + DeployZone + ) + end + end end end @@ -174,10 +189,18 @@ do -- TASK_CARGO self:__PrepareBoarding( 1.0, Cargo ) end + function Fsm:MenuUnBoardCargo( Cargo ) + self:__PrepareUnBoarding( 1.0, Cargo ) + end + function Fsm:MenuRouteToPickup( Cargo ) self:__RouteToPickup( 1.0, Cargo ) end + function Fsm:MenuRouteToDeploy( DeployZone ) + self:__RouteToDeploy( 1.0, DeployZone ) + end + --- Route to Cargo -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit @@ -196,16 +219,54 @@ do -- TASK_CARGO -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit -- @param Tasking.Task_CARGO#TASK_CARGO Task - function Fsm:OnAfterArriveAtPickup( TaskUnit, Task ) + function Fsm:onafterArriveAtPickup( TaskUnit, Task ) self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then - self:__Land( -0.1 ) + if TaskUnit:IsAir() then + self:__Land( -0.1 ) + else + self:__SelectAction( -0.1 ) + end else - self:__ArriveAtCargo( -10 ) + self:__ArriveAtPickup( -10 ) end end + + --- Route to DeployZone + -- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + function Fsm:onafterRouteToDeploy( TaskUnit, Task, From, Event, To, DeployZone ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + + + self.DeployZone = DeployZone + Task:SetDeployZone( self.DeployZone, TaskUnit ) + self:__RouteToDeployZone( 0.1 ) + end + + + --- + -- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + -- @param Tasking.Task_CARGO#TASK_CARGO Task + function Fsm:onafterArriveAtDeploy( TaskUnit, Task ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + + if TaskUnit:IsInZone( self.DeployZone ) then + if TaskUnit:IsAir() then + self:__Land( -0.1 ) + else + self:__SelectAction( -0.1 ) + end + else + self:__ArriveAtDeploy( -10 ) + end + end + + + --- -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit @@ -291,7 +352,8 @@ do -- TASK_CARGO self:__ArriveAtCargo( -0.1 ) end end - + + --- -- @param #FSM_PROCESS self -- @param Wrapper.Unit#UNIT TaskUnit @@ -300,8 +362,53 @@ do -- TASK_CARGO self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) Task:GetMission():GetCommandCenter():MessageToGroup( "Boarded ...", TaskUnit:GetGroup(), "Boarding" ) + self:__SelectAction( 1 ) end + + --- + -- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + -- @param Tasking.Task_CARGO#TASK_CARGO Task + function Fsm:OnAfterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo, DeployZone ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + + self.DeployZone = DeployZone + self.Cargo:__UnBoard( -0.1, DeployZone ) + end + + --- + -- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + -- @param Tasking.Task_CARGO#TASK_CARGO Task + function Fsm:OnAfterUnBoard( TaskUnit, Task ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + + function self.Cargo:OnEnterUnLoaded( From, Event, To, TaskUnit, TaskProcess ) + + self:E({From, Event, To, TaskUnit, TaskProcess }) + + TaskProcess:__UnBoarded( 0.1 ) + + end + + Task:GetMission():GetCommandCenter():MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup(), "UnBoarding" ) + self.Cargo:__UnBoard( -0.1, self.DeployZone ) + end + + + --- + -- @param #FSM_PROCESS self + -- @param Wrapper.Unit#UNIT TaskUnit + -- @param Tasking.Task_CARGO#TASK_CARGO Task + function Fsm:OnAfterUnBoarded( TaskUnit, Task ) + self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } ) + + Task:GetMission():GetCommandCenter():MessageToGroup( "UnBoarded ...", TaskUnit:GetGroup(), "UnBoarding" ) + self:__SelectAction( 1 ) + end + + return self end @@ -311,6 +418,7 @@ do -- TASK_CARGO return self:GetStateString() .. " - " .. self:GetTaskName() .. " ( " .. self.TargetSetUnit:GetUnitTypesText() .. " )" end + --- @param #TASK_CARGO self -- @param AI.AI_Cargo#AI_CARGO Cargo The cargo. -- @param Wrapper.Unit#UNIT TaskUnit @@ -326,41 +434,57 @@ do -- TASK_CARGO return self end + --- @param #TASK_CARGO self - -- @param Core.Point#POINT_VEC2 TargetPointVec2 The PointVec2 object where the Target is located on the map. + -- @param Core.Zone#ZONE DeployZone -- @param Wrapper.Unit#UNIT TaskUnit - function TASK_CARGO:SetTargetPointVec2( TargetPointVec2, TaskUnit ) + -- @return #TASK_CARGO + function TASK_CARGO:SetDeployZone( DeployZone, TaskUnit ) local ProcessUnit = self:GetUnitProcess( TaskUnit ) - local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT - ActRouteTarget:SetPointVec2( TargetPointVec2 ) + local ActRouteDeployZone = ProcessUnit:GetProcess( "RoutingToDeploy", "RouteToDeployZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE + ActRouteDeployZone:SetZone( DeployZone ) + return self end - - --- @param #TASK_CARGO self - -- @param Wrapper.Unit#UNIT TaskUnit - -- @return Core.Point#POINT_VEC2 The PointVec2 object where the Target is located on the map. - function TASK_CARGO:GetTargetPointVec2( TaskUnit ) - - local ProcessUnit = self:GetUnitProcess( TaskUnit ) - - local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetPoint" ) -- Actions.Act_Route#ACT_ROUTE_POINT - return ActRouteTarget:GetPointVec2() - end - - - --- @param #TASK_CARGO 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_CARGO:SetTargetZone( TargetZone, TaskUnit ) - local ProcessUnit = self:GetUnitProcess( TaskUnit ) + --- @param #TASK_CARGO self + -- @param Core.Zone#ZONE DeployZone + -- @param Wrapper.Unit#UNIT TaskUnit + -- @return #TASK_CARGO + function TASK_CARGO:AddDeployZone( DeployZone, TaskUnit ) + + self.DeployZones[DeployZone:GetName()] = DeployZone - local ActRouteTarget = ProcessUnit:GetProcess( "Engaging", "RouteToTargetZone" ) -- Actions.Act_Route#ACT_ROUTE_ZONE - ActRouteTarget:SetZone( TargetZone ) + return self end - + + --- @param #TASK_CARGO self + -- @param Core.Zone#ZONE DeployZone + -- @param Wrapper.Unit#UNIT TaskUnit + -- @return #TASK_CARGO + function TASK_CARGO:RemoveDeployZone( DeployZone, TaskUnit ) + + self.DeployZones[DeployZone:GetName()] = nil + + return self + end + + --- @param #TASK_CARGO self + -- @param @list DeployZones + -- @param Wrapper.Unit#UNIT TaskUnit + -- @return #TASK_CARGO + function TASK_CARGO:SetDeployZones( DeployZones, TaskUnit ) + + for DeployZoneID, DeployZone in pairs( DeployZones ) do + self.DeployZones[DeployZone:GetName()] = DeployZone + end + + return self + end + + --- @param #TASK_CARGO self -- @param Wrapper.Unit#UNIT TaskUnit diff --git a/Moose Test Missions/TAD - Task Dispatching/TAD-100 - A2G Task Dispatching DETECTION_AREAS/TAD-100 - A2G Task Dispatching DETECTION_AREAS.lua b/Moose Test Missions/TAD - Task Dispatching/TAD-100 - A2G Task Dispatching DETECTION_AREAS/TAD-100 - A2G Task Dispatching DETECTION_AREAS.lua deleted file mode 100644 index afcfee050..000000000 --- a/Moose Test Missions/TAD - Task Dispatching/TAD-100 - A2G Task Dispatching DETECTION_AREAS/TAD-100 - A2G Task Dispatching DETECTION_AREAS.lua +++ /dev/null @@ -1,35 +0,0 @@ ---- --- Name: TAD-100 - A2G Task Dispatching DETECTION_AREAS --- Author: FlightControl --- Date Created: 06 Mar 2017 --- --- # Situation: --- --- This mission demonstrates the dynamic task dispatching for Air to Ground operations. --- FACA's and FAC's are patrolling around the battle zone, while detecting targets. --- The detection method used is the DETECTION_AREAS method, which groups detected targets into zones. --- --- # Test cases: --- --- 1. Observe the FAC(A)'s detecting targets and grouping them. --- For test, each zone will have a circle of tyres, that are visible on the map too. --- 2. Check that the HQ provides menus to engage on a task set by the FACs. --- -HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) - -CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) - -Scoring = SCORING:New( "Detect Demo" ) - -Mission = MISSION - :New( CommandCenter, "Overlord", "High", "Attack Detect Mission Briefing", coalition.side.RED ) - :AddScoring( Scoring ) - -FACSet = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterCoalitions("red"):FilterStart() - -FACAreas = DETECTION_AREAS:New( FACSet, 500 ) -FACAreas:BoundDetectedZones() - -AttackGroups = SET_GROUP:New():FilterCoalitions( "red" ):FilterPrefixes( "Attack" ):FilterStart() -TaskDispatcher = TASK_A2G_DISPATCHER:New( Mission, HQ, AttackGroups, FACAreas ) - diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.lua b/Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.lua deleted file mode 100644 index 363e7fcdc..000000000 --- a/Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.lua +++ /dev/null @@ -1,35 +0,0 @@ ---- --- Name: TSK-100 - Cargo Pickup --- Author: FlightControl --- Date Created: 25 Mar 2017 --- --- # Situation: --- --- This mission demonstrates the pickup of cargo. --- --- # Test cases: --- --- - -do - HQ = GROUP:FindByName( "HQ", "Bravo HQ" ) - - CommandCenter = COMMANDCENTER:New( HQ, "Lima" ) - - Scoring = SCORING:New( "Pickup Demo" ) - - Mission = MISSION - :New( CommandCenter, "Transport", "High", "Pickup the team", coalition.side.BLUE ) - :AddScoring( Scoring ) - - TransportHelicopters = SET_GROUP:New():FilterPrefixes( "Transport" ):FilterStart() - - CargoEngineer = UNIT:FindByName( "Engineer" ) - InfantryCargo = AI_CARGO_UNIT:New( CargoEngineer, "Engineer", "Engineer Sven", "81", 500, 25 ) - - SetCargo = SET_CARGO:New():FilterTypes( "Engineer" ):FilterStart() - - Task_Cargo_Pickup = TASK_CARGO_TRANSPORT:New( Mission, TransportHelicopters, "Transport.001", SetCargo ) - -end - diff --git a/Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.miz b/Moose Test Missions/TSK - Task Modelling/TSK-100 - Cargo Pickup/TSK-100 - Cargo Pickup.miz deleted file mode 100644 index a06b1f4d141b36bc1a151176192ca167d3a8229d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28460 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 Xfd;K6|1jMB0M-U_ZP&H_$GiUmfm786