From 25777afdd188793696380ccfccefcc02cfa13243 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Wed, 29 Aug 2018 19:23:46 +0200 Subject: [PATCH 1/2] - Now the cargo is sorted from large to small for dispatching. - The carrier which has a unit that fits the group size, will be routed towards that cargo. - When boarding, the carrier(s) will then be boarded with any cargo group that is available that fits the remaining cargo bays. --- Moose Development/Moose/AI/AI_Cargo_APC.lua | 5 +++-- .../Moose/AI/AI_Cargo_Dispatcher.lua | 22 +++++++++++++++---- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index 466803656..19e674583 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -420,7 +420,8 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To ) self.APC_Cargo = {} for _, APCUnit in pairs( APC:GetUnits() ) do local APCUnit = APCUnit -- Wrapper.Unit#UNIT - for _, Cargo in pairs( self.CargoSet:GetSet() ) do + --for _, Cargo in pairs( self.CargoSet:GetSet() ) do + for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do local Cargo = Cargo -- Cargo.Cargo#CARGO self:F( { IsUnLoaded = Cargo:IsUnLoaded(), IsDeployed = Cargo:IsDeployed(), Cargo:GetName(), APC:GetName() } ) if Cargo:IsUnLoaded() then -- and not Cargo:IsDeployed() then @@ -472,7 +473,7 @@ function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo ) else for _, APCUnit in pairs( APC:GetUnits() ) do local APCUnit = APCUnit -- Wrapper.Unit#UNIT - for _, Cargo in pairs( self.CargoSet:GetSet() ) do + for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do local Cargo = Cargo -- Cargo.Cargo#CARGO if Cargo:IsUnLoaded() then if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then diff --git a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua index 602868607..71359203b 100644 --- a/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua +++ b/Moose Development/Moose/AI/AI_Cargo_Dispatcher.lua @@ -411,7 +411,7 @@ function AI_CARGO_DISPATCHER:onafterMonitor() local PickupCargo = nil - for CargoName, Cargo in pairs( self.SetCargo:GetSet() ) do + for CargoName, Cargo in UTILS.spairs( self.SetCargo:GetSet(), function( t, a, b ) return t[a]:GetWeight() < t[b]:GetWeight() end ) do local Cargo = Cargo -- Cargo.Cargo#CARGO self:F( { Cargo = Cargo:GetName(), UnLoaded = Cargo:IsUnLoaded(), Deployed = Cargo:IsDeployed(), PickupCargo = self.PickupCargo[Carrier] ~= nil } ) if Cargo:IsUnLoaded() == true and Cargo:IsDeployed() == false then @@ -428,9 +428,23 @@ function AI_CARGO_DISPATCHER:onafterMonitor() end end if CoordinateFree == true then - self.PickupCargo[Carrier] = CargoCoordinate - PickupCargo = Cargo - break + -- Check if this cargo can be picked-up by at least one carrier unit of AI_Cargo. + local LargestLoadCapacity = 0 + for _, Carrier in pairs( Carrier:GetUnits() ) do + local LoadCapacity = Carrier:GetCargoBayFreeWeight() + if LargestLoadCapacity < LoadCapacity then + LargestLoadCapacity = LoadCapacity + 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. + -- Otherwise break and go to the next carrier. + -- This will skip cargo which is too large to be able to be loaded by carriers + -- and will secure an efficient dispatching scheme. + if LargestLoadCapacity >= Cargo:GetWeight() then + self.PickupCargo[Carrier] = CargoCoordinate + PickupCargo = Cargo + break + end end end end From 42b04dedaaf667a633d71a6a31596a3aaea29d33 Mon Sep 17 00:00:00 2001 From: FlightControl Date: Thu, 30 Aug 2018 06:07:26 +0200 Subject: [PATCH 2/2] Optimized boarding logic. Now it works correct. Adjust speed at the end to ensure that vehicles park closer to the cargo when carriers are in formation. --- Moose Development/Moose/AI/AI_Cargo_APC.lua | 57 ++++++++++--------- .../Moose/Wrapper/Controllable.lua | 2 + 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/Moose Development/Moose/AI/AI_Cargo_APC.lua b/Moose Development/Moose/AI/AI_Cargo_APC.lua index 19e674583..73a94800d 100644 --- a/Moose Development/Moose/AI/AI_Cargo_APC.lua +++ b/Moose Development/Moose/AI/AI_Cargo_APC.lua @@ -418,8 +418,12 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To ) if APC and APC:IsAlive() then self.APC_Cargo = {} + self.APC_Cargo_Weight = {} for _, APCUnit in pairs( APC:GetUnits() ) do local APCUnit = APCUnit -- Wrapper.Unit#UNIT + + self.APC_Cargo_Weight[APCUnit] = APCUnit:GetCargoBayFreeWeight() + --for _, Cargo in pairs( self.CargoSet:GetSet() ) do for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do local Cargo = Cargo -- Cargo.Cargo#CARGO @@ -428,7 +432,7 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To ) if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then self:F( { "In radius", APCUnit:GetName() } ) - local CargoBayFreeWeight = APCUnit:GetCargoBayFreeWeight() + local CargoBayFreeWeight = self.APC_Cargo_Weight[APCUnit] local CargoWeight = Cargo:GetWeight() self:F({CargoBayFreeWeight=CargoBayFreeWeight}) @@ -438,11 +442,12 @@ function AI_CARGO_APC:onbeforeLoad( APC, From, Event, To ) APC:RouteStop() --Cargo:Ungroup() Cargo:Board( APCUnit, 25 ) - self:__Board( 1, Cargo ) + self:__Board( 1, Cargo, APCUnit ) -- So now this APCUnit has Cargo that is being loaded. -- This will be used further in the logic to follow and to check cargo status. self.APC_Cargo[APCUnit] = Cargo + self.APC_Cargo_Weight[APCUnit] = self.APC_Cargo_Weight[APCUnit] - CargoWeight Boarding = true break end @@ -462,35 +467,34 @@ end -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. --- @param #string Cargo.Cargo#CARGO Cargo Cargo object. -function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo ) - self:F( { APC, From, Event, To, Cargo } ) +-- @param Cargo.Cargo#CARGO Cargo Cargo object. +-- @param Wrapper.Unit#UNIT APCUnit +function AI_CARGO_APC:onafterBoard( APC, From, Event, To, Cargo, APCUnit ) + self:F( { APC, From, Event, To, Cargo, APCUnit:GetName() } ) if APC and APC:IsAlive() then self:F({ IsLoaded = Cargo:IsLoaded(), Cargo:GetName(), APC:GetName() } ) if not Cargo:IsLoaded() then - self:__Board( 10, Cargo ) + self:__Board( 10, Cargo, APCUnit ) else - for _, APCUnit in pairs( APC:GetUnits() ) do - local APCUnit = APCUnit -- Wrapper.Unit#UNIT - for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do - local Cargo = Cargo -- Cargo.Cargo#CARGO - if Cargo:IsUnLoaded() then - if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then - local CargoBayFreeWeight = APCUnit:GetCargoBayFreeWeight() - local CargoWeight = Cargo:GetWeight() - - self:F({CargoBayFreeWeight=CargoBayFreeWeight}) + for _, Cargo in UTILS.spairs( self.CargoSet:GetSet(), function( t, a, b ) return t[a]:GetWeight() > t[b]:GetWeight() end ) do + local Cargo = Cargo -- Cargo.Cargo#CARGO + if Cargo:IsUnLoaded() then + if Cargo:IsInLoadRadius( APCUnit:GetCoordinate() ) then + local CargoBayFreeWeight = self.APC_Cargo_Weight[APCUnit] + 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 --and CargoBayFreeVolume > CargoVolume then - Cargo:Board( APCUnit, 25 ) - self:__Board( 10, Cargo ) - -- So now this APCUnit has Cargo that is being loaded. - -- This will be used further in the logic to follow and to check cargo status. - self.APC_Cargo[APCUnit] = Cargo - return - end + -- Only when there is space within the bay to load the next cargo item! + if CargoBayFreeWeight > CargoWeight then --and CargoBayFreeVolume > CargoVolume then + Cargo:Board( APCUnit, 25 ) + self:__Board( 10, Cargo, APCUnit ) + -- So now this APCUnit has Cargo that is being loaded. + -- This will be used further in the logic to follow and to check cargo status. + self.APC_Cargo[APCUnit] = Cargo + self.APC_Cargo_Weight[APCUnit] = self.APC_Cargo_Weight[APCUnit] - CargoWeight + return end end end @@ -552,6 +556,7 @@ function AI_CARGO_APC:onafterUnload( APC, From, Event, To, Deployed ) for _, Cargo in pairs( APCUnit:GetCargo() ) do if Cargo:IsLoaded() then Cargo:UnBoard() + Cargo:SetDeployed( true ) self:__Unboard( 10, Cargo, Deployed ) end end @@ -580,6 +585,7 @@ function AI_CARGO_APC:onafterUnboard( APC, From, Event, To, Cargo, Deployed ) for _, Cargo in pairs( APCUnit:GetCargo() ) do if Cargo:IsLoaded() then Cargo:UnBoard() + Cargo:SetDeployed( true ) self:__Unboard( 10, Cargo, Deployed ) return end @@ -604,7 +610,6 @@ function AI_CARGO_APC:onbeforeUnloaded( APC, From, Event, To, Cargo, Deployed ) self:F( { APC, From, Event, To, Cargo:GetName(), Deployed = Deployed } ) local AllUnloaded = true - Cargo:SetDeployed( true ) --Cargo:Regroup() diff --git a/Moose Development/Moose/Wrapper/Controllable.lua b/Moose Development/Moose/Wrapper/Controllable.lua index 84c25a1f4..a6f83c5c0 100644 --- a/Moose Development/Moose/Wrapper/Controllable.lua +++ b/Moose Development/Moose/Wrapper/Controllable.lua @@ -2062,6 +2062,8 @@ do -- Route methods local dist=ToCoordinate:Get2DDistance(PathOnRoad[#PathOnRoad-1]) if dist>10 then table.insert(route, ToCoordinate:WaypointGround(Speed, OffRoadFormation)) + table.insert(route, ToCoordinate:GetRandomCoordinateInRadius(10,5):WaypointGround(5, OffRoadFormation)) + table.insert(route, ToCoordinate:GetRandomCoordinateInRadius(10,5):WaypointGround(5, OffRoadFormation)) end end