mirror of
https://github.com/FlightControl-Master/MOOSE.git
synced 2025-10-29 16:58:06 +00:00
* Documentation fixes. (#1810) Fix documentation references. Correct spelling errors. Remove empty whitespaces. Correct a single mis-spelled ZONE_BASE variable, see 'Core/Zone.lua' (variable "Sureface" -> "Surface", no references to mis-spelled "Sureface" throughout the codebase). Correct mis-spelling of "coaltion" in 'Functional/Mantis.lua', corrected to "coalition". * Documentation fixes. (#1811) Update documentation text and links. Fix spelling errors. Other minor adjustments where appropriate, such as remove whitespaces and format code. * Documentation fixes. (#1815) Minor documentation and code formatting fixes. This is mostly intended to have something re-trigger the documentation generation to see if the filename capitalization is resolved. * Code formatting preparation. (#1817) Use EmmyLuaCodeStyle that comes with "Lua" VS Code extension (https://marketplace.visualstudio.com/items?itemName=sumneko.lua). More features and configurability than LuaFormatter, and no need for additional extension (beyond "Lua"). Formatting file set up from default template with some tweaks to correspond to most common coding style observed in the code base. Further tweaks are likely required. * Documentation fixes. (#1816) Co-authored-by: TommyC81 <tommyc81@gmail.com>
769 lines
24 KiB
Lua
769 lines
24 KiB
Lua
--- **Cargo** - Management of grouped cargo logistics, which are based on a @{Wrapper.Group} object.
|
|
--
|
|
-- ===
|
|
--
|
|
-- ### [Demo Missions]()
|
|
--
|
|
-- ### [YouTube Playlist]()
|
|
--
|
|
-- ===
|
|
--
|
|
-- ### Author: **FlightControl**
|
|
-- ### Contributions:
|
|
--
|
|
-- ===
|
|
--
|
|
-- @module Cargo.CargoGroup
|
|
-- @image Cargo_Groups.JPG
|
|
|
|
|
|
do -- CARGO_GROUP
|
|
|
|
--- @type CARGO_GROUP
|
|
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
|
|
-- @field #string GroupName The name of the CargoGroup.
|
|
-- @extends Cargo.Cargo#CARGO_REPORTABLE
|
|
|
|
--- Defines a cargo that is represented by a @{Wrapper.Group} object within the simulator.
|
|
-- The cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
|
|
--
|
|
-- The above cargo classes are used by the following AI_CARGO_ classes to allow AI groups to transport cargo:
|
|
--
|
|
-- * AI Armoured Personnel Carriers to transport cargo and engage in battles, using the @{AI.AI_Cargo_APC} module.
|
|
-- * AI Helicopters to transport cargo, using the @{AI.AI_Cargo_Helicopter} module.
|
|
-- * AI Planes to transport cargo, using the @{AI.AI_Cargo_Airplane} module.
|
|
-- * AI Ships is planned.
|
|
--
|
|
-- The above cargo classes are also used by the TASK_CARGO_ classes to allow human players to transport cargo as part of a tasking:
|
|
--
|
|
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_TRANSPORT} to transport cargo by human players.
|
|
-- * @{Tasking.Task_Cargo_Transport#TASK_CARGO_CSAR} to transport downed pilots by human players.
|
|
--
|
|
-- @field #CARGO_GROUP CARGO_GROUP
|
|
--
|
|
CARGO_GROUP = {
|
|
ClassName = "CARGO_GROUP",
|
|
}
|
|
|
|
--- CARGO_GROUP constructor.
|
|
-- This make a new CARGO_GROUP from a @{Wrapper.Group} object.
|
|
-- It will "ungroup" the group object within the sim, and will create a @{Core.Set} of individual Unit objects.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Wrapper.Group#GROUP CargoGroup Group to be transported as cargo.
|
|
-- @param #string Type Cargo type, e.g. "Infantry". This is the type used in SET_CARGO:New():FilterTypes("Infantry") to define the valid cargo groups of the set.
|
|
-- @param #string Name A user defined name of the cargo group. This name CAN be the same as the group object but can also have a different name. This name MUST be unique!
|
|
-- @param #number LoadRadius (optional) Distance in meters until which a cargo is loaded into the carrier. Cargo outside this radius has to be routed by other means to within the radius to be loaded.
|
|
-- @param #number NearRadius (optional) Once the units are within this radius of the carrier, they are actually loaded, i.e. disappear from the scene.
|
|
-- @return #CARGO_GROUP Cargo group object.
|
|
function CARGO_GROUP:New( CargoGroup, Type, Name, LoadRadius, NearRadius )
|
|
|
|
-- Inherit CAROG_REPORTABLE
|
|
local self = BASE:Inherit( self, CARGO_REPORTABLE:New( Type, Name, 0, LoadRadius, NearRadius ) ) -- #CARGO_GROUP
|
|
self:F( { Type, Name, LoadRadius } )
|
|
|
|
self.CargoSet = SET_CARGO:New()
|
|
self.CargoGroup = CargoGroup
|
|
self.Grouped = true
|
|
self.CargoUnitTemplate = {}
|
|
|
|
self.NearRadius = NearRadius
|
|
|
|
self:SetDeployed( false )
|
|
|
|
local WeightGroup = 0
|
|
local VolumeGroup = 0
|
|
|
|
self.CargoGroup:Destroy() -- destroy and generate a unit removal event, so that the database gets cleaned, and the linked sets get properly cleaned.
|
|
|
|
local GroupName = CargoGroup:GetName()
|
|
self.CargoName = Name
|
|
self.CargoTemplate = UTILS.DeepCopy( _DATABASE:GetGroupTemplate( GroupName ) )
|
|
|
|
-- Deactivate late activation.
|
|
self.CargoTemplate.lateActivation=false
|
|
|
|
self.GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
|
|
self.GroupTemplate.name = self.CargoName .. "#CARGO"
|
|
self.GroupTemplate.groupId = nil
|
|
|
|
self.GroupTemplate.units = {}
|
|
|
|
for UnitID, UnitTemplate in pairs( self.CargoTemplate.units ) do
|
|
UnitTemplate.name = UnitTemplate.name .. "#CARGO"
|
|
local CargoUnitName = UnitTemplate.name
|
|
self.CargoUnitTemplate[CargoUnitName] = UnitTemplate
|
|
|
|
self.GroupTemplate.units[#self.GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName]
|
|
self.GroupTemplate.units[#self.GroupTemplate.units].unitId = nil
|
|
|
|
-- And we register the spawned unit as part of the CargoSet.
|
|
local Unit = UNIT:Register( CargoUnitName )
|
|
|
|
end
|
|
|
|
-- Then we register the new group in the database
|
|
self.CargoGroup = GROUP:NewTemplate( self.GroupTemplate, self.GroupTemplate.CoalitionID, self.GroupTemplate.CategoryID, self.GroupTemplate.CountryID )
|
|
|
|
-- Now we spawn the new group based on the template created.
|
|
self.CargoObject = _DATABASE:Spawn( self.GroupTemplate )
|
|
|
|
for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do
|
|
|
|
|
|
local CargoUnitName = CargoUnit:GetName()
|
|
|
|
local Cargo = CARGO_UNIT:New( CargoUnit, Type, CargoUnitName, LoadRadius, NearRadius )
|
|
self.CargoSet:Add( CargoUnitName, Cargo )
|
|
|
|
WeightGroup = WeightGroup + Cargo:GetWeight()
|
|
|
|
end
|
|
|
|
self:SetWeight( WeightGroup )
|
|
|
|
self:T( { "Weight Cargo", WeightGroup } )
|
|
|
|
-- Cargo objects are added to the _DATABASE and SET_CARGO objects.
|
|
_EVENTDISPATCHER:CreateEventNewCargo( self )
|
|
|
|
self:HandleEvent( EVENTS.Dead, self.OnEventCargoDead )
|
|
self:HandleEvent( EVENTS.Crash, self.OnEventCargoDead )
|
|
--self:HandleEvent( EVENTS.RemoveUnit, self.OnEventCargoDead )
|
|
self:HandleEvent( EVENTS.PlayerLeaveUnit, self.OnEventCargoDead )
|
|
|
|
self:SetEventPriority( 4 )
|
|
|
|
return self
|
|
end
|
|
|
|
|
|
--- Respawn the CargoGroup.
|
|
-- @param #CARGO_GROUP self
|
|
function CARGO_GROUP:Respawn()
|
|
|
|
self:F( { "Respawning" } )
|
|
|
|
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
|
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
|
Cargo:Destroy() -- Destroy the cargo and generate a remove unit event to update the sets.
|
|
Cargo:SetStartState( "UnLoaded" )
|
|
end
|
|
|
|
-- Now we spawn the new group based on the template created.
|
|
_DATABASE:Spawn( self.GroupTemplate )
|
|
|
|
for CargoUnitID, CargoUnit in pairs( self.CargoObject:GetUnits() ) do
|
|
|
|
local CargoUnitName = CargoUnit:GetName()
|
|
|
|
local Cargo = CARGO_UNIT:New( CargoUnit, self.Type, CargoUnitName, self.LoadRadius )
|
|
self.CargoSet:Add( CargoUnitName, Cargo )
|
|
|
|
end
|
|
|
|
self:SetDeployed( false )
|
|
self:SetStartState( "UnLoaded" )
|
|
|
|
end
|
|
|
|
--- Ungroup the cargo group into individual groups with one unit.
|
|
-- This is required because by default a group will move in formation and this is really an issue for group control.
|
|
-- Therefore this method is made to be able to ungroup a group.
|
|
-- This works for ground only groups.
|
|
-- @param #CARGO_GROUP self
|
|
function CARGO_GROUP:Ungroup()
|
|
|
|
if self.Grouped == true then
|
|
|
|
self.Grouped = false
|
|
|
|
self.CargoGroup:Destroy()
|
|
|
|
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
|
|
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
|
|
|
|
if CargoUnit:IsUnLoaded() then
|
|
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
|
|
--local GroupName = env.getValueDictByKey( GroupTemplate.name )
|
|
|
|
-- We create a new group object with one unit...
|
|
-- First we prepare the template...
|
|
GroupTemplate.name = self.CargoName .. "#CARGO#" .. CargoUnitName
|
|
GroupTemplate.groupId = nil
|
|
|
|
if CargoUnit:IsUnLoaded() then
|
|
GroupTemplate.units = {}
|
|
GroupTemplate.units[1] = self.CargoUnitTemplate[CargoUnitName]
|
|
GroupTemplate.units[#GroupTemplate.units].unitId = nil
|
|
GroupTemplate.units[#GroupTemplate.units].x = CargoUnit:GetX()
|
|
GroupTemplate.units[#GroupTemplate.units].y = CargoUnit:GetY()
|
|
GroupTemplate.units[#GroupTemplate.units].heading = CargoUnit:GetHeading()
|
|
end
|
|
|
|
|
|
-- Then we register the new group in the database
|
|
local CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID)
|
|
|
|
-- Now we spawn the new group based on the template created.
|
|
_DATABASE:Spawn( GroupTemplate )
|
|
end
|
|
end
|
|
|
|
self.CargoObject = nil
|
|
end
|
|
|
|
|
|
end
|
|
|
|
--- Regroup the cargo group into one group with multiple unit.
|
|
-- This is required because by default a group will move in formation and this is really an issue for group control.
|
|
-- Therefore this method is made to be able to regroup a group.
|
|
-- This works for ground only groups.
|
|
-- @param #CARGO_GROUP self
|
|
function CARGO_GROUP:Regroup()
|
|
|
|
self:F("Regroup")
|
|
|
|
if self.Grouped == false then
|
|
|
|
self.Grouped = true
|
|
|
|
local GroupTemplate = UTILS.DeepCopy( self.CargoTemplate )
|
|
GroupTemplate.name = self.CargoName .. "#CARGO"
|
|
GroupTemplate.groupId = nil
|
|
GroupTemplate.units = {}
|
|
|
|
for CargoUnitName, CargoUnit in pairs( self.CargoSet:GetSet() ) do
|
|
local CargoUnit = CargoUnit -- Cargo.CargoUnit#CARGO_UNIT
|
|
|
|
self:F( { CargoUnit:GetName(), UnLoaded = CargoUnit:IsUnLoaded() } )
|
|
|
|
if CargoUnit:IsUnLoaded() then
|
|
|
|
CargoUnit.CargoObject:Destroy()
|
|
|
|
GroupTemplate.units[#GroupTemplate.units+1] = self.CargoUnitTemplate[CargoUnitName]
|
|
GroupTemplate.units[#GroupTemplate.units].unitId = nil
|
|
GroupTemplate.units[#GroupTemplate.units].x = CargoUnit:GetX()
|
|
GroupTemplate.units[#GroupTemplate.units].y = CargoUnit:GetY()
|
|
GroupTemplate.units[#GroupTemplate.units].heading = CargoUnit:GetHeading()
|
|
end
|
|
end
|
|
|
|
-- Then we register the new group in the database
|
|
self.CargoGroup = GROUP:NewTemplate( GroupTemplate, GroupTemplate.CoalitionID, GroupTemplate.CategoryID, GroupTemplate.CountryID )
|
|
|
|
self:F( { "Regroup", GroupTemplate } )
|
|
|
|
-- Now we spawn the new group based on the template created.
|
|
self.CargoObject = _DATABASE:Spawn( GroupTemplate )
|
|
end
|
|
|
|
end
|
|
|
|
|
|
--- @param #CARGO_GROUP self
|
|
-- @param Core.Event#EVENTDATA EventData
|
|
function CARGO_GROUP:OnEventCargoDead( EventData )
|
|
|
|
self:E(EventData)
|
|
|
|
local Destroyed = false
|
|
|
|
if self:IsDestroyed() or self:IsUnLoaded() or self:IsBoarding() or self:IsUnboarding() then
|
|
Destroyed = true
|
|
for CargoID, CargoData in pairs( self.CargoSet:GetSet() ) do
|
|
local Cargo = CargoData -- Cargo.Cargo#CARGO
|
|
if Cargo:IsAlive() then
|
|
Destroyed = false
|
|
else
|
|
Cargo:Destroyed()
|
|
end
|
|
end
|
|
else
|
|
local CarrierName = self.CargoCarrier:GetName()
|
|
if CarrierName == EventData.IniDCSUnitName then
|
|
MESSAGE:New( "Cargo is lost from carrier " .. CarrierName, 15 ):ToAll()
|
|
Destroyed = true
|
|
self.CargoCarrier:ClearCargo()
|
|
end
|
|
end
|
|
|
|
if Destroyed then
|
|
self:Destroyed()
|
|
self:E( { "Cargo group destroyed" } )
|
|
end
|
|
|
|
end
|
|
|
|
--- After Board Event.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param #string Event
|
|
-- @param #string From
|
|
-- @param #string To
|
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
|
function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
|
|
self:F( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
|
|
|
|
NearRadius = NearRadius or self.NearRadius
|
|
|
|
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
|
|
self.CargoSet:ForEach(
|
|
function( Cargo, ... )
|
|
self:F( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } )
|
|
local CargoGroup = Cargo.CargoObject --Wrapper.Group#GROUP
|
|
CargoGroup:OptionAlarmStateGreen()
|
|
Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
|
|
end, ...
|
|
)
|
|
|
|
self:__Boarding( -1, CargoCarrier, NearRadius, ... )
|
|
|
|
end
|
|
|
|
--- Enter Loaded State.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param #string Event
|
|
-- @param #string From
|
|
-- @param #string To
|
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
|
function CARGO_GROUP:onafterLoad( 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
|
|
if not Cargo:IsDestroyed() then
|
|
Cargo:Load( CargoCarrier )
|
|
end
|
|
end
|
|
end
|
|
|
|
--self.CargoObject:Destroy()
|
|
self.CargoCarrier = CargoCarrier
|
|
self.CargoCarrier:AddCargo( self )
|
|
|
|
end
|
|
|
|
--- Leave Boarding State.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param #string Event
|
|
-- @param #string From
|
|
-- @param #string To
|
|
-- @param Wrapper.Unit#UNIT CargoCarrier
|
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
|
function CARGO_GROUP:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
|
|
--self:F( { CargoCarrier.UnitName, From, Event, To } )
|
|
|
|
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" )
|
|
and (not Cargo:is( "Destroyed" )) then -- If one or more units of a group defined as CARGO_GROUP died, the CARGO_GROUP:Board() command does not trigger the CARGO_GRUOP:OnEnterLoaded() function.
|
|
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( -5, CargoCarrier, NearRadius, ... )
|
|
else
|
|
self:F("Group Cargo is loaded")
|
|
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 #string Event
|
|
-- @param #string From
|
|
-- @param #string To
|
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
|
function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
|
|
self:F( {From, Event, To, ToPointVec2, NearRadius } )
|
|
|
|
NearRadius = NearRadius or 25
|
|
|
|
local Timer = 1
|
|
|
|
if From == "Loaded" then
|
|
|
|
if self.CargoObject then
|
|
self.CargoObject:Destroy()
|
|
end
|
|
|
|
-- For each Cargo object within the CARGO_GROUP, route each object to the CargoLoadPointVec2
|
|
self.CargoSet:ForEach(
|
|
--- @param Cargo.Cargo#CARGO Cargo
|
|
function( Cargo, NearRadius )
|
|
if not Cargo:IsDestroyed() then
|
|
local ToVec=nil
|
|
if ToPointVec2==nil then
|
|
ToVec=self.CargoCarrier:GetPointVec2():GetRandomPointVec2InRadius(2*NearRadius, NearRadius)
|
|
else
|
|
ToVec=ToPointVec2
|
|
end
|
|
Cargo:__UnBoard( Timer, ToVec, NearRadius )
|
|
Timer = Timer + 1
|
|
end
|
|
end, { NearRadius }
|
|
)
|
|
|
|
|
|
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
|
|
end
|
|
|
|
end
|
|
|
|
--- Leave UnBoarding State.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param #string Event
|
|
-- @param #string From
|
|
-- @param #string To
|
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
|
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
|
|
function CARGO_GROUP:onafterUnBoarding( 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:GetName(), Cargo.current } )
|
|
if not Cargo:is( "UnLoaded" ) and not Cargo:IsDestroyed() then
|
|
UnBoarded = false
|
|
end
|
|
end
|
|
|
|
if UnBoarded then
|
|
self:__UnLoad( 1, ToPointVec2, ... )
|
|
else
|
|
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
end
|
|
|
|
--- Enter UnLoaded State.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param #string Event
|
|
-- @param #string From
|
|
-- @param #string To
|
|
-- @param Core.Point#POINT_VEC2 ToPointVec2
|
|
function CARGO_GROUP:onafterUnLoad( 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 )
|
|
local RandomVec2=nil
|
|
if ToPointVec2 then
|
|
RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(20, 10)
|
|
end
|
|
Cargo:UnBoard( RandomVec2 )
|
|
end
|
|
)
|
|
|
|
end
|
|
|
|
self.CargoCarrier:RemoveCargo( self )
|
|
self.CargoCarrier = nil
|
|
|
|
end
|
|
|
|
|
|
--- Get the current Coordinate of the CargoGroup.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return Core.Point#COORDINATE The current Coordinate of the first Cargo of the CargoGroup.
|
|
-- @return #nil There is no valid Cargo in the CargoGroup.
|
|
function CARGO_GROUP:GetCoordinate()
|
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
return Cargo.CargoObject:GetCoordinate()
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Get the x position of the cargo.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #number
|
|
function CARGO:GetX()
|
|
|
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
return Cargo:GetCoordinate().x
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Get the y position of the cargo.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #number
|
|
function CARGO:GetY()
|
|
|
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
return Cargo:GetCoordinate().z
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
|
|
|
|
--- Check if the CargoGroup is alive.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #boolean true if the CargoGroup is alive.
|
|
-- @return #boolean false if the CargoGroup is dead.
|
|
function CARGO_GROUP:IsAlive()
|
|
|
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
return Cargo ~= nil
|
|
|
|
end
|
|
|
|
|
|
--- Get the first alive Cargo Unit of the Cargo Group.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #CARGO_GROUP
|
|
function CARGO_GROUP:GetFirstAlive()
|
|
|
|
local CargoFirstAlive = nil
|
|
|
|
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
|
if not Cargo:IsDestroyed() then
|
|
CargoFirstAlive = Cargo
|
|
break
|
|
end
|
|
end
|
|
return CargoFirstAlive
|
|
end
|
|
|
|
|
|
--- Get the amount of cargo units in the group.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #CARGO_GROUP
|
|
function CARGO_GROUP:GetCount()
|
|
return self.CargoSet:Count()
|
|
end
|
|
|
|
|
|
--- Get the amount of cargo units in the group.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #CARGO_GROUP
|
|
function CARGO_GROUP:GetGroup( Cargo )
|
|
local Cargo = Cargo or self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
return Cargo.CargoObject:GetGroup()
|
|
end
|
|
|
|
|
|
--- Route Cargo to Coordinate and randomize locations.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Core.Point#COORDINATE Coordinate
|
|
function CARGO_GROUP:RouteTo( Coordinate )
|
|
--self:F( {Coordinate = Coordinate } )
|
|
|
|
-- For each Cargo within the CargoSet, route each object to the Coordinate
|
|
self.CargoSet:ForEach(
|
|
function( Cargo )
|
|
Cargo.CargoObject:RouteGroundTo( Coordinate, 10, "vee", 0 )
|
|
end
|
|
)
|
|
|
|
end
|
|
|
|
--- Check if Cargo is near to the Carrier.
|
|
-- The Cargo is near to the Carrier if the first unit of the Cargo Group is within NearRadius.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Wrapper.Group#GROUP CargoCarrier
|
|
-- @param #number NearRadius
|
|
-- @return #boolean The Cargo is near to the Carrier or #nil if the Cargo is not near to the Carrier.
|
|
function CARGO_GROUP:IsNear( CargoCarrier, NearRadius )
|
|
self:F( {NearRadius = NearRadius } )
|
|
|
|
for _, Cargo in pairs( self.CargoSet:GetSet() ) do
|
|
local Cargo = Cargo -- Cargo.Cargo#CARGO
|
|
if Cargo:IsAlive() then
|
|
if Cargo:IsNear( CargoCarrier:GetCoordinate(), NearRadius ) then
|
|
self:F( "Near" )
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return nil
|
|
end
|
|
|
|
--- Check if Cargo Group is in the radius for the Cargo to be Boarded.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Core.Point#COORDINATE Coordinate
|
|
-- @return #boolean true if the Cargo Group is within the load radius.
|
|
function CARGO_GROUP:IsInLoadRadius( Coordinate )
|
|
--self:F( { Coordinate } )
|
|
|
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
local Distance = 0
|
|
local CargoCoordinate
|
|
if Cargo:IsLoaded() then
|
|
CargoCoordinate = Cargo.CargoCarrier:GetCoordinate()
|
|
else
|
|
CargoCoordinate = Cargo.CargoObject:GetCoordinate()
|
|
end
|
|
|
|
-- FF check if coordinate could be obtained. This was commented out for some (unknown) reason. But the check seems valid!
|
|
if CargoCoordinate then
|
|
Distance = Coordinate:Get2DDistance( CargoCoordinate )
|
|
else
|
|
return false
|
|
end
|
|
|
|
self:F( { Distance = Distance, LoadRadius = self.LoadRadius } )
|
|
if Distance <= self.LoadRadius then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
--- Check if Cargo Group is in the report radius.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Core.Point#Coordinate Coordinate
|
|
-- @return #boolean true if the Cargo Group is within the report radius.
|
|
function CARGO_GROUP:IsInReportRadius( Coordinate )
|
|
--self:F( { Coordinate } )
|
|
|
|
local Cargo = self:GetFirstAlive() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
self:F( { Cargo } )
|
|
local Distance = 0
|
|
if Cargo:IsUnLoaded() then
|
|
Distance = Coordinate:Get2DDistance( Cargo.CargoObject:GetCoordinate() )
|
|
--self:T( Distance )
|
|
if Distance <= self.LoadRadius then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
|
|
--- Signal a flare at the position of the CargoGroup.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Utilities.Utils#FLARECOLOR FlareColor
|
|
function CARGO_GROUP:Flare( FlareColor )
|
|
|
|
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
|
if Cargo then
|
|
Cargo:Flare( FlareColor )
|
|
end
|
|
end
|
|
|
|
--- Smoke the CargoGroup.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Utilities.Utils#SMOKECOLOR SmokeColor The color of the smoke.
|
|
-- @param #number Radius The radius of randomization around the center of the first element of the CargoGroup.
|
|
function CARGO_GROUP:Smoke( SmokeColor, Radius )
|
|
|
|
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
Cargo:Smoke( SmokeColor, Radius )
|
|
end
|
|
end
|
|
|
|
--- Check if the first element of the CargoGroup is the given @{Core.Zone}.
|
|
-- @param #CARGO_GROUP self
|
|
-- @param Core.Zone#ZONE_BASE Zone
|
|
-- @return #boolean **true** if the first element of the CargoGroup is in the Zone
|
|
-- @return #boolean **false** if there is no element of the CargoGroup in the Zone.
|
|
function CARGO_GROUP:IsInZone( Zone )
|
|
--self:F( { Zone } )
|
|
|
|
local Cargo = self.CargoSet:GetFirst() -- Cargo.Cargo#CARGO
|
|
|
|
if Cargo then
|
|
return Cargo:IsInZone( Zone )
|
|
end
|
|
|
|
return nil
|
|
|
|
end
|
|
|
|
--- Get the transportation method of the Cargo.
|
|
-- @param #CARGO_GROUP self
|
|
-- @return #string The transportation method of the Cargo.
|
|
function CARGO_GROUP:GetTransportationMethod()
|
|
if self:IsLoaded() then
|
|
return "for unboarding"
|
|
else
|
|
if self:IsUnLoaded() then
|
|
return "for boarding"
|
|
else
|
|
if self:IsDeployed() then
|
|
return "delivered"
|
|
end
|
|
end
|
|
end
|
|
return ""
|
|
end
|
|
|
|
|
|
|
|
end -- CARGO_GROUP
|