Optimized the boarding and unboarding of cargo. fixed bug when in defence of APC, cargo would not be loaded. The boarding and unboarding has become much more stable now.

This commit is contained in:
FlightControl 2018-10-18 07:27:09 +02:00
parent 3c1547bd6c
commit 07d666b030
7 changed files with 187 additions and 151 deletions

View File

@ -307,7 +307,7 @@ function AI_CARGO:onafterBoard( Carrier, From, Event, To, Cargo, CarrierUnit, Pi
if Carrier and Carrier:IsAlive() then if Carrier and Carrier:IsAlive() then
self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } ) self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), Carrier:GetName() } )
if not Cargo:IsLoaded() then if not Cargo:IsLoaded() and not Cargo:IsDestroyed() then
self:__Board( -10, Cargo, CarrierUnit, PickupZone ) self:__Board( -10, Cargo, CarrierUnit, PickupZone )
return return
end end
@ -487,6 +487,7 @@ function AI_CARGO:onafterDeployed( Carrier, From, Event, To, DeployZone, Defend
self.Transporting = false self.Transporting = false
else else
self:F( "Defending" ) self:F( "Defending" )
end end
end end

View File

@ -276,9 +276,10 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
if self.CarrierCoordinate then if self.CarrierCoordinate then
if self:IsTransporting() == true then if self:IsTransporting() == true then
local Coordinate = APC:GetCoordinate() local Coordinate = APC:GetCoordinate()
if self:Is( "Unloaded" ) or self:Is( "Loaded" ) then
self.Zone:Scan( { Object.Category.UNIT } ) self.Zone:Scan( { Object.Category.UNIT } )
if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then if self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then
if self:Is( "Unloaded" ) or self:Is( "Following" ) then if self:Is( "Unloaded" ) then
-- There are no enemies within combat radius. Load the CargoCarrier. -- There are no enemies within combat radius. Load the CargoCarrier.
self:Load() self:Load()
end end
@ -288,7 +289,7 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
self:__Unload( 1, nil, true ) -- The 2nd parameter is true, which means that the unload is for defending the carrier, not to deploy! self:__Unload( 1, nil, true ) -- The 2nd parameter is true, which means that the unload is for defending the carrier, not to deploy!
else else
if self:Is( "Unloaded" ) then if self:Is( "Unloaded" ) then
self:Follow() --self:Follow()
end end
self:F( "I am here" .. self:GetCurrentState() ) self:F( "I am here" .. self:GetCurrentState() )
if self:Is( "Following" ) then if self:Is( "Following" ) then
@ -313,6 +314,7 @@ function AI_CARGO_APC:onafterMonitor( APC, From, Event, To )
end end
end end
end end
end
end end
self.CarrierCoordinate = APC:GetCoordinate() self.CarrierCoordinate = APC:GetCoordinate()
@ -456,6 +458,30 @@ function AI_CARGO_APC:onafterDeployed( APC, From, Event, To, DeployZone, Defend
self:GetParent( self, AI_CARGO_APC ).onafterDeployed( self, APC, From, Event, To, DeployZone, Defend ) self:GetParent( self, AI_CARGO_APC ).onafterDeployed( self, APC, From, Event, To, DeployZone, Defend )
-- If Defend == true then we need to scan for possible enemies within combat zone and engage only ground forces.
if Defend == true then
self.Zone:Scan( { Object.Category.UNIT } )
if not self.Zone:IsAllInZoneOfCoalition( self.Coalition ) then
-- OK, enemies nearby, now find the enemies and attack them.
local AttackUnits = self.Zone:GetScannedUnits() -- #list<DCS#Unit>
local Move = {}
for CargoId, CargoData in pairs( self.CargoSet:GetSet() ) do
local CargoGroup = CargoData.CargoObject -- Wrapper.Group#GROUP
Move[#Move+1] = CargoGroup:GetCoordinate():WaypointGround( 70, "Custom" )
for UnitId, AttackUnit in pairs( AttackUnits ) do
local MooseUnit = UNIT:Find( AttackUnit )
if MooseUnit:GetCoalition() ~= CargoGroup:GetCoalition() then
Move[#Move+1] = MooseUnit:GetCoordinate():WaypointGround( 70, "Line abreast" )
--MoveTo.Task = CargoGroup:TaskCombo( CargoGroup:TaskAttackUnit( MooseUnit, true ) )
self:F( { MooseUnit = MooseUnit:GetName(), CargoGroup = CargoGroup:GetName() } )
end
end
CargoGroup:RoutePush( Move, 0.1 )
end
end
end
end end

View File

@ -1143,7 +1143,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor()
LargestLoadCapacity = LoadCapacity LargestLoadCapacity = LoadCapacity
end end
end end
-- So if there is aa carrier that has the required load capacity to load the total weight of the cargo, dispatch the carrier. -- So if there is a carrier that has the required load capacity to load the total weight of the cargo, dispatch the carrier.
-- Otherwise break and go to the next carrier. -- Otherwise break and go to the next carrier.
-- This will skip cargo which is too large to be able to be loaded by carriers -- This will skip cargo which is too large to be able to be loaded by carriers
-- and will secure an efficient dispatching scheme. -- and will secure an efficient dispatching scheme.

View File

@ -20,9 +20,9 @@
do -- CARGO_GROUP do -- CARGO_GROUP
--- @type CARGO_GROUP --- @type CARGO_GROUP
-- @extends Cargo.Cargo#CARGO_REPORTABLE
-- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects. -- @field Core.Set#SET_CARGO CargoSet The collection of derived CARGO objects.
-- @field #string GroupName The name of the CargoGroup. -- @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. --- 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 cargo can be Loaded, UnLoaded, Boarded, UnBoarded to and from Carriers.
@ -291,29 +291,27 @@ do -- CARGO_GROUP
end end
--- Enter Boarding State. --- After Board Event.
-- @param #CARGO_GROUP self -- @param #CARGO_GROUP self
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier -- @param Wrapper.Unit#UNIT CargoCarrier
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
function CARGO_GROUP:onenterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) function CARGO_GROUP:onafterBoard( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } ) self:F( { CargoCarrier.UnitName, From, Event, To, NearRadius = NearRadius } )
NearRadius = NearRadius or self.NearRadius NearRadius = NearRadius or self.NearRadius
if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2 -- For each Cargo object within the CARGO_GROUPED, route each object to the CargoLoadPointVec2
self.CargoSet:ForEach( self.CargoSet:ForEach(
function( Cargo, ... ) function( Cargo, ... )
self:F( { "Board Unit", Cargo:GetName( ), Cargo:IsDestroyed(), Cargo.CargoObject:IsAlive() } )
Cargo:__Board( 1, CargoCarrier, NearRadius, ... ) Cargo:__Board( 1, CargoCarrier, NearRadius, ... )
end, ... end, ...
) )
self:__Boarding( 1, CargoCarrier, NearRadius, ... ) self:__Boarding( -1, CargoCarrier, NearRadius, ... )
end
end end
@ -323,15 +321,17 @@ do -- CARGO_GROUP
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Wrapper.Unit#UNIT CargoCarrier -- @param Wrapper.Unit#UNIT CargoCarrier
function CARGO_GROUP:onenterLoaded( From, Event, To, CargoCarrier, ... ) function CARGO_GROUP:onafterLoad( From, Event, To, CargoCarrier, ... )
--self:F( { From, Event, To, CargoCarrier, ...} ) --self:F( { From, Event, To, CargoCarrier, ...} )
if From == "UnLoaded" then if From == "UnLoaded" then
-- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier. -- For each Cargo object within the CARGO_GROUP, load each cargo to the CargoCarrier.
for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do for CargoID, Cargo in pairs( self.CargoSet:GetSet() ) do
if not Cargo:IsDestroyed() then
Cargo:Load( CargoCarrier ) Cargo:Load( CargoCarrier )
end end
end end
end
--self.CargoObject:Destroy() --self.CargoObject:Destroy()
self.CargoCarrier = CargoCarrier self.CargoCarrier = CargoCarrier
@ -400,7 +400,7 @@ do -- CARGO_GROUP
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
function CARGO_GROUP:onenterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) function CARGO_GROUP:onafterUnBoard( From, Event, To, ToPointVec2, NearRadius, ... )
self:F( {From, Event, To, ToPointVec2, NearRadius } ) self:F( {From, Event, To, ToPointVec2, NearRadius } )
NearRadius = NearRadius or 25 NearRadius = NearRadius or 25
@ -443,7 +443,7 @@ do -- CARGO_GROUP
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 ToPointVec2 -- @param Core.Point#POINT_VEC2 ToPointVec2
-- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier. -- @param #number NearRadius If distance is smaller than this number, cargo is loaded into the carrier.
function CARGO_GROUP:onleaveUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... ) function CARGO_GROUP:onafterUnBoarding( From, Event, To, ToPointVec2, NearRadius, ... )
--self:F( { From, Event, To, ToPointVec2, NearRadius } ) --self:F( { From, Event, To, ToPointVec2, NearRadius } )
--local NearRadius = NearRadius or 25 --local NearRadius = NearRadius or 25
@ -464,7 +464,7 @@ do -- CARGO_GROUP
end end
if UnBoarded then if UnBoarded then
return true self:__UnLoad( 1, ToPointVec2, ... )
else else
self:__UnBoarding( 1, ToPointVec2, NearRadius, ... ) self:__UnBoarding( 1, ToPointVec2, NearRadius, ... )
end end
@ -474,30 +474,13 @@ do -- CARGO_GROUP
end end
--- UnBoard Event.
-- @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
self:__UnLoad( 1, ToPointVec2, ... )
end
--- Enter UnLoaded State. --- Enter UnLoaded State.
-- @param #CARGO_GROUP self -- @param #CARGO_GROUP self
-- @param #string Event -- @param #string Event
-- @param #string From -- @param #string From
-- @param #string To -- @param #string To
-- @param Core.Point#POINT_VEC2 -- @param Core.Point#POINT_VEC2
function CARGO_GROUP:onenterUnLoaded( From, Event, To, ToPointVec2, ... ) function CARGO_GROUP:onafterUnLoad( From, Event, To, ToPointVec2, ... )
--self:F( { From, Event, To, ToPointVec2 } ) --self:F( { From, Event, To, ToPointVec2 } )
if From == "Loaded" then if From == "Loaded" then
@ -507,7 +490,7 @@ do -- CARGO_GROUP
function( Cargo ) function( Cargo )
--Cargo:UnLoad( ToPointVec2 ) --Cargo:UnLoad( ToPointVec2 )
local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(20, 10) local RandomVec2=ToPointVec2:GetRandomPointVec2InRadius(20, 10)
Cargo:UnLoad( RandomVec2 ) Cargo:UnBoard( RandomVec2 )
end end
) )

View File

@ -233,6 +233,8 @@ do -- CARGO_UNIT
--self:F({Unit=self.CargoObject:GetName()}) --self:F({Unit=self.CargoObject:GetName()})
-- A cargo unit can only be boarded if it is not dead
-- 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
@ -272,7 +274,6 @@ do -- CARGO_UNIT
end end
end end
end end
end end
@ -286,19 +287,19 @@ do -- CARGO_UNIT
function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... ) function CARGO_UNIT:onafterBoarding( From, Event, To, CargoCarrier, NearRadius, ... )
self:F( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } ) self:F( { From, Event, To, CargoCarrier:GetName(), NearRadius = NearRadius } )
--self:F({Unit=self.CargoObject:GetName()}) self:F( { IsAlive=self.CargoObject:IsAlive() } )
if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then if CargoCarrier and CargoCarrier:IsAlive() then -- and self.CargoObject and self.CargoObject:IsAlive() then
if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then if (CargoCarrier:IsAir() and not CargoCarrier:InAir()) or true then
local NearRadius = NearRadius or CargoCarrier:GetBoundingRadius( NearRadius ) + 5 local NearRadius = NearRadius or CargoCarrier:GetBoundingRadius( NearRadius ) + 5
if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then if self:IsNear( CargoCarrier:GetPointVec2(), NearRadius ) then
self:__Load( 1, CargoCarrier, ... ) self:__Load( -1, CargoCarrier, ... )
else else
if self:IsNear( CargoCarrier:GetPointVec2(), 20 ) then if self:IsNear( CargoCarrier:GetPointVec2(), 20 ) then
self:__Boarding( 1, CargoCarrier, NearRadius, ... ) self:__Boarding( -1, CargoCarrier, NearRadius, ... )
self.RunCount = self.RunCount + 1 self.RunCount = self.RunCount + 1
else else
self:__Boarding( 2, CargoCarrier, NearRadius, ... ) self:__Boarding( -2, CargoCarrier, NearRadius, ... )
self.RunCount = self.RunCount + 2 self.RunCount = self.RunCount + 2
end end
if self.RunCount >= 40 then if self.RunCount >= 40 then

View File

@ -1975,6 +1975,24 @@ do -- Route methods
return nil return nil
end end
--- Make the controllable to push follow a given route.
-- @param #CONTROLLABLE self
-- @param #table Route A table of Route Points.
-- @param #number DelaySeconds (Optional) Wait for the specified seconds before executing the Route. Default is one second.
-- @return #CONTROLLABLE The CONTROLLABLE.
function CONTROLLABLE:RoutePush( Route, DelaySeconds )
self:F2( Route )
local DCSControllable = self:GetDCSObject()
if DCSControllable then
local RouteTask = self:TaskRoute( Route ) -- Create a RouteTask, that will route the CONTROLLABLE to the Route.
self:PushTask( RouteTask, DelaySeconds or 1 ) -- Execute the RouteTask after the specified seconds (default is 1).
return self
end
return nil
end
--- Stops the movement of the vehicle on the route. --- Stops the movement of the vehicle on the route.
-- @param #CONTROLLABLE self -- @param #CONTROLLABLE self

View File

@ -908,8 +908,10 @@ function UNIT:InAir()
-- Implementation of workaround. The original code is below. -- Implementation of workaround. The original code is below.
-- This to simulate the landing on buildings. -- This to simulate the landing on buildings.
-- local UnitInAir = DCSUnit:inAir()
local UnitInAir = true local UnitInAir = true
local UnitCategory = DCSUnit:getDesc().category
if UnitCategory == Unit.Category.HELICOPTER then
local VelocityVec3 = DCSUnit:getVelocity() local VelocityVec3 = DCSUnit:getVelocity()
local Velocity = ( VelocityVec3.x ^ 2 + VelocityVec3.y ^ 2 + VelocityVec3.z ^ 2 ) ^ 0.5 -- in meters / sec local Velocity = ( VelocityVec3.x ^ 2 + VelocityVec3.y ^ 2 + VelocityVec3.z ^ 2 ) ^ 0.5 -- in meters / sec
local Coordinate = DCSUnit:getPoint() local Coordinate = DCSUnit:getPoint()
@ -918,6 +920,11 @@ function UNIT:InAir()
if Velocity < 1 and Height <= 60 then if Velocity < 1 and Height <= 60 then
UnitInAir = false UnitInAir = false
end end
else
UnitInAir = DCSUnit:inAir()
end
self:T3( UnitInAir ) self:T3( UnitInAir )
return UnitInAir return UnitInAir
end end