Merge pull request #1999 from FlightControl-Master/FF/Ops

OPSTRANSPORT
This commit is contained in:
Frank 2023-08-27 18:46:50 +02:00 committed by GitHub
commit 1337815f05
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 971 additions and 290 deletions

View File

@ -1517,6 +1517,36 @@ function FLIGHTGROUP:Status()
end
---
-- Track flight
---
if false then
for _,_element in pairs(self.elements) do
local element=_element --Ops.OpsGroup#OPSGROUP.Element
local unit=element.unit
if unit and unit:IsAlive() then
local vec3=unit:GetVec3()
if vec3 and element.pos then
local id=UTILS.GetMarkID()
trigger.action.lineToAll(-1, id, vec3, element.pos, {1,1,1,0.5}, 1)
end
element.pos=vec3
end
end
end
---
-- Fuel State
---

View File

@ -489,11 +489,17 @@ OPSGROUP.CargoStatus={
--- Element cargo bay data.
-- @type OPSGROUP.MyCargo
-- @field #OPSGROUP group The cargo group.
-- @field #number storageType Type of storage.
-- @field #number storageAmount Amount of storage.
-- @field #number storageWeight Weight of storage item.
-- @field #boolean reserved If `true`, the cargo bay space is reserved but cargo has not actually been loaded yet.
--- Cargo group data.
-- @type OPSGROUP.CargoGroup
-- @field #number uid Unique ID of this cargo data.
-- @field #string type Type of cargo: "OPSGROUP" or "STORAGE".
-- @field #OPSGROUP opsgroup The cargo opsgroup.
-- @field Ops.OpsTransport#OPSTRANSPORT.Storage storage Storage data.
-- @field #boolean delivered If `true`, group was delivered.
-- @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.
@ -2268,22 +2274,27 @@ end
-- @param #OPSGROUP self
-- @param #number Delay Delay in seconds. Default now.
-- @param #number ExplosionPower (Optional) Explosion power in kg TNT. Default 100 kg.
-- @param #string ElementName Name of the element that should be destroyed. Default is all elements.
-- @return #OPSGROUP self
function OPSGROUP:SelfDestruction(Delay, ExplosionPower)
function OPSGROUP:SelfDestruction(Delay, ExplosionPower, ElementName)
if Delay and Delay>0 then
self:ScheduleOnce(Delay, OPSGROUP.SelfDestruction, self, 0, ExplosionPower)
self:ScheduleOnce(Delay, OPSGROUP.SelfDestruction, self, 0, ExplosionPower, ElementName)
else
-- Loop over all elements.
for i,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
if ElementName==nil or ElementName==element.name then
local unit=element.unit
if unit and unit:IsAlive() then
unit:Explode(ExplosionPower or 100)
end
end
end
end
@ -5452,10 +5463,10 @@ function OPSGROUP:onafterMissionExecute(From, Event, To, Mission)
if self.isFlightgroup then
if Mission.prohibitABExecute == true then
self:SetProhibitAfterburner()
self:I("Set prohibit AB")
self:T(self.lid.."Set prohibit AB")
elseif Mission.prohibitABExecute == false then
self:SetAllowAfterburner()
self:T2("Set allow AB")
self:T2(self.lid.."Set allow AB")
end
end
@ -7446,36 +7457,55 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element)
-- Clear cargo bay of element.
for i=#Element.cargoBay,1,-1 do
local cargo=Element.cargoBay[i] --#OPSGROUP.MyCargo
local mycargo=Element.cargoBay[i] --#OPSGROUP.MyCargo
if mycargo.group then
-- Remove from cargo bay.
self:_DelCargobay(cargo.group)
self:_DelCargobay(mycargo.group)
if cargo.group and not (cargo.group:IsDead() or cargo.group:IsStopped()) then
if mycargo.group and not (mycargo.group:IsDead() or mycargo.group:IsStopped()) then
-- Remove my carrier
cargo.group:_RemoveMyCarrier()
mycargo.group:_RemoveMyCarrier()
if cargo.reserved then
if mycargo.reserved then
-- This group was not loaded yet ==> Not cargo any more.
cargo.group:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO)
mycargo.group:_NewCargoStatus(OPSGROUP.CargoStatus.NOTCARGO)
else
-- Carrier dead ==> cargo dead.
for _,cargoelement in pairs(cargo.group.elements) do
for _,cargoelement in pairs(mycargo.group.elements) do
-- Debug info.
self:T2(self.lid.."Cargo element dead "..cargoelement.name)
-- Trigger dead event.
cargo.group:ElementDead(cargoelement)
mycargo.group:ElementDead(cargoelement)
end
end
end
else
-- Add cargo to lost.
if self.cargoTZC then
for _,_cargo in pairs(self.cargoTZC.Cargos) do
local cargo=_cargo --#OPSGROUP.CargoGroup
if cargo.uid==mycargo.cargoUID then
cargo.storage.cargoLost=cargo.storage.cargoLost+mycargo.storageAmount
end
end
end
-- Remove cargo from cargo bay.
self:_DelCargobayElement(Element, mycargo)
end
end
end
@ -7972,7 +8002,12 @@ function OPSGROUP:_CheckCargoTransport()
local element=_element --#OPSGROUP.Element
for _,_cargo in pairs(element.cargoBay) do
local cargo=_cargo --#OPSGROUP.MyCargo
if cargo.group then
text=text..string.format("\n- %s in carrier %s, reserved=%s", tostring(cargo.group:GetName()), tostring(element.name), tostring(cargo.reserved))
else
text=text..string.format("\n- storage %s=%d kg in carrier %s [UID=%s]",
tostring(cargo.storageType), tostring(cargo.storageAmount*cargo.storageWeight), tostring(element.name), tostring(cargo.cargoUID))
end
end
end
if text=="" then
@ -7993,6 +8028,7 @@ function OPSGROUP:_CheckCargoTransport()
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
local cargo=_cargo --#OPSGROUP.CargoGroup
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local state=cargo.opsgroup:GetState()
local status=cargo.opsgroup.cargoStatus
local name=cargo.opsgroup.groupname
@ -8000,6 +8036,9 @@ function OPSGROUP:_CheckCargoTransport()
local carrierGroupname=carriergroup and carriergroup.groupname or "none"
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
if text~="" then
@ -8074,42 +8113,51 @@ function OPSGROUP:_CheckCargoTransport()
-- Current pickup time.
local tloading=Time-self.Tloading
--TODO: Check max loading time. If exceeded ==> abort transport.
--TODO: Check max loading time. If exceeded ==> abort transport. Time might depend on required cargos, because we need to give them time to arrive.
-- Debug info.
self:T(self.lid..string.format("Loading at %s [TZC UID=%d] for %s sec...", self.cargoTZC.PickupZone and self.cargoTZC.PickupZone:GetName() or "unknown", self.cargoTZC.uid, tloading))
self:T(self.lid..string.format("Loading at %s [TZC UID=%d] for %.1f sec...", self.cargoTZC.PickupZone and self.cargoTZC.PickupZone:GetName() or "unknown", self.cargoTZC.uid, tloading))
local boarding=false
local gotcargo=false
for _,_cargo in pairs(self.cargoTZC.Cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if cargo.type==OPSTRANSPORT.CargoType.OPSTRANPORT then
-- Check if anyone is still boarding.
if cargo.opsgroup:IsBoarding(self.groupname) then
if cargo.opsgroup and cargo.opsgroup:IsBoarding(self.groupname) then
boarding=true
end
-- Check if we have any cargo to transport.
if cargo.opsgroup:IsLoaded(self.groupname) then
if cargo.opsgroup and cargo.opsgroup:IsLoaded(self.groupname) then
gotcargo=true
end
else
-- Get cargo if it is in the cargo bay of any carrier element.
local mycargo=self:_GetMyCargoBayFromUID(cargo.uid)
if mycargo and mycargo.storageAmount>0 then
gotcargo=true
end
end
end
-- Boarding finished ==> Transport cargo.
if gotcargo and self.cargoTransport:_CheckRequiredCargos(self.cargoTZC, self) and not boarding then
self:T(self.lid.."Boarding finished ==> Loaded")
self:T(self.lid.."Boarding/loading finished ==> Loaded")
self.Tloading=nil
self:LoadingDone()
else
-- No cargo and no one is boarding ==> check again if we can make anyone board.
self:Loading()
end
-- No cargo and no one is boarding ==> check again if we can make anyone board.
if not gotcargo and not boarding then
--self:Loading()
end
elseif self:IsTransporting() then
-- Set time stamp.
@ -8136,6 +8184,8 @@ function OPSGROUP:_CheckCargoTransport()
for _,_cargo in pairs(self.cargoTZC.Cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local carrierGroup=cargo.opsgroup:_GetMyCarrierGroup()
-- Check that this group is
@ -8144,6 +8194,21 @@ function OPSGROUP:_CheckCargoTransport()
break
end
else
---
-- STORAGE
---
-- Get cargo if it is in the cargo bay of any carrier element.
local mycargo=self:_GetMyCargoBayFromUID(cargo.uid)
if mycargo and not cargo.delivered then
delivered=false
break
end
end
end
-- Unloading finished ==> pickup next batch or call it a day.
@ -8165,6 +8230,7 @@ function OPSGROUP:_CheckCargoTransport()
local text=string.format("Carrier [%s]: %s --> %s", self.carrierStatus, pickupname, deployname)
for _,_cargo in pairs(self.cargoTransport:GetCargos(self.cargoTZC)) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local name=cargo.opsgroup:GetName()
local gstatus=cargo.opsgroup:GetState()
local cstatus=cargo.opsgroup.cargoStatus
@ -8173,6 +8239,9 @@ function OPSGROUP:_CheckCargoTransport()
local carrierGroupname=carriergroup and carriergroup.groupname or "none"
local carrierElementname=carrierelement and carrierelement.name or "none"
text=text..string.format("\n- %s (%.1f kg) [%s]: %s, carrier=%s (%s), delivered=%s", name, weight, gstatus, cstatus, carrierElementname, carrierGroupname, tostring(cargo.delivered))
else
--TODO: Storage
end
end
self:I(self.lid..text)
end
@ -8217,6 +8286,8 @@ function OPSGROUP:_AddCargobay(CargoGroup, CarrierElement, Reserved)
cargo.reserved=Reserved
else
--cargo=self:_CreateMyCargo(CargoUID, CargoGroup)
cargo={} --#OPSGROUP.MyCargo
cargo.group=CargoGroup
cargo.reserved=Reserved
@ -8244,6 +8315,95 @@ function OPSGROUP:_AddCargobay(CargoGroup, CarrierElement, Reserved)
return self
end
--- Add warehouse storage to cargo bay of a carrier.
-- @param #OPSGROUP self
-- @param #OPSGROUP.Element CarrierElement The element of the carrier.
-- @param #number CargoUID UID of the cargo data.
-- @param #string StorageType Storage type.
-- @param #number StorageAmount Storage amount.
-- @param #number StorageWeight Weight of a single storage item in kg.
function OPSGROUP:_AddCargobayStorage(CarrierElement, CargoUID, StorageType, StorageAmount, StorageWeight)
local MyCargo=self:_CreateMyCargo(CargoUID, nil, StorageType, StorageAmount, StorageWeight)
self:_AddMyCargoBay(MyCargo, CarrierElement)
end
--- Add OPSGROUP to cargo bay of a carrier.
-- @param #OPSGROUP self
-- @param #number CargoUID UID of the cargo data.
-- @param #OPSGROUP OpsGroup Cargo group.
-- @param #string StorageType Storage type.
-- @param #number StorageAmount Storage amount.
-- @param #number StorageWeight Weight of a single storage item in kg.
-- @return #OPSGROUP.MyCargo My cargo object.
function OPSGROUP:_CreateMyCargo(CargoUID, OpsGroup, StorageType, StorageAmount, StorageWeight)
local cargo={} --#OPSGROUP.MyCargo
cargo.cargoUID=CargoUID
cargo.group=OpsGroup
cargo.storageType=StorageType
cargo.storageAmount=StorageAmount
cargo.storageWeight=StorageWeight
cargo.reserved=false
return cargo
end
--- Add storage to cargo bay of a carrier.
-- @param #OPSGROUP self
-- @param #OPSGROUP.MyCargo MyCargo My cargo.
-- @param #OPSGROUP.Element CarrierElement The element of the carrier.
function OPSGROUP:_AddMyCargoBay(MyCargo, CarrierElement)
table.insert(CarrierElement.cargoBay, MyCargo)
if not MyCargo.reserved then
-- Cargo weight.
local weight=0
if MyCargo.group then
weight=MyCargo.group:GetWeightTotal()
else
weight=MyCargo.storageAmount*MyCargo.storageWeight
end
-- Add weight to carrier.
self:AddWeightCargo(CarrierElement.name, weight)
end
end
--- Get cargo bay data from a cargo data id.
-- @param #OPSGROUP self
-- @param #number uid Unique ID of cargo data.
-- @return #OPSGROUP.MyCargo Cargo My cargo.
-- @return #OPSGROUP.Element Element that has loaded the cargo.
function OPSGROUP:_GetMyCargoBayFromUID(uid)
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
for i,_mycargo in pairs(element.cargoBay) do
local mycargo=_mycargo --#OPSGROUP.MyCargo
if mycargo.cargoUID and mycargo.cargoUID==uid then
return mycargo, element, i
end
end
end
return nil, nil, nil
end
--- Get all groups currently loaded as cargo.
-- @param #OPSGROUP self
-- @param #string CarrierName (Optional) Only return cargo groups loaded into a particular carrier unit.
@ -8291,6 +8451,51 @@ function OPSGROUP:_GetCargobay(CargoGroup)
return nil, nil, nil
end
--- Remove OPSGROUP from cargo bay of a carrier.
-- @param #OPSGROUP self
-- @param #OPSGROUP.Element Element Cargo group.
-- @param #number CargoUID Cargo UID.
-- @return #OPSGROUP.MyCargo MyCargo My cargo data.
function OPSGROUP:_GetCargobayElement(Element, CargoUID)
self:T3({Element=Element, CargoUID=CargoUID})
for i,_mycargo in pairs(Element.cargoBay) do
local mycargo=_mycargo --#OPSGROUP.MyCargo
if mycargo.cargoUID and mycargo.cargoUID==CargoUID then
return mycargo
end
end
return nil
end
--- Remove OPSGROUP from cargo bay of a carrier.
-- @param #OPSGROUP self
-- @param #OPSGROUP.Element Element Cargo group.
-- @param #OPSGROUP.MyCargo MyCargo My cargo data.
-- @return #boolean If `true`, cargo could be removed.
function OPSGROUP:_DelCargobayElement(Element, MyCargo)
for i,_mycargo in pairs(Element.cargoBay) do
local mycargo=_mycargo --#OPSGROUP.MyCargo
if mycargo.cargoUID and MyCargo.cargoUID and mycargo.cargoUID==MyCargo.cargoUID then
if MyCargo.group then
self:RedWeightCargo(Element.name, MyCargo.group:GetWeightTotal())
else
self:RedWeightCargo(Element.name, MyCargo.storageAmount*MyCargo.storageWeight)
end
table.remove(Element.cargoBay, i)
return true
end
end
return false
end
--- Remove OPSGROUP from cargo bay of a carrier.
-- @param #OPSGROUP self
-- @param #OPSGROUP CargoGroup Cargo group.
@ -8385,11 +8590,13 @@ function OPSGROUP:_CheckDelivered(CargoTransport)
for _,_cargo in pairs(CargoTransport:GetCargos()) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if self:CanCargo(cargo.opsgroup) then
if self:CanCargo(cargo) then
if cargo.delivered then
-- This one is delivered.
elseif cargo.opsgroup==nil or cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped() then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup==nil then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and (cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then
-- This one is dead.
else
done=false --Someone is not done!
@ -8419,13 +8626,13 @@ function OPSGROUP:_CheckGoPickup(CargoTransport)
for _,_cargo in pairs(CargoTransport:GetCargos()) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if self:CanCargo(cargo.opsgroup) then
if self:CanCargo(cargo) then
if cargo.delivered then
-- This one is delivered.
elseif cargo.opsgroup==nil or cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped() then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and (cargo.opsgroup==nil or cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then
-- This one is dead.
elseif cargo.opsgroup:IsLoaded(CargoTransport:_GetCarrierNames()) then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and (cargo.opsgroup:IsLoaded(CargoTransport:_GetCarrierNames())) then
-- This one is loaded into a(nother) carrier.
else
done=false --Someone is not done!
@ -8650,8 +8857,11 @@ function OPSGROUP:GetWeightCargo(UnitName, IncludeReserved)
for _,_cargo in pairs(element.cargoBay) do
local cargo=_cargo --#OPSGROUP.MyCargo
if (not cargo.reserved) or (cargo.reserved==true and (IncludeReserved==true or IncludeReserved==nil)) then
local cargoweight=cargo.group:GetWeightTotal()
gewicht=gewicht+cargoweight
if cargo.group then
gewicht=gewicht+cargo.group:GetWeightTotal()
else
gewicht=gewicht+cargo.storageAmount*cargo.storageWeight
end
--self:I(self.lid..string.format("unit=%s (reserved=%s): cargo=%s weight=%d, total weight=%d", tostring(UnitName), tostring(IncludeReserved), cargo.group:GetName(), cargoweight, weight))
end
end
@ -8745,16 +8955,46 @@ function OPSGROUP:RedWeightCargo(UnitName, Weight)
return self
end
--- Get weight of warehouse storage to transport.
-- @param #OPSGROUP self
-- @param Ops.OpsTransport#OPSTRANSPORT.Storage Storage
-- @param #boolean Total Get total weight. Otherweise the amount left to deliver (total-loaded-lost-delivered).
-- @param #boolean Reserved Reduce weight that is reserved.
-- @param #boolean Amount Return amount not weight.
-- @return #number Weight of cargo in kg or amount in number of items, if `Amount=true`.
function OPSGROUP:_GetWeightStorage(Storage, Total, Reserved, Amount)
local weight=Storage.cargoAmount
if not Total then
weight=weight-Storage.cargoLost-Storage.cargoLoaded-Storage.cargoDelivered
end
if Reserved then
weight=weight-Storage.cargoReserved
end
if not Amount then
weight=weight*Storage.cargoWeight
end
return weight
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).
-- **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 CargoGroup Cargo group, which needs a carrier.
-- @param Ops.OpsGroup#OPSGROUP.CargoGroup Cargo Cargo data, which needs a carrier.
-- @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
local weight=Cargo.opsgroup:GetWeightTotal()
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
@ -8763,31 +9003,58 @@ function OPSGROUP:CanCargo(CargoGroup)
if element and element.status~=OPSGROUP.ElementStatus.DEAD and element.weightMaxCargo>=weight then
return true
end
end
else
---
-- STORAGE
---
-- Since storage cargo can be devided onto multiple carriers, we take the weight of a single cargo item (even 1 kg of fuel).
weight=Cargo.storage.cargoWeight
end
-- Calculate cargo bay space.
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
-- Check if cargo fits into cargo bay(s) of carrier group.
if bay>=weight then
return true
end
end
return false
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 CargoGroup Cargo group, which needs a carrier.
-- @param #number Weight Weight of cargo in kg.
-- @return #OPSGROUP.Element Carrier able to transport the cargo.
function OPSGROUP:FindCarrierForCargo(CargoGroup)
local weight=CargoGroup:GetWeightTotal()
function OPSGROUP:FindCarrierForCargo(Weight)
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
local free=self:GetFreeCargobay(element.name)
if free>=weight then
if free>=Weight then
return element
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
@ -9068,6 +9335,36 @@ function OPSGROUP:onafterPickup(From, Event, To)
end
--- On after "Loading" event.
-- @param #OPSGROUP self
-- @param #table Cargos Table of cargos.
-- @return #table Table of sorted cargos.
function OPSGROUP:_SortCargo(Cargos)
-- Sort results table wrt descending weight.
local function _sort(a, b)
local cargoA=a --Ops.OpsGroup#OPSGROUP.CargoGroup
local cargoB=b --Ops.OpsGroup#OPSGROUP.CargoGroup
local weightA=0
local weightB=0
if cargoA.opsgroup then
weightA=cargoA.opsgroup:GetWeightTotal()
else
weightA=self:_GetWeightStorage(cargoA.storage)
end
if cargoB.opsgroup then
weightB=cargoB.opsgroup:GetWeightTotal()
else
weightB=self:_GetWeightStorage(cargoB.storage)
end
return weightA>weightB
end
table.sort(Cargos, _sort)
return Cargos
end
--- On after "Loading" event.
-- @param #OPSGROUP self
@ -9079,32 +9376,30 @@ function OPSGROUP:onafterLoading(From, Event, To)
-- Set carrier status.
self:_NewCarrierStatus(OPSGROUP.CarrierStatus.LOADING)
-- Loading time stamp.
self.Tloading=timer.getAbsTime()
-- Get valid cargos of the TZC.
local cargos={}
for _,_cargo in pairs(self.cargoTZC.Cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
-- Check if this group can carry the cargo.
local canCargo=self:CanCargo(cargo.opsgroup)
local canCargo=self:CanCargo(cargo)
-- Check if this group is currently acting as carrier.
local isCarrier=cargo.opsgroup:IsPickingup() or cargo.opsgroup:IsLoading() or cargo.opsgroup:IsTransporting() or cargo.opsgroup:IsUnloading()
local isCarrier=false
-- Check if cargo is not already cargo.
local isNotCargo=cargo.opsgroup:IsNotCargo(true)
local isNotCargo=true
-- 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.
-- 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.
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.
if isOnMission then
@ -9114,39 +9409,114 @@ function OPSGROUP:onafterLoading(From, Event, To)
end
end
local isAvail=true
if cargo.type==OPSTRANSPORT.CargoType.STORAGE then
local nAvail=cargo.storage.storageFrom:GetAmount(cargo.storage.cargoType)
if nAvail>0 then
isAvail=true
else
isAvail=false
end
else
isCarrier=cargo.opsgroup:IsPickingup() or cargo.opsgroup:IsLoading() or cargo.opsgroup:IsTransporting() or cargo.opsgroup:IsUnloading()
isNotCargo=cargo.opsgroup:IsNotCargo(true)
end
local isDead=cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsDead() or false
-- Debug message.
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)))
-- 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)
end
end
-- Sort results table wrt descending weight.
local function _sort(a, b)
local cargoA=a --Ops.OpsGroup#OPSGROUP.CargoGroup
local cargoB=b --Ops.OpsGroup#OPSGROUP.CargoGroup
return cargoA.opsgroup:GetWeightTotal()>cargoB.opsgroup:GetWeightTotal()
end
table.sort(cargos, _sort)
-- Sort cargos.
self:_SortCargo(cargos)
-- Loop over all cargos.
for _,_cargo in pairs(cargos) do
local cargo=_cargo --#OPSGROUP.CargoGroup
-- Find a carrier for this cargo.
local carrier=self:FindCarrierForCargo(cargo.opsgroup)
local weight=nil
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
if carrier then
weight=cargo.opsgroup:GetWeightTotal()
-- Find a carrier for this cargo.
local carrier=self:FindCarrierForCargo(weight)
-- Order cargo group to board the carrier.
if carrier then
cargo.opsgroup:Board(self, carrier)
end
else
---
-- STORAGE
---
-- Get weight of cargo that needs to be transported.
weight=self:_GetWeightStorage(cargo.storage, false)
-- Get amount that the warehouse currently has.
local Amount=cargo.storage.storageFrom:GetAmount(cargo.storage.cargoType)
local Weight=Amount*cargo.storage.cargoWeight
-- Make sure, we do not take more than the warehouse can provide.
weight=math.min(weight, Weight)
-- Debug info.
self:T(self.lid..string.format("Loading storage weight=%d kg (warehouse has %d kg)!", weight, Weight))
-- Loop over all elements of the carrier group.
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
-- Get the free cargo space of the carrier.
local free=self:GetFreeCargobay(element.name)
-- Min of weight or bay.
local w=math.min(weight, free)
-- Check that weight is >0 and also greater that at least one item. We cannot transport half a missile.
if w>=cargo.storage.cargoWeight then
-- Calculate item amount.
local amount=math.floor(w/cargo.storage.cargoWeight)
-- Remove items from warehouse.
cargo.storage.storageFrom:RemoveAmount(cargo.storage.cargoType, amount)
-- Add amount to loaded cargo.
cargo.storage.cargoLoaded=cargo.storage.cargoLoaded+amount
-- Add cargo to cargo by of element.
self:_AddCargobayStorage(element, cargo.uid, cargo.storage.cargoType, amount, cargo.storage.cargoWeight)
-- Reduce weight for the next element (if any).
weight=weight-amount*cargo.storage.cargoWeight
-- Debug info.
local text=string.format("Element %s: loaded amount=%d (weight=%d) ==> left=%d kg", element.name, amount, amount*cargo.storage.cargoWeight, weight)
self:T(self.lid..text)
-- If no cargo left, break the loop.
if weight<=0 then
break
end
end
end
end
end
end
--- Set (new) cargo status.
@ -9323,6 +9693,8 @@ function OPSGROUP:onafterTransport(From, Event, To)
end
end
--env.info(string.format("FF Transport: Zone=%s inzone=%s, ready2deploy=%s", Zone:GetName(), tostring(inzone), tostring(ready2deploy)))
if inzone then
-- We are already in the deploy zone ==> wait and initiate unloading.
@ -9480,6 +9852,8 @@ function OPSGROUP:onafterUnloading(From, Event, To)
for _,_cargo in pairs(self.cargoTZC.Cargos) do
local cargo=_cargo --#OPSGROUP.CargoGroup
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
-- Check that cargo is loaded into this group.
-- NOTE: Could be that the element carriing this cargo group is DEAD, which would mean that the cargo group is also DEAD.
if cargo.opsgroup:IsLoaded(self.groupname) and not cargo.opsgroup:IsDead() then
@ -9617,6 +9991,67 @@ function OPSGROUP:onafterUnloading(From, Event, To)
-- Not loaded or dead
end
else
---
-- STORAGE
---
-- TODO: should proabaly move this check to the top to include OPSGROUPS as well?!
if not cargo.delivered then
for _,_element in pairs(self.elements) do
local element=_element --#OPSGROUP.Element
-- Get my cargo from cargo bay of element.
local mycargo=self:_GetCargobayElement(element, cargo.uid)
if mycargo then
-- Add cargo to warehouse storage.
cargo.storage.storageTo:AddAmount(mycargo.storageType, mycargo.storageAmount)
-- Add amount to delivered.
cargo.storage.cargoDelivered=cargo.storage.cargoDelivered+mycargo.storageAmount
-- Reduce loaded amount.
cargo.storage.cargoLoaded=cargo.storage.cargoLoaded-mycargo.storageAmount
-- Remove cargo from bay.
self:_DelCargobayElement(element, mycargo)
-- Debug info
self:T2(self.lid..string.format("Cargo loaded=%d, delivered=%d, lost=%d", cargo.storage.cargoLoaded, cargo.storage.cargoDelivered, cargo.storage.cargoLost))
end
end
-- Get amount that was delivered.
local amountToDeliver=self:_GetWeightStorage(cargo.storage, false, false, true)
-- Get total amount to be delivered.
local amountTotal=self:_GetWeightStorage(cargo.storage, true, false, true)
-- Debug info.
local text=string.format("Amount delivered=%d, total=%d", amountToDeliver, amountTotal)
self:T(self.lid..text)
if amountToDeliver<=0 then
-- Cargo was delivered (somehow).
cargo.delivered=true
-- Increase number of delivered cargos.
self.cargoTransport.Ndelivered=self.cargoTransport.Ndelivered+1
-- Debug info.
local text=string.format("Ndelivered=%d delivered=%s", self.cargoTransport.Ndelivered, tostring(cargo.delivered))
self:T(self.lid..text)
end
end
end
end -- loop over cargos
end
@ -10047,7 +10482,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier)
-- Debug info.
self:T(self.lid..string.format("Group is loaded currently ==> Moving directly to new carrier - No Unload(), Disembart() events triggered!"))
-- Remove my carrier.
-- Remove old/current carrier.
self:_RemoveMyCarrier()
-- Trigger Load event.

View File

@ -1,8 +1,9 @@
--- **Ops** - Troop transport assignment for OPS groups.
--- **Ops** - Transport assignment for OPS groups and storage.
--
-- ## Main Features:
--
-- * Transport troops from A to B
-- * Transport of warehouse storage (fuel, weapons and equipment)
-- * Supports ground, naval and airborne (airplanes and helicopters) units as carriers
-- * Use combined forces (ground, naval, air) to transport the troops
-- * Additional FSM events to hook into and customize your mission design
@ -63,6 +64,7 @@
-- @field Ops.Chief#CHIEF chief Chief of the transport.
-- @field Ops.OpsZone#OPSZONE opszone OPS zone.
-- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the transport was cancelled before the request is processed.
-- @field #number cargocounter Running number to generate cargo UIDs.
--
-- @extends Core.Fsm#FSM
@ -79,7 +81,7 @@
-- * Cargo groups are **not** split and distributed into different carrier *units*. That means that the whole cargo group **must fit** into one of the carrier units.
-- * Cargo groups must be inside the pickup zones to be considered for loading. Groups not inside the pickup zone will not get the command to board.
--
-- # Constructor
-- # Troop Transport
--
-- A new cargo transport assignment is created with the @{#OPSTRANSPORT.New}() function
--
@ -101,6 +103,30 @@
--
-- You can also mix carrier types. For instance, you can assign the same transport to APCs and helicopters. Or to helicopters and airplanes.
--
-- # Storage Transport
--
-- An instance of the OPSTRANSPORT class is created similarly to the troop transport case. However, the first parameter is `nil` as not troops
-- are transported.
--
-- local storagetransport=OPSTRANSPORT:New(nil, PickupZone, DeployZone)
--
-- ## Defining Storage
--
-- The storage warehouses from which the cargo is taken and to which the cargo is delivered have to be specified
--
-- storagetransport:AddCargoStorage(berlinStorage, batumiStorage, STORAGE.Liquid.JETFUEL, 1000)
--
-- Here `berlinStorage` and `batumiStorage` are @{Wrapper.Storage#STORAGE} objects of DCS warehouses.
--
-- Furthermore, that type of cargo (liquids or weapons/equipment) and the amount has to be specified. If weapons/equipment is the cargo,
-- we also need to specify the weight per storage item as this cannot be retrieved from the DCS API and is not stored in any MOOSE database.
--
-- storagetransport:AddCargoStorage(berlinStorage, batumiStorage, ENUMS.Storage.weapons.bombs.Mk_82, 9, 230)
--
-- Finally, the transport is assigned to one or multiple groups, which carry out the transport
--
-- myopsgroup:AddOpsTransport(storagetransport)
--
-- # Examples
--
-- A carrier group is assigned to transport infantry troops from zone "Zone Kobuleti X" to zone "Zone Alpha".
@ -131,6 +157,7 @@ OPSTRANSPORT = {
legions = {},
statusLegion = {},
requestID = {},
cargocounter = 0,
}
--- Cargo transport status.
@ -186,6 +213,27 @@ OPSTRANSPORT.Status={
-- @field #number radius Radomization radius for waypoints in meters. Default 0 m.
-- @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 that should be transported.
-- @field #number cargoReserved Amount of cargo that is reserved for a carrier group.
-- @field #number cargoDelivered Amount of cargo that has been delivered.
-- @field #number cargoLost Amount of cargo that was lost.
-- @field #number cargoLoaded Amount of cargo that is loading.
-- @field #number cargoWeight Weight of one single cargo item in kg. Default 1 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.
-- @type OPSTRANSPORT.Condition
-- @field #function func Callback function to check for a condition. Should return a #boolean.
@ -196,7 +244,7 @@ _OPSTRANSPORTID=0
--- Army Group version.
-- @field #string version
OPSTRANSPORT.version="0.7.0"
OPSTRANSPORT.version="0.8.0"
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- TODO list
@ -205,6 +253,7 @@ OPSTRANSPORT.version="0.7.0"
-- TODO: Trains.
-- TODO: Stop transport.
-- TODO: Improve pickup and transport paths.
-- DONE: Storage.
-- DONE: Disembark parameters per cargo group.
-- DONE: Special transport cohorts/legions. Similar to mission.
-- DONE: Cancel transport.
@ -576,6 +625,38 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo, DisembarkActi
return self
end
--- Add cargo warehouse storage to be transported. This adds items such as fuel, weapons and other equipment, which is to be transported
-- from one DCS warehouse to another.
-- For weapons and equipment, the weight per item has to be specified explicitly as these cannot be retrieved by the DCS API. For liquids the
-- default value of 1 kg per item should be used as the amount of liquid is already given in kg.
-- @param #OPSTRANSPORT self
-- @param Wrapper.Storage#STORAGE StorageFrom Storage warehouse from which the cargo is taken.
-- @param Wrapper.Storage#STORAGE StorageTo Storage warehouse to which the cargo is delivered.
-- @param #string CargoType Type of cargo, *e.g.* `"weapons.bombs.Mk_84"` or liquid type as #number.
-- @param #number CargoAmount Amount of cargo. Liquids in kg.
-- @param #number CargoWeight Weight of a single cargo item in kg. Default 1 kg.
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo if other than default.
-- @return #OPSTRANSPORT self
function OPSTRANSPORT:AddCargoStorage(StorageFrom, StorageTo, CargoType, CargoAmount, CargoWeight, 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, CargoWeight, TransportZoneCombo)
if cargo then
-- Add total amount of ever assigned cargos.
self.Ncargo=self.Ncargo+1
-- Add to TZC table.
table.insert(TransportZoneCombo.Cargos, cargo)
end
end
--- Set pickup zone.
-- @param #OPSTRANSPORT self
@ -1063,18 +1144,37 @@ end
-- @return #table Cargo Ops groups. Can be and empty table `{}`.
function OPSTRANSPORT:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
local cargos=self:GetCargos(TransportZoneCombo)
local cargos=self:GetCargos(TransportZoneCombo, Carrier, Delivered)
local opsgroups={}
for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if Delivered==nil or cargo.delivered==Delivered then
if cargo.type=="OPSGROUP" then
if cargo.opsgroup and not (cargo.opsgroup:IsDead() or cargo.opsgroup:IsStopped()) then
if Carrier==nil or Carrier:CanCargo(cargo.opsgroup) then
table.insert(opsgroups, cargo.opsgroup)
end
end
end
return opsgroups
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, Carrier, Delivered)
local opsgroups={}
for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if cargo.type=="STORAGE" then
table.insert(opsgroups, cargo.storage)
end
end
return opsgroups
@ -1090,22 +1190,60 @@ end
--- Get cargos.
-- @param #OPSTRANSPORT self
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
-- @param Ops.OpsGroup#OPSGROUP Carrier Specific carrier.
-- @param #boolean Delivered Delivered status.
-- @return #table Cargos.
function OPSTRANSPORT:GetCargos(TransportZoneCombo)
function OPSTRANSPORT:GetCargos(TransportZoneCombo, Carrier, Delivered)
local tczs=self.tzCombos
if TransportZoneCombo then
return TransportZoneCombo.Cargos
else
tczs={TransportZoneCombo}
end
local cargos={}
for _,_tzc in pairs(self.tzCombos) do
local tzc=_tzc --#OPSTRANSPORT.TransportZoneCombo
for _,cargo in pairs(tzc.Cargos) do
for _,_tcz in pairs(tczs) do
local tcz=_tcz --#OPSTRANSPORT.TransportZoneCombo
for _,_cargo in pairs(tcz.Cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if Delivered==nil or cargo.delivered==Delivered then
if Carrier==nil or Carrier:CanCargo(cargo) then
table.insert(cargos, cargo)
end
end
return cargos
end
end
return cargos
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
if IncludeReserved then
return Cargo.storage.cargoAmount+Cargo.storage.cargoReserved
else
return Cargo.storage.cargoAmount
end
else
if IncludeReserved then
return Cargo.storage.cargoAmount*100 -- Assume 100 kg per item
else
return (Cargo.storage.cargoAmount+Cargo.storage.cargoReserved)*100 -- Assume 100 kg per item
end
end
end
return weight
end
--- Set transport start and stop time.
@ -1642,11 +1780,18 @@ function OPSTRANSPORT:onafterStatusUpdate(From, Event, To)
text=text..string.format("\nCargos:")
for _,_cargo in pairs(self:GetCargos()) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local carrier=cargo.opsgroup:_GetMyCarrierElement()
local name=carrier and carrier.name or "none"
local cstate=carrier and carrier.status or "N/A"
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
local storage=cargo.storage
text=text..string.format("\n- storage type=%s: amount: total=%d loaded=%d, lost=%d, delivered=%d, delivered=%s [UID=%s]",
storage.cargoType, storage.cargoAmount, storage.cargoLoaded, storage.cargoLost, storage.cargoDelivered, tostring(cargo.delivered), tostring(cargo.uid))
end
end
text=text..string.format("\nCarriers:")
@ -1923,14 +2068,14 @@ function OPSTRANSPORT:_CheckDelivered()
if cargo.delivered then
-- This one is delivered.
dead=false
elseif cargo.opsgroup==nil then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup==nil then
-- This one is nil?!
dead=false
elseif cargo.opsgroup:IsDestroyed() then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsDestroyed() then
-- This one was destroyed.
elseif cargo.opsgroup:IsDead() then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsDead() then
-- This one is dead.
elseif cargo.opsgroup:IsStopped() then
elseif cargo.type==OPSTRANSPORT.CargoType.OPSGROUP and cargo.opsgroup:IsStopped() then
-- This one is stopped.
dead=false
else
@ -2116,10 +2261,12 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, Disembark
end
end
self.cargocounter=self.cargocounter+1
-- Create a new data item.
local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup
cargo.uid=self.cargocounter
cargo.type="OPSGROUP"
cargo.opsgroup=opsgroup
cargo.delivered=false
cargo.status="Unknown"
@ -2133,6 +2280,45 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, Disembark
return cargo
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 Total amount of cargo that should be transported. Liquids in kg.
-- @param #number CargoWeight Weight of a single cargo item in kg. Default 1 kg.
-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo.
-- @return Ops.OpsGroup#OPSGROUP.CargoGroup Cargo group data.
function OPSTRANSPORT:_CreateCargoStorage(StorageFrom, StorageTo, CargoType, CargoAmount, CargoWeight, TransportZoneCombo)
local storage={} --#OPSTRANSPORT.Storage
storage.storageFrom=StorageFrom
storage.storageTo=StorageTo
storage.cargoType=CargoType
storage.cargoAmount=CargoAmount
storage.cargoDelivered=0
storage.cargoLost=0
storage.cargoReserved=0
storage.cargoLoaded=0
storage.cargoWeight=CargoWeight or 1
self.cargocounter=self.cargocounter+1
-- Create a new data item.
local cargo={} --Ops.OpsGroup#OPSGROUP.CargoGroup
cargo.uid=self.cargocounter
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.
-- @param #OPSTRANSPORT self
-- @param Core.Zone#ZONE Zone The zone object.
@ -2143,7 +2329,9 @@ end
function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZoneCombo)
-- Get cargo ops groups.
local cargos=self:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
--local cargos=self:GetCargoOpsGroups(Delivered, Carrier, TransportZoneCombo)
local cargos=self:GetCargos(TransportZoneCombo, Carrier, Delivered)
--- Function to check if carrier is supposed to be disembarked to.
local function iscarrier(_cargo)
@ -2185,22 +2373,33 @@ function OPSTRANSPORT:_CountCargosInZone(Zone, Delivered, Carrier, TransportZone
local N=0
for _,_cargo in pairs(cargos) do
local cargo=_cargo --Ops.OpsGroup#OPSGROUP
local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup
local isNotCargo=true
local isInZone=true
local isInUtero=true
if cargo.type==OPSTRANSPORT.CargoType.OPSGROUP then
local opsgroup=cargo.opsgroup
-- Is not cargo?
local isNotCargo=cargo:IsNotCargo(true)
isNotCargo=opsgroup:IsNotCargo(true)
if not isNotCargo then
isNotCargo=iscarrier(cargo)
isNotCargo=iscarrier(opsgroup)
end
-- Is in zone?
local isInZone=cargo:IsInZone(Zone)
isInZone=opsgroup:IsInZone(Zone)
-- Is in utero?
local isInUtero=cargo:IsInUtero()
isInUtero=opsgroup:IsInUtero()
-- Debug info.
self:T(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", cargo:GetName(), tostring(cargo:IsNotCargo(true)), tostring(iscarrier(cargo)), tostring(isInZone), tostring(isInUtero)))
self:T(self.lid..string.format("Cargo=%s: notcargo=%s, iscarrier=%s inzone=%s, inutero=%s", opsgroup:GetName(), tostring(opsgroup:IsNotCargo(true)), tostring(iscarrier(opsgroup)), tostring(isInZone), tostring(isInUtero)))
end
-- We look for groups that are not cargo, in the zone or in utero.
if isNotCargo and (isInZone or isInUtero) then

View File

@ -900,6 +900,23 @@ function MSRS:_ExecCommand(command)
timer.scheduleFunction(os.remove, filename, timer.getTime()+1)
timer.scheduleFunction(os.remove, filenvbs, timer.getTime()+1)
elseif false then
-- Create a tmp file.
local filenvbs = os.getenv('TMP') .. "\\MSRS-"..STTS.uuid()..".vbs"
-- VBS script
local script = io.open(filenvbs, "w+")
script:write(string.format('Set oShell = CreateObject ("Wscript.Shell")\n'))
script:write(string.format('Dim strArgs\n'))
script:write(string.format('strArgs = "cmd /c %s"\n', filename))
script:write(string.format('oShell.Run strArgs, 0, false'))
script:close()
local runvbs=string.format('cscript.exe //Nologo //B "%s"', filenvbs)
-- Play file in 0.01 seconds
res=os.execute(runvbs)
else