OPSTRANSPORT

Storage
This commit is contained in:
Frank 2023-08-21 01:02:04 +02:00
parent 944ef6332b
commit f84e2ede66
2 changed files with 218 additions and 37 deletions

View File

@ -493,7 +493,9 @@ OPSGROUP.CargoStatus={
--- Cargo group data. --- Cargo group data.
-- @type OPSGROUP.CargoGroup -- @type OPSGROUP.CargoGroup
-- @field #string type Type of cargo: "OPSGROUP" or "STORAGE".
-- @field #OPSGROUP opsgroup The cargo opsgroup. -- @field #OPSGROUP opsgroup The cargo opsgroup.
-- @field Ops.OpsTransport#OPSTRANSPORT.Storage storage Storage data.
-- @field #boolean delivered If `true`, group was delivered. -- @field #boolean delivered If `true`, group was delivered.
-- @field #boolean disembarkActivation If `true`, group is activated. If `false`, group is late activated. -- @field #boolean disembarkActivation If `true`, group is activated. If `false`, group is late activated.
-- @field Core.Zone#ZONE disembarkZone Zone where this group is disembarked to. -- @field Core.Zone#ZONE disembarkZone Zone where this group is disembarked to.
@ -7993,13 +7995,17 @@ function OPSGROUP:_CheckCargoTransport()
text=text..string.format("\n[%d] UID=%d Status=%s: %s --> %s", i, transport.uid, transport:GetState(), pickupname, deployname) text=text..string.format("\n[%d] UID=%d Status=%s: %s --> %s", i, transport.uid, transport:GetState(), pickupname, deployname)
for j,_cargo in pairs(transport:GetCargos()) do for j,_cargo in pairs(transport:GetCargos()) do
local cargo=_cargo --#OPSGROUP.CargoGroup local cargo=_cargo --#OPSGROUP.CargoGroup
local state=cargo.opsgroup:GetState() if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local status=cargo.opsgroup.cargoStatus local state=cargo.opsgroup:GetState()
local name=cargo.opsgroup.groupname local status=cargo.opsgroup.cargoStatus
local carriergroup, carrierelement, reserved=cargo.opsgroup:_GetMyCarrier() local name=cargo.opsgroup.groupname
local carrierGroupname=carriergroup and carriergroup.groupname or "none" local carriergroup, carrierelement, reserved=cargo.opsgroup:_GetMyCarrier()
local carrierElementname=carrierelement and carrierelement.name or "none" local carrierGroupname=carriergroup and carriergroup.groupname or "none"
text=text..string.format("\n (%d) %s [%s]: %s, carrier=%s(%s), delivered=%s", j, name, state, status, carrierGroupname, carrierElementname, tostring(cargo.delivered)) local carrierElementname=carrierelement and carrierelement.name or "none"
text=text..string.format("\n (%d) %s [%s]: %s, carrier=%s(%s), delivered=%s", j, name, state, status, carrierGroupname, carrierElementname, tostring(cargo.delivered))
else
--TODO: STORAGE
end
end end
end end
if text~="" then if text~="" then
@ -8748,46 +8754,72 @@ end
--- Check if the group can *in principle* be carrier of a cargo group. This checks the max cargo capacity of the group but *not* how much cargo is already loaded (if any). --- Check if the group can *in principle* be carrier of a cargo group. This checks the max cargo capacity of the group but *not* how much cargo is already loaded (if any).
-- **Note** that the cargo group *cannot* be split into units, i.e. the largest cargo bay of any element of the group must be able to load the whole cargo group in one piece. -- **Note** that the cargo group *cannot* be split into units, i.e. the largest cargo bay of any element of the group must be able to load the whole cargo group in one piece.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @param #OPSGROUP CargoGroup Cargo group, which needs a carrier. -- @param Ops.OpsGroup#OPSGROUP.CargoGroup CargoGroup Cargo group, which needs a carrier.
-- @return #boolean If `true`, there is an element of the group that can load the whole cargo group. -- @return #boolean If `true`, there is an element of the group that can load the whole cargo group.
function OPSGROUP:CanCargo(CargoGroup) function OPSGROUP:CanCargo(Cargo)
if CargoGroup then if Cargo then
local weight=CargoGroup:GetWeightTotal() local weight=math.huge
if Cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
for _,_element in pairs(self.elements) do local weight=Cargo.opsgroup:GetWeightTotal()
local element=_element --#OPSGROUP.Element
-- Check that element is not dead and has for _,_element in pairs(self.elements) do
if element and element.status~=OPSGROUP.ElementStatus.DEAD and element.weightMaxCargo>=weight then local element=_element --#OPSGROUP.Element
-- Check that element is not dead and has
if element and element.status~=OPSGROUP.ElementStatus.DEAD and element.weightMaxCargo>=weight then
return true
end
end
else
if type(Cargo.storage.cargoType)=="number" then
weight=Cargo.storage.cargoAmount
else
weight=Cargo.storage.cargoAmount*100
end
local bay=0
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
-- Check that element is not dead and has
if element and element.status~=OPSGROUP.ElementStatus.DEAD then
bay=bay+element.weightMaxCargo
end
end
if bay>=weight then
return true return true
end end
end end
end end
return false return false
end end
--- Add weight to the internal cargo of an element of the group. --- Find carrier for cargo by evaluating the free cargo bay storage.
-- @param #OPSGROUP self -- @param #OPSGROUP self
-- @param #OPSGROUP CargoGroup Cargo group, which needs a carrier. -- @param #number Weight Weight of cargo in kg.
-- @return #OPSGROUP.Element Carrier able to transport the cargo. -- @return #OPSGROUP.Element Carrier able to transport the cargo.
function OPSGROUP:FindCarrierForCargo(CargoGroup) function OPSGROUP:FindCarrierForCargo(Weight)
local weight=CargoGroup:GetWeightTotal()
for _,_element in pairs(self.elements) do for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element local element=_element --#OPSGROUP.Element
local free=self:GetFreeCargobay(element.name) local free=self:GetFreeCargobay(element.name)
if free>=weight then if free>=Weight then
return element return element
else else
self:T3(self.lid..string.format("%s: Weight %d>%d free cargo bay", element.name, weight, free)) self:T3(self.lid..string.format("%s: Weight %d>%d free cargo bay", element.name, Weight, free))
end end
end end
@ -9097,14 +9129,14 @@ function OPSGROUP:onafterLoading(From, Event, To)
local isNotCargo=cargo.opsgroup:IsNotCargo(true) local isNotCargo=cargo.opsgroup:IsNotCargo(true)
-- Check if cargo is holding or loaded -- Check if cargo is holding or loaded
local isHolding=cargo.opsgroup:IsHolding() or cargo.opsgroup:IsLoaded() local isHolding=cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and (cargo.opsgroup:IsHolding() or cargo.opsgroup:IsLoaded()) or true
-- Check if cargo is in embark/pickup zone. -- Check if cargo is in embark/pickup zone.
-- Added InUtero here, if embark zone is moving (ship) and cargo has been spawned late activated and its position is not updated. Not sure if that breaks something else! -- Added InUtero here, if embark zone is moving (ship) and cargo has been spawned late activated and its position is not updated. Not sure if that breaks something else!
local inZone=cargo.opsgroup:IsInZone(self.cargoTZC.EmbarkZone) or cargo.opsgroup:IsInUtero() local inZone=cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and (cargo.opsgroup:IsInZone(self.cargoTZC.EmbarkZone) or cargo.opsgroup:IsInUtero()) or true
-- Check if cargo is currently on a mission. -- Check if cargo is currently on a mission.
local isOnMission=cargo.opsgroup:IsOnMission() local isOnMission=cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsOnMission() or false
-- Check if current mission is using this ops transport. -- Check if current mission is using this ops transport.
if isOnMission then if isOnMission then
@ -9114,12 +9146,29 @@ function OPSGROUP:onafterLoading(From, Event, To)
end end
end end
local isAvail=true
if cargo.type==OPSTRANSPORT.CargoType.STORAGE then
local nAvail=0
if type(cargo.storage.cargoType)=="number" then
nAvail=cargo.storage.storageFrom:GetLiquidAmount(cargo.storage.cargoType)
else
nAvail=cargo.storage.storageFrom:GetItemAmount(cargo.storage.cargoType)
end
if nAvail>0 then
isAvail=true
else
isAvail=false
end
end
local isDead=cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsDead() or false
-- Debug message. -- Debug message.
self:T(self.lid..string.format("Loading: canCargo=%s, isCarrier=%s, isNotCargo=%s, isHolding=%s, isOnMission=%s", self:T(self.lid..string.format("Loading: canCargo=%s, isCarrier=%s, isNotCargo=%s, isHolding=%s, isOnMission=%s",
tostring(canCargo), tostring(isCarrier), tostring(isNotCargo), tostring(isHolding), tostring(isOnMission))) tostring(canCargo), tostring(isCarrier), tostring(isNotCargo), tostring(isHolding), tostring(isOnMission)))
-- TODO: Need a better :IsBusy() function or :IsReadyForMission() :IsReadyForBoarding() :IsReadyForTransport() -- TODO: Need a better :IsBusy() function or :IsReadyForMission() :IsReadyForBoarding() :IsReadyForTransport()
if canCargo and inZone and isNotCargo and isHolding and (not (cargo.delivered or cargo.opsgroup:IsDead() or isCarrier or isOnMission)) then if canCargo and inZone and isNotCargo and isHolding and isAvail and (not (cargo.delivered or isDead or isCarrier or isOnMission)) then
table.insert(cargos, cargo) table.insert(cargos, cargo)
end end
end end
@ -9136,8 +9185,23 @@ function OPSGROUP:onafterLoading(From, Event, To)
for _,_cargo in pairs(cargos) do for _,_cargo in pairs(cargos) do
local cargo=_cargo --#OPSGROUP.CargoGroup local cargo=_cargo --#OPSGROUP.CargoGroup
local weight=nil
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
weight=cargo.opsgroup:GetWeightTotal()
else
if type(cargo.storage.cargoType)=="number" then
weight=cargo.storage.cargoAmount
else
weight=cargo.storage.cargoAmount*100 -- Assume 100 kg per item
end
end
-- Find a carrier for this cargo. -- Find a carrier for this cargo.
local carrier=self:FindCarrierForCargo(cargo.opsgroup) local carrier=self:FindCarrierForCargo(weight)
if carrier then if carrier then

View File

@ -186,6 +186,22 @@ OPSTRANSPORT.Status={
-- @field #number radius Radomization radius for waypoints in meters. Default 0 m. -- @field #number radius Radomization radius for waypoints in meters. Default 0 m.
-- @field #boolean reverse If `true`, path is used in reversed order. -- @field #boolean reverse If `true`, path is used in reversed order.
--- Storage data.
-- @type OPSTRANSPORT.Storage
-- @field Wrapper.Storage#STORAGE storageFrom Storage from.
-- @field Wrapper.Storage#STORAGE storageTo Storage To.
-- @field #string cargoType Type of cargo.
-- @field #number cargoAmount Amount of cargo. Liquids in kg.
--- Storage data.
-- @type OPSTRANSPORT.CargoType
-- @field #string OPSGROUP Cargo is an OPSGROUP.
-- @field #string STORAGE Cargo is storage of DCS warehouse.
OPSTRANSPORT.CargoType={
OPSGROUP="OPSGROUP",
STORAGE="STORAGE",
}
--- Generic transport condition. --- Generic transport condition.
-- @type OPSTRANSPORT.Condition -- @type OPSTRANSPORT.Condition
-- @field #function func Callback function to check for a condition. Should return a #boolean. -- @field #function func Callback function to check for a condition. Should return a #boolean.
@ -576,6 +592,27 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo, DisembarkActi
return self return self
end end
--- Add cargo groups to be transported.
-- @param #OPSTRANSPORT self
-- @param Wrapper.Storage#STORAGE StorageFrom Storage from.
-- @param Wrapper.Storage#STORAGE StorageTo Storage to.
-- @param #string CargoType Type of cargo.
-- @param #number CargoAmount Amount of cargo. Liquids in kg.
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
-- @return #OPSTRANSPORT self
function OPSTRANSPORT:AddCargoStorage(StorageFrom, StorageTo, CargoType, CargoAmount, TransportZoneCombo)
-- Use default TZC if no transport zone combo is provided.
TransportZoneCombo=TransportZoneCombo or self.tzcDefault
-- Cargo data.
local cargo=self:_CreateCargoStorage(StorageFrom,StorageTo, CargoType, CargoAmount, TransportZoneCombo)
-- Add to TZC table.
table.insert(TransportZoneCombo.Cargos, cargo)
end
--- Set pickup zone. --- Set pickup zone.
-- @param #OPSTRANSPORT self -- @param #OPSTRANSPORT self
@ -1068,7 +1105,7 @@ function OPSTRANSPORT:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
local opsgroups={} local opsgroups={}
for _,_cargo in pairs(cargos) do for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if Delivered==nil or cargo.delivered==Delivered then if cargo.type=="OPSGROUP" and (Delivered==nil or cargo.delivered==Delivered) then
if cargo.opsgroup and not (cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then if cargo.opsgroup and not (cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then
if Carrier==nil or Carrier:CanCargo(cargo.opsgroup) then if Carrier==nil or Carrier:CanCargo(cargo.opsgroup) then
table.insert(opsgroups, cargo.opsgroup) table.insert(opsgroups, cargo.opsgroup)
@ -1080,6 +1117,29 @@ function OPSTRANSPORT:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
return opsgroups return opsgroups
end end
--- Get (all) cargo @{Ops.OpsGroup#OPSGROUP}s. Optionally, only delivered or undelivered groups can be returned.
-- @param #OPSTRANSPORT self
-- @param #boolean Delivered If `true`, only delivered groups are returned. If `false` only undelivered groups are returned. If `nil`, all groups are returned.
-- @param Ops.OpsGroup#OPSGROUP Carrier (Optional) Only count cargo groups that fit into the given carrier group. Current cargo is not a factor.
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
-- @return #table Cargo Ops groups. Can be and empty table `{}`.
function OPSTRANSPORT:GetCargoStorages(Delivered, Carrier, TransportZoneCombo)
local cargos=self:GetCargos(TransportZoneCombo)
local opsgroups={}
for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if cargo.type=="STORAGE" and (Delivered==nil or cargo.delivered==Delivered) then
if Carrier==nil or Carrier:CanCargo(cargo.opsgroup) then
table.insert(opsgroups, cargo.opsgroup)
end
end
end
return opsgroups
end
--- Get carriers. --- Get carriers.
-- @param #OPSTRANSPORT self -- @param #OPSTRANSPORT self
-- @return #table Carrier Ops groups. -- @return #table Carrier Ops groups.
@ -1108,6 +1168,28 @@ function OPSTRANSPORT:GetCargos(TransportZoneCombo)
end end
--- Get total weight.
-- @param #OPSTRANSPORT self
-- @param Ops.OpsGroup#OPSGROUP.CargoGroup Cargo Cargo data.
-- @param #boolean IncludeReserved Include reserved cargo.
-- @return #number Weight in kg.
function OPSTRANSPORT:GetCargoTotalWeight(Cargo, IncludeReserved)
local weight=0
if Cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
weight=Cargo.opsgroup:GetWeightTotal(nil, IncludeReserved)
else
if type(Cargo.storage.cargoType)=="number" then
return Cargo.storage.cargoAmount
else
return Cargo.storage.cargoAmount*100 -- Assume 100 kg per item
end
end
return weight
end
--- Set transport start and stop time. --- Set transport start and stop time.
-- @param #OPSTRANSPORT self -- @param #OPSTRANSPORT self
-- @param #string ClockStart Time the transport is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added. -- @param #string ClockStart Time the transport is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added.
@ -1642,11 +1724,15 @@ function OPSTRANSPORT:onafterStatusUpdate(From, Event, To)
text=text..string.format("\nCargos:") text=text..string.format("\nCargos:")
for _,_cargo in pairs(self:GetCargos()) do for _,_cargo in pairs(self:GetCargos()) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
local carrier=cargo.opsgroup:_GetMyCarrierElement() if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local name=carrier and carrier.name or "none" local carrier=cargo.opsgroup:_GetMyCarrierElement()
local cstate=carrier and carrier.status or "N/A" local name=carrier and carrier.name or "none"
text=text..string.format("\n- %s: %s [%s], weight=%d kg, carrier=%s [%s], delivered=%s [UID=%s]", local cstate=carrier and carrier.status or "N/A"
cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered), tostring(cargo.opsgroup.cargoTransportUID)) text=text..string.format("\n- %s: %s [%s], weight=%d kg, carrier=%s [%s], delivered=%s [UID=%s]",
cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered), tostring(cargo.opsgroup.cargoTransportUID))
else
--TODO: Storage
end
end end
text=text..string.format("\nCarriers:") text=text..string.format("\nCarriers:")
@ -2119,7 +2205,7 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, Disembark
-- Create a new data item. -- Create a new data item.
local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup
cargo.type="OPSGROUP"
cargo.opsgroup=opsgroup cargo.opsgroup=opsgroup
cargo.delivered=false cargo.delivered=false
cargo.status="Unknown" cargo.status="Unknown"
@ -2133,6 +2219,37 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, Disembark
return cargo return cargo
end end
--- Create a cargo group data structure.
-- @param #OPSTRANSPORT self
-- @param Wrapper.Storage#STORAGE StorageFrom Storage from.
-- @param Wrapper.Storage#STORAGE StorageTo Storage to.
-- @param #string CargoType Type of cargo.
-- @param #number CargoAmount Amount of cargo. Liquids in kg.
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
-- @return Ops.OpsGroup#OPSGROUP.CargoGroup Cargo group data.
function OPSTRANSPORT:_CreateCargoStorage(StorageFrom, StorageTo, CargoType, CargoAmount, TransportZoneCombo)
local storage={} --#OPSTRANSPORT.Storage
storage.storageFrom=StorageFrom
storage.storageTo=StorageTo
storage.cargoType=CargoType
storage.cargoAmount=CargoAmount
-- Create a new data item.
local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup
cargo.type="STORAGE"
cargo.opsgroup=nil
cargo.storage=storage
cargo.delivered=false
cargo.status="Unknown"
cargo.tzcUID=TransportZoneCombo
cargo.disembarkZone=nil
cargo.disembarkCarriers=nil
return cargo
end
--- Count how many cargo groups are inside a zone. --- Count how many cargo groups are inside a zone.
-- @param #OPSTRANSPORT self -- @param #OPSTRANSPORT self
-- @param Core.Zone#ZONE Zone The zone object. -- @param Core.Zone#ZONE Zone The zone object.