Merge remote-tracking branch 'refs/remotes/origin/master' into 344-AI-Bomb-Zone

This commit is contained in:
FlightControl
2017-05-09 09:29:43 +02:00
49 changed files with 4259 additions and 1037 deletions

View File

@@ -173,8 +173,6 @@ do -- ACT_ASSIGN_ACCEPT
local ProcessGroup = ProcessUnit:GetGroup()
self:Message( "You are assigned to the task " .. self.Task:GetName() )
self.Task:Assign( ProcessUnit, ProcessUnit:GetPlayerName() )
end

View File

@@ -239,12 +239,15 @@ function CARGO:New( Type, Name, Weight ) --R2.1
self:SetStartState( "UnLoaded" )
self:AddTransition( { "UnLoaded", "Boarding" }, "Board", "Boarding" )
self:AddTransition( "Boarding" , "Boarding", "Boarding" )
self:AddTransition( "Boarding", "CancelBoarding", "UnLoaded" )
self:AddTransition( "Boarding", "Load", "Loaded" )
self:AddTransition( "UnLoaded", "Load", "Loaded" )
self:AddTransition( "Loaded", "UnBoard", "UnBoarding" )
self:AddTransition( "UnBoarding", "UnBoarding", "UnBoarding" )
self:AddTransition( "UnBoarding", "UnLoad", "UnLoaded" )
self:AddTransition( "Loaded", "UnLoad", "UnLoaded" )
self:AddTransition( "*", "Destroyed", "Destroyed" )
self:AddTransition( "*", "Respawn", "UnLoaded" )
self.Type = Type
@@ -262,6 +265,7 @@ function CARGO:New( Type, Name, Weight ) --R2.1
CARGOS[self.Name] = self
self:SetEventPriority( 5 )
return self
end
@@ -273,6 +277,17 @@ function CARGO:GetName() --R2.1
return self.Name
end
--- Get the object name of the Cargo.
-- @param #CARGO self
-- @return #string The object name of the Cargo.
function CARGO:GetObjectName() --R2.1
if self:IsLoaded() then
return self.CargoCarrier:GetName()
else
return self.CargoObject:GetName()
end
end
--- Get the type of the Cargo.
-- @param #CARGO self
-- @return #string The type of the Cargo.
@@ -280,6 +295,14 @@ function CARGO:GetType()
return self.Type
end
--- Get the current coordinates of the Cargo.
-- @param #CARGO self
-- @return Core.Point#COORDINATE The coordinates of the Cargo.
function CARGO:GetCoordinate()
return self.CargoObject:GetCoordinate()
end
--- Check if cargo is loaded.
-- @param #CARGO self
-- @return #boolean true if loaded
@@ -294,6 +317,20 @@ function CARGO:IsUnLoaded()
return self:Is( "UnLoaded" )
end
--- Check if cargo is alive.
-- @param #CARGO self
-- @return #boolean true if unloaded
function CARGO:IsAlive()
if self:IsLoaded() then
return self.CargoCarrier:IsAlive()
else
return self.CargoObject:IsAlive()
end
end
--- Template method to spawn a new representation of the CARGO in the simulator.
-- @param #CARGO self
@@ -329,7 +366,7 @@ end
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).
-- @return #boolean
function CARGO:IsNear( PointVec2, NearRadius )
self:F( { PointVec2 } )
self:F( { PointVec2, NearRadius } )
local Distance = PointVec2:DistanceFromPointVec2( self.CargoObject:GetPointVec2() )
self:T( Distance )
@@ -520,6 +557,16 @@ function CARGO_UNIT:New( CargoUnit, Type, Name, Weight, NearRadius )
self:T( self.ClassName )
self:HandleEvent( EVENTS.Dead,
--- @param #CARGO Cargo
-- @param Core.Event#EVENTDATA EventData
function( Cargo, EventData )
if Cargo:GetObjectName() == EventData.IniUnit:GetName() then
self:E( { "Cargo destroyed", Cargo } )
Cargo:Destroyed()
end
end
)
return self
end
@@ -542,7 +589,7 @@ end
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:F()
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
@@ -575,7 +622,7 @@ function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius
-- Respawn the group...
if self.CargoObject then
self.CargoObject:ReSpawn( CargoDeployPointVec2:GetVec3(), CargoDeployHeading )
self:E( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
self:F( { "CargoUnits:", self.CargoObject:GetGroup():GetName() } )
self.CargoCarrier = nil
local Points = {}
@@ -586,7 +633,8 @@ function CARGO_UNIT:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius
local TaskRoute = self.CargoObject:TaskRoute( Points )
self.CargoObject:SetTask( TaskRoute, 1 )
self:__UnBoarding( -1, ToPointVec2, NearRadius )
self:__UnBoarding( 1, ToPointVec2, NearRadius )
end
end
@@ -599,7 +647,7 @@ end
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:F( { ToPointVec2, From, Event, To } )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
@@ -611,6 +659,7 @@ function CARGO_UNIT:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius
if self:IsNear( ToPointVec2, NearRadius ) then
return true
else
self:__UnBoarding( 1, ToPointVec2, NearRadius )
end
return false
@@ -625,7 +674,7 @@ end
-- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2
function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius )
self:F( { ToPointVec2, From, Event, To } )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
@@ -639,7 +688,7 @@ function CARGO_UNIT:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius
end
self:__UnLoad( 1, ToPointVec2 )
self:__UnLoad( 1, ToPointVec2, NearRadius )
end
@@ -687,9 +736,9 @@ end
-- @param #string From
-- @param #string To
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
self:F()
self:F( { From, Event, To, CargoCarrier, NearRadius } )
NearRadius = NearRadius or 25
local NearRadius = NearRadius or 25
self.CargoInAir = self.CargoObject:InAir()
@@ -722,32 +771,13 @@ function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ...
local TaskRoute = self.CargoObject:TaskRoute( Points )
self.CargoObject:SetTask( TaskRoute, 2 )
self:__Boarding( -1, CargoCarrier, NearRadius )
self.RunCount = 0
end
end
end
--- Leave Boarding State.
-- @param #CARGO_UNIT self
-- @param #string Event
-- @param #string From
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_UNIT:onleaveBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
NearRadius = NearRadius or 25
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
self:__Load( 1, CargoCarrier, ... )
return true
end
return true
end
--- Boarding Event.
-- @param #CARGO_UNIT self
-- @param #string Event
@@ -759,8 +789,45 @@ function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius,
self:F( { From, Event, To, CargoCarrier.UnitName, NearRadius } )
self:__Boarding( -1, CargoCarrier, NearRadius, ... )
self:__Board( -15, CargoCarrier, NearRadius, ... )
if CargoCarrier and CargoCarrier:IsAlive() then
if CargoCarrier:InAir() == false then
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
self:__Load( 1, CargoCarrier, ... )
else
self:__Boarding( -1, CargoCarrier, NearRadius, ... )
self.RunCount = self.RunCount + 1
if self.RunCount >= 20 then
self.RunCount = 0
local Speed = 90
local Angle = 180
local Distance = 5
NearRadius = NearRadius or 25
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
local CargoDeployPointVec2 = CargoCarrierPointVec2:Translate( Distance, CargoDeployHeading )
local Points = {}
local PointStartVec2 = self.CargoObject:GetPointVec2()
Points[#Points+1] = PointStartVec2:RoutePointGround( Speed )
Points[#Points+1] = CargoDeployPointVec2:RoutePointGround( Speed )
local TaskRoute = self.CargoObject:TaskRoute( Points )
self.CargoObject:SetTask( TaskRoute, 0.2 )
end
end
else
self.CargoObject:MessageToGroup( "Cancelling Boarding... Get back on the ground!", 5, CargoCarrier:GetGroup(), self:GetName() )
self:CancelBoarding( CargoCarrier, NearRadius, ... )
self.CargoObject:SetCommand( self.CargoObject:CommandStopRoute( true ) )
end
else
self:E("Something is wrong")
end
end
@@ -778,7 +845,7 @@ function CARGO_UNIT:onenterBoarding( From, Event, To, CargoCarrier, NearRadius,
local Angle = 180
local Distance = 5
NearRadius = NearRadius or 25
local NearRadius = NearRadius or 25
if From == "UnLoaded" or From == "Boarding" then
@@ -793,7 +860,7 @@ end
-- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_UNIT:onenterLoaded( From, Event, To, CargoCarrier )
self:F()
self:F( { From, Event, To, CargoCarrier } )
self.CargoCarrier = CargoCarrier
@@ -808,6 +875,263 @@ end
end
do -- CARGO_GROUP
--- @type CARGO_GROUP
-- @extends #CARGO_REPORTABLE
--- # CARGO\_GROUP class
--
-- The CARGO\_GROUP class defines a cargo that is represented by a @{Group} object within the simulator, and can be transported by a carrier.
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_GROUP to and from carrier.
--
-- @field #CARGO_GROUP CARGO_GROUP
--
CARGO_GROUP = {
ClassName = "CARGO_GROUP",
}
--- CARGO_GROUP constructor.
-- @param #CARGO_GROUP self
-- @param Wrapper.Group#GROUP CargoGroup
-- @param #string Type
-- @param #string Name
-- @param #number ReportRadius (optional)
-- @param #number NearRadius (optional)
-- @return #CARGO_GROUP
function CARGO_GROUP:New( CargoGroup, Type, Name, ReportRadius )
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( CargoGroup, Type, Name, 0, ReportRadius ) ) -- #CARGO_GROUP
self:F( { Type, Name, ReportRadius } )
self.CargoSet = SET_CARGO:New()
self.CargoObject = CargoGroup
local WeightGroup = 0
for UnitID, UnitData in pairs( CargoGroup:GetUnits() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
local WeightUnit = Unit:GetDesc().massEmpty
WeightGroup = WeightGroup + WeightUnit
local CargoUnit = CARGO_UNIT:New( Unit, Type, Unit:GetName(), WeightUnit )
self.CargoSet:Add( CargoUnit:GetName(), CargoUnit )
end
self:SetWeight( WeightGroup )
self:T( { "Weight Cargo", WeightGroup } )
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
return self
end
--- Enter Boarding State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
local NearRadius = NearRadius or 25
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo, ... )
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
end, ...
)
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
end
end
--- Enter Loaded State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... )
self:F( { From, Event, To, CargoCarrier, ...} )
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
Cargo:Load( CargoCarrier )
end
end
self.CargoObject:Destroy()
self.CargoCarrier = CargoCarrier
end
--- Leave Boarding State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
local NearRadius = NearRadius or 25
local Boarded = true
local Cancelled = false
local Dead = true
self.CargoSet:Flush()
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
self:T( { Cargo:GetName(), Cargo.current } )
if not Cargo:is( "Loaded" ) then
Boarded = false
end
if Cargo:is( "UnLoaded" ) then
Cancelled = true
end
if not Cargo:is( "Destroyed" ) then
Dead = false
end
end
if not Dead then
if not Cancelled then
if not Boarded then
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
else
self:__Load( 1, CargoCarrier, ... )
end
else
self:__CancelBoarding( 1, CargoCarrier, NearRadius, ... )
end
else
self:__Destroyed( 1, CargoCarrier, NearRadius, ... )
end
end
--- Enter UnBoarding State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
self:F( {From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
local Timer = 1
if From == "Loaded" then
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo, NearRadius )
Cargo:__UnBoard( Timer, ToPointVec2, NearRadius )
Timer = Timer + 10
end, { NearRadius }
)
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end
end
--- Leave UnBoarding State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
--local NearRadius = NearRadius or 25
local Angle = 180
local Speed = 10
local Distance = 5
if From == "UnBoarding" then
local UnBoarded = true
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
self:T( Cargo.current )
if not Cargo:is( "UnLoaded" ) then
UnBoarded = false
end
end
if UnBoarded then
return true
else
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end
return false
end
end
--- UnBoard Event.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
--local NearRadius = NearRadius or 25
self:__UnLoad( 1, ToPointVec2, ... )
end
--- Enter UnLoaded State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... )
self:F( { From, Event, To, ToPointVec2 } )
if From == "Loaded" then
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo )
Cargo:UnLoad( ToPointVec2 )
end
)
end
end
end -- CARGO_GROUP
do -- CARGO_PACKAGE
--- @type CARGO_PACKAGE
@@ -1022,238 +1346,3 @@ end
end
do -- CARGO_GROUP
--- @type CARGO_GROUP
-- @extends #CARGO_REPORTABLE
--- # CARGO\_GROUP class
--
-- The CARGO\_GROUP class defines a cargo that is represented by a @{Group} object within the simulator, and can be transported by a carrier.
-- Use the event functions as described above to Load, UnLoad, Board, UnBoard the CARGO\_GROUP to and from carrier.
--
-- @field #CARGO_GROUP CARGO_GROUP
--
CARGO_GROUP = {
ClassName = "CARGO_GROUP",
}
--- CARGO_GROUP constructor.
-- @param #CARGO_GROUP self
-- @param Wrapper.Group#GROUP CargoGroup
-- @param #string Type
-- @param #string Name
-- @param #number ReportRadius (optional)
-- @param #number NearRadius (optional)
-- @return #CARGO_GROUP
function CARGO_GROUP:New( CargoGroup, Type, Name, ReportRadius )
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( CargoGroup, Type, Name, 0, ReportRadius ) ) -- #CARGO_GROUP
self:F( { Type, Name, ReportRadius } )
self.CargoSet = SET_CARGO:New()
self.CargoObject = CargoGroup
local WeightGroup = 0
for UnitID, UnitData in pairs( CargoGroup:GetUnits() ) do
local Unit = UnitData -- Wrapper.Unit#UNIT
local WeightUnit = Unit:GetDesc().massEmpty
WeightGroup = WeightGroup + WeightUnit
local CargoUnit = CARGO_UNIT:New( Unit, Type, Unit:GetName(), WeightUnit )
self.CargoSet:Add( CargoUnit:GetName(), CargoUnit )
end
self:SetWeight( WeightGroup )
self:T( { "Weight Cargo", WeightGroup } )
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
_EVENTDISPATCHER:CreateEventNewCargo( self )
return self
end
--- Enter Boarding State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
NearRadius = NearRadius or 25
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo )
Cargo:__Board( 1, CargoCarrier, NearRadius )
end
)
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
end
end
--- Enter Loaded State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
Cargo:Load( CargoCarrier )
end
end
self.CargoObject:Destroy()
self.CargoCarrier = CargoCarrier
end
--- Leave Boarding State.
-- @param #CARGO_GROUP self
-- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onleaveBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { CargoCarrier.UnitName, From, Event, To } )
NearRadius = NearRadius or 25
local Boarded = true
self.CargoSet:Flush()
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
self:T( { Cargo:GetName(), Cargo.current } )
if not Cargo:is( "Loaded" ) then
Boarded = false
end
end
if not Boarded then
self:__Boarding( 1, CargoCarrier, NearRadius, ... )
else
self:__Load( 1, CargoCarrier, ... )
end
return Boarded
end
--- Enter UnBoarding State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
self:F({From, Event, To, ToPointVec2, NearRadius})
NearRadius = NearRadius or 25
local Timer = 1
if From == "Loaded" then
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo )
Cargo:__UnBoard( Timer, ToPointVec2, NearRadius )
Timer = Timer + 10
end
)
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end
end
--- Leave UnBoarding State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
local Angle = 180
local Speed = 10
local Distance = 5
if From == "UnBoarding" then
local UnBoarded = true
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
self:T( Cargo.current )
if not Cargo:is( "UnLoaded" ) then
UnBoarded = false
end
end
if UnBoarded then
return true
else
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end
return false
end
end
--- UnBoard Event.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
self:F( { From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25
self:__UnLoad( 1, ToPointVec2, ... )
end
--- Enter UnLoaded State.
-- @param #CARGO_GROUP self
-- @param Core.Point#POINT_VEC2
-- @param #string Event
-- @param #string From
-- @param #string To
function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... )
self:F( { From, Event, To, ToPointVec2 } )
if From == "Loaded" then
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach(
function( Cargo )
Cargo:UnLoad( ToPointVec2 )
end
)
end
end
end -- CARGO_GROUP

View File

@@ -51,6 +51,7 @@ DATABASE = {
ClientsByID = {},
},
UNITS = {},
UNITS_Index = {},
STATICS = {},
GROUPS = {},
PLAYERS = {},
@@ -99,7 +100,7 @@ function DATABASE:New()
self:HandleEvent( EVENTS.DeleteCargo )
-- Follow alive players and clients
self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
-- self:HandleEvent( EVENTS.PlayerEnterUnit, self._EventOnPlayerEnterUnit )
self:HandleEvent( EVENTS.PlayerLeaveUnit, self._EventOnPlayerLeaveUnit )
self:_RegisterTemplates()
@@ -108,6 +109,33 @@ function DATABASE:New()
self:_RegisterStatics()
self:_RegisterPlayers()
self:_RegisterAirbases()
self.UNITS_Position = 0
--- @param #DATABASE self
local function CheckPlayers( self )
local UNITS_Count = #self.UNITS_Index
if UNITS_Count > 0 then
self.UNITS_Position = ( ( self.UNITS_Position <= UNITS_Count ) and self.UNITS_Position + 1 ) or 1
local PlayerUnit = self.UNITS[self.UNITS_Index[self.UNITS_Position]]
if PlayerUnit then
local UnitName = PlayerUnit:GetName()
local PlayerName = PlayerUnit:GetPlayerName()
--self:E( { UNITS_Count, self.UNITS_Position, UnitName, PlayerName } )
if PlayerName and PlayerName ~= "" then
if self.PLAYERS[PlayerName] == nil or self.PLAYERS[PlayerName] ~= UnitName then
self:E( { "Add player for unit:", UnitName, PlayerName } )
self:AddPlayer( UnitName, PlayerName )
--_EVENTDISPATCHER:CreateEventPlayerEnterUnit( PlayerUnit )
end
end
end
end
end
self:E( "Scheduling" )
--local PlayerCheckSchedule = SCHEDULER:New( nil, CheckPlayers, { self }, 2, 0.1 )
return self
end
@@ -130,6 +158,8 @@ function DATABASE:AddUnit( DCSUnitName )
if not self.UNITS[DCSUnitName] then
local UnitRegister = UNIT:Register( DCSUnitName )
self.UNITS[DCSUnitName] = UNIT:Register( DCSUnitName )
table.insert( self.UNITS_Index, DCSUnitName )
end
return self.UNITS[DCSUnitName]
@@ -140,7 +170,7 @@ end
-- @param #DATABASE self
function DATABASE:DeleteUnit( DCSUnitName )
--self.UNITS[DCSUnitName] = nil
self.UNITS[DCSUnitName] = nil
end
--- Adds a Static based on the Static Name in the DATABASE.
@@ -281,7 +311,7 @@ function DATABASE:AddPlayer( UnitName, PlayerName )
if PlayerName then
self:E( { "Add player for unit:", UnitName, PlayerName } )
self.PLAYERS[PlayerName] = self:FindUnit( UnitName )
self.PLAYERS[PlayerName] = UnitName
self.PLAYERSJOINED[PlayerName] = PlayerName
end
end

View File

@@ -730,6 +730,21 @@ do -- Event Creation
world.onEvent( Event )
end
--- Creation of a S_EVENT_PLAYER_ENTER_UNIT Event.
-- @param #EVENT self
-- @param Wrapper.Unit#UNIT PlayerUnit.
function EVENT:CreateEventPlayerEnterUnit( PlayerUnit )
self:F( { PlayerUnit } )
local Event = {
id = EVENTS.PlayerEnterUnit,
time = timer.getTime(),
initiator = PlayerUnit:GetDCSObject()
}
world.onEvent( Event )
end
end
--- @param #EVENT self
@@ -748,7 +763,7 @@ function EVENT:onEvent( Event )
local EventMeta = _EVENTMETA[Event.id]
if self and self.Events and self.Events[Event.id] then
if Event.initiator then
@@ -863,7 +878,7 @@ function EVENT:onEvent( Event )
local PriorityBegin = PriorityOrder == -1 and 5 or 1
local PriorityEnd = PriorityOrder == -1 and 1 or 5
if Event.IniObjectCategory ~= 3 then
if Event.IniObjectCategory ~= Object.Category.STATIC then
self:E( { EventMeta.Text, Event, Event.IniDCSUnitName, Event.TgtDCSUnitName, PriorityOrder } )
end
@@ -874,8 +889,10 @@ function EVENT:onEvent( Event )
-- Okay, we got the event from DCS. Now loop the SORTED self.EventSorted[] 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][EventPriority] ) do
self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
if Event.IniObjectCategory ~= Object.Category.STATIC then
--self:E( { "Evaluating: ", EventClass:GetClassNameAndID() } )
end
Event.IniGroup = GROUP:FindByName( Event.IniDCSGroupName )
Event.TgtGroup = GROUP:FindByName( Event.TgtDCSGroupName )

View File

@@ -1003,15 +1003,20 @@ do -- FSM_PROCESS
-- @param #FSM_PROCESS self
-- @return #FSM_PROCESS
function FSM_PROCESS:Remove()
self:T( { self:GetClassNameAndID() } )
self:F( { self:GetClassNameAndID() } )
self:F( "Clearing Schedules" )
self.CallScheduler:Clear()
-- Copy Processes
for ProcessID, Process in pairs( self:GetProcesses() ) do
self:E( { Process} )
Process.fsm:Remove()
Process.fsm = nil
if Process.fsm then
Process.fsm:Remove()
Process.fsm = nil
end
end
return self
end
@@ -1116,7 +1121,7 @@ end
self:T( { ProcessUnit, From, Event, To, Dummy, self:IsTrace() } )
if self:IsTrace() then
MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
--MESSAGE:New( "@ Process " .. self:GetClassNameAndID() .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
end
self:T( { Scores = self._Scores, To = To } )

View File

@@ -82,7 +82,7 @@ do -- MENU_BASE
-- @param #string MenuText The text of the child menu.
-- @return #MENU_BASE
function MENU_BASE:GetMenu( MenuText )
self:F( { self.Menus, MenuText } )
self:F2( { Menu = self.Menus[MenuText] } )
return self.Menus[MenuText]
end
@@ -91,7 +91,7 @@ do -- MENU_BASE
-- @param #boolean RemoveParent If true, the parent menu is automatically removed when this menu is the last child menu of that parent @{Menu}.
-- @return #MENU_BASE
function MENU_BASE:SetRemoveParent( RemoveParent )
self:F( { RemoveParent } )
self:F2( { RemoveParent } )
self.MenuRemoveParent = RemoveParent
return self
end
@@ -780,7 +780,9 @@ do
self = MenuGroup._Menus[Path]
else
self = BASE:Inherit( self, MENU_BASE:New( MenuText, ParentMenu ) )
MenuGroup._Menus[Path] = self
--if MenuGroup:IsAlive() then
MenuGroup._Menus[Path] = self
--end
self.MenuGroup = MenuGroup
self.Path = Path
@@ -808,9 +810,9 @@ do
-- @param MenuTime
-- @return #MENU_GROUP self
function MENU_GROUP:RemoveSubMenus( MenuTime )
self:F2( { self.MenuPath, MenuTime, self.MenuTime } )
--self:F2( { self.MenuPath, MenuTime, self.MenuTime } )
self:T( { "Removing Group SubMenus:", self.MenuGroup:GetName(), self.MenuPath } )
--self:T( { "Removing Group SubMenus:", self.MenuGroup:GetName(), self.MenuPath } )
for MenuText, Menu in pairs( self.Menus ) do
Menu:Remove( MenuTime )
end
@@ -823,7 +825,7 @@ do
-- @param MenuTime
-- @return #nil
function MENU_GROUP:Remove( MenuTime )
self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
--self:F2( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
self:RemoveSubMenus( MenuTime )
@@ -837,12 +839,12 @@ do
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
if self.MenuRemoveParent == true then
self:T( "Removing Parent Menu " )
self:T2( "Removing Parent Menu " )
self.ParentMenu:Remove()
end
end
end
self:T( { "Removing Group Menu:", self.MenuGroup:GetName(), self.MenuGroup._Menus[self.Path].Path } )
self:T( { "Removing Group Menu:", MenuGroup = self.MenuGroup:GetName(), MenuPath = self.MenuGroup._Menus[self.Path].Path } )
self.MenuGroup._Menus[self.Path] = nil
self = nil
end
@@ -880,10 +882,13 @@ do
local Path = ( ParentMenu and ( table.concat( ParentMenu.MenuPath or {}, "@" ) .. "@" .. MenuText ) ) or MenuText
if MenuGroup._Menus[Path] then
self = MenuGroup._Menus[Path]
self:T( { "Re-using Group Command Menu:", MenuGroup:GetName(), MenuText } )
self:F2( { "Re-using Group Command Menu:", MenuGroup:GetName(), MenuText } )
else
self = BASE:Inherit( self, MENU_COMMAND_BASE:New( MenuText, ParentMenu, CommandMenuFunction, arg ) )
MenuGroup._Menus[Path] = self
--if MenuGroup:IsAlive() then
MenuGroup._Menus[Path] = self
--end
self.Path = Path
self.MenuGroup = MenuGroup
@@ -891,13 +896,13 @@ do
self.MenuText = MenuText
self.ParentMenu = ParentMenu
self:T( { "Adding Group Command Menu:", MenuGroup:GetName(), MenuText, self.MenuParentPath } )
self:F( { "Adding Group Command Menu:", MenuGroup = MenuGroup:GetName(), MenuText = MenuText, MenuPath = self.MenuParentPath } )
self.MenuPath = missionCommands.addCommandForGroup( self.MenuGroupID, MenuText, self.MenuParentPath, self.MenuCallHandler, arg )
if self.ParentMenu and self.ParentMenu.Menus then
self.ParentMenu.Menus[MenuText] = self
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount + 1
self:F( { ParentMenu.Menus, MenuText } )
self:F2( { ParentMenu.Menus, MenuText } )
end
end
@@ -909,20 +914,20 @@ do
-- @param MenuTime
-- @return #nil
function MENU_GROUP_COMMAND:Remove( MenuTime )
self:F( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
--self:F2( { self.MenuGroupID, self.MenuPath, MenuTime, self.MenuTime } )
if not MenuTime or self.MenuTime ~= MenuTime then
if self.MenuGroup._Menus[self.Path] then
self = self.MenuGroup._Menus[self.Path]
missionCommands.removeItemForGroup( self.MenuGroupID, self.MenuPath )
self:T( { "Removing Group Command Menu:", self.MenuGroup:GetName(), self.MenuText, self.Path, self.MenuGroup._Menus[self.Path].Path } )
self:T( { "Removing Group Command Menu:", MenuGroup = self.MenuGroup:GetName(), MenuText = self.MenuText, MenuPath = self.Path } )
self.ParentMenu.Menus[self.MenuText] = nil
self.ParentMenu.MenuCount = self.ParentMenu.MenuCount - 1
if self.ParentMenu.MenuCount == 0 then
if self.MenuRemoveParent == true then
self:T( "Removing Parent Menu " )
self:T2( "Removing Parent Menu " )
self.ParentMenu:Remove()
end
end

View File

@@ -191,7 +191,7 @@ function SCHEDULEDISPATCHER:Start( Scheduler, CallID )
)
end
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Start( Scheduler, CallID ) -- Recursive
end
end
@@ -209,7 +209,7 @@ function SCHEDULEDISPATCHER:Stop( Scheduler, CallID )
Schedule[CallID].ScheduleID = nil
end
else
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Stop( Scheduler, CallID ) -- Recursive
end
end
@@ -218,7 +218,7 @@ end
function SCHEDULEDISPATCHER:Clear( Scheduler )
self:F2( { Scheduler = Scheduler } )
for CallID, Schedule in pairs( self.Schedule[Scheduler] ) do
for CallID, Schedule in pairs( self.Schedule[Scheduler] or {} ) do
self:Stop( Scheduler, CallID ) -- Recursive
end
end

View File

@@ -165,11 +165,10 @@ end
-- @param #SET_BASE self
-- @param #string ObjectName
function SET_BASE:Remove( ObjectName )
self:F( ObjectName )
local t = self.Set[ObjectName]
self:E( { ObjectName, t } )
self:F3( { ObjectName, t } )
if t then
if t._next then
@@ -1337,6 +1336,11 @@ SET_UNIT = {
}
--- Get the first unit from the set.
-- @function [parent=#SET_UNIT] GetFirst
-- @param #SET_UNIT self
-- @return Wrapper.Unit#UNIT The UNIT object.
--- Creates a new SET_UNIT object, building a set of units belonging to a coalitions, categories, countries, types or with defined prefix names.
-- @param #SET_UNIT self
-- @return #SET_UNIT
@@ -1568,7 +1572,7 @@ end
-- @return #string The name of the UNIT
-- @return #table The UNIT
function SET_UNIT:FindInDatabase( Event )
self:E( { Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName], Event } )
self:F2( { Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName], Event } )
return Event.IniDCSUnitName, self.Set[Event.IniDCSUnitName]

View File

@@ -731,7 +731,7 @@ end
-- @param #ZONE_UNIT self
-- @return Dcs.DCSTypes#Vec2 The location of the zone based on the @{Unit#UNIT}location.
function ZONE_UNIT:GetVec2()
self:F( self.ZoneName )
self:F2( self.ZoneName )
local ZoneVec2 = self.ZoneUNIT:GetVec2()
if ZoneVec2 then
@@ -741,7 +741,7 @@ function ZONE_UNIT:GetVec2()
return self.LastVec2
end
self:T( { ZoneVec2 } )
self:T2( { ZoneVec2 } )
return nil
end

View File

@@ -190,7 +190,7 @@ do -- DETECTION_BASE
-- local SetGroup = SET_GROUP:New():FilterPrefixes( "FAC" ):FilterStart() -- Build a SetGroup of Forward Air Controllers.
--
-- -- Build a detect object.
-- local Detection = DETECTION_BASE:New( SetGroup )
-- local Detection = DETECTION_UNITS:New( SetGroup )
--
-- -- This will accept detected units if the range is below 5000 meters.
-- Detection:SetAcceptRange( 5000 )
@@ -211,7 +211,7 @@ do -- DETECTION_BASE
-- local ZoneAccept2 = ZONE:New( "AcceptZone2" )
--
-- -- Build a detect object.
-- local Detection = DETECTION_BASE:New( SetGroup )
-- local Detection = DETECTION_UNITS:New( SetGroup )
--
-- -- This will accept detected units by Detection when the unit is within ZoneAccept1 OR ZoneAccept2.
-- Detection:SetAcceptZones( { ZoneAccept1, ZoneAccept2 } )
@@ -232,7 +232,7 @@ do -- DETECTION_BASE
-- local ZoneReject2 = ZONE:New( "RejectZone2" )
--
-- -- Build a detect object.
-- local Detection = DETECTION_BASE:New( SetGroup )
-- local Detection = DETECTION_UNITS:New( SetGroup )
--
-- -- This will reject detected units by Detection when the unit is within ZoneReject1 OR ZoneReject2.
-- Detection:SetRejectZones( { ZoneReject1, ZoneReject2 } )
@@ -273,10 +273,16 @@ do -- DETECTION_BASE
--- @type DETECTION_BASE.DetectedObject
-- @field #string Name
-- @field #boolean Visible
-- @field #boolean IsVisible
-- @field #boolean KnowType
-- @field #boolean KnowDistance
-- @field #string Type
-- @field #number Distance
-- @field #boolean Identified
-- @field #number LastTime
-- @field #boolean LastPos
-- @field #number LastVelocity
--- @type DETECTION_BASE.DetectedItems
-- @list <#DETECTION_BASE.DetectedItem>
@@ -309,12 +315,12 @@ do -- DETECTION_BASE
self.DetectionInterval = 30
self:InitDetectVisual( false )
self:InitDetectOptical( false )
self:InitDetectRadar( false )
self:InitDetectRWR( false )
self:InitDetectIRST( false )
self:InitDetectDLINK( false )
self:InitDetectVisual( nil )
self:InitDetectOptical( nil )
self:InitDetectRadar( nil )
self:InitDetectRWR( nil )
self:InitDetectIRST( nil )
self:InitDetectDLINK( nil )
self:FilterCategories( {
Unit.Category.AIRPLANE,
@@ -531,6 +537,7 @@ do -- DETECTION_BASE
self:T( { "DetectionGroup is Alive", DetectionGroup:GetName() } )
local DetectionGroupName = DetectionGroup:GetName()
local DetectionUnit = DetectionGroup:GetUnit(1)
local DetectedUnits = {}
@@ -550,6 +557,18 @@ do -- DETECTION_BASE
if DetectedObject and DetectedObject:isExist() and DetectedObject.id_ < 50000000 then -- and ( DetectedObject:getCategory() == Object.Category.UNIT or DetectedObject:getCategory() == Object.Category.STATIC ) then
local TargetIsDetected, TargetIsVisible, TargetLastTime, TargetKnowType, TargetKnowDistance, TargetLastPos, TargetLastVelocity = DetectionUnit:IsTargetDetected(
DetectedObject,
self.DetectVisual,
self.DetectOptical,
self.DetectRadar,
self.DetectIRST,
self.DetectRWR,
self.DetectDLINK
)
self:T2( { TargetIsDetected = TargetIsDetected, TargetIsVisible = TargetIsVisible, TargetLastTime = TargetLastTime, TargetKnowType = TargetKnowType, TargetKnowDistance = TargetKnowDistance, TargetLastPos = TargetLastPos, TargetLastVelocity = TargetLastVelocity } )
local DetectionAccepted = true
local DetectedObjectName = DetectedObject:getName()
@@ -566,7 +585,7 @@ do -- DETECTION_BASE
local DetectedUnitCategory = DetectedObject:getDesc().category
self:T( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory } )
self:T2( { "Detected Target:", DetectionGroupName, DetectedObjectName, Distance, DetectedUnitCategory } )
-- Calculate Acceptance
@@ -648,12 +667,14 @@ do -- DETECTION_BASE
HasDetectedObjects = true
if not self.DetectedObjects[DetectedObjectName] then
self.DetectedObjects[DetectedObjectName] = {}
end
self.DetectedObjects[DetectedObjectName] = self.DetectedObjects[DetectedObjectName] or {}
self.DetectedObjects[DetectedObjectName].Name = DetectedObjectName
self.DetectedObjects[DetectedObjectName].Visible = Detection.visible
self.DetectedObjects[DetectedObjectName].Type = Detection.type
self.DetectedObjects[DetectedObjectName].IsVisible = TargetIsVisible
self.DetectedObjects[DetectedObjectName].LastTime = TargetLastTime
self.DetectedObjects[DetectedObjectName].LastPos = TargetLastPos
self.DetectedObjects[DetectedObjectName].LastVelocity = TargetLastVelocity
self.DetectedObjects[DetectedObjectName].KnowType = TargetKnowType
self.DetectedObjects[DetectedObjectName].KnowDistance = Detection.distance -- TargetKnowDistance
self.DetectedObjects[DetectedObjectName].Distance = Distance
local DetectedUnit = UNIT:FindByName( DetectedObjectName )
@@ -707,7 +728,7 @@ do -- DETECTION_BASE
local DetectedSet = DetectedItem.Set
if DetectedSet:Count() == 0 then
self.DetectedItems[DetectedItemID] = nil
self:RemoveDetectedItem(DetectedItemID)
end
end
@@ -1133,7 +1154,7 @@ do -- DETECTION_BASE
-- @param #string ObjectName
-- @return #DETECTION_BASE.DetectedObject
function DETECTION_BASE:GetDetectedObject( ObjectName )
self:F( ObjectName )
self:F2( ObjectName )
if ObjectName then
local DetectedObject = self.DetectedObjects[ObjectName]
@@ -1200,8 +1221,10 @@ do -- DETECTION_BASE
-- @param #number DetectedItemIndex The index or position in the DetectedItems list where the item needs to be removed.
function DETECTION_BASE:RemoveDetectedItem( DetectedItemIndex )
self.DetectedItemCount = self.DetectedItemCount - 1
self.DetectedItems[DetectedItemIndex] = nil
if self.DetectedItems[DetectedItemIndex] then
self.DetectedItemCount = self.DetectedItemCount - 1
self.DetectedItems[DetectedItemIndex] = nil
end
end
@@ -1215,7 +1238,7 @@ do -- DETECTION_BASE
--- Get the amount of SETs with detected objects.
-- @param #DETECTION_BASE self
-- @return #number Count
-- @return #number The amount of detected items. Note that the amount of detected items can differ with the reality, because detections are not real-time but doen in intervals!
function DETECTION_BASE:GetDetectedItemsCount()
local DetectedCount = self.DetectedItemCount
@@ -1435,7 +1458,6 @@ do -- DETECTION_UNITS
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItemSet = DetectedItem.Set -- Core.Set#SET_UNIT
local DetectedTypeName = DetectedItem.Type
for DetectedUnitName, DetectedUnitData in pairs( DetectedItemSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
@@ -1450,6 +1472,17 @@ do -- DETECTION_UNITS
-- Yes, the DetectedUnit is still detected or exists. Flag as identified.
self:IdentifyDetectedObject( DetectedObject )
-- Update the detection with the new data provided.
DetectedItem.TypeName = DetectedUnit:GetTypeName()
DetectedItem.Name = DetectedObject.Name
DetectedItem.IsVisible = DetectedObject.IsVisible
DetectedItem.LastTime = DetectedObject.LastTime
DetectedItem.LastPos = DetectedObject.LastPos
DetectedItem.LastVelocity = DetectedObject.LastVelocity
DetectedItem.KnowType = DetectedObject.KnowType
DetectedItem.KnowDistance = DetectedObject.KnowDistance
DetectedItem.Distance = DetectedObject.Distance
else
-- There was no DetectedObject, remove DetectedUnit from the Set.
self:AddChangeUnit( DetectedItem, "RU", DetectedUnitName )
@@ -1474,10 +1507,15 @@ do -- DETECTION_UNITS
if not DetectedItem then
self:T( "Added new DetectedItem" )
DetectedItem = self:AddDetectedItem( "UNIT", DetectedUnitName )
DetectedItem.Type = DetectedUnit:GetTypeName()
DetectedItem.Name = DetectedObjectData.Name
DetectedItem.Visible = DetectedObjectData.Visible
DetectedItem.Distance = DetectedObjectData.Distance
DetectedItem.TypeName = DetectedUnit:GetTypeName()
DetectedItem.Name = DetectedObject.Name
DetectedItem.IsVisible = DetectedObject.IsVisible
DetectedItem.LastTime = DetectedObject.LastTime
DetectedItem.LastPos = DetectedObject.LastPos
DetectedItem.LastVelocity = DetectedObject.LastVelocity
DetectedItem.KnowType = DetectedObject.KnowType
DetectedItem.KnowDistance = DetectedObject.KnowDistance
DetectedItem.Distance = DetectedObject.Distance
end
DetectedItem.Set:AddUnit( DetectedUnit )
@@ -1557,19 +1595,27 @@ do -- DETECTION_UNITS
if DetectedItemUnit and DetectedItemUnit:IsAlive() then
self:T(DetectedItemUnit)
local UnitCategoryName = DetectedItemUnit:GetCategoryName() or ""
local UnitCategoryType = DetectedItemUnit:GetTypeName() or ""
if DetectedItem.Type and UnitCategoryName and UnitCategoryType then
UnitCategoryText = UnitCategoryName .. " (" .. UnitCategoryType .. ") at "
if DetectedItem.KnowType then
local UnitCategoryName = DetectedItemUnit:GetCategoryName()
if UnitCategoryName then
UnitCategoryText = UnitCategoryName
end
if DetectedItem.TypeName then
UnitCategoryText = UnitCategoryText .. " (" .. DetectedItem.TypeName .. ")"
end
else
UnitCategoryText = "Unknown target at "
UnitCategoryText = "Unknown"
end
if DetectedItem.Visible == false then
UnitDistanceText = string.format( "%.2f", DetectedItem.Distance ) .. " km, estimated"
if DetectedItem.KnowDistance then
if DetectedItem.IsVisible then
UnitDistanceText = " at " .. string.format( "%.2f", DetectedItem.Distance ) .. " km"
end
else
UnitDistanceText = string.format( "%.2f", DetectedItem.Distance ) .. " km, visual"
if DetectedItem.IsVisible then
UnitDistanceText = " at +/- " .. string.format( "%.0f", DetectedItem.Distance ) .. " km"
end
end
local DetectedItemCoordinate = DetectedItemUnit:GetCoordinate()
@@ -1699,7 +1745,7 @@ do -- DETECTION_TYPES
for DetectedItemID, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItemSet = DetectedItem.Set -- Core.Set#SET_UNIT
local DetectedTypeName = DetectedItem.Type
local DetectedTypeName = DetectedItem.TypeName
for DetectedUnitName, DetectedUnitData in pairs( DetectedItemSet:GetSet() ) do
local DetectedUnit = DetectedUnitData -- Wrapper.Unit#UNIT
@@ -1736,7 +1782,7 @@ do -- DETECTION_TYPES
local DetectedItem = self:GetDetectedItem( DetectedTypeName )
if not DetectedItem then
DetectedItem = self:AddDetectedItem( "TYPE", DetectedTypeName )
DetectedItem.Type = DetectedUnit:GetTypeName()
DetectedItem.TypeName = DetectedUnit:GetTypeName()
end
DetectedItem.Set:AddUnit( DetectedUnit )
@@ -1808,7 +1854,7 @@ do -- DETECTION_TYPES
local ThreatLevelA2G = DetectedSet:CalculateThreatLevelA2G()
local DetectedItemsCount = DetectedSet:Count()
local DetectedItemType = DetectedItem.Type
local DetectedItemType = DetectedItem.TypeName
local DetectedItemUnit = DetectedSet:GetFirst()
@@ -1967,7 +2013,7 @@ do -- DETECTION_AREAS
local ThreatLevelA2G = self:GetTreatLevelA2G( DetectedItem )
local DetectedItemsCount = DetectedSet:Count()
local DetectedItemsTypes = DetectedSet:GetTypeNames()
local ReportSummary = string.format(
"%s - %s - Threat:[%s](%2d)\n %2d of %s",
DetectedItemID,
@@ -1983,6 +2029,25 @@ do -- DETECTION_AREAS
return nil
end
--- Report detailed of a detection result.
-- @param #DETECTION_AREAS self
-- @return #string
function DETECTION_AREAS:DetectedReportDetailed() --R2.1 Fixed missing report
self:F()
local Report = REPORT:New( "Detected areas:" )
for DetectedItemIndex, DetectedItem in pairs( self.DetectedItems ) do
local DetectedItem = DetectedItem -- #DETECTION_BASE.DetectedItem
local ReportSummary = self:DetectedItemReportSummary( DetectedItemIndex )
Report:Add( ReportSummary )
end
local ReportText = Report:Text()
return ReportText
end
--- Returns if there are friendlies nearby the FAC units ...

View File

@@ -442,7 +442,7 @@ function MISSILETRAINER._MenuMessages( MenuParameters )
if MenuParameters.Distance ~= nil then
self.Distance = MenuParameters.Distance
MESSAGE:New( "Hit detection distance set to " .. self.Distance .. " meters", 15, "Menu" ):ToAll()
MESSAGE:New( "Hit detection distance set to " .. self.Distance * 1000 .. " meters", 15, "Menu" ):ToAll()
end
end

View File

@@ -1595,11 +1595,13 @@ function SPAWN:_OnBirth( EventData )
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "Birth Event:", EventPrefix, self.SpawnTemplatePrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits + 1
self:T( "Alive Units: " .. self.AliveUnits )
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Birth Event:", EventPrefix, self.SpawnTemplatePrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits + 1
self:T( "Alive Units: " .. self.AliveUnits )
end
end
end
end
@@ -1616,11 +1618,13 @@ function SPAWN:_OnDeadOrCrash( EventData )
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "Dead event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits - 1
self:T( "Alive Units: " .. self.AliveUnits )
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Dead event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self.AliveUnits = self.AliveUnits - 1
self:T( "Alive Units: " .. self.AliveUnits )
end
end
end
end
@@ -1634,10 +1638,12 @@ function SPAWN:_OnTakeOff( EventData )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "TakeOff event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self:T( "self.Landed = false" )
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", false )
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "TakeOff event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
self:T( "self.Landed = false" )
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", false )
end
end
end
end
@@ -1652,16 +1658,18 @@ function SPAWN:_OnLand( EventData )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "Land event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- TODO: Check if this is the last unit of the group that lands.
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", true )
if self.RepeatOnLanding then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "Landed:", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "Land event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- TODO: Check if this is the last unit of the group that lands.
SpawnGroup:SetState( SpawnGroup, "Spawn_Landed", true )
if self.RepeatOnLanding then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "Landed:", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
end
end
end
@@ -1676,16 +1684,18 @@ function SPAWN:_OnEngineShutDown( EventData )
local SpawnGroup = EventData.IniGroup
if SpawnGroup then
local EventPrefix = self:_GetPrefixFromGroup( SpawnGroup )
self:T( { "EngineShutdown event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- todo: test if on the runway
local Landed = SpawnGroup:GetState( SpawnGroup, "Spawn_Landed" )
if Landed and self.RepeatOnEngineShutDown then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "EngineShutDown: ", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
if EventPrefix then -- EventPrefix can be nil if no # is found, which means, no spawnable group!
self:T( { "EngineShutdown event: " .. EventPrefix } )
if EventPrefix == self.SpawnTemplatePrefix or ( self.SpawnAliasPrefix and EventPrefix == self.SpawnAliasPrefix ) then
-- todo: test if on the runway
local Landed = SpawnGroup:GetState( SpawnGroup, "Spawn_Landed" )
if Landed and self.RepeatOnEngineShutDown then
local SpawnGroupIndex = self:GetSpawnIndexFromGroup( SpawnGroup )
self:T( { "EngineShutDown: ", "ReSpawn:", SpawnGroup:GetName(), SpawnGroupIndex } )
self:ReSpawn( SpawnGroupIndex )
end
end
end
end
end

View File

@@ -9,4 +9,4 @@ _SCHEDULEDISPATCHER = SCHEDULEDISPATCHER:New() -- Core.Timer#SCHEDULEDISPATCHER
--- Declare the main database object, which is used internally by the MOOSE classes.
_DATABASE = DATABASE:New() -- Database#DATABASE
COORDINATE:CoordinateMenu()
--COORDINATE:CoordinateMenu()

View File

@@ -9,6 +9,7 @@
-- @extends Core.Base#BASE
REPORT = {
ClassName = "REPORT",
Title = "",
}
--- Create a new REPORT.
@@ -20,13 +21,24 @@ function REPORT:New( Title )
local self = BASE:Inherit( self, BASE:New() ) -- #REPORT
self.Report = {}
Title = Title or ""
if Title then
self.Report[#self.Report+1] = Title
self.Title = Title
end
return self
end
--- Has the REPORT Text?
-- @param #REPORT self
-- @return #boolean
function REPORT:HasText() --R2.1
return #self.Report > 0
end
--- Set indent of a REPORT.
-- @param #REPORT self
-- @param #number Indent
@@ -61,7 +73,7 @@ end
-- @return #string The report text.
function REPORT:Text( Delimiter )
Delimiter = Delimiter or "\n"
local ReportText = table.concat( self.Report, Delimiter ) or ""
local ReportText = ( self.Title ~= "" and self.Title .. Delimiter or self.Title ) .. table.concat( self.Report, Delimiter ) or ""
return ReportText
end
@@ -100,9 +112,9 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
if EventData.IniObjectCategory == 1 then
local EventGroup = GROUP:Find( EventData.IniDCSGroup )
if EventGroup and self:HasGroup( EventGroup ) then
local MenuReporting = MENU_GROUP:New( EventGroup, "Reporting", self.CommandCenterMenu )
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Summary Report", MenuReporting, self.ReportSummary, self, EventGroup )
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Details Report", MenuReporting, self.ReportDetails, self, EventGroup )
local MenuReporting = MENU_GROUP:New( EventGroup, "Missions Reports", self.CommandCenterMenu )
local MenuMissionsSummary = MENU_GROUP_COMMAND:New( EventGroup, "Missions Status Report", MenuReporting, self.ReportMissionsStatus, self, EventGroup )
local MenuMissionsDetails = MENU_GROUP_COMMAND:New( EventGroup, "Missions Players Report", MenuReporting, self.ReportMissionsPlayers, self, EventGroup )
self:ReportSummary( EventGroup )
end
local PlayerUnit = EventData.IniUnit
@@ -161,7 +173,7 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
local Mission = Mission -- Tasking.Mission#MISSION
if Mission:IsOngoing() then
if Mission:IsENGAGED() then
Mission:AbortUnit( PlayerUnit )
end
end
@@ -177,7 +189,10 @@ function COMMANDCENTER:New( CommandCenterPositionable, CommandCenterName )
function( self, EventData )
local PlayerUnit = EventData.IniUnit
for MissionID, Mission in pairs( self:GetMissions() ) do
Mission:CrashUnit( PlayerUnit )
local Mission = Mission -- Tasking.Mission#MISSION
if Mission:IsENGAGED() then
Mission:CrashUnit( PlayerUnit )
end
end
end
)
@@ -257,7 +272,6 @@ end
-- @param #COMMANDCENTER self
-- @return Core.Menu#MENU_COALITION
function COMMANDCENTER:GetMenu()
self:F()
return self.CommandCenterMenu
end
@@ -293,11 +307,9 @@ end
-- @param #string Message
-- @param Wrapper.Group#GROUP TaskGroup
-- @param #sring Name (optional) The name of the Group used as a prefix for the message to the Group. If not provided, there will be nothing shown.
function COMMANDCENTER:MessageToGroup( Message, TaskGroup, Name )
function COMMANDCENTER:MessageToGroup( Message, TaskGroup )
local Prefix = Name and "@ " .. Name .. ": " or "@ " .. TaskGroup:GetCallsign() .. ": "
Message = Prefix .. Message
self:GetPositionable():MessageToGroup( Message , 20, TaskGroup, self:GetName() )
self:GetPositionable():MessageToGroup( Message , 15, TaskGroup, self:GetName() )
end
@@ -307,7 +319,8 @@ function COMMANDCENTER:MessageToCoalition( Message )
local CCCoalition = self:GetPositionable():GetCoalition()
--TODO: Fix coalition bug!
self:GetPositionable():MessageToCoalition( Message, 20, CCCoalition, self:GetName() )
self:GetPositionable():MessageToCoalition( Message, 15, CCCoalition )
end
@@ -315,18 +328,37 @@ end
--- Report the status of all MISSIONs to a GROUP.
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
-- @param #COMMANDCENTER self
function COMMANDCENTER:ReportSummary( ReportGroup )
function COMMANDCENTER:ReportMissionsStatus( ReportGroup )
self:E( ReportGroup )
local Report = REPORT:New()
Report:Add( "Status report of all missions." )
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
Report:Add( " - " .. Mission:ReportStatus() )
end
self:MessageToGroup( Report:Text(), ReportGroup )
end
--- Report the players of all MISSIONs to a GROUP.
-- Each Mission is listed, with an indication how many Tasks are still to be completed.
-- @param #COMMANDCENTER self
function COMMANDCENTER:ReportMissionsPlayers( ReportGroup )
self:E( ReportGroup )
local Report = REPORT:New()
Report:Add( "Players active in all missions." )
for MissionID, Mission in pairs( self.Missions ) do
local Mission = Mission -- Tasking.Mission#MISSION
Report:Add( " - " .. Mission:ReportOverview() )
Report:Add( " - " .. Mission:ReportPlayers() )
end
self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup )
self:MessageToGroup( Report:Text(), ReportGroup )
end
--- Report the status of a Task to a Group.
@@ -342,6 +374,6 @@ function COMMANDCENTER:ReportDetails( ReportGroup, Task )
Report:Add( " - " .. Mission:ReportDetails() )
end
self:GetPositionable():MessageToGroup( Report:Text(), 30, ReportGroup )
self:MessageToGroup( Report:Text(), ReportGroup )
end

View File

@@ -76,6 +76,7 @@ do -- DETECTION MANAGER
self:SetReportInterval( 30 )
self:SetReportDisplayTime( 25 )
self:E( { Detection = Detection } )
Detection:__Start( 1 )
return self

View File

@@ -12,6 +12,7 @@ MISSION = {
ClassName = "MISSION",
Name = "",
MissionStatus = "PENDING",
AssignedGroups = {},
}
--- This is the main MISSION declaration method. Each Mission is like the master or a Mission orchestration between, Clients, Tasks, Stages etc.
@@ -26,35 +27,47 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
local self = BASE:Inherit( self, FSM:New() ) -- Core.Fsm#FSM
self:SetStartState( "Idle" )
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
self:AddTransition( "Idle", "Start", "Ongoing" )
self.CommandCenter = CommandCenter
CommandCenter:AddMission( self )
--- OnLeave Transition Handler for State Idle.
-- @function [parent=#MISSION] OnLeaveIdle
self.Name = MissionName
self.MissionPriority = MissionPriority
self.MissionBriefing = MissionBriefing
self.MissionCoalition = MissionCoalition
self.Tasks = {}
self:SetStartState( "IDLE" )
self:AddTransition( "IDLE", "Start", "ENGAGED" )
--- OnLeave Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnLeaveIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Idle.
-- @function [parent=#MISSION] OnEnterIdle
--- OnEnter Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnEnterIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
--- OnLeave Transition Handler for State Ongoing.
-- @function [parent=#MISSION] OnLeaveOngoing
--- OnLeave Transition Handler for State ENGAGED.
-- @function [parent=#MISSION] OnLeaveENGAGED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Ongoing.
-- @function [parent=#MISSION] OnEnterOngoing
--- OnEnter Transition Handler for State ENGAGED.
-- @function [parent=#MISSION] OnEnterENGAGED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@@ -84,18 +97,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Ongoing", "Stop", "Idle" )
self:AddTransition( "ENGAGED", "Stop", "IDLE" )
--- OnLeave Transition Handler for State Idle.
-- @function [parent=#MISSION] OnLeaveIdle
--- OnLeave Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnLeaveIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Idle.
-- @function [parent=#MISSION] OnEnterIdle
--- OnEnter Transition Handler for State IDLE.
-- @function [parent=#MISSION] OnEnterIDLE
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@@ -125,18 +138,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "Ongoing", "Complete", "Completed" )
self:AddTransition( "ENGAGED", "Complete", "COMPLETED" )
--- OnLeave Transition Handler for State Completed.
-- @function [parent=#MISSION] OnLeaveCompleted
--- OnLeave Transition Handler for State COMPLETED.
-- @function [parent=#MISSION] OnLeaveCOMPLETED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Completed.
-- @function [parent=#MISSION] OnEnterCompleted
--- OnEnter Transition Handler for State COMPLETED.
-- @function [parent=#MISSION] OnEnterCOMPLETED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@@ -166,18 +179,18 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:AddTransition( "*", "Fail", "Failed" )
self:AddTransition( "*", "Fail", "FAILED" )
--- OnLeave Transition Handler for State Failed.
-- @function [parent=#MISSION] OnLeaveFailed
--- OnLeave Transition Handler for State FAILED.
-- @function [parent=#MISSION] OnLeaveFAILED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
-- @param #string To The To State string.
-- @return #boolean Return false to cancel Transition.
--- OnEnter Transition Handler for State Failed.
-- @function [parent=#MISSION] OnEnterFailed
--- OnEnter Transition Handler for State FAILED.
-- @function [parent=#MISSION] OnEnterFAILED
-- @param #MISSION self
-- @param #string From The From State string.
-- @param #string Event The Event string.
@@ -207,17 +220,6 @@ function MISSION:New( CommandCenter, MissionName, MissionPriority, MissionBriefi
-- @param #MISSION self
-- @param #number Delay The delay in seconds.
self:T( { MissionName, MissionPriority, MissionBriefing, MissionCoalition } )
self.CommandCenter = CommandCenter
CommandCenter:AddMission( self )
self.Name = MissionName
self.MissionPriority = MissionPriority
self.MissionBriefing = MissionBriefing
self.MissionCoalition = MissionCoalition
self.Tasks = {}
-- Private implementations
@@ -235,7 +237,7 @@ function MISSION:onbeforeComplete( From, Event, To )
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if not Task:IsStateSuccess() and not Task:IsStateFailed() and not Task:IsStateAborted() and not Task:IsStateCancelled() then
if not Task:IsStateSuccess() and not Task:IsStateFAILED() and not Task:IsStateAborted() and not Task:IsStateCancelled() then
return false -- Mission cannot be completed. Other Tasks are still active.
end
end
@@ -247,7 +249,7 @@ end
-- @param #string From
-- @param #string Event
-- @param #string To
function MISSION:onenterCompleted( From, Event, To )
function MISSION:onenterCOMPLETED( From, Event, To )
self:GetCommandCenter():MessageToCoalition( "Mission " .. self:GetName() .. " has been completed! Good job guys!" )
end
@@ -256,7 +258,7 @@ end
-- @param #MISSION self
-- @return #MISSION self
function MISSION:GetName()
return self.Name
return string.format( 'Mission "%s (%s)"', self.Name, self.MissionPriority )
end
--- Add a Unit to join the Mission.
@@ -288,19 +290,17 @@ end
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player joining the Mission.
-- @return #boolean true if Unit is part of a Task in the Mission.
-- @return #MISSION
function MISSION:AbortUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitRemoved = false
for TaskID, Task in pairs( self:GetTasks() ) do
if Task:AbortUnit( PlayerUnit ) then
PlayerUnitRemoved = true
end
local Task = Task -- Tasking.Task#TASK
local PlayerGroup = PlayerUnit:GetGroup()
Task:AbortGroup( PlayerGroup )
end
return PlayerUnitRemoved
return self
end
--- Handles a crash of a PlayerUnit from the Mission.
@@ -309,19 +309,17 @@ end
-- If the Unit is part of a Task in the Mission, true is returned.
-- @param #MISSION self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player crashing.
-- @return #boolean true if Unit is part of a Task in the Mission.
-- @return #MISSION
function MISSION:CrashUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitRemoved = false
for TaskID, Task in pairs( self:GetTasks() ) do
if Task:CrashUnit( PlayerUnit ) then
PlayerUnitRemoved = true
end
local Task = Task -- Tasking.Task#TASK
local PlayerGroup = PlayerUnit:GetGroup()
Task:CrashGroup( PlayerGroup )
end
return PlayerUnitRemoved
return self
end
--- Add a scoring to the mission.
@@ -365,7 +363,7 @@ end
-- @param #MISSION self
-- @param #number MenuTime
function MISSION:SetMenu( MenuTime )
self:F()
self:F( { self:GetName(), MenuTime } )
for _, TaskData in pairs( self:GetTasks() ) do
local Task = TaskData -- Tasking.Task#TASK
@@ -377,7 +375,7 @@ end
-- @param #MISSION self
-- @param #number MenuTime
function MISSION:RemoveMenu( MenuTime )
self:F()
self:F( { self:GetName(), MenuTime } )
for _, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
@@ -386,6 +384,58 @@ function MISSION:RemoveMenu( MenuTime )
end
do -- Group Assignment
--- Returns if the @{Mission} is assigned to the Group.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup
-- @return #boolean
function MISSION:IsGroupAssigned( MissionGroup )
local MissionGroupName = MissionGroup:GetName()
if self.AssignedGroups[MissionGroupName] == MissionGroup then
self:T( { "Mission is assigned to:", MissionGroup:GetName() } )
return true
end
self:T( { "Mission is not assigned to:", MissionGroup:GetName() } )
return false
end
--- Set @{Group} assigned to the @{Mission}.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup
-- @return #MISSION
function MISSION:SetGroupAssigned( MissionGroup )
local MissionName = self:GetName()
local MissionGroupName = MissionGroup:GetName()
self.AssignedGroups[MissionGroupName] = MissionGroup
self:E( string.format( "Mission %s is assigned to %s", MissionName, MissionGroupName ) )
return self
end
--- Clear the @{Group} assignment from the @{Mission}.
-- @param #MISSION self
-- @param Wrapper.Group#GROUP MissionGroup
-- @return #MISSION
function MISSION:ClearGroupAssignment( MissionGroup )
local MissionName = self:GetName()
local MissionGroupName = MissionGroup:GetName()
self.AssignedGroups[MissionGroupName] = nil
self:E( string.format( "Mission %s is unassigned to %s", MissionName, MissionGroupName ) )
return self
end
end
--- Gets the COMMANDCENTER.
-- @param #MISSION self
-- @return Tasking.CommandCenter#COMMANDCENTER
@@ -489,39 +539,39 @@ function MISSION:GetNextTaskID( Task )
return self.Tasks[TaskName].n
end
--- Is the @{Mission} **Completed**.
--- Is the @{Mission} **COMPLETED**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsCompleted()
return self:Is( "Completed" )
function MISSION:IsCOMPLETED()
return self:Is( "COMPLETED" )
end
--- Is the @{Mission} **Idle**.
--- Is the @{Mission} **IDLE**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsIdle()
return self:Is( "Idle" )
function MISSION:IsIDLE()
return self:Is( "IDLE" )
end
--- Is the @{Mission} **Ongoing**.
--- Is the @{Mission} **ENGAGED**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsOngoing()
return self:Is( "Ongoing" )
function MISSION:IsENGAGED()
return self:Is( "ENGAGED" )
end
--- Is the @{Mission} **Failed**.
--- Is the @{Mission} **FAILED**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsFailed()
return self:Is( "Failed" )
function MISSION:IsFAILED()
return self:Is( "FAILED" )
end
--- Is the @{Mission} **Hold**.
--- Is the @{Mission} **HOLD**.
-- @param #MISSION self
-- @return #boolean
function MISSION:IsHold()
return self:Is( "Hold" )
function MISSION:IsHOLD()
return self:Is( "HOLD" )
end
--- Validates if the Mission has a Group
@@ -556,6 +606,117 @@ function MISSION:GetTasksRemaining()
return TasksRemaining
end
--- @param #MISSION self
-- @return #number
function MISSION:GetTaskTypes()
-- Determine how many tasks are remaining.
local TaskTypeList = {}
local TasksRemaining = 0
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
local TaskType = Task:GetType()
TaskTypeList[TaskType] = TaskType
end
return TaskTypeList
end
--- Create a status report of the Mission.
-- This reports provides a one liner of the mission status. It indicates how many players and how many Tasks.
--
-- Mission "<MissionName>" - Status "<MissionStatus>"
-- - Task Types: <TaskType>, <TaskType>
-- - <xx> Planned Tasks (xp)
-- - <xx> Assigned Tasks(xp)
-- - <xx> Success Tasks (xp)
-- - <xx> Hold Tasks (xp)
-- - <xx> Cancelled Tasks (xp)
-- - <xx> Aborted Tasks (xp)
-- - <xx> Failed Tasks (xp)
--
-- @param #MISSION self
-- @return #string
function MISSION:ReportStatus()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
local TaskTypes = self:GetTaskTypes()
Report:Add( string.format( " - Task Types: %s", table.concat(TaskTypes, ", " ) ) )
local TaskStatusList = { "Planned", "Assigned", "Success", "Hold", "Cancelled", "Aborted", "Failed" }
for TaskStatusID, TaskStatus in pairs( TaskStatusList ) do
local TaskCount = 0
local TaskPlayerCount = 0
-- Determine how many tasks are remaining.
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
if Task:Is( TaskStatus ) then
TaskCount = TaskCount + 1
TaskPlayerCount = TaskPlayerCount + Task:GetPlayerCount()
end
end
if TaskCount > 0 then
Report:Add( string.format( " - %02d %s Tasks (%dp)", TaskCount, TaskStatus, TaskPlayerCount ) )
end
end
return Report:Text()
end
--- Create a player report of the Mission.
-- This reports provides a one liner of the mission status. It indicates how many players and how many Tasks.
--
-- Mission "<MissionName>" - Status "<MissionStatus>"
-- - Player "<PlayerName>: Task <TaskName> <TaskStatus>, Task <TaskName> <TaskStatus>
-- - Player <PlayerName>: Task <TaskName> <TaskStatus>, Task <TaskName> <TaskStatus>
-- - ..
--
-- @param #MISSION self
-- @return #string
function MISSION:ReportPlayers()
local Report = REPORT:New()
-- List the name of the mission.
local Name = self:GetName()
-- Determine the status of the mission.
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
local PlayerList = {}
-- Determine how many tasks are remaining.
for TaskID, Task in pairs( self:GetTasks() ) do
local Task = Task -- Tasking.Task#TASK
local PlayerNames = Task:GetPlayerNames()
for PlayerID, PlayerName in pairs( PlayerNames ) do
PlayerList[PlayerName] = Task:GetName()
end
end
for PlayerName, TaskName in pairs( PlayerList ) do
Report:Add( string.format( ' - Player (%s): Task "%s"', PlayerName, TaskName ) )
end
return Report:Text()
end
--- Create a summary report of the Mission (one line).
-- @param #MISSION self
-- @return #string
@@ -595,7 +756,7 @@ function MISSION:ReportOverview( TaskStatus )
local Status = self:GetState()
local TasksRemaining = self:GetTasksRemaining()
Report:Add( "Mission " .. Name .. " - " .. Status .. " Task Report ")
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
@@ -622,7 +783,7 @@ function MISSION:ReportDetails()
-- Determine the status of the mission.
local Status = self:GetState()
Report:Add( "Mission " .. Name .. " - " .. Status )
Report:Add( string.format( '%s - Status "%s"', Name, Status ) )
-- Determine how many tasks are remaining.
local TasksRemaining = 0
@@ -641,7 +802,6 @@ end
-- Tasks = Mission:GetTasks()
-- env.info( "Task 2 Completion = " .. Tasks[2]:GetGoalPercentage() .. "%" )
function MISSION:GetTasks()
self:F()
return self.Tasks
end

View File

@@ -78,6 +78,7 @@ TASK = {
Mission = nil,
CommandCenter = nil,
TimeOut = 0,
AssignedGroups = {},
}
--- FSM PlayerAborted event handler prototype for TASK.
@@ -156,14 +157,15 @@ TASK = {
-- @param #string TaskName The name of the Task
-- @param #string TaskType The type of the Task
-- @return #TASK self
function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
function TASK:New( Mission, SetGroupAssign, TaskName, TaskType, TaskBriefing )
local self = BASE:Inherit( self, FSM_TASK:New() ) -- Core.Fsm#FSM_TASK
local self = BASE:Inherit( self, FSM_TASK:New() ) -- Tasking.Task#TASK
self:SetStartState( "Planned" )
self:AddTransition( "Planned", "Assign", "Assigned" )
self:AddTransition( "Assigned", "AssignUnit", "Assigned" )
self:AddTransition( "Assigned", "Success", "Success" )
self:AddTransition( "Assigned", "Hold", "Hold" )
self:AddTransition( "Assigned", "Fail", "Failed" )
self:AddTransition( "Assigned", "Abort", "Aborted" )
self:AddTransition( "Assigned", "Cancel", "Cancelled" )
@@ -187,7 +189,7 @@ function TASK:New( Mission, SetGroupAssign, TaskName, TaskType )
self:SetName( TaskName )
self:SetID( Mission:GetNextTaskID( self ) ) -- The Mission orchestrates the task sequences ..
self.TaskBriefing = "You are invited for the task: " .. self.TaskName .. "."
self:SetBriefing( TaskBriefing )
self.FsmTemplate = self.FsmTemplate or FSM_PROCESS:New()
@@ -241,9 +243,9 @@ function TASK:JoinUnit( PlayerUnit, PlayerGroup )
--self:MessageToGroups( PlayerUnit:GetPlayerName() .. " is planning to join Task " .. self:GetName() )
end
if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
self:E( { IsAssignedToGroup = IsAssignedToGroup } )
if IsAssignedToGroup then
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:E( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then
self:AssignToUnit( PlayerUnit )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " joined Task " .. self:GetName() )
end
@@ -258,14 +260,11 @@ end
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task.
-- @return #boolean true if Unit is part of the Task.
function TASK:AbortUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitAborted = false
-- @return #TASK
function TASK:AbortGroup( PlayerGroup )
self:F( { PlayerGroup = PlayerGroup } )
local PlayerGroups = self:GetGroups()
local PlayerGroup = PlayerUnit:GetGroup()
-- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then
@@ -273,25 +272,39 @@ function TASK:AbortUnit( PlayerUnit )
-- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is aborted from the Task.
-- If the PlayerUnit was the last unit of the PlayerGroup, the menu needs to be removed from the Group.
if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
self:E( { IsAssignedToGroup = IsAssignedToGroup } )
if IsAssignedToGroup then
local PlayerName = PlayerUnit:GetPlayerName()
self:UnAssignFromUnit( PlayerUnit )
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:E( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then
local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName()
self:MessageToGroups( PlayerName .. " aborted Task " .. self:GetName() )
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
if #PlayerGroup:GetUnits() == 1 then
self:UnAssignFromGroup( PlayerGroup )
PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
self:RemoveMenuForGroup( PlayerGroup )
self:UnAssignFromGroup( PlayerGroup )
--self:Abort()
-- Now check if the task needs to go to hold...
-- It will go to hold, if there are no players in the mission...
PlayerGroups:Flush()
local IsRemaining = false
for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do
if self:IsGroupAssigned( AssignedGroup ) == true then
IsRemaining = true
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
break
end
end
self:Abort()
self:PlayerAborted( PlayerUnit )
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
if IsRemaining == false then
self:Abort()
end
self:PlayerAborted( PlayerGroup:GetUnit(1) )
end
end
end
return PlayerUnitAborted
return self
end
--- A PlayerUnit crashed in a Task. Abort the Player.
@@ -299,14 +312,11 @@ end
-- If the Unit is part of the Task, true is returned.
-- @param #TASK self
-- @param Wrapper.Unit#UNIT PlayerUnit The CLIENT or UNIT of the Player aborting the Task.
-- @return #boolean true if Unit is part of the Task.
function TASK:CrashUnit( PlayerUnit )
self:F( { PlayerUnit = PlayerUnit } )
local PlayerUnitCrashed = false
-- @return #TASK
function TASK:CrashGroup( PlayerGroup )
self:F( { PlayerGroup = PlayerGroup } )
local PlayerGroups = self:GetGroups()
local PlayerGroup = PlayerUnit:GetGroup()
-- Is the PlayerGroup part of the PlayerGroups?
if PlayerGroups:IsIncludeObject( PlayerGroup ) then
@@ -314,22 +324,38 @@ function TASK:CrashUnit( PlayerUnit )
-- Check if the PlayerGroup is already assigned to the Task. If yes, the PlayerGroup is aborted from the Task.
-- If the PlayerUnit was the last unit of the PlayerGroup, the menu needs to be removed from the Group.
if self:IsStateAssigned() then
local IsAssignedToGroup = self:IsAssignedToGroup( PlayerGroup )
self:E( { IsAssignedToGroup = IsAssignedToGroup } )
if IsAssignedToGroup then
self:UnAssignFromUnit( PlayerUnit )
self:MessageToGroups( PlayerUnit:GetPlayerName() .. " crashed in Task " .. self:GetName() )
self:E( { TaskGroup = PlayerGroup:GetName(), GetUnits = PlayerGroup:GetUnits() } )
if #PlayerGroup:GetUnits() == 1 then
PlayerGroup:SetState( PlayerGroup, "Assigned", nil )
self:RemoveMenuForGroup( PlayerGroup )
local IsGroupAssigned = self:IsGroupAssigned( PlayerGroup )
self:E( { IsGroupAssigned = IsGroupAssigned } )
if IsGroupAssigned then
local PlayerName = PlayerGroup:GetUnit(1):GetPlayerName()
self:MessageToGroups( PlayerName .. " crashed! " )
self:UnAssignFromGroup( PlayerGroup )
-- Now check if the task needs to go to hold...
-- It will go to hold, if there are no players in the mission...
PlayerGroups:Flush()
local IsRemaining = false
for GroupName, AssignedGroup in pairs( PlayerGroups:GetSet() or {} ) do
if self:IsGroupAssigned( AssignedGroup ) == true then
IsRemaining = true
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
break
end
end
self:PlayerCrashed( PlayerUnit )
self:F( { Task = self:GetName(), IsRemaining = IsRemaining } )
if IsRemaining == false then
self:Abort()
end
self:PlayerCrashed( PlayerGroup:GetUnit(1) )
end
end
end
return PlayerUnitCrashed
return self
end
@@ -350,39 +376,148 @@ function TASK:GetGroups()
return self.SetGroup
end
do -- Group Assignment
--- Assign the @{Task} to a @{Group}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:AssignToGroup( TaskGroup )
self:F2( TaskGroup:GetName() )
--- Returns if the @{Task} is assigned to the Group.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #boolean
function TASK:IsGroupAssigned( TaskGroup )
local TaskGroupName = TaskGroup:GetName()
TaskGroup:SetState( TaskGroup, "Assigned", self )
local Mission = self:GetMission()
local MissionMenu = Mission:GetMenu( TaskGroup )
MissionMenu:RemoveSubMenus()
--self:RemoveMenuForGroup( TaskGroup )
self:SetAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
self:E(PlayerName)
if PlayerName ~= nil or PlayerName ~= "" then
self:AssignToUnit( TaskUnit )
local TaskGroupName = TaskGroup:GetName()
if self.AssignedGroups[TaskGroupName] then
self:T( { "Task is assigned to:", TaskGroup:GetName() } )
return true
end
self:T( { "Task is not assigned to:", TaskGroup:GetName() } )
return false
end
--- Set @{Group} assigned to the @{Task}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:SetGroupAssigned( TaskGroup )
local TaskName = self:GetName()
local TaskGroupName = TaskGroup:GetName()
self.AssignedGroups[TaskGroupName] = TaskGroup
self:E( string.format( "Task %s is assigned to %s", TaskName, TaskGroupName ) )
-- Set the group to be assigned at mission level. This allows to decide the menu options on mission level for this group.
self:GetMission():SetGroupAssigned( TaskGroup )
local SetAssignedGroups = self:GetGroups()
-- SetAssignedGroups:ForEachGroup(
-- function( AssignedGroup )
-- if self:IsGroupAssigned(AssignedGroup) then
-- self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to group %s.", TaskName, TaskGroupName ), AssignedGroup )
-- else
-- self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is assigned to your group.", TaskName ), AssignedGroup )
-- end
-- end
-- )
return self
end
--- Clear the @{Group} assignment from the @{Task}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:ClearGroupAssignment( TaskGroup )
local TaskName = self:GetName()
local TaskGroupName = TaskGroup:GetName()
self.AssignedGroups[TaskGroupName] = nil
self:E( string.format( "Task %s is unassigned to %s", TaskName, TaskGroupName ) )
-- Set the group to be assigned at mission level. This allows to decide the menu options on mission level for this group.
self:GetMission():ClearGroupAssignment( TaskGroup )
local SetAssignedGroups = self:GetGroups()
SetAssignedGroups:ForEachGroup(
function( AssignedGroup )
if self:IsGroupAssigned(AssignedGroup) then
self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is unassigned from group %s.", TaskName, TaskGroupName ), AssignedGroup )
else
self:GetMission():GetCommandCenter():MessageToGroup( string.format( "Task %s is unassigned from your group.", TaskName ), AssignedGroup )
end
end
)
return self
end
return self
end
do -- Group Assignment
--- Assign the @{Task} to a @{Group}.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #TASK
function TASK:AssignToGroup( TaskGroup )
self:F( TaskGroup:GetName() )
local TaskGroupName = TaskGroup:GetName()
local Mission = self:GetMission()
local CommandCenter = Mission:GetCommandCenter()
self:SetGroupAssigned( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
self:E(PlayerName)
if PlayerName ~= nil or PlayerName ~= "" then
self:AssignToUnit( TaskUnit )
CommandCenter:MessageToGroup(
string.format( 'Task "%s": Briefing for player (%s):\n%s',
self:GetName(),
PlayerName,
self:GetBriefing()
), TaskGroup
)
end
end
CommandCenter:SetMenu()
return self
end
--- UnAssign the @{Task} from a @{Group}.
-- @param #TASK self
function TASK:UnAssignFromGroup( TaskGroup )
self:F2( { TaskGroup } )
self:ClearGroupAssignment( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
if PlayerName ~= nil or PlayerName ~= "" then
self:UnAssignFromUnit( TaskUnit )
end
end
local Mission = self:GetMission()
local CommandCenter = Mission:GetCommandCenter()
CommandCenter:SetMenu()
end
end
---
-- @param #TASK self
-- @param Wrapper.Group#GROUP FindGroup
@@ -458,7 +593,7 @@ function TASK:SendBriefingToAssignedGroups()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsAssignedToGroup( TaskGroup ) then
if self:IsGroupAssigned( TaskGroup ) then
TaskGroup:Message( self.TaskBriefing, 60 )
end
end
@@ -471,50 +606,14 @@ function TASK:UnAssignFromGroups()
self:F2()
for TaskGroupName, TaskGroup in pairs( self.SetGroup:GetSet() ) do
self:UnAssignFromGroup( TaskGroup )
end
end
--- UnAssign the @{Task} from a @{Group}.
-- @param #TASK self
function TASK:UnAssignFromGroup( TaskGroup )
self:F2( { TaskGroup } )
TaskGroup:SetState( TaskGroup, "Assigned", nil )
self:RemoveAssignedMenuForGroup( TaskGroup )
local TaskUnits = TaskGroup:GetUnits()
for UnitID, UnitData in pairs( TaskUnits ) do
local TaskUnit = UnitData -- Wrapper.Unit#UNIT
local PlayerName = TaskUnit:GetPlayerName()
if PlayerName ~= nil or PlayerName ~= "" then
self:UnAssignFromUnit( TaskUnit )
if self:IsGroupAssigned(TaskGroup) then
self:UnAssignFromGroup( TaskGroup )
end
end
end
--- Returns if the @{Task} is assigned to the Group.
-- @param #TASK self
-- @param Wrapper.Group#GROUP TaskGroup
-- @return #boolean
function TASK:IsAssignedToGroup( TaskGroup )
local TaskGroupName = TaskGroup:GetName()
if self:IsStateAssigned() then
if TaskGroup:GetState( TaskGroup, "Assigned" ) == self then
self:T( { "Task is assigned to:", TaskGroup:GetName() } )
return true
end
end
self:T( { "Task is not assigned to:", TaskGroup:GetName() } )
return false
end
--- Returns if the @{Task} has still alive and assigned Units.
-- @param #TASK self
-- @return #boolean
@@ -523,7 +622,7 @@ function TASK:HasAliveUnits()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if self:IsStateAssigned() then
if self:IsAssignedToGroup( TaskGroup ) then
if self:IsGroupAssigned( TaskGroup ) then
for TaskUnitID, TaskUnit in pairs( TaskGroup:GetUnits() ) do
if TaskUnit:IsAlive() then
self:T( { HasAliveUnits = true } )
@@ -543,9 +642,9 @@ end
-- @param #number MenuTime
-- @return #TASK
function TASK:SetMenu( MenuTime ) --R2.1 Mission Reports and Task Reports added. Fixes issue #424.
self:F()
self:F( { self:GetName(), MenuTime } )
self.SetGroup:Flush()
--self.SetGroup:Flush()
for TaskGroupID, TaskGroupData in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroupData -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
@@ -558,15 +657,15 @@ function TASK:SetMenu( MenuTime ) --R2.1 Mission Reports and Task Reports added.
TaskGroup.MenuReports = MENU_GROUP:New( TaskGroup, "Reports", MissionMenu )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Tasks", TaskGroup.MenuReports, Mission.MenuReportSummary, Mission, TaskGroup )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Planned Tasks", TaskGroup.MenuReports, Mission.MenuReportOverview, Mission, TaskGroup, "Planned" )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Ongoing Tasks", TaskGroup.MenuReports, Mission.MenuReportOverview, Mission, TaskGroup, "Ongoing" )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Assigned Tasks", TaskGroup.MenuReports, Mission.MenuReportOverview, Mission, TaskGroup, "Assigned" )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Successful Tasks", TaskGroup.MenuReports, Mission.MenuReportOverview, Mission, TaskGroup, "Success" )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Failed Tasks", TaskGroup.MenuReports, Mission.MenuReportOverview, Mission, TaskGroup, "Failed" )
MENU_GROUP_COMMAND:New( TaskGroup, "Report Held Tasks", TaskGroup.MenuReports, Mission.MenuReportOverview, Mission, TaskGroup, "Hold" )
end
if self:IsStatePlanned() or self:IsStateReplanned() then
-- if self:IsStatePlanned() or self:IsStateReplanned() then
self:SetMenuForGroup( TaskGroup, MenuTime )
end
-- end
end
end
end
@@ -579,12 +678,9 @@ end
-- @return #TASK
function TASK:SetMenuForGroup( TaskGroup, MenuTime )
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
self:SetPlannedMenuForGroup( TaskGroup, self:GetTaskName(), MenuTime )
else
if not self:IsAssignedToGroup( TaskGroup ) then
self:SetAssignedMenuForGroup( TaskGroup, MenuTime )
end
self:SetPlannedMenuForGroup( TaskGroup, MenuTime )
if self:IsGroupAssigned( TaskGroup ) then
self:SetAssignedMenuForGroup( TaskGroup, MenuTime )
end
end
@@ -595,7 +691,7 @@ end
-- @param #string MenuText The menu text.
-- @param #number MenuTime
-- @return #TASK self
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText, MenuTime )
function TASK:SetPlannedMenuForGroup( TaskGroup, MenuTime )
self:E( TaskGroup:GetName() )
local Mission = self:GetMission()
@@ -603,14 +699,26 @@ function TASK:SetPlannedMenuForGroup( TaskGroup, MenuText, MenuTime )
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local TaskType = self:GetType()
-- local TaskThreatLevel = self.TaskInfo["ThreatLevel"]
-- local TaskThreatLevelString = TaskThreatLevel and " [" .. string.rep( "■", TaskThreatLevel ) .. "]" or " []"
local TaskPlayerCount = self:GetPlayerCount()
local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount )
local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString )
local TaskName = string.format( "%s", self:GetName() )
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskType = self:GetType()
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, MissionMenu ):SetTime( MenuTime )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, MenuText, TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true )
local TaskPlannedMenu = MENU_GROUP:New( TaskGroup, "Planned Tasks", MissionMenu ):SetTime( MenuTime )
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskType, TaskPlannedMenu ):SetTime( MenuTime ):SetRemoveParent( true )
local TaskTypeMenu = MENU_GROUP:New( TaskGroup, TaskText, TaskTypeMenu ):SetTime( MenuTime ):SetRemoveParent( true )
local ReportTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Status" ), TaskTypeMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true )
if not Mission:IsGroupAssigned( TaskGroup ) then
local JoinTaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Join Task" ), TaskTypeMenu, self.MenuAssignToGroup, { self = self, TaskGroup = TaskGroup } ):SetTime( MenuTime ):SetRemoveParent( true )
end
return self
end
@@ -621,15 +729,27 @@ end
-- @param #number MenuTime
-- @return #TASK self
function TASK:SetAssignedMenuForGroup( TaskGroup, MenuTime )
self:E( TaskGroup:GetName() )
self:F( { TaskGroup:GetName(), MenuTime } )
local Mission = self:GetMission()
local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local TaskType = self:GetType()
-- local TaskThreatLevel = self.TaskInfo["ThreatLevel"]
-- local TaskThreatLevelString = TaskThreatLevel and " [" .. string.rep( "■", TaskThreatLevel ) .. "]" or " []"
local TaskPlayerCount = self:GetPlayerCount()
local TaskPlayerString = string.format( " (%dp)", TaskPlayerCount )
local TaskText = string.format( "%s%s", self:GetName(), TaskPlayerString ) --, TaskThreatLevelString )
local TaskName = string.format( "%s", self:GetName() )
local MissionMenu = MENU_GROUP:New( TaskGroup, MissionName, CommandCenterMenu ):SetTime( MenuTime )
local MissionMenu = Mission:GetMenu( TaskGroup )
self:E( { MissionMenu = MissionMenu } )
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Task Status", MissionMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, "Abort Task", MissionMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime )
local TaskAssignedMenu = MENU_GROUP:New( TaskGroup, string.format( "Assigned Task %s", TaskName ), MissionMenu ):SetTime( MenuTime )
local TaskTypeMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Report Task Status" ), TaskAssignedMenu, self.MenuTaskStatus, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true )
local TaskMenu = MENU_GROUP_COMMAND:New( TaskGroup, string.format( "Abort Group from Task" ), TaskAssignedMenu, self.MenuTaskAbort, self, TaskGroup ):SetTime( MenuTime ):SetRemoveParent( true )
return self
end
@@ -639,14 +759,12 @@ end
-- @param #number MenuTime
-- @return #TASK
function TASK:RemoveMenu( MenuTime )
self:F()
self:F( { self:GetName(), MenuTime } )
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
local TaskGroup = TaskGroup -- Wrapper.Group#GROUP
if TaskGroup:IsAlive() and TaskGroup:GetPlayerNames() then
if not self:IsAssignedToGroup( TaskGroup ) then
self:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
end
self:RefreshMenus( TaskGroup, MenuTime )
end
end
end
@@ -657,24 +775,26 @@ end
-- @param Wrapper.Group#GROUP TaskGroup
-- @param #number MenuTime
-- @return #TASK self
function TASK:RemovePlannedMenuForGroup( TaskGroup, MenuTime )
self:F()
function TASK:RefreshMenus( TaskGroup, MenuTime )
self:F( { TaskGroup:GetName(), MenuTime } )
local Mission = self:GetMission()
local MissionName = Mission:GetName()
local CommandCenter = Mission:GetCommandCenter()
local CommandCenterMenu = CommandCenter:GetMenu()
local MissionMenu = Mission:GetMenu( TaskGroup )
local TaskName = self:GetName()
local PlannedMenu = MissionMenu:GetMenu( "Planned Tasks" )
local AssignedMenu = MissionMenu:GetMenu( string.format( "Assigned Task %s", TaskName ) )
if MissionMenu then
local TaskType = self:GetType()
local TypeMenu = MissionMenu:GetMenu( TaskType )
if TypeMenu then
local TaskMenu = TypeMenu:GetMenu( self:GetTaskName() )
if TaskMenu then
TaskMenu:Remove( MenuTime )
end
end
if PlannedMenu then
PlannedMenu:Remove( MenuTime )
end
if AssignedMenu then
AssignedMenu:Remove( MenuTime )
end
end
@@ -723,7 +843,7 @@ end
-- @param #TASK self
function TASK:MenuTaskAbort( TaskGroup )
self:Abort()
self:AbortGroup( TaskGroup )
end
@@ -735,6 +855,13 @@ function TASK:GetTaskName()
return self.TaskName
end
--- Returns the @{Task} briefing.
-- @param #TASK self
-- @return #string Task briefing.
function TASK:GetTaskBriefing()
return self.TaskBriefing
end
@@ -794,11 +921,14 @@ end
function TASK:RemoveStateMachine( TaskUnit )
self:F( { TaskUnit, self.Fsm[TaskUnit] ~= nil } )
self:E( self.Fsm )
for TaskUnitT, Fsm in pairs( self.Fsm ) do
self:E( TaskUnitT )
end
--self:E( self.Fsm )
--for TaskUnitT, Fsm in pairs( self.Fsm ) do
--local Fsm = Fsm -- Core.Fsm#FSM_PROCESS
--self:E( TaskUnitT )
--self.Fsm[TaskUnit] = nil
--end
self.Fsm[TaskUnit]:Remove()
self.Fsm[TaskUnit] = nil
collectgarbage()
@@ -1001,10 +1131,18 @@ end
-- @param #string TaskBriefing
-- @return #TASK self
function TASK:SetBriefing( TaskBriefing )
self:E(TaskBriefing)
self.TaskBriefing = TaskBriefing
return self
end
--- Gets the @{Task} briefing.
-- @param #TASK self
-- @return #string The briefing text.
function TASK:GetBriefing()
return self.TaskBriefing
end
@@ -1017,14 +1155,17 @@ function TASK:onenterAssigned( From, Event, To, PlayerUnit, PlayerName )
self:E( { "Task Assigned", self.Dispatcher } )
self:MessageToGroups( "Task " .. self:GetName() .. " has been assigned to your group." )
if self.Dispatcher then
self:E( "Firing Assign event " )
self.Dispatcher:Assign( self, PlayerUnit, PlayerName )
if From ~= "Assigned" then
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " is assigned." )
if self.Dispatcher then
self:E( "Firing Assign event " )
self.Dispatcher:Assign( self, PlayerUnit, PlayerName )
end
self:GetMission():__Start( 1 )
self:SetMenu()
end
self:GetMission():__Start( 1 )
end
@@ -1053,12 +1194,13 @@ end
function TASK:onenterAborted( From, Event, To )
self:E( "Task Aborted" )
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " has been aborted! Task may be replanned." )
self:UnAssignFromGroups()
if From ~= "Aborted" then
self:GetMission():GetCommandCenter():MessageToCoalition( "Task " .. self:GetName() .. " has been aborted! Task may be replanned." )
self:__Replan( 5 )
self:SetMenu()
end
self:__Replan( 5 )
end
--- FSM function for a TASK
@@ -1098,7 +1240,7 @@ end
function TASK:onstatechange( From, Event, To )
if self:IsTrace() then
MESSAGE:New( "@ Task " .. self.TaskName .. " : " .. Event .. " changed to state " .. To, 2 ):ToAll()
--MESSAGE:New( "@ Task " .. self.TaskName .. " : " .. From .. " changed to " .. To .. " by " .. Event, 2 ):ToAll()
end
if self.Scores[To] then
@@ -1189,6 +1331,47 @@ function TASK:ReportOverview() --R2.1 fixed report. Now nicely formatted and con
return Report:Text()
end
--- Create a count of the players in the Task.
-- @param #TASK self
-- @return #number The total number of players in the task.
function TASK:GetPlayerCount() --R2.1 Get a count of the players.
local PlayerCount = 0
-- Loop each Unit active in the Task, and find Player Names.
for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( PlayerGroup ) then
local PlayerNames = PlayerGroup:GetPlayerNames()
PlayerCount = PlayerCount + #PlayerNames
end
end
return PlayerCount
end
--- Create a list of the players in the Task.
-- @param #TASK self
-- @return #map<#string,Wrapper.Group#GROUP> A map of the players
function TASK:GetPlayerNames() --R2.1 Get a map of the players.
local PlayerNameMap = {}
-- Loop each Unit active in the Task, and find Player Names.
for TaskGroupID, PlayerGroup in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroup -- Wrapper.Group#GROUP
if self:IsGroupAssigned( PlayerGroup ) then
local PlayerNames = PlayerGroup:GetPlayerNames()
for PlayerNameID, PlayerName in pairs( PlayerNames ) do
PlayerNameMap[PlayerName] = PlayerGroup
end
end
end
return PlayerNameMap
end
--- Create a detailed report of the Task.
-- List the Task Status, and the Players assigned to the Task.
@@ -1203,18 +1386,13 @@ function TASK:ReportDetails() --R2.1 fixed report. Now nicely formatted and cont
-- Determine the status of the Task.
local State = self:GetState()
-- Loop each Unit active in the Task, and find Player Names.
local PlayerNames = {}
local PlayerNames = self:GetPlayerNames()
local PlayerReport = REPORT:New()
for PlayerGroupID, PlayerGroupData in pairs( self:GetGroups():GetSet() ) do
local PlayerGroup = PlayerGroupData -- Wrapper.Group#GROUP
PlayerNames = PlayerGroup:GetPlayerNames()
if PlayerNames then
PlayerReport:Add( "Group " .. PlayerGroup:GetCallsign() .. ": " .. table.concat( PlayerNames, ", " ) )
end
for PlayerName, PlayerGroup in pairs( PlayerNames ) do
PlayerReport:Add( "Group " .. PlayerGroup:GetCallsign() .. ": " .. PlayerName )
end
local Players = PlayerReport:Text()

View File

@@ -86,15 +86,13 @@ do -- TASK_A2G
-- @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_A2G self
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- Tasking.Task#TASK_A2G
function TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskType, TaskBriefing )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- Tasking.Task#TASK_A2G
self:F()
self.TargetSetUnit = TargetSetUnit
self.TaskType = TaskType
Mission:AddTask( self )
local Fsm = self:GetUnitProcess()
@@ -366,14 +364,28 @@ do -- TASK_SEAD
--- Instantiates a new TASK_SEAD.
-- @param #TASK_SEAD self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @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 Set#SET_UNIT TargetSetUnit
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_SEAD self
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD" ) ) -- #TASK_SEAD
function TASK_SEAD:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "SEAD", TaskBriefing ) ) -- #TASK_SEAD
self:F()
Mission:AddTask( self )
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Execute a Suppression of Enemy Air Defenses.\n" ..
"Initial Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end
@@ -392,17 +404,28 @@ do -- TASK_BAI
--- Instantiates a new TASK_BAI.
-- @param #TASK_BAI self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @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 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.
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_BAI self
function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI" ) ) -- #TASK_BAI
function TASK_BAI:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "BAI", TaskBriefing ) ) -- #TASK_BAI
self:F()
Mission:AddTask( self )
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Execute a Battleground Air Interdiction of a group of enemy targets.\n" ..
"Initial Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end
@@ -421,17 +444,29 @@ do -- TASK_CAS
--- Instantiates a new TASK_CAS.
-- @param #TASK_CAS self
-- @param Tasking.Mission#MISSION Mission
-- @param Set#SET_GROUP SetGroup The set of groups for which the Task can be assigned.
-- @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 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.
-- @param Core.Set#SET_UNIT TargetSetUnit
-- @param #string TaskBriefing The briefing of the task.
-- @return #TASK_CAS self
function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS" ) ) -- #TASK_CAS
function TASK_CAS:New( Mission, SetGroup, TaskName, TargetSetUnit, TaskBriefing )
local self = BASE:Inherit( self, TASK_A2G:New( Mission, SetGroup, TaskName, TargetSetUnit, "CAS", TaskBriefing ) ) -- #TASK_CAS
self:F()
Mission:AddTask( self )
local TargetCoord = TargetSetUnit:GetFirst():GetCoordinate()
local TargetPositionText = TargetCoord:ToString()
local TargetThreatLevel = TargetSetUnit:CalculateThreatLevelA2G()
self:SetBriefing(
TaskBriefing or
"Execute a Close Air Support for a group of enemy targets.\n" ..
"Beware of friendlies at the vicinity!\n" ..
"Initial Coordinates: " .. TargetPositionText .. "\n" ..
"Threat Level: [" .. string.rep( "", TargetThreatLevel ) .. "]"
)
return self
end

View File

@@ -55,6 +55,7 @@ do -- TASK_A2G_DISPATCHER
ClassName = "TASK_A2G_DISPATCHER",
Mission = nil,
Detection = nil,
Tasks = {},
}
@@ -181,14 +182,16 @@ do -- TASK_A2G_DISPATCHER
-- @param #TASK_A2G_DISPATCHER self
-- @param Tasking.Mission#MISSION Mission
-- @param Tasking.Task#TASK Task
-- @param Functional.Detection#DETECTION_AREAS.DetectedItem DetectedItem
-- @param #boolean DetectedItemID
-- @param #boolean DetectedItemChange
-- @return Tasking.Task#TASK
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItem )
function TASK_A2G_DISPATCHER:EvaluateRemoveTask( Mission, Task, DetectedItemID, DetectedItemChanged )
if Task then
if Task:IsStatePlanned() and DetectedItem.Changed == true then
if Task:IsStatePlanned() and DetectedItemChanged == true then
self:E( "Removing Tasking: " .. Task:GetTaskName() )
Task = Mission:RemoveTask( Task )
Mission:RemoveTask( Task )
self.Tasks[DetectedItemID] = nil
end
end
@@ -208,82 +211,78 @@ do -- TASK_A2G_DISPATCHER
local ChangeMsg = {}
local Mission = self.Mission
--- 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 -- Functional.Detection#DETECTION_BASE.DetectedSet
local DetectedZone = DetectedItem.Zone
self:E( { "Targets in DetectedItem", DetectedItem.ItemID, DetectedSet:Count(), tostring( DetectedItem ) } )
DetectedSet:Flush()
local ItemID = DetectedItem.ID
-- Evaluate SEAD Tasking
local SEADTask = Mission:GetTask( string.format( "SEAD.%03d", ItemID ) )
SEADTask = self:EvaluateRemoveTask( Mission, SEADTask, DetectedItem )
if not SEADTask then
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
Task:SetInfo( "Detection", Detection:DetectedItemReportSummary( DetectedItemID ) )
Task:SetInfo( "Changes", Detection:GetChangeText( DetectedItem ) )
SEADTask = Mission:AddTask( Task )
end
end
-- Evaluate CAS Tasking
local CASTask = Mission:GetTask( string.format( "CAS.%03d", ItemID ) )
CASTask = self:EvaluateRemoveTask( Mission, CASTask, DetectedItem )
if not CASTask then
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
Task:SetInfo( "Detection", Detection:DetectedItemReportSummary( DetectedItemID ) )
Task:SetInfo( "Changes", Detection:GetChangeText( DetectedItem ) )
CASTask = Mission:AddTask( Task )
end
end
-- Evaluate BAI Tasking
local BAITask = Mission:GetTask( string.format( "BAI.%03d", ItemID ) )
BAITask = self:EvaluateRemoveTask( Mission, BAITask, DetectedItem )
if not BAITask then
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
local Task = TASK_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", ItemID ), TargetSetUnit )
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
Task:SetInfo( "Detection", Detection:DetectedItemReportSummary( DetectedItemID ) )
Task:SetInfo( "Changes", Detection:GetChangeText( DetectedItem ) )
BAITask = Mission:AddTask( Task )
end
end
-- OK, so the tasking has been done, now delete the changes reported for the area.
Detection:AcceptChanges( DetectedItem )
end
if Mission:IsIDLE() or Mission:IsENGAGED() then
-- TODO set menus using the HQ coordinator
Mission:GetCommandCenter():SetMenu()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
Mission:GetCommandCenter():MessageToGroup( string.format( "There are %d tasks remaining for mission *%s*. Subscribe to a task using the menu.", Mission:GetTasksRemaining(), Mission:GetName() ), TaskGroup )
if not TaskGroup:GetState( TaskGroup, "Assigned" ) then
-- Mission:GetCommandCenter():MessageToGroup(
-- string.format( "HQ Reporting - Planned tasks for mission '%s':\n\n%s\n",
-- self.Mission:GetName(),
-- string.format( "%s\n\n%s\n\n%s\n\n%s", ReportSEAD:Text(), ReportCAS:Text(), ReportBAI:Text(), ReportChanges:Text()
-- )
-- ), TaskGroup
-- )
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 DetectedItemID = DetectedItem.ID
local DetectedItemChanged = DetectedItem.Changed
local Task = self.Tasks[DetectedItemID]
Task = self:EvaluateRemoveTask( Mission, Task, DetectedItemID, DetectedItemChanged ) -- Task will be removed if it is planned and changed.
-- Evaluate SEAD
if not Task then
local TargetSetUnit = self:EvaluateSEAD( DetectedItem ) -- Returns a SetUnit if there are targets to be SEADed...
if TargetSetUnit then
Task = TASK_SEAD:New( Mission, self.SetGroup, string.format( "SEAD.%03d", DetectedItemID ), TargetSetUnit )
end
-- Evaluate CAS
if not Task then
local TargetSetUnit = self:EvaluateCAS( DetectedItem ) -- Returns a SetUnit if there are targets to be CASed...
if TargetSetUnit then
Task = TASK_CAS:New( Mission, self.SetGroup, string.format( "CAS.%03d", DetectedItemID ), TargetSetUnit )
end
-- Evaluate BAI
if not Task then
local TargetSetUnit = self:EvaluateBAI( DetectedItem, self.Mission:GetCommandCenter():GetPositionable():GetCoalition() ) -- Returns a SetUnit if there are targets to be BAIed...
if TargetSetUnit then
Task = TASK_BAI:New( Mission, self.SetGroup, string.format( "BAI.%03d", DetectedItemID ), TargetSetUnit )
end
end
end
if Task then
self.Tasks[DetectedItemID] = Task
Task:SetTargetZone( DetectedZone )
Task:SetDispatcher( self )
Task:SetInfo( "ThreatLevel", DetectedSet:CalculateThreatLevelA2G() )
Task:SetInfo( "Detection", Detection:DetectedItemReportSummary( DetectedItemID ) )
Task:SetInfo( "Changes", Detection:GetChangeText( DetectedItem ) )
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()
for TaskGroupID, TaskGroup in pairs( self.SetGroup:GetSet() ) do
if not Mission:IsGroupAssigned(TaskGroup) then
Mission:GetCommandCenter():MessageToGroup( string.format( "Mission *%s* has tasks %s. Subscribe to a task using the Mission *Overlord* radio menu.", Mission:GetName(), TaskReport:Text(", ") ), TaskGroup )
end
end
end
return true

View File

@@ -153,7 +153,7 @@ do -- TASK_CARGO
--
-- ===
--
-- @field #TASK_CARGO TASK_CARGO
-- @field #TASK_CARGO
--
TASK_CARGO = {
ClassName = "TASK_CARGO",
@@ -166,9 +166,10 @@ do -- TASK_CARGO
-- @param #string TaskName The name of the Task.
-- @param Core.Set#SET_CARGO SetCargo The scope of the cargo to be transported.
-- @param #string TaskType The type of Cargo task.
-- @param #string TaskBriefing The Cargo Task briefing.
-- @return #TASK_CARGO self
function TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, TaskType )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType ) ) -- #TASK_CARGO
function TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, TaskType, TaskBriefing )
local self = BASE:Inherit( self, TASK:New( Mission, SetGroup, TaskName, TaskType, TaskBriefing ) ) -- #TASK_CARGO
self:F( {Mission, SetGroup, TaskName, SetCargo, TaskType})
self.SetCargo = SetCargo
@@ -181,24 +182,24 @@ do -- TASK_CARGO
Fsm:AddProcess ( "Planned", "Accept", ACT_ASSIGN_ACCEPT:New( self.TaskBriefing ), { Assigned = "SelectAction", Rejected = "Reject" } )
Fsm:AddTransition( { "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Landed" }, "SelectAction", "WaitingForCommand" )
Fsm:AddTransition( { "Assigned", "WaitingForCommand", "ArrivedAtPickup", "ArrivedAtDeploy", "Boarded", "UnBoarded", "Landed", "Boarding" }, "SelectAction", "*" )
Fsm:AddTransition( "WaitingForCommand", "RouteToPickup", "RoutingToPickup" )
Fsm:AddTransition( "*", "RouteToPickup", "RoutingToPickup" )
Fsm:AddProcess ( "RoutingToPickup", "RouteToPickupPoint", ACT_ROUTE_POINT:New(), { Arrived = "ArriveAtPickup" } )
Fsm:AddTransition( "Arrived", "ArriveAtPickup", "ArrivedAtPickup" )
Fsm:AddTransition( "WaitingForCommand", "RouteToDeploy", "RoutingToDeploy" )
Fsm:AddTransition( "*", "RouteToDeploy", "RoutingToDeploy" )
Fsm:AddProcess ( "RoutingToDeploy", "RouteToDeployZone", ACT_ROUTE_ZONE:New(), { Arrived = "ArriveAtDeploy" } )
Fsm:AddTransition( "Arrived", "ArriveAtDeploy", "ArrivedAtDeploy" )
Fsm:AddTransition( { "ArrivedAtPickup", "ArrivedAtDeploy", "Landing" }, "Land", "Landing" )
Fsm:AddTransition( "Landing", "Landed", "Landed" )
Fsm:AddTransition( "WaitingForCommand", "PrepareBoarding", "AwaitBoarding" )
Fsm:AddTransition( "*", "PrepareBoarding", "AwaitBoarding" )
Fsm:AddTransition( "AwaitBoarding", "Board", "Boarding" )
Fsm:AddTransition( "Boarding", "Boarded", "Boarded" )
Fsm:AddTransition( "WaitingForCommand", "PrepareUnBoarding", "AwaitUnBoarding" )
Fsm:AddTransition( "*", "PrepareUnBoarding", "AwaitUnBoarding" )
Fsm:AddTransition( "AwaitUnBoarding", "UnBoard", "UnBoarding" )
Fsm:AddTransition( "UnBoarding", "UnBoarded", "UnBoarded" )
@@ -211,71 +212,79 @@ do -- TASK_CARGO
---
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
function Fsm:onenterWaitingForCommand( TaskUnit, Task )
-- @param Tasking.Task_CARGO#TASK_CARGO Task
function Fsm:onafterSelectAction( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if TaskUnit.Menu then
TaskUnit.Menu:Remove()
end
local MenuTime = timer.getTime()
TaskUnit.Menu = MENU_GROUP:New( TaskUnit:GetGroup(), Task:GetName() .. " @ " .. TaskUnit:GetName() )
TaskUnit.Menu = MENU_GROUP:New( TaskUnit:GetGroup(), Task:GetName() .. " @ " .. TaskUnit:GetName() ):SetTime( MenuTime )
Task.SetCargo:ForEachCargo(
--- @param Core.Cargo#CARGO Cargo
function( Cargo )
if Cargo:IsUnLoaded() then
if Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Board cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuBoardCargo,
self,
Cargo
)
else
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Route to Pickup cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuRouteToPickup,
self,
Cargo
)
end
end
if Cargo:IsLoaded() then
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
if Cargo:IsInZone( DeployZone ) then
if Cargo:IsAlive() then
if Cargo:IsUnLoaded() then
if Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Unboard cargo " .. Cargo.Name,
"Board cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuUnBoardCargo,
self.MenuBoardCargo,
self,
Cargo,
DeployZone
)
Cargo
):SetTime(MenuTime)
else
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Route to Deploy cargo at " .. DeployZoneName,
"Route to Pickup cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuRouteToDeploy,
self.MenuRouteToPickup,
self,
DeployZone
)
Cargo
):SetTime(MenuTime)
end
end
if Cargo:IsLoaded() then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Unboard cargo " .. Cargo.Name,
TaskUnit.Menu,
self.MenuUnBoardCargo,
self,
Cargo
):SetTime(MenuTime)
-- Deployzones are optional zones that can be selected to request routing information.
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
if not Cargo:IsInZone( DeployZone ) then
MENU_GROUP_COMMAND:New(
TaskUnit:GetGroup(),
"Route to Deploy cargo at " .. DeployZoneName,
TaskUnit.Menu,
self.MenuRouteToDeploy,
self,
DeployZone
):SetTime(MenuTime)
end
end
end
end
end
)
TaskUnit.Menu:Remove( MenuTime )
self:__SelectAction( -15 )
Task:GetMission():GetCommandCenter():MessageToGroup("Cargo menu is ready ...", TaskUnit:GetGroup() )
end
---
@@ -308,13 +317,19 @@ do -- TASK_CARGO
-- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit
-- @param Tasking.Task_Cargo#TASK_CARGO Task
-- @param From
-- @param Event
-- @param To
-- @param Core.Cargo#CARGO Cargo
function Fsm:onafterRouteToPickup( TaskUnit, Task, From, Event, To, Cargo )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if Cargo:IsAlive() then
self.Cargo = Cargo -- Core.Cargo#CARGO
Task:SetCargoPickup( self.Cargo, TaskUnit )
self:__RouteToPickupPoint( -0.1 )
end
self.Cargo = Cargo
Task:SetCargoPickup( self.Cargo, TaskUnit )
self:__RouteToPickupPoint( -0.1 )
end
@@ -325,10 +340,13 @@ do -- TASK_CARGO
function Fsm:onafterArriveAtPickup( TaskUnit, Task )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if TaskUnit:IsAir() then
self:__Land( -0.1, "Pickup" )
else
self:__SelectAction( -0.1 )
if self.Cargo:IsAlive() then
if TaskUnit:IsAir() then
self.Cargo.CargoObject:GetUnit(1):SmokeRed()
self:__Land( -0.1, "Pickup" )
else
self:__SelectAction( -0.1 )
end
end
end
@@ -369,19 +387,21 @@ do -- TASK_CARGO
function Fsm:onafterLand( TaskUnit, Task, From, Event, To, Action )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
Task:GetMission():GetCommandCenter():MessageToGroup( "Land", TaskUnit:GetGroup() )
self:__Land( -10, Action )
if self.Cargo:IsAlive() then
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
Task:GetMission():GetCommandCenter():MessageToGroup( "Land", TaskUnit:GetGroup() )
self:__Land( -10, Action )
else
Task:GetMission():GetCommandCenter():MessageToGroup( "Landed ...", TaskUnit:GetGroup() )
self:__Landed( -0.1, Action )
end
else
Task:GetMission():GetCommandCenter():MessageToGroup( "Landed ...", TaskUnit:GetGroup() )
self:__Landed( -0.1, Action )
end
else
if Action == "Pickup" then
self:__RouteToPickupZone( -0.1 )
else
self:__RouteToDeployZone( -0.1 )
if Action == "Pickup" then
self:__RouteToPickupZone( -0.1 )
else
self:__RouteToDeployZone( -0.1 )
end
end
end
end
@@ -393,17 +413,19 @@ do -- TASK_CARGO
function Fsm:onafterLanded( TaskUnit, Task, From, Event, To, Action )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
self:__Land( -0.1, Action )
if self.Cargo:IsAlive() then
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
self:__Land( -0.1, Action )
else
self:__SelectAction( -0.1 )
end
else
self:__SelectAction( -0.1 )
end
else
if Action == "Pickup" then
self:__RouteToPickupZone( -0.1 )
else
self:__RouteToDeployZone( -0.1 )
if Action == "Pickup" then
self:__RouteToPickupZone( -0.1 )
else
self:__RouteToDeployZone( -0.1 )
end
end
end
end
@@ -415,8 +437,10 @@ do -- TASK_CARGO
function Fsm:onafterPrepareBoarding( TaskUnit, Task, From, Event, To, Cargo )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
self.Cargo = Cargo -- Core.Cargo#CARGO_GROUP
self:__Board( -0.1 )
if Cargo and Cargo:IsAlive() then
self.Cargo = Cargo -- Core.Cargo#CARGO_GROUP
self:__Board( -0.1 )
end
end
---
@@ -427,23 +451,21 @@ do -- TASK_CARGO
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID() } )
function self.Cargo:OnEnterLoaded( From, Event, To, TaskUnit, TaskProcess )
self:E({From, Event, To, TaskUnit, TaskProcess })
TaskProcess:__Boarded( 0.1 )
end
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
--- ABORT the boarding. Split group if any and go back to select action.
if self.Cargo:IsAlive() then
if self.Cargo:IsInRadius( TaskUnit:GetPointVec2() ) then
if TaskUnit:InAir() then
--- ABORT the boarding. Split group if any and go back to select action.
else
self.Cargo:MessageToGroup( "Boarding ...", TaskUnit:GetGroup() )
self.Cargo:Board( TaskUnit, 20, self )
end
else
self.Cargo:MessageToGroup( "Boarding ...", TaskUnit:GetGroup() )
self.Cargo:Board( TaskUnit, 20, self )
--self:__ArriveAtCargo( -0.1 )
end
else
--self:__ArriveAtCargo( -0.1 )
end
end
@@ -460,8 +482,10 @@ do -- TASK_CARGO
-- TODO:I need to find a more decent solution for this.
Task:E( { CargoPickedUp = Task.CargoPickedUp } )
if Task.CargoPickedUp then
Task:CargoPickedUp( TaskUnit, self.Cargo )
if self.Cargo:IsAlive() then
if Task.CargoPickedUp then
Task:CargoPickedUp( TaskUnit, self.Cargo )
end
end
end
@@ -471,31 +495,50 @@ do -- TASK_CARGO
-- @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() } )
-- @param From
-- @param Event
-- @param To
-- @param Cargo
-- @param Core.Zone#ZONE_BASE DeployZone
function Fsm:onafterPrepareUnBoarding( TaskUnit, Task, From, Event, To, Cargo )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo } )
self.Cargo = Cargo
self.DeployZone = DeployZone
self:__UnBoard( -0.1 )
self.DeployZone = nil
-- Check if the Cargo is at a deployzone... If it is, provide it as a parameter!
if Cargo:IsAlive() then
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do
if Cargo:IsInZone( DeployZone ) then
self.DeployZone = DeployZone -- Core.Zone#ZONE_BASE
break
end
end
self:__UnBoard( -0.1, Cargo, self.DeployZone )
end
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() } )
-- @param From
-- @param Event
-- @param To
-- @param Cargo
-- @param Core.Zone#ZONE_BASE DeployZone
function Fsm:onafterUnBoard( TaskUnit, Task, From, Event, To, Cargo, DeployZone )
self:E( { TaskUnit = TaskUnit, Task = Task and Task:GetClassNameAndID(), From, Event, To, Cargo, DeployZone } )
function self.Cargo:OnEnterUnLoaded( From, Event, To, DeployZone, TaskProcess )
self:E({From, Event, To, TaskUnit, TaskProcess })
self:E({From, Event, To, DeployZone, TaskProcess })
TaskProcess:__UnBoarded( -0.1 )
end
self.Cargo:MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup() )
self.Cargo:UnBoard( self.DeployZone:GetPointVec2(), 20, self )
if self.Cargo:IsAlive() then
self.Cargo:MessageToGroup( "UnBoarding ...", TaskUnit:GetGroup() )
self.Cargo:UnBoard( DeployZone:GetPointVec2(), 400, self )
end
end
@@ -510,8 +553,10 @@ do -- TASK_CARGO
-- TODO:I need to find a more decent solution for this.
Task:E( { CargoDeployed = Task.CargoDeployed } )
if Task.CargoDeployed then
Task:CargoDeployed( TaskUnit, self.Cargo, self.DeployZone )
if self.Cargo:IsAlive() then
if Task.CargoDeployed then
Task:CargoDeployed( TaskUnit, self.Cargo, self.DeployZone )
end
end
self:__SelectAction( 1 )
@@ -685,9 +730,10 @@ do -- TASK_CARGO_TRANSPORT
-- @param 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_CARGO SetCargo The scope of the cargo to be transported.
-- @param #string TaskBriefing The Cargo Task briefing.
-- @return #TASK_CARGO_TRANSPORT self
function TASK_CARGO_TRANSPORT:New( Mission, SetGroup, TaskName, SetCargo )
local self = BASE:Inherit( self, TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, "Transport" ) ) -- #TASK_CARGO_TRANSPORT
function TASK_CARGO_TRANSPORT:New( Mission, SetGroup, TaskName, SetCargo, TaskBriefing )
local self = BASE:Inherit( self, TASK_CARGO:New( Mission, SetGroup, TaskName, SetCargo, "Transport", TaskBriefing ) ) -- #TASK_CARGO_TRANSPORT
self:F()
Mission:AddTask( self )
@@ -698,8 +744,6 @@ do -- TASK_CARGO_TRANSPORT
self:AddTransition( "*", "CargoPickedUp", "*" )
self:AddTransition( "*", "CargoDeployed", "*" )
do
--- OnBefore Transition Handler for Event CargoPickedUp.
-- @function [parent=#TASK_CARGO_TRANSPORT] OnBeforeCargoPickedUp
-- @param #TASK_CARGO_TRANSPORT self
@@ -731,9 +775,7 @@ do -- TASK_CARGO_TRANSPORT
-- @param #number Delay The delay in seconds.
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that PickedUp the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
end
do
--- OnBefore Transition Handler for Event CargoDeployed.
-- @function [parent=#TASK_CARGO_TRANSPORT] OnBeforeCargoDeployed
-- @param #TASK_CARGO_TRANSPORT self
@@ -769,10 +811,26 @@ do -- TASK_CARGO_TRANSPORT
-- @param Wrapper.Unit#UNIT TaskUnit The Unit (Client) that Deployed the cargo. You can use this to retrieve the PlayerName etc.
-- @param Core.Cargo#CARGO Cargo The Cargo that got PickedUp by the TaskUnit. You can use this to check Cargo Status.
-- @param Core.Zone#ZONE DeployZone The zone where the Cargo got Deployed or UnBoarded.
end
local Fsm = self:GetUnitProcess()
local CargoReport = REPORT:New( "Transport Cargo. The following cargo needs to be transported including initial positions:")
SetCargo:ForEachCargo(
--- @param Core.Cargo#CARGO Cargo
function( Cargo )
local CargoType = Cargo:GetType()
local CargoName = Cargo:GetName()
local CargoCoordinate = Cargo:GetCoordinate()
CargoReport:Add( string.format( '- "%s" (%s) at %s', CargoName, CargoType, CargoCoordinate:ToString() ) )
end
)
self:SetBriefing(
TaskBriefing or
CargoReport:Text()
)
return self
end
@@ -804,7 +862,7 @@ do -- TASK_CARGO_TRANSPORT
end
end
end
return CargoDeployed
end

View File

@@ -1782,7 +1782,7 @@ function CONTROLLABLE:GetDetectedTargets( DetectVisual, DetectOptical, DetectRad
return nil
end
function CONTROLLABLE:IsTargetDetected( DCSObject )
function CONTROLLABLE:IsTargetDetected( DCSObject, DetectVisual, DetectOptical, DetectRadar, DetectIRST, DetectRWR, DetectDLINK )
self:F2( self.ControllableName )
local DCSControllable = self:GetDCSObject()

View File

@@ -156,7 +156,6 @@ end
-- @param #GROUP self
-- @return Dcs.DCSWrapper.Group#Group The DCS Group.
function GROUP:GetDCSObject()
self:F(self.GroupName)
local DCSGroup = Group.getByName( self.GroupName )
if DCSGroup then
@@ -1142,7 +1141,7 @@ do -- Players
end
end
self:F( PlayerNames )
self:F2( PlayerNames )
return PlayerNames
end

View File

@@ -334,7 +334,7 @@ function POSITIONABLE:GetMessageText( Message, Name ) --R2.1 added
local DCSObject = self:GetDCSObject()
if DCSObject then
Name = Name and ( " (" .. Name .. ")" ) or ""
local Callsign = self:GetCallsign() ~= "" and self:GetCallsign() or self:GetName()
local Callsign = string.format( "[%s]", self:GetCallsign() ~= "" and self:GetCallsign() or self:GetName() )
local MessageText = Callsign .. Name .. ": " .. Message
return MessageText
end
@@ -383,12 +383,19 @@ end
-- @param #string Message The message text
-- @param Dcs.DCSTYpes#Duration Duration The duration of the message.
-- @param Dcs.DCScoalition#coalition MessageCoalition The Coalition receiving the message.
-- @param #string Name (optional) The Name of the sender. If not provided, the Name is the type of the Positionable.
function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition, Name )
function POSITIONABLE:MessageToCoalition( Message, Duration, MessageCoalition )
self:F2( { Message, Duration } )
local Name = ""
local DCSObject = self:GetDCSObject()
if DCSObject then
if MessageCoalition == coalition.side.BLUE then
Name = "Blue coalition"
end
if MessageCoalition == coalition.side.RED then
Name = "Red coalition"
end
self:GetMessage( Message, Duration, Name ):ToCoalition( MessageCoalition )
end

View File

@@ -724,7 +724,7 @@ function UNIT:IsInZone( Zone )
if self:IsAlive() then
local IsInZone = Zone:IsVec3InZone( self:GetVec3() )
self:T( { IsInZone } )
self:T2( { IsInZone } )
return IsInZone
end