New weight driven limits logic for cargo to load multiple cargo.

Fixed near range issue for carriers. now the infantry disappearance range for boarding is calculated by the carrier bounding range, which is derived from the bounding rectangle on the Y-axis. The near range parameter can still be provided and will be interpreted as the loading range for static cargo objects!
This commit is contained in:
FlightControl
2018-08-22 20:41:37 +02:00
parent 7a2dee4162
commit bf903c0cc7
8 changed files with 134 additions and 105 deletions

View File

@@ -197,42 +197,7 @@ function AI_CARGO_APC:New( APC, CargoSet, CombatRadius )
self:SetCarrier( APC ) self:SetCarrier( APC )
for _, APCUnit in pairs( APC:GetUnits() ) do for _, APCUnit in pairs( APC:GetUnits() ) do
local Desc = APCUnit:GetDesc() APCUnit:SetCargoBayWeightLimit()
local VolumeUnit = ( Desc.box.max.x - Desc.box.min.x ) * ( Desc.box.max.y - Desc.box.min.y ) * ( Desc.box.max.z - Desc.box.min.z )
local Weights = {
["M1126 Stryker ICV"] = 9,
["M-113"] = 9,
["AAV7"] = 25,
["M2A1_halftrack"] = 9,
["BMD-1"] = 9,
["BMP-1"] = 8,
["BMP-2"] = 7,
["BMP-3"] = 8,
["Boman"] = 25,
["BTR-80"] = 9,
["BTR_D"] = 12,
["Cobra"] = 8,
["LAV-25"] = 6,
["M-2 Bradley"] = 6,
["M1043 HMMWV Armament"] = 4,
["M1045 HMMWV TOW"] = 4,
["M1126 Stryker ICV"] = 9,
["M1134 Stryker ATGM"] = 9,
["Marder"] = 6,
["MCV-80"] = 9,
["MLRS FDDM"] = 4,
["MTLB"] = 25,
["TPZ"] = 10,
}
local CargoBayWeightLimit = ( Weights[Desc.typeName] or 0 ) * 70
APCUnit:SetCargoBayWeightLimit( CargoBayWeightLimit )
--Airplane:SetCargoBayVolumeLimit( 15 )
self:F( {TypeName = Desc.typeName, Desc = Desc, WeightLimit = CargoBayWeightLimit } )
end end
self.Transporting = false self.Transporting = false

View File

@@ -128,10 +128,7 @@ function AI_CARGO_AIRPLANE:New( Airplane, CargoSet )
-- Set carrier. -- Set carrier.
self:SetCarrier( Airplane ) self:SetCarrier( Airplane )
local Desc = Airplane:GetUnit(1):GetDesc() Airplane:SetCargoBayWeightLimit()
self:F({Desc=Desc})
Airplane:SetCargoBayWeightLimit( Desc.massMax - ( Desc.massEmpty + Desc.fuelMassMax ) )
--Airplane:SetCargoBayVolumeLimit( 15 )
self.Relocating = true self.Relocating = true

View File

@@ -146,9 +146,7 @@ function AI_CARGO_HELICOPTER:New( Helicopter, CargoSet )
) )
for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do for _, HelicopterUnit in pairs( Helicopter:GetUnits() ) do
local Desc = HelicopterUnit:GetDesc() HelicopterUnit:SetCargoBayWeightLimit()
self:F({Desc=Desc})
HelicopterUnit:SetCargoBayWeightLimit( Desc.massMax - ( Desc.massEmpty + Desc.fuelMassMax ) )
end end
self.Relocating = false self.Relocating = false

View File

@@ -811,7 +811,7 @@ do -- CARGO
end end
--- Check if CargoCarrier is near the Cargo to be Loaded. --- Check if CargoCarrier is near the coordinate within NearRadius.
-- @param #CARGO self -- @param #CARGO self
-- @param Core.Point#COORDINATE Coordinate -- @param Core.Point#COORDINATE Coordinate
-- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision). -- @param #number NearRadius The radius when the cargo will board the Carrier (to avoid collision).

View File

@@ -226,8 +226,6 @@ do -- CARGO_UNIT
function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... ) function CARGO_UNIT:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { From, Event, To, CargoCarrier, NearRadius } ) self:F( { From, Event, To, CargoCarrier, NearRadius } )
local NearRadius = NearRadius or 25
self.CargoInAir = self.CargoObject:InAir() self.CargoInAir = self.CargoObject:InAir()
local Desc = self.CargoObject:GetDesc() local Desc = self.CargoObject:GetDesc()
@@ -239,6 +237,9 @@ do -- CARGO_UNIT
-- Only move the group to the carrier when the cargo is not in the air -- Only move the group to the carrier when the cargo is not in the air
-- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea). -- (eg. cargo can be on a oil derrick, moving the cargo on the oil derrick will drop the cargo on the sea).
if not self.CargoInAir then if not self.CargoInAir then
-- If NearRadius is given, then use the given NearRadius, otherwise calculate the NearRadius
-- based upon the Carrier bounding radius, which is calculated from the bounding rectangle on the Y axis.
local NearRadius = CargoCarrier:GetBoundingRadius( NearRadius )
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
self:Load( CargoCarrier, NearRadius, ... ) self:Load( CargoCarrier, NearRadius, ... )
else else
@@ -250,8 +251,6 @@ do -- CARGO_UNIT
local Angle = 180 local Angle = 180
local Distance = 5 local Distance = 5
NearRadius = NearRadius or 25
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees. local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
@@ -302,8 +301,6 @@ do -- CARGO_UNIT
local Angle = 180 local Angle = 180
local Distance = 5 local Distance = 5
NearRadius = NearRadius or 25
local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2() local CargoCarrierPointVec2 = CargoCarrier:GetPointVec2()
local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees. local CargoCarrierHeading = CargoCarrier:GetHeading() -- Get Heading of object in degrees.
local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle ) local CargoDeployHeading = ( ( CargoCarrierHeading + Angle ) >= 360 ) and ( CargoCarrierHeading + Angle - 360 ) or ( CargoCarrierHeading + Angle )
@@ -349,8 +346,6 @@ do -- CARGO_UNIT
local Angle = 180 local Angle = 180
local Distance = 5 local Distance = 5
local NearRadius = NearRadius or 25
if From == "UnLoaded" or From == "Boarding" then if From == "UnLoaded" or From == "Boarding" then
end end

View File

@@ -589,6 +589,12 @@ do -- TASK_CARGO
Fsm:AddTransition( "Rejected", "Reject", "Aborted" ) Fsm:AddTransition( "Rejected", "Reject", "Aborted" )
Fsm:AddTransition( "Failed", "Fail", "Failed" ) Fsm:AddTransition( "Failed", "Fail", "Failed" )
for _, Group in pairs( SetGroup:GetSet() ) do
for __, Unit in pairs( Group:GetUnits() ) do
local Unit = Unit -- Wrapper.Unit#UNIT
Unit:SetCargoBayWeightLimit()
end
end
---- @param #FSM_PROCESS self ---- @param #FSM_PROCESS self
-- @param Wrapper.Unit#UNIT TaskUnit -- @param Wrapper.Unit#UNIT TaskUnit
@@ -610,7 +616,6 @@ do -- TASK_CARGO
local TaskUnitName = TaskUnit:GetName() local TaskUnitName = TaskUnit:GetName()
local MenuTime = Task:InitTaskControlMenu( TaskUnit ) local MenuTime = Task:InitTaskControlMenu( TaskUnit )
local MenuControl = Task:GetTaskControlMenu( TaskUnit ) local MenuControl = Task:GetTaskControlMenu( TaskUnit )
local CargoItemCount = TaskUnit:CargoItemCount()
Task.SetCargo:ForEachCargo( Task.SetCargo:ForEachCargo(
@@ -635,7 +640,13 @@ do -- TASK_CARGO
local TaskGroup = TaskUnit:GetGroup() local TaskGroup = TaskUnit:GetGroup()
if Cargo:IsUnLoaded() then if Cargo:IsUnLoaded() then
if CargoItemCount < 1 then local CargoBayFreeWeight = TaskUnit:GetCargoBayFreeWeight()
local CargoWeight = Cargo:GetWeight()
self:F({CargoBayFreeWeight=CargoBayFreeWeight})
-- Only when there is space within the bay to load the next cargo item!
if CargoBayFreeWeight > CargoWeight then
if Cargo:IsInReportRadius( TaskUnit:GetPointVec2() ) then if Cargo:IsInReportRadius( TaskUnit:GetPointVec2() ) then
local NotInDeployZones = true local NotInDeployZones = true
for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do for DeployZoneName, DeployZone in pairs( Task.DeployZones ) do

View File

@@ -243,7 +243,7 @@ end
--- Get the bounding box of the underlying POSITIONABLE DCS Object. --- Get the bounding box of the underlying POSITIONABLE DCS Object.
-- @param #POSITIONABLE self -- @param #POSITIONABLE self
-- @return DCS#Distance The bounding box of the POSITIONABLE. -- @return DCS#Box3 The bounding box of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive. -- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetBoundingBox() --R2.1 function POSITIONABLE:GetBoundingBox() --R2.1
self:F2() self:F2()
@@ -264,6 +264,29 @@ function POSITIONABLE:GetBoundingBox() --R2.1
end end
--- Get the bounding radius of the underlying POSITIONABLE DCS Object.
-- @param #POSITIONABLE self
-- @return DCS#Distance The bounding radius of the POSITIONABLE.
-- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetBoundingRadius()
self:F2()
local Box = self:GetBoundingBox()
if Box then
local X = Box.max.x - Box.min.x
local Z = Box.max.z - Box.min.z
local CX = X / 2
local CZ = Z / 2
return math.max( CX, CZ )
end
BASE:E( { "Cannot GetBoundingRadius", Positionable = self, Alive = self:IsAlive() } )
return nil
end
--- Returns the altitude of the POSITIONABLE. --- Returns the altitude of the POSITIONABLE.
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @return DCS#Distance The altitude of the POSITIONABLE. -- @return DCS#Distance The altitude of the POSITIONABLE.
@@ -323,7 +346,7 @@ end
--- Returns the POSITIONABLE heading in degrees. --- Returns the POSITIONABLE heading in degrees.
-- @param Wrapper.Positionable#POSITIONABLE self -- @param Wrapper.Positionable#POSITIONABLE self
-- @return #number The POSTIONABLE heading -- @return #number The POSITIONABLE heading
-- @return #nil The POSITIONABLE is not existing or alive. -- @return #nil The POSITIONABLE is not existing or alive.
function POSITIONABLE:GetHeading() function POSITIONABLE:GetHeading()
local DCSPositionable = self:GetDCSObject() local DCSPositionable = self:GetDCSObject()
@@ -347,6 +370,52 @@ function POSITIONABLE:GetHeading()
return nil return nil
end end
-- Is Methods
--- Returns if the unit is of an air category.
-- If the unit is a helicopter or a plane, then this method will return true, otherwise false.
-- @param #POSITIONABLE self
-- @return #boolean Air category evaluation result.
function POSITIONABLE:IsAir()
self:F2()
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local UnitDescriptor = DCSUnit:getDesc()
self:T3( { UnitDescriptor.category, Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
local IsAirResult = ( UnitDescriptor.category == Unit.Category.AIRPLANE ) or ( UnitDescriptor.category == Unit.Category.HELICOPTER )
self:T3( IsAirResult )
return IsAirResult
end
return nil
end
--- Returns if the unit is of an ground category.
-- If the unit is a ground vehicle or infantry, this method will return true, otherwise false.
-- @param #POSITIONABLE self
-- @return #boolean Ground category evaluation result.
function POSITIONABLE:IsGround()
self:F2()
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local UnitDescriptor = DCSUnit:getDesc()
self:T3( { UnitDescriptor.category, Unit.Category.GROUND_UNIT } )
local IsGroundResult = ( UnitDescriptor.category == Unit.Category.GROUND_UNIT )
self:T3( IsGroundResult )
return IsGroundResult
end
return nil
end
--- Returns true if the POSITIONABLE is in the air. --- Returns true if the POSITIONABLE is in the air.
-- Polymorphic, is overridden in GROUP and UNIT. -- Polymorphic, is overridden in GROUP and UNIT.
@@ -895,12 +964,50 @@ do -- Cargo
-- @param #POSITIONABLE self -- @param #POSITIONABLE self
-- @param #number WeightLimit -- @param #number WeightLimit
function POSITIONABLE:SetCargoBayWeightLimit( WeightLimit ) function POSITIONABLE:SetCargoBayWeightLimit( WeightLimit )
self.__.CargoBayWeightLimit = WeightLimit if WeightLimit then
end self.__.CargoBayWeightLimit = WeightLimit
else
-- If weightlimit is not provided, we will calculate it depending on the type of unit.
-- When an airplane or helicopter, we calculate the weightlimit based on the descriptor.
if self:IsAir() then
local Desc = self:GetDesc()
self:F({Desc=Desc})
self.__.CargoBayWeightLimit = Desc.massMax - ( Desc.massEmpty + Desc.fuelMassMax )
else
local Desc = self:GetDesc()
local Weights = {
["M1126 Stryker ICV"] = 9,
["M-113"] = 9,
["AAV7"] = 25,
["M2A1_halftrack"] = 9,
["BMD-1"] = 9,
["BMP-1"] = 8,
["BMP-2"] = 7,
["BMP-3"] = 8,
["Boman"] = 25,
["BTR-80"] = 9,
["BTR_D"] = 12,
["Cobra"] = 8,
["LAV-25"] = 6,
["M-2 Bradley"] = 6,
["M1043 HMMWV Armament"] = 4,
["M1045 HMMWV TOW"] = 4,
["M1126 Stryker ICV"] = 9,
["M1134 Stryker ATGM"] = 9,
["Marder"] = 6,
["MCV-80"] = 9,
["MLRS FDDM"] = 4,
["MTLB"] = 25,
["TPZ"] = 10,
}
local CargoBayWeightLimit = ( Weights[Desc.typeName] or 0 ) * 70
self.__.CargoBayWeightLimit = CargoBayWeightLimit
end
end
end
end --- Cargo end --- Cargo
--- Signal a flare at the position of the POSITIONABLE. --- Signal a flare at the position of the POSITIONABLE.

View File

@@ -854,51 +854,7 @@ end
-- Is methods
--- Returns if the unit is of an air category.
-- If the unit is a helicopter or a plane, then this method will return true, otherwise false.
-- @param #UNIT self
-- @return #boolean Air category evaluation result.
function UNIT:IsAir()
self:F2()
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local UnitDescriptor = DCSUnit:getDesc()
self:T3( { UnitDescriptor.category, Unit.Category.AIRPLANE, Unit.Category.HELICOPTER } )
local IsAirResult = ( UnitDescriptor.category == Unit.Category.AIRPLANE ) or ( UnitDescriptor.category == Unit.Category.HELICOPTER )
self:T3( IsAirResult )
return IsAirResult
end
return nil
end
--- Returns if the unit is of an ground category.
-- If the unit is a ground vehicle or infantry, this method will return true, otherwise false.
-- @param #UNIT self
-- @return #boolean Ground category evaluation result.
function UNIT:IsGround()
self:F2()
local DCSUnit = self:GetDCSObject()
if DCSUnit then
local UnitDescriptor = DCSUnit:getDesc()
self:T3( { UnitDescriptor.category, Unit.Category.GROUND_UNIT } )
local IsGroundResult = ( UnitDescriptor.category == Unit.Category.GROUND_UNIT )
self:T3( IsGroundResult )
return IsGroundResult
end
return nil
end
--- Returns if the unit is a friendly unit. --- Returns if the unit is a friendly unit.
-- @param #UNIT self -- @param #UNIT self