From 3c6e8d6d01e31f1ce06c0cc690e8a2e2a7d99aa1 Mon Sep 17 00:00:00 2001 From: Frank Date: Thu, 1 Jul 2021 12:29:29 +0200 Subject: [PATCH] OPS - Transport - Respawn --- Moose Development/Moose/Ops/FlightGroup.lua | 2 +- Moose Development/Moose/Ops/OpsGroup.lua | 177 +++++++++---------- Moose Development/Moose/Ops/OpsTransport.lua | 70 +++++--- 3 files changed, 121 insertions(+), 128 deletions(-) diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index c68ae0edc..5534aa11e 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -863,7 +863,7 @@ function FLIGHTGROUP:onafterStatus(From, Event, To) -- FSM state. local fsmstate=self:GetState() - + -- Update position. self:_UpdatePosition() diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 5273b0176..fc0022178 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -525,7 +525,7 @@ function OPSGROUP:New(group) -- Add FSM transitions. -- From State --> Event --> To State self:AddTransition("InUtero", "Spawned", "Spawned") -- The whole group was spawned. - self:AddTransition("*", "Respawn", "*") -- Respawn group. + self:AddTransition("*", "Respawn", "InUtero") -- Respawn group. self:AddTransition("*", "Dead", "Dead") -- The whole group is dead. self:AddTransition("*", "InUtero", "InUtero") -- Deactivated group goes back to mummy. self:AddTransition("*", "Stop", "Stopped") -- Stop FSM. @@ -4473,7 +4473,7 @@ end -- @param #string To To state. -- @param #OPSGROUP.Element Element The flight group element. function OPSGROUP:onafterElementInUtero(From, Event, To, Element) - self:I(self.lid..string.format("Element in utero %s", Element.name)) + self:T(self.lid..string.format("Element in utero %s", Element.name)) -- Set element status. self:_UpdateStatus(Element, OPSGROUP.ElementStatus.INUTERO) @@ -4503,9 +4503,6 @@ function OPSGROUP:onafterElementDestroyed(From, Event, To, Element) -- Element is dead. self:ElementDead(Element) - -- Set element status. - --self:_UpdateStatus(Element, OPSGROUP.ElementStatus.DEAD) - end --- On after "ElementDead" event. @@ -4554,36 +4551,40 @@ function OPSGROUP:onafterElementDead(From, Event, To, Element) end end - - -- Check cargo bay and declare cargo groups dead. - for _,_element in pairs(self.elements) do - local element=_element --#OPSGROUP.Element - for _,_cargo in pairs(element.cargoBay) do - local cargo=_cargo --#OPSGROUP.MyCargo - if cargo.group and not (cargo.group:IsDead() or cargo.group:IsStopped()) then + + -- Clear cargo bay of element. + --for _,_cargo in pairs(Element.cargoBay) do + for i=#Element.cargoBay,1,-1 do + local cargo=Element.cargoBay[i] --#OPSGROUP.MyCargo --_cargo --#OPSGROUP.MyCargo + + -- Remove from cargo bay. + self:_DelCargobay(cargo.group) + + if cargo.group and not (cargo.group:IsDead() or cargo.group:IsStopped()) then + + -- Remove my carrier + cargo.group:_RemoveMyCarrier() - -- Remove my carrier - cargo.group:_RemoveMyCarrier() + if cargo.reserved then + + -- This group was not loaded yet ==> Not cargo any more. + cargo.group.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO - if cargo.reserved then - -- This group was not loaded yet ==> Not cargo any more. - cargo.group.cargoStatus=OPSGROUP.CargoStatus.NOTCARGO - else - - -- Carrier dead ==> cargo dead. - for _,cargoelement in pairs(cargo.group.elements) do - - -- Debug info. - self:T2(self.lid.."Cargo element dead "..cargoelement.name) - - -- Trigger dead event. - cargo.group:ElementDead(cargoelement) - - end + else + + -- Carrier dead ==> cargo dead. + for _,cargoelement in pairs(cargo.group.elements) do + + -- Debug info. + self:T2(self.lid.."Cargo element dead "..cargoelement.name) + + -- Trigger dead event. + cargo.group:ElementDead(cargoelement) + end - - end - end + end + + end end end @@ -4596,14 +4597,15 @@ end -- @param #table Template The template used to respawn the group. Default is the inital template of the group. function OPSGROUP:onafterRespawn(From, Event, To, Template) + -- Debug info. self:I(self.lid.."Respawning group!") + -- Copy template. local template=UTILS.DeepCopy(Template or self.template) + -- Late activation off. template.lateActivation=false - --self.respawning=true - self:_Respawn(0, template) end @@ -4686,12 +4688,8 @@ function OPSGROUP:_Respawn(Delay, Template, Reset) end -- Debug output. - self:I({Template=Template}) + self:T({Template=Template}) - --if self:IsStopped() then - --self:InitWaypoints() - --end - -- Spawn new group. _DATABASE:Spawn(Template) @@ -4699,6 +4697,10 @@ function OPSGROUP:_Respawn(Delay, Template, Reset) self.isLateActivated=Template.lateActivation self.isUncontrolled=Template.uncontrolled + -- Not dead or destroyed any more. + self.isDead=false + self.isDestroyed=false + self.Ndestroyed=0 -- Reset events. --self:ResetEvents() @@ -4765,7 +4767,7 @@ function OPSGROUP:onafterDead(From, Event, To) mycarrier:_DelCargobay(self) self:_RemoveMyCarrier() end - + -- Inform all transports in the queue that this carrier group is dead now. for i,_transport in pairs(self.cargoqueue) do local transport=_transport --Ops.OpsTransport#OPSTRANSPORT @@ -4783,7 +4785,9 @@ end -- @param #string To To state. function OPSGROUP:onbeforeStop(From, Event, To) + -- We check if if self:IsAlive() then + self:E(self.lid..string.format("WARNING: Group is still alive! Will not stop the FSM. Use :Despawn() instead")) return false end @@ -4849,7 +4853,7 @@ function OPSGROUP:_CheckCargoTransport() -- Cargo bay debug info. -- Check cargo bay and declare cargo groups dead. - if self.verbose>=0 then + if self.verbose>=1 then local text="" for _,_element in pairs(self.elements) do local element=_element --#OPSGROUP.Element @@ -4858,9 +4862,10 @@ function OPSGROUP:_CheckCargoTransport() text=text..string.format("\n- %s in carrier %s, reserved=%s", tostring(cargo.group:GetName()), tostring(element.name), tostring(cargo.reserved)) end end - if text~="" then - self:I(self.lid.."Cargo bay:"..text) - end + if text=="" then + text=" empty" + end + self:I(self.lid.."Cargo bay:"..text) end -- Cargo queue debug info. @@ -5110,47 +5115,15 @@ function OPSGROUP:_DelCargobay(CargoGroup) self.cargoBay[CargoGroup.groupname]=nil end - - - --[[ - local MyCarrierGroup, MyCarrierElement, MyIsReserved=CargoGroup:_GetMyCarrier() - - if MyCarrierGroup and MyCarrierGroup.groupname==self.groupname then - if not IsReserved then - - -- Reduce carrier weight. - local weight=CargoGroup:GetWeightTotal() - - self:RedWeightCargo(CarrierElement.name, weight) - - end - - end - ]] - - - -- Loop over elements and their cargo bay items. - --[[ - local CarrierElement=nil --#OPSGROUP.Element - local cargobayIndex=nil - local reserved=nil - for i,_element in pairs(self.elements) do - local element=_element --#OPSGROUP.Element - for j,_cargo in pairs(element.cargoBay) do - local cargo=_cargo --#OPSGROUP.MyCargo - if cargo.group and cargo.group.groupname==CargoGroup.groupname then - CarrierElement=element - cargobayIndex=j - reserved=cargo.reserved - end - end - end - ]] - + + -- Get cargo bay info. local cargoBayItem, cargoBayIndex, CarrierElement=self:_GetCargobay(CargoGroup) if cargoBayItem and cargoBayIndex then + -- Debug info. + self:T(self.lid..string.format("Removing cargo group %s from cargo bay (index=%d) of carrier %s", CargoGroup:GetName(), cargoBayIndex, CarrierElement.name)) + -- Remove table.remove(CarrierElement.cargoBay, cargoBayIndex) @@ -5163,7 +5136,7 @@ function OPSGROUP:_DelCargobay(CargoGroup) return true end - env.error(self.lid.."ERROR: Group is not in cargo bay. Cannot remove it!") + self:E(self.lid.."ERROR: Group is not in cargo bay. Cannot remove it!") return false end @@ -5320,13 +5293,18 @@ end -- @return #number Free cargo bay in kg. function OPSGROUP:GetFreeCargobay(UnitName, IncludeReserved) + -- Max cargo weight. local weightCargoMax=self:GetWeightCargoMax(UnitName) + -- Current cargo weight. local weightCargo=self:GetWeightCargo(UnitName, IncludeReserved) + -- Free cargo. local Free=weightCargoMax-weightCargo - self:I(self.lid..string.format("Free cargo bay=%d kg (unit=%s)", Free, (UnitName or "whole group"))) + -- Debug info. + self:T(self.lid..string.format("Free cargo bay=%d kg (unit=%s)", Free, (UnitName or "whole group"))) + return Free end @@ -5368,6 +5346,7 @@ end -- @return #number Cargo weight in kg. function OPSGROUP:GetWeightCargo(UnitName, IncludeReserved) + -- Calculate weight based on actual cargo weight. local weight=0 for _,_element in pairs(self.elements) do local element=_element --#OPSGROUP.Element @@ -5380,20 +5359,28 @@ function OPSGROUP:GetWeightCargo(UnitName, IncludeReserved) end + -- Calculate weight from stuff in cargo bay. By default this includes the reserved weight if a cargo group was assigned and is currently boarding. local gewicht=0 for _,_element in pairs(self.elements) do local element=_element --#OPSGROUP.Element if (UnitName==nil or UnitName==element.name) and (element and element.status~=OPSGROUP.ElementStatus.DEAD) then 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 - gewicht=gewicht+cargo.group:GetWeightTotal() + if (not cargo.reserved) or (cargo.reserved==true and (IncludeReserved==true or IncludeReserved==nil)) then + local cargoweight=cargo.group:GetWeightTotal() + gewicht=gewicht+cargoweight + --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 end end + + -- Debug info. + self:T2(self.lid..string.format("Unit=%s (reserved=%s): weight=%d, gewicht=%d", tostring(UnitName), tostring(IncludeReserved), weight, gewicht)) + + -- Quick check. if IncludeReserved==false and gewicht~=weight then - self:I(self.lid..string.format("ERROR: FF weight!=gewicht: weight=%.1f, gewicht=%.1f", weight, gewicht)) + self:E(self.lid..string.format("ERROR: FF weight!=gewicht: weight=%.1f, gewicht=%.1f", weight, gewicht)) end return gewicht @@ -5434,7 +5421,7 @@ function OPSGROUP:AddWeightCargo(UnitName, Weight) element.weightCargo=element.weightCargo+Weight -- Debug info. - self:I(self.lid..string.format("FF %s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo)) + self:T(self.lid..string.format("%s: Adding %.1f kg cargo weight. New cargo weight=%.1f kg", UnitName, Weight, element.weightCargo)) -- For airborne units, we set the weight in game. if self.isFlightgroup then @@ -5516,7 +5503,7 @@ end function OPSGROUP:_SetMyCarrier(CarrierGroup, CarrierElement, Reserved) -- Debug info. - self:I(self.lid..string.format("Setting My Carrier: %s (%s), reserved=%s", CarrierGroup:GetName(), tostring(CarrierElement.name), tostring(Reserved))) + self:T(self.lid..string.format("Setting My Carrier: %s (%s), reserved=%s", CarrierGroup:GetName(), tostring(CarrierElement.name), tostring(Reserved))) self.mycarrier.group=CarrierGroup self.mycarrier.element=CarrierElement @@ -5572,6 +5559,7 @@ end -- @param #OPSGROUP self -- @return #OPSGROUP self function OPSGROUP:_RemoveMyCarrier() + self:I(self.lid..string.format("Removing my carrier!")) self.mycarrier.group=nil self.mycarrier.element=nil self.mycarrier.reserved=nil @@ -5635,8 +5623,6 @@ function OPSGROUP:onafterPickup(From, Event, To) -- Add waypoint. if self.isFlightgroup then - - env.info("FF pickup is flightgroup") if airbasePickup then @@ -5651,13 +5637,10 @@ function OPSGROUP:onafterPickup(From, Event, To) -- Activate uncontrolled group. if self:IsParking() then - env.info("FF pickup start uncontrolled while parking at current airbase") self:StartUncontrolled() end else - - env.info("FF pickup land at airbase") -- Order group to land at an airbase. self:LandAtAirbase(airbasePickup) @@ -5669,12 +5652,9 @@ function OPSGROUP:onafterPickup(From, Event, To) --- -- Helo can also land in a zone (NOTE: currently VTOL cannot!) --- - - env.info("FF pickup helo addwaypoint") -- Activate uncontrolled group. if self:IsParking() then - env.info("FF pickup start uncontrolled while parking airbase") self:StartUncontrolled() end @@ -5809,6 +5789,7 @@ end -- @param #OPSGROUP CargoGroup The OPSGROUP loaded as cargo. -- @param #OPSGROUP.Element Carrier The carrier element/unit. function OPSGROUP:onafterLoad(From, Event, To, CargoGroup, Carrier) + -- Debug info. self:I(self.lid..string.format("Loading group %s", tostring(CargoGroup.groupname))) @@ -5904,6 +5885,7 @@ end -- @param #string Event Event. -- @param #string To To state. function OPSGROUP:onafterTransport(From, Event, To) + -- Debug info. self:I(self.lid..string.format("New carrier status: %s --> %s", self.carrierStatus, OPSGROUP.CarrierStatus.TRANSPORTING)) @@ -6107,7 +6089,7 @@ function OPSGROUP:onafterUnloading(From, Event, To) --- -- Issue warning. - env.info("ERROR: Deploy/disembark zone is a ZONE_AIRBASE of a ship! Where to put the cargo? Dumping into the sea, sorry!") + self:E(self.lid.."ERROR: Deploy/disembark zone is a ZONE_AIRBASE of a ship! Where to put the cargo? Dumping into the sea, sorry!") --TODO: Dumb into sea. else @@ -6479,7 +6461,6 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) -- Set carrier. As long as the group is not loaded, we only reserve the cargo space.´ CarrierGroup:_AddCargobay(self, Carrier, true) - --self:_SetMyCarrier(CarrierGroup, Carrier, true) end diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index 3b5434add..c8d69a5ca 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -32,9 +32,11 @@ -- @field #table cargos Cargos. Each element is a @{Ops.OpsGroup#OPSGROUP.CargoGroup}. -- @field #table carriers Carriers assigned for this transport. -- @field #number prio Priority of this transport. Should be a number between 0 (high prio) and 100 (low prio). +-- @field #boolean urgent If true, transport is urgent. -- @field #number importance Importance of this transport. Smaller=higher. -- @field #number Tstart Start time in *abs.* seconds. -- @field #number Tstop Stop time in *abs.* seconds. Default `#nil` (never stops). +-- @field #number duration Duration (`Tstop-Tstart`) of the transport in seconds. -- @field #table conditionStart Start conditions. -- @field Core.Zone#ZONE pickupzone Zone where the cargo is picked up. -- @field Core.Zone#ZONE deployzone Zone where the cargo is dropped off. @@ -70,7 +72,7 @@ -- @field #OPSTRANSPORT OPSTRANSPORT = { ClassName = "OPSTRANSPORT", - verbose = 1, + verbose = 0, cargos = {}, carriers = {}, carrierTransportStatus = {}, @@ -108,12 +110,13 @@ _OPSTRANSPORTID=0 --- Army Group version. -- @field #string version -OPSTRANSPORT.version="0.0.7" +OPSTRANSPORT.version="0.0.8" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- TODO: Stop/abort transport. -- DONE: Add start conditions. -- DONE: Check carrier(s) dead. @@ -140,7 +143,6 @@ function OPSTRANSPORT:New(GroupSet, Pickupzone, Deployzone) -- Defaults. self.uid=_OPSTRANSPORTID - --self.status=OPSTRANSPORT.Status.PLANNING self.pickupzone=Pickupzone self.deployzone=Deployzone @@ -277,7 +279,8 @@ end -- @return #OPSTRANSPORT self function OPSTRANSPORT:SetDisembarkCarriers(Carriers) - self:I(self.lid.."Setting transfer carriers!") + -- Debug info. + self:T(self.lid.."Setting transfer carriers!") -- Create table. self.disembarkCarriers=self.disembarkCarriers or {} @@ -326,7 +329,8 @@ end -- @return #OPSTRANSPORT self function OPSTRANSPORT:SetRequiredCargos(Cargos) - self:I(self.lid.."Setting required cargos!") + -- Debug info. + self:T(self.lid.."Setting required cargos!") -- Create table. self.requiredCargos=self.requiredCargos or {} @@ -390,11 +394,11 @@ function OPSTRANSPORT:_DelCarrier(CarrierGroup) if self:IsCarrier(CarrierGroup) then - for i,_carrier in pairs(self.carriers) do - local carrier=_carrier --Ops.OpsGroup#OPSGROUP + for i=#self.carriers,1,-1 do + local carrier=self.carriers[i] --Ops.OpsGroup#OPSGROUP if carrier.groupname==CarrierGroup.groupname then - self:I(self.lid..string.format("Removing carrier %s", CarrierGroup.groupname)) - table.remove(self.carriers, i) + self:T(self.lid..string.format("Removing carrier %s", CarrierGroup.groupname)) + table.remove(self.carriers, i) end end @@ -704,29 +708,37 @@ function OPSTRANSPORT:onafterStatus(From, Event, To) -- Current FSM state. local fsmstate=self:GetState() - -- Info text. - local text=string.format("%s [%s --> %s]: Ncargo=%d/%d, Ncarrier=%d/%d", fsmstate:upper(), self.pickupzone:GetName(), self.deployzone:GetName(), self.Ncargo, self.Ndelivered, #self.carriers,self.Ncarrier) + if self.verbose>=1 then - text=text..string.format("\nCargos:") - for _,_cargo in pairs(self.cargos) do - local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup - 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]", cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate) + -- Info text. + local text=string.format("%s [%s --> %s]: Ncargo=%d/%d, Ncarrier=%d/%d", fsmstate:upper(), self.pickupzone:GetName(), self.deployzone:GetName(), self.Ncargo, self.Ndelivered, #self.carriers,self.Ncarrier) + + -- Info about cargo and carrier. + if self.verbose>=2 then + + text=text..string.format("\nCargos:") + for _,_cargo in pairs(self.cargos) do + local cargo=_cargo --Ops.OpsGroup#OPSGROUP.CargoGroup + 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", + cargo.opsgroup:GetName(), cargo.opsgroup.cargoStatus:upper(), cargo.opsgroup:GetState(), cargo.opsgroup:GetWeightTotal(), name, cstate, tostring(cargo.delivered)) + end + + text=text..string.format("\nCarriers:") + for _,_carrier in pairs(self.carriers) do + local carrier=_carrier --Ops.OpsGroup#OPSGROUP + text=text..string.format("\n- %s: %s [%s], Cargo Bay [current/reserved/total]=%d/%d/%d kg [free %d/%d/%d kg]", + carrier:GetName(), carrier.carrierStatus:upper(), carrier:GetState(), + carrier:GetWeightCargo(nil, false), carrier:GetWeightCargo(), carrier:GetWeightCargoMax(), + carrier:GetFreeCargobay(nil, false), carrier:GetFreeCargobay(), carrier:GetFreeCargobayMax()) + end + end + + self:I(self.lid..text) end - text=text..string.format("\nCarriers:") - for _,_carrier in pairs(self.carriers) do - local carrier=_carrier --Ops.OpsGroup#OPSGROUP - text=text..string.format("\n- %s: %s [%s], Cargo Bay [current/reserved/total]=%d/%d/%d kg [free %d/%d/%d kg]", - carrier:GetName(), carrier.carrierStatus:upper(), carrier:GetState(), - carrier:GetWeightCargo(nil, false), carrier:GetWeightCargo(), carrier:GetWeightCargoMax(), - carrier:GetFreeCargobay(nil, false), carrier:GetFreeCargobay(), carrier:GetFreeCargobayMax()) - end - - self:I(self.lid..text) - -- Check if all cargo was delivered (or is dead). self:_CheckDelivered()