diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index bcf8227e7..87b98c88b 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -2252,9 +2252,14 @@ function FLIGHTGROUP:onbeforeRTB(From, Event, To, airbase, SpeedTo, SpeedHold) allowed=false Tsuspend=-20 local groupspeed = self.group:GetVelocityMPS() - if groupspeed <= 1 then self.RTBRecallCount = self.RTBRecallCount+1 end + if groupspeed<=1 and not self:IsParking() then + self.RTBRecallCount = self.RTBRecallCount+1 + end if self.RTBRecallCount > 6 then + self:I(self.lid..string.format("WARNING: Group is not moving and was called RTB %d times. Assuming a problem and despawning!", self.RTBRecallCount)) + self.RTBRecallCount=0 self:Despawn(5) + return end end diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 2792b93f5..4c29c2338 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -1104,6 +1104,9 @@ function OPSGROUP:GetVelocity(UnitName) local vel=UTILS.VecNorm(velvec3) return vel + + else + self:E(self.lid.."WARNING: Unit does not exist. Cannot get velocity!") end else @@ -1751,9 +1754,9 @@ function OPSGROUP:IsPickingup() return self.carrierStatus==OPSGROUP.CarrierStatus.PICKUP end ---- Check if the group is picking up cargo. +--- Check if the group is loading cargo. -- @param #OPSGROUP self --- @return #boolean If true, group is picking up. +-- @return #boolean If true, group is loading. function OPSGROUP:IsLoading() return self.carrierStatus==OPSGROUP.CarrierStatus.LOADING end @@ -1803,14 +1806,20 @@ end --- Check if the group is currently loaded into a carrier. -- @param #OPSGROUP self --- @param #string CarrierGroupName (Optional) Additionally check if group is loaded into this particular carrier group. +-- @param #string CarrierGroupName (Optional) Additionally check if group is loaded into a particular carrier group(s). -- @return #boolean If true, group is loaded. function OPSGROUP:IsLoaded(CarrierGroupName) if CarrierGroupName then - local carrierGroup=self:_GetMyCarrierGroup() - if carrierGroup and carrierGroup.groupname~=CarrierGroupName then - return false + if type(CarrierGroupName)~="table" then + CarrierGroupName={CarrierGroupName} end + for _,CarrierName in pairs(CarrierGroupName) do + local carrierGroup=self:_GetMyCarrierGroup() + if carrierGroup and carrierGroup.groupname==CarrierName then + return true + end + end + return false end return self.cargoStatus==OPSGROUP.CargoStatus.LOADED end @@ -4881,16 +4890,23 @@ function OPSGROUP:_CheckCargoTransport() end end + + self:I(self.lid.."gotcargo="..tostring(gotcargo)) + self:I(self.lid.."boarding="..tostring(boarding)) + self:I(self.lid.."required="..tostring(self.cargoTransport:_CheckRequiredCargos())) -- Boarding finished ==> Transport cargo. - if gotcargo and not boarding then + if gotcargo and self.cargoTransport:_CheckRequiredCargos() and not boarding then self:I(self.lid.."Boarding finished ==> Loaded") self:Loaded() + 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() + --self:Loading() end elseif self:IsTransporting() then @@ -5671,10 +5687,10 @@ function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) end -- Trigger embarked event for cargo group. - CargoGroup:Embarked(self, Carrier) + CargoGroup:Embarked(self, carrier) -- Trigger "Loaded" event for current cargo transport. - self.cargoTransport:Loaded(CargoGroup, Carrier) + self.cargoTransport:Loaded(CargoGroup, carrier) else self:E(self.lid.."ERROR: Cargo has no carrier on Load event!") @@ -5904,6 +5920,9 @@ function OPSGROUP:onafterUnloading(From, Event, To) -- Delivered to another carrier group. --- + -- Debug info. + self:I(self.lid..string.format("Transferring cargo %s to new carrier group %s", cargo.opsgroup:GetName(), carrierGroup:GetName())) + -- Unload from this and directly load into the other carrier. self:Unload(cargo.opsgroup) carrierGroup:Load(cargo.opsgroup, carrier) @@ -6229,7 +6248,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) local CargoIsArmyOrNavy=self:IsArmygroup() or self:IsNavygroup() -- Check that carrier is standing still. - if (CarrierIsArmyOrNavy and CarrierGroup:IsHolding()) or (CarrierGroup:IsParking() or CarrierGroup:IsLandedAt()) then + if (CarrierIsArmyOrNavy and (CarrierGroup:IsHolding() and CarrierGroup:GetVelocity(Carrier.name)<=1)) or (CarrierGroup:IsFlightgroup() and (CarrierGroup:IsParking() or CarrierGroup:IsLandedAt())) then -- Board if group is mobile, not late activated and army or navy. Everything else is loaded directly. local board=self.speedMax>0 and CargoIsArmyOrNavy and self:IsAlive() and CarrierGroup:IsAlive() diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index 4eca27af6..7d9e725c3 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -44,6 +44,7 @@ -- @field #boolean disembarkActivation Activation setting when group is disembared from carrier. -- @field #boolean disembarkInUtero Do not spawn the group in any any state but leave it "*in utero*". For example, to directly load it into another carrier. -- @field #table disembarkCarriers Table of carriers to which the cargo is disembared. This is a direct transfer from the old to the new carrier. +-- @field #table requiredCargos Table of cargo groups that must be loaded before the first transport is started. -- @field #number Ncargo Total number of cargo groups. -- @field #number Ncarrier Total number of assigned carriers. -- @field #number Ndelivered Total number of cargo groups delivered. @@ -70,6 +71,7 @@ OPSTRANSPORT = { carrierTransportStatus = {}, conditionStart = {}, pathsTransport = {}, + requiredCargos = {}, } --- Cargo transport status. @@ -266,7 +268,7 @@ end --- Set transfer carrier(s). These are carrier groups, where the cargo is directly loaded into when disembarked. -- @param #OPSTRANSPORT self --- @param Core.Set#SET_GROUP Carriers Carrier set. +-- @param Core.Set#SET_GROUP Carriers Carrier set. Can also be passed as a #GROUP, #OPSGROUP or #SET_OPSGROUP object. -- @return #OPSTRANSPORT self function OPSTRANSPORT:SetDisembarkCarriers(Carriers) @@ -313,6 +315,41 @@ function OPSTRANSPORT:SetDisembarkInUtero(InUtero) end +--- Set required cargo. This is a list of cargo groups that need to be loaded before the **first** transport will start. +-- @param #OPSTRANSPORT self +-- @param Core.Set#SET_GROUP Cargos Required cargo set. Can also be passed as a #GROUP, #OPSGROUP or #SET_OPSGROUP object. +-- @return #OPSTRANSPORT self +function OPSTRANSPORT:SetRequiredCargos(Cargos) + + self:I(self.lid.."Setting required cargos!") + + -- Create table. + self.requiredCargos=self.requiredCargos or {} + + if Cargos:IsInstanceOf("GROUP") or Cargos:IsInstanceOf("OPSGROUP") then + + local cargo=self:_GetOpsGroupFromObject(Cargos) + if cargo then + table.insert(self.requiredCargos, cargo) + end + + elseif Cargos:IsInstanceOf("SET_GROUP") or Cargos:IsInstanceOf("SET_OPSGROUP") then + + for _,object in pairs(Cargos:GetSet()) do + local cargo=self:_GetOpsGroupFromObject(object) + if cargo then + table.insert(self.requiredCargos, cargo) + end + end + + else + self:E(self.lid.."ERROR: Required Cargos must be a GROUP, OPSGROUP, SET_GROUP or SET_OPSGROUP object!") + end + + return self +end + + --- Add a carrier assigned for this transport. -- @param #OPSTRANSPORT self @@ -365,6 +402,22 @@ function OPSTRANSPORT:_DelCarrier(CarrierGroup) return self end +--- Get a list of alive carriers. +-- @param #OPSTRANSPORT self +-- @return #table Names of all carriers +function OPSTRANSPORT:_GetCarrierNames() + + local names={} + for _,_carrier in pairs(self.carriers) do + local carrier=_carrier --Ops.OpsGroup#OPSGROUP + if carrier:IsAlive()~=nil then + table.insert(names, carrier.groupname) + end + end + + return names +end + --- Set transport start and stop time. -- @param #OPSTRANSPORT self @@ -778,6 +831,31 @@ function OPSTRANSPORT:_CheckDelivered() end +--- Check if all required cargos are loaded. +-- @param #OPSTRANSPORT self +-- @return #boolean If true, all required cargos are loaded or there is no required cargo. +function OPSTRANSPORT:_CheckRequiredCargos() + + if self.requiredCargos==nil or #self.requiredCargos==0 then + return true + end + + local carrierNames=self:_GetCarrierNames() + + local gotit=true + for _,_cargo in pairs(self.requiredCargos) do + local cargo=_cargo --Ops.OpsGroup#OPSGROUP + + + if not cargo:IsLoaded(carrierNames) then + return false + end + + end + + return true +end + --- Check if all given condition are true. -- @param #OPSTRANSPORT self -- @param #table Conditions Table of conditions. @@ -820,17 +898,22 @@ function OPSTRANSPORT:FindTransferCarrierForCargo(CargoGroup, Zone) for _,_carrier in pairs(self.disembarkCarriers or {}) do local carrierGroup=_carrier --Ops.OpsGroup#OPSGROUP - -- Find an element of the group that has enough free space. - carrier=carrierGroup:FindCarrierForCargo(CargoGroup) + -- First check if carrier is alive and loading cargo. + if carrierGroup and carrierGroup:IsAlive() and carrierGroup:IsLoading() then - if carrier then - if Zone==nil or Zone:IsCoordinateInZone(carrier.unit:GetCoordinate()) then - return carrier, carrierGroup + -- Find an element of the group that has enough free space. + carrier=carrierGroup:FindCarrierForCargo(CargoGroup) + + if carrier then + if Zone==nil or Zone:IsCoordinateInZone(carrier.unit:GetCoordinate()) then + return carrier, carrierGroup + else + self:T3(self.lid.."Got transfer carrier but carrier not in zone (yet)!") + end else - self:T3(self.lid.."Got transfer carrier but carrier not in zone (yet)!") + self:T3(self.lid.."No transfer carrier available!") end - else - self:T3(self.lid.."No transfer carrier available!") + end end diff --git a/Moose Development/Moose/Wrapper/Positionable.lua b/Moose Development/Moose/Wrapper/Positionable.lua index 86843e1c1..01a6269d9 100644 --- a/Moose Development/Moose/Wrapper/Positionable.lua +++ b/Moose Development/Moose/Wrapper/Positionable.lua @@ -1449,8 +1449,8 @@ do -- Cargo self:F({Desc=Desc}) local Weights = { - ["C-17A"] = 35000, --77519 cannot be used, because it loads way too much apcs and infantry., - ["C-130"] = 22000 --The real value cannot be used, because it loads way too much apcs and infantry., + ["C-17A"] = 35000, --77519 cannot be used, because it loads way too much apcs and infantry. + ["C-130"] = 22000 --The real value cannot be used, because it loads way too much apcs and infantry. } self.__.CargoBayWeightLimit = Weights[Desc.typeName] or ( Desc.massMax - ( Desc.massEmpty + Desc.fuelMassMax ) ) @@ -1467,6 +1467,7 @@ do -- Cargo ["Higgins_boat"] = 3700, -- Higgins Boat can load 3700 kg of general cargo or 36 men (source wikipedia). ["USS_Samuel_Chase"] = 25000, -- Let's say 25 tons for now. Wiki says 33 Higgins boats, which would be 264 tons (can't be right!) and/or 578 troops. ["LST_Mk2"] =2100000, -- Can carry 2100 tons according to wiki source! + ["speedboat"] = 500, -- 500 kg ~ 5 persons } self.__.CargoBayWeightLimit = ( Weights[Desc.typeName] or 50000 )