From c823a686166183dcc5942159eb01cb3f7b6be4b8 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 2 Nov 2021 21:14:15 +0100 Subject: [PATCH] OPS - Fixed several bugs --- Moose Development/Moose/Ops/ArmyGroup.lua | 12 +- Moose Development/Moose/Ops/Auftrag.lua | 2 +- Moose Development/Moose/Ops/Chief.lua | 4 +- Moose Development/Moose/Ops/FlightGroup.lua | 2 +- Moose Development/Moose/Ops/NavyGroup.lua | 4 +- Moose Development/Moose/Ops/OpsGroup.lua | 184 ++++++++++++++----- Moose Development/Moose/Ops/OpsTransport.lua | 110 ++++++++--- 7 files changed, 238 insertions(+), 80 deletions(-) diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index fdb9fda9f..131c168b1 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -816,7 +816,7 @@ function ARMYGROUP:onafterSpawned(From, Event, To) -- Update route. if #self.waypoints>1 then self:T(self.lid.."Got waypoints on spawn ==> Cruise in -0.1 sec!") - self:__Cruise(-0.1, nil, self.option.Formation) + self:__Cruise(-1, nil, self.option.Formation) else self:T(self.lid.."No waypoints on spawn ==> Full Stop!") self:FullStop() @@ -910,7 +910,7 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation) wp.action=ENUMS.Formation.Vehicle.OffRoad -- Add "On Road" waypoint in between. - local wproad=wp.roadcoord:WaypointGround(wp.speed, ENUMS.Formation.Vehicle.OnRoad) --Ops.OpsGroup#OPSGROUP.Waypoint + local wproad=wp.roadcoord:WaypointGround(UTILS.MpsToKmph(wp.speed), ENUMS.Formation.Vehicle.OnRoad) --Ops.OpsGroup#OPSGROUP.Waypoint -- Insert road waypoint. table.insert(waypoints, wproad) @@ -946,10 +946,12 @@ function ARMYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Formation) -- Debug output. - if self.verbose>=5 then + if self.verbose>=0 then for i,_wp in pairs(waypoints) do - local wp=_wp + local wp=_wp --Ops.OpsGroup#OPSGROUP.Waypoint local text=string.format("WP #%d UID=%d type=%s: Speed=%d m/s, alt=%d m, Action=%s", i, wp.uid and wp.uid or -1, wp.type, wp.speed, wp.alt, wp.action) + local coord=COORDINATE:NewFromWaypoint(wp):MarkToAll(text) + --wp.coordinate:MarkToAll(text) self:T(text) end end @@ -1487,7 +1489,7 @@ function ARMYGROUP:onafterCruise(From, Event, To, Speed, Formation) self.Twaiting=nil self.dTwait=nil - self:__UpdateRoute(-1, nil, nil, Speed, Formation) + self:__UpdateRoute(-0.1, nil, nil, Speed, Formation) end diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 61fb8aa4b..e35841cb4 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -1760,7 +1760,7 @@ end --- **[GROUND, NAVAL]** Create an ON GUARD mission. -- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Coordinate, were to be on guard. +-- @param Core.Point#COORDINATE Coordinate Coordinate, where to stand guard. -- @return #AUFTRAG self function AUFTRAG:NewONGUARD(Coordinate) diff --git a/Moose Development/Moose/Ops/Chief.lua b/Moose Development/Moose/Ops/Chief.lua index 1e522f3fd..7a6ffe020 100644 --- a/Moose Development/Moose/Ops/Chief.lua +++ b/Moose Development/Moose/Ops/Chief.lua @@ -2161,7 +2161,9 @@ function CHIEF:RecruitAssetsForZone(StratZone, MissionType, NassetsMin, NassetsM elseif MissionType==AUFTRAG.Type.CAS then -- Create Patrol zone mission. - local mission=AUFTRAG:NewCAS(StratZone.opszone.zone, 7000) + --local mission=AUFTRAG:NewCAS(StratZone.opszone.zone, 7000) + local mission=AUFTRAG:NewPATROLZONE(StratZone.opszone.zone, 250, 7000) + mission:SetEngageDetected(25, TargetTypes,EngageZoneSet,NoEngageZoneSet) -- Add assets to mission. for _,asset in pairs(assets) do diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 65aa7c3f5..3850d41f0 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -2155,7 +2155,7 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime) --- -- Got current mission or task? - if self.currentmission==nil and self.taskcurrent==0 and self.cargoTransport==nil then + if self.currentmission==nil and self.taskcurrent==0 and (self.cargoTransport==nil or self.cargoTransport:GetCarrierTransportStatus(self)==OPSTRANSPORT.Status.DELIVERED) then -- Number of remaining tasks/missions? if nTasks==0 and nMissions==0 and nTransports==0 then diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index d76cd10b4..c0c581eb9 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -1008,7 +1008,7 @@ function NAVYGROUP:onafterUpdateRoute(From, Event, To, n, N, Speed, Depth) wp.speed=UTILS.KnotsToMps(Speed) else -- Take default waypoint speed. But make sure speed>0 if patrol ad infinitum. - if self.adinfinitum and wp.speed<0.1 then + if wp.speed<0.1 then --self.adinfinitum and wp.speed=UTILS.KmphToMps(self.speedCruise) end end @@ -1275,7 +1275,7 @@ function NAVYGROUP:onafterCruise(From, Event, To, Speed) -- No set depth. self.depth=nil - self:__UpdateRoute(-1, nil, nil, Speed) + self:__UpdateRoute(-0.1, nil, nil, Speed) end diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index f93519b40..ea6a20683 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -460,8 +460,7 @@ OPSGROUP.CargoStatus={ -- @type OPSGROUP.CargoGroup -- @field #OPSGROUP opsgroup The cargo opsgroup. -- @field #boolean delivered If `true`, group was delivered. --- @field #OPSGROUP disembarkCarrierGroup Carrier group where the cargo group is directly loaded to. --- @field #OPSGROUP disembarkCarrierElement Carrier element to which the cargo group is directly loaded to. +-- @field #boolean disembarkActivation If `true`, group is activated. If `false`, group is late activated. -- @field #string status Status of the cargo group. Not used yet. --- OpsGroup version. @@ -533,7 +532,6 @@ function OPSGROUP:New(group) self.isTrain=true elseif self.category==Group.Category.SHIP then self.isNavygroup=true - -- TODO submarine elseif self.category==Group.Category.AIRPLANE then self.isFlightgroup=true elseif self.category==Group.Category.HELICOPTER then @@ -3663,6 +3661,13 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) -- Just stay put. --TODO: Change ALARM STATE + if self:IsArmygroup() or self:IsNavygroup() then + -- Especially NAVYGROUP needs a full stop as patrol ad infinitum + self:FullStop() + else + -- FLIGHTGROUP not implemented (intended!) for this AUFTRAG type. + end + else -- If task is scheduled (not waypoint) set task. @@ -3874,10 +3879,17 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task) else if Task.description=="Engage_Target" then + self:T(self.lid.."Taske DONE Engage_Target ==> Cruise") self:Disengage() end + + if Task.description==AUFTRAG.SpecialTask.ONGUARD then + self:T(self.lid.."Taske DONE OnGuard ==> Cruise") + self:Cruise() + end if Task.description=="Task_Land_At" then + self:T(self.lid.."Taske DONE Task_Land_At ==> Wait") self:Wait(20, 100) else self:T(self.lid.."Task Done but NO mission found ==> _CheckGroupDone in 0 sec") @@ -3997,7 +4009,7 @@ function OPSGROUP:CountRemainingTransports() end -- In case we directly set the cargo transport (not in queue). - if N==0 and self.cargoTransport then + if N==0 and self.cargoTransport and self.cargoTransport:GetState()~=OPSTRANSPORT.Status.DELIVERED then N=1 end @@ -4916,32 +4928,46 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint) -- Final waypoint reached? if wpindex==nil or wpindex==#self.waypoints then - -- Ad infinitum? - if self.adinfinitum then - + -- Ad infinitum and not mission waypoint? + if self.adinfinitum then --- - -- Ad Infinitum and last waypoint reached. + -- Ad Infinitum --- - - if #self.waypoints<=1 then - -- Only one waypoint. Ad infinitum does not really make sense. However, another waypoint could be added later... - self:_PassedFinalWaypoint(true, "PassingWaypoint: adinfinitum but only ONE WAYPOINT left") + + if Waypoint.missionUID then + --- + -- Last waypoint was a mission waypoint ==> Do nothing (when mission is over, it should take care of this) + --- else - - -- Looks like the passing waypoint function is triggered over and over again if the group is near the final waypoint. - -- So the only good solution is to guide the group away from that waypoint and then update the route. - - -- Get first waypoint. - local wp1=self:GetWaypointByIndex(1) - - -- Get a waypoint - local Coordinate=Waypoint.coordinate:GetIntermediateCoordinate(wp1.coordinate, 0.1) - - -- Detour to the temp waypoint. When reached, the normal route is resumed. - self:Detour(Coordinate, self.speedCruise, nil, true) - + + --- + -- Last waypoint reached. + --- + + if #self.waypoints<=1 then + -- Only one waypoint. Ad infinitum does not really make sense. However, another waypoint could be added later... + self:_PassedFinalWaypoint(true, "PassingWaypoint: adinfinitum but only ONE WAYPOINT left") + else + + -- Looks like the passing waypoint function is triggered over and over again if the group is near the final waypoint. + -- So the only good solution is to guide the group away from that waypoint and then update the route. + + -- Get first waypoint. + local wp1=self:GetWaypointByIndex(1) + + -- Get a waypoint + local Coordinate=Waypoint.coordinate:GetIntermediateCoordinate(wp1.coordinate, 0.1) + + -- Detour to the temp waypoint. When reached, the normal route is resumed. + self:Detour(Coordinate, self.speedCruise, nil, true) + + end end else + --- + -- NOT Ad Infinitum + --- + -- Final waypoint reached. self:_PassedFinalWaypoint(true, "PassingWaypoint: wpindex=#self.waypoints (or wpindex=nil)") end @@ -6182,6 +6208,14 @@ function OPSGROUP:_CheckCargoTransport() self:I(self.lid.."Cargo queue:"..text) end end + + if self.cargoTransport and self.cargoTransport:GetCarrierTransportStatus(self)==OPSTRANSPORT.Status.DELIVERED then + -- Remove transport from queue. + self:DelOpsTransport(self.cargoTransport) + -- No current transport any more. + self.cargoTransport=nil + self.cargoTZC=nil + end -- Check if there is anything in the queue. if not self.cargoTransport and not self:IsOnMission() then @@ -6311,7 +6345,7 @@ function OPSGROUP:_CheckCargoTransport() -- Unloading finished ==> pickup next batch or call it a day. if delivered then self:T(self.lid.."Unloading finished ==> UnloadingDone") - self:__UnloadingDone(10) + self:UnloadingDone() else self:Unloading() end @@ -6614,11 +6648,14 @@ function OPSGROUP:DelOpsTransport(CargoTransport) local transport=self.cargoqueue[i] --Ops.OpsTransport#OPSTRANSPORT if transport.uid==CargoTransport.uid then + -- Debug info. + self:T(self.lid..string.format("Removing transport UID=%d", transport.uid)) + -- Remove from queue. table.remove(self.cargoqueue, i) -- Remove carrier from ops transport. - CargoTransport:_DelCarrier(self) + CargoTransport:_DelCarrier(self, 1) return self end @@ -6627,6 +6664,22 @@ function OPSGROUP:DelOpsTransport(CargoTransport) return self end +--- Get cargo transport assignment from the cargo queue by its unique ID. +-- @param #OPSGROUP self +-- @param #number uid Unique ID of the transport +-- @return Ops.OpsTransport#OPSTRANSPORT Transport. +function OPSGROUP:GetOpsTransportByUID(uid) + + for i=#self.cargoqueue,1,-1 do + local transport=self.cargoqueue[i] --Ops.OpsTransport#OPSTRANSPORT + if transport.uid==uid then + return transport + end + end + + return nil +end + --- Get total weight of the group including cargo. Optionally, the total weight of a specific unit can be requested. -- @param #OPSGROUP self @@ -7110,7 +7163,7 @@ function OPSGROUP:onafterPickup(From, Event, To) end -- NAVYGROUP - local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=1 + local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid, self.altitudeCruise) ; waypoint.detour=1 -- Give cruise command. self:__Cruise(-2) @@ -7397,9 +7450,16 @@ function OPSGROUP:onafterTransport(From, Event, To) self:__Unloading(-5) else + + local surfacetypes=nil + if self:IsArmygroup() then + surfacetypes={land.SurfaceType.LAND} + elseif self:IsNavygroup() then + surfacetypes={land.SurfaceType.WATER} + end -- Coord where the carrier goes to unload. - local Coordinate=Zone:GetRandomCoordinate() --Core.Point#COORDINATE + local Coordinate=Zone:GetRandomCoordinate(nil, nil, surfacetypes) --Core.Point#COORDINATE -- Add waypoint. if self:IsFlightgroup() then @@ -7452,6 +7512,14 @@ function OPSGROUP:onafterTransport(From, Event, To) -- Formation used for transporting. local Formation=self.cargoTransport:_GetFormationTransport(self.cargoTZC) + --[[ + local coordinate=self:GetCoordinate() + local pathonroad=coordinate:GetPathOnRoad(Coordinate, false, false, true) + if pathonroad then + env.info("FF got path on road") + end + ]] + if path then -- Loop over coordinates. for i,coordinate in pairs(path) do @@ -7483,7 +7551,7 @@ function OPSGROUP:onafterTransport(From, Event, To) end -- NAVYGROUP - local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid) ; waypoint.detour=1 + local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate, nil, uid, self.altitudeCruise) ; waypoint.detour=1 -- Give cruise command. self:Cruise() @@ -7585,26 +7653,40 @@ function OPSGROUP:onafterUnloading(From, Event, To) local Coordinate=nil - if DisembarkZone then + if DisembarkZone then -- Random coordinate in disembark zone. Coordinate=DisembarkZone:GetRandomCoordinate() else + + local element=cargo.opsgroup:_GetMyCarrierElement() + + if element then - -- Get random point in disembark zone. - local zoneCarrier=self:GetElementZoneUnload(cargo.opsgroup:_GetMyCarrierElement().name) - - -- Random coordinate/heading in the zone. - Coordinate=zoneCarrier:GetRandomCoordinate() + -- Get random point in disembark zone. + local zoneCarrier=self:GetElementZoneUnload(element.name) + + -- Random coordinate/heading in the zone. + Coordinate=zoneCarrier:GetRandomCoordinate() + + else + env.info(string.format("FF ERROR carrier element nil!")) + end end -- Random heading of the group. local Heading=math.random(0,359) + + -- Activation on/off. + local activation=self.cargoTransport:GetDisembarkActivation(self.cargoTZC) + if cargo.disembarkActivation~=nil then + activation=cargo.disembarkActivation + end -- Unload to Coordinate. - self:Unload(cargo.opsgroup, Coordinate, self.cargoTransport:GetDisembarkActivation(self.cargoTZC), Heading) + self:Unload(cargo.opsgroup, Coordinate, activation, Heading) end @@ -7771,6 +7853,7 @@ function OPSGROUP:onafterUnloadingDone(From, Event, To) if not delivered then + -- Get new TZC. self.cargoTZC=self.cargoTransport:_GetTransportZoneCombo(self) if self.cargoTZC then @@ -7856,17 +7939,18 @@ function OPSGROUP:onafterDelivered(From, Event, To, CargoTransport) self:__Cruise(0.1) end - -- Check group done. - self:T(self.lid.."All cargo delivered ==> check group done in 0.2 sec") - self:_CheckGroupDone(0.2) + -- Set carrier transport status. + self.cargoTransport:SetCarrierTransportStatus(self, OPSTRANSPORT.Status.DELIVERED) + + -- Check group done. + self:T(self.lid..string.format("All cargo of transport UID=%d delivered ==> check group done in 0.2 sec", self.cargoTransport.uid)) + self:_CheckGroupDone(0.2) + - -- No current transport any more. - self.cargoTransport=nil - self.cargoTZC=nil end -- Remove cargo transport from cargo queue. - self:DelOpsTransport(CargoTransport) + --self:DelOpsTransport(CargoTransport) end @@ -8023,7 +8107,8 @@ 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() and CarrierGroup:GetVelocity(Carrier.name)<=1)) or (CarrierGroup:IsFlightgroup() and (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 + if (CarrierIsArmyOrNavy 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() @@ -8036,7 +8121,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) if board then -- Debug info. - self:T(self.lid..string.format("Boarding group=%s [%s], carrier=%s", CarrierGroup:GetName(), CarrierGroup:GetState(), Carrier.name)) + self:T(self.lid..string.format("Boarding group=%s [%s], carrier=%s", CarrierGroup:GetName(), CarrierGroup:GetState(), tostring(Carrier.name))) -- TODO: Implement embarkzone. local Coordinate=Carrier.unit:GetCoordinate() @@ -8062,7 +8147,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) --- -- Debug info. - self:T(self.lid..string.format("Board with direct load to carrier %s", CarrierGroup:GetName())) + self:T(self.lid..string.format("Board [loaded=%s] with direct load to carrier group=%s, element=%s", tostring(self:IsLoaded()), CarrierGroup:GetName(), tostring(Carrier.name))) -- Get current carrier group. local mycarriergroup=self:_GetMyCarrierGroup() @@ -8071,8 +8156,9 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) end -- Unload cargo first. - if mycarriergroup and mycarriergroup:GetName()~=CarrierGroup:GetName() and self:IsLoaded() then + if mycarriergroup and mycarriergroup:GetName()~=CarrierGroup:GetName() then -- TODO: Unload triggers other stuff like Disembarked. This can be a problem! + self:T(self.lid.."Unloading from mycarrier") mycarriergroup:Unload(self) end @@ -8340,7 +8426,7 @@ function OPSGROUP:_CheckGroupDone(delay) -- Debug info. self:T(self.lid..string.format("Adinfinitum=TRUE ==> Goto WP index=%d at speed=%d knots", i, speed)) - + else self:E(self.lid..string.format("WARNING: No waypoints left! Commanding a Full Stop")) self:__FullStop(-1) diff --git a/Moose Development/Moose/Ops/OpsTransport.lua b/Moose Development/Moose/Ops/OpsTransport.lua index d515ae44b..1838be0de 100644 --- a/Moose Development/Moose/Ops/OpsTransport.lua +++ b/Moose Development/Moose/Ops/OpsTransport.lua @@ -503,8 +503,9 @@ end -- @param #OPSTRANSPORT self -- @param Core.Set#SET_GROUP GroupSet Set of groups to be transported. Can also be passed as a single GROUP or OPSGROUP object. -- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. +-- @param #boolean DisembarkActivation If `true`, cargo group is activated when disembarked. If `false`, cargo groups are late activated when disembarked. Default `nil` (usually activated). -- @return #OPSTRANSPORT self -function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo) +function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo, DisembarkActivation) -- Use default TZC if no transport zone combo is provided. TransportZoneCombo=TransportZoneCombo or self.tzcDefault @@ -513,7 +514,7 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo) if GroupSet:IsInstanceOf("GROUP") or GroupSet:IsInstanceOf("OPSGROUP") then -- We got a single GROUP or OPSGROUP object. - local cargo=self:_CreateCargoGroupData(GroupSet, TransportZoneCombo) + local cargo=self:_CreateCargoGroupData(GroupSet, TransportZoneCombo, DisembarkActivation) if cargo then @@ -536,7 +537,7 @@ function OPSTRANSPORT:AddCargoGroups(GroupSet, TransportZoneCombo) for _,group in pairs(GroupSet.Set) do -- Call iteravely for each group. - self:AddCargoGroups(group, TransportZoneCombo) + self:AddCargoGroups(group, TransportZoneCombo, DisembarkActivation) end end @@ -651,6 +652,58 @@ function OPSTRANSPORT:GetEmbarkZone(TransportZoneCombo) return TransportZoneCombo.EmbarkZone 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. Can also be passed as a #GROUP, #OPSGROUP or #SET_OPSGROUP object. +-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. +-- @return #OPSTRANSPORT self +function OPSTRANSPORT:SetEmbarkCarriers(Carriers, TransportZoneCombo) + + -- Debug info. + self:T(self.lid.."Setting embark carriers!") + + -- Use default TZC if no transport zone combo is provided. + TransportZoneCombo=TransportZoneCombo or self.tzcDefault + + if Carriers:IsInstanceOf("GROUP") or Carriers:IsInstanceOf("OPSGROUP") then + + local carrier=self:_GetOpsGroupFromObject(Carriers) + if carrier then + table.insert(TransportZoneCombo.EmbarkCarriers, carrier) + end + + elseif Carriers:IsInstanceOf("SET_GROUP") or Carriers:IsInstanceOf("SET_OPSGROUP") then + + for _,object in pairs(Carriers:GetSet()) do + local carrier=self:_GetOpsGroupFromObject(object) + if carrier then + table.insert(TransportZoneCombo.EmbarkCarriers, carrier) + end + end + + else + self:E(self.lid.."ERROR: Carriers must be a GROUP, OPSGROUP, SET_GROUP or SET_OPSGROUP object!") + end + + return self +end + +--- Get embark transfer carrier(s). These are carrier groups, where the cargo is directly loaded into when disembarked. +-- @param #OPSTRANSPORT self +-- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. +-- @return #table Table of carrier OPS groups. +function OPSTRANSPORT:GetEmbarkCarriers(TransportZoneCombo) + + -- Use default TZC if no transport zone combo is provided. + TransportZoneCombo=TransportZoneCombo or self.tzcDefault + + return TransportZoneCombo.EmbarkCarriers +end + +]] + --- Set disembark zone. -- @param #OPSTRANSPORT self -- @param Core.Zone#ZONE DisembarkZone Zone where the troops are disembarked. @@ -953,19 +1006,24 @@ end --- Remove group from the current carrier list/table. -- @param #OPSTRANSPORT self -- @param Ops.OpsGroup#OPSGROUP CarrierGroup Carrier OPSGROUP. +-- @param #number Delay Delay in seconds before the carrier is removed. -- @return #OPSTRANSPORT self -function OPSTRANSPORT:_DelCarrier(CarrierGroup) +function OPSTRANSPORT:_DelCarrier(CarrierGroup, Delay) - if self:IsCarrier(CarrierGroup) then - - for i=#self.carriers,1,-1 do - local carrier=self.carriers[i] --Ops.OpsGroup#OPSGROUP - if carrier.groupname==CarrierGroup.groupname then - self:T(self.lid..string.format("Removing carrier %s", CarrierGroup.groupname)) - table.remove(self.carriers, i) + if Delay and Delay>0 then + self:ScheduleOnce(Delay, OPSTRANSPORT._DelCarrier, CarrierGroup) + else + if self:IsCarrier(CarrierGroup) then + + for i=#self.carriers,1,-1 do + local carrier=self.carriers[i] --Ops.OpsGroup#OPSGROUP + if carrier.groupname==CarrierGroup.groupname then + self:T(self.lid..string.format("Removing carrier %s", CarrierGroup.groupname)) + table.remove(self.carriers, i) + end end + end - end return self @@ -1280,6 +1338,13 @@ end -- @return #OPSTRANSPORT self function OPSTRANSPORT:SetCarrierTransportStatus(CarrierGroup, Status) + -- Old status + local oldstatus=self:GetCarrierTransportStatus(CarrierGroup) + + -- Debug info. + self:I(self.lid..string.format("New carrier transport status for %s: %s --> %s", CarrierGroup:GetName(), oldstatus, Status)) + + -- Set new status. self.carrierTransportStatus[CarrierGroup.groupname]=Status return self @@ -1290,7 +1355,8 @@ end -- @param Ops.OpsGroup#OPSGROUP CarrierGroup Carrier OPSGROUP. -- @return #string Carrier status. function OPSTRANSPORT:GetCarrierTransportStatus(CarrierGroup) - return self.carrierTransportStatus[CarrierGroup.groupname] + local status=self.carrierTransportStatus[CarrierGroup.groupname] or "unknown" + return status end --- Get unique ID of the transport assignment. @@ -1423,10 +1489,12 @@ end -- @return #boolean If true, group is an assigned carrier. function OPSTRANSPORT:IsCarrier(CarrierGroup) - for _,_carrier in pairs(self.carriers) do - local carrier=_carrier --Ops.OpsGroup#OPSGROUP - if carrier.groupname==CarrierGroup.groupname then - return true + if CarrierGroup then + for _,_carrier in pairs(self.carriers) do + local carrier=_carrier --Ops.OpsGroup#OPSGROUP + if carrier.groupname==CarrierGroup.groupname then + return true + end end end @@ -2001,9 +2069,10 @@ end --- Create a cargo group data structure. -- @param #OPSTRANSPORT self -- @param Wrapper.Group#GROUP group The GROUP or OPSGROUP object. --- @return Ops.OpsGroup#OPSGROUP.CargoGroup Cargo group data. -- @param #OPSTRANSPORT.TransportZoneCombo TransportZoneCombo Transport zone combo. -function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo) +-- @param #boolean DisembarkActivation If `true`, cargo group is activated when disembarked. +-- @return Ops.OpsGroup#OPSGROUP.CargoGroup Cargo group data. +function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo, DisembarkActivation) -- Get ops group. local opsgroup=self:_GetOpsGroupFromObject(group) @@ -2024,8 +2093,7 @@ function OPSTRANSPORT:_CreateCargoGroupData(group, TransportZoneCombo) cargo.opsgroup=opsgroup cargo.delivered=false cargo.status="Unknown" - cargo.disembarkCarrierElement=nil - cargo.disembarkCarrierGroup=nil + cargo.disembarkActivation=DisembarkActivation cargo.tzcUID=TransportZoneCombo return cargo