From 259b201e65f14625b5411a3575c94a34b76c2ec6 Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 24 Aug 2021 23:10:38 +0200 Subject: [PATCH] OPS Good version solving a few bugs and adding some new stuff. --- Moose Development/Moose/Core/Point.lua | 9 +- Moose Development/Moose/Ops/ArmyGroup.lua | 6 +- Moose Development/Moose/Ops/FlightGroup.lua | 53 +++-- Moose Development/Moose/Ops/NavyGroup.lua | 4 +- Moose Development/Moose/Ops/OpsGroup.lua | 207 +++++++++++++------- 5 files changed, 185 insertions(+), 94 deletions(-) diff --git a/Moose Development/Moose/Core/Point.lua b/Moose Development/Moose/Core/Point.lua index b450eebbf..4245e9591 100644 --- a/Moose Development/Moose/Core/Point.lua +++ b/Moose Development/Moose/Core/Point.lua @@ -225,6 +225,8 @@ do -- COORDINATE -- @field #string FlyoverPoint Fly over point. -- @field #string FromParkingArea From parking area. -- @field #string FromParkingAreaHot From parking area hot. + -- @field #string FromGroundAreaHot From ground area hot. + -- @field #string FromGroundArea From ground area. -- @field #string FromRunway From runway. -- @field #string Landing Landing. -- @field #string LandingReFuAr Landing and refuel and rearm. @@ -233,6 +235,8 @@ do -- COORDINATE FlyoverPoint = "Fly Over Point", FromParkingArea = "From Parking Area", FromParkingAreaHot = "From Parking Area Hot", + FromGroundAreaHot = "From Ground Area Hot", + FromGroundArea = "From Ground Area", FromRunway = "From Runway", Landing = "Landing", LandingReFuAr = "LandingReFuAr", @@ -243,6 +247,7 @@ do -- COORDINATE -- @field #string TakeOffParking Take of parking. -- @field #string TakeOffParkingHot Take of parking hot. -- @field #string TakeOff Take off parking hot. + -- @field #string TakeOffGroundHot Take of from ground hot. -- @field #string TurningPoint Turning point. -- @field #string Land Landing point. -- @field #string LandingReFuAr Landing and refuel and rearm. @@ -250,9 +255,11 @@ do -- COORDINATE TakeOffParking = "TakeOffParking", TakeOffParkingHot = "TakeOffParkingHot", TakeOff = "TakeOffParkingHot", + TakeOffGroundHot = "TakeOffGroundHot", + TakeOffGround = "TakeOffGround", TurningPoint = "Turning Point", Land = "Land", - LandingReFuAr = "LandingReFuAr", + LandingReFuAr = "LandingReFuAr", } diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index c3e957dfe..3c5a9d193 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -83,7 +83,7 @@ ARMYGROUP.version="0.7.0" -- @param Wrapper.Group#GROUP group The GROUP object. Can also be given by its group name as `#string`. -- @return #ARMYGROUP self function ARMYGROUP:New(group) - + -- First check if we already have an OPS group for this group. local og=_DATABASE:GetOpsGroup(group) if og then @@ -91,6 +91,9 @@ function ARMYGROUP:New(group) return og end + -- First set ARMYGROUP. + self.isArmygroup=true + -- Inherit everything from FSM class. local self=BASE:Inherit(self, OPSGROUP:New(group)) -- #ARMYGROUP @@ -98,7 +101,6 @@ function ARMYGROUP:New(group) self.lid=string.format("ARMYGROUP %s | ", self.groupname) -- Defaults - self.isArmygroup=true self:SetDefaultROE() self:SetDefaultAlarmstate() self:SetDetection() diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 18a804e6b..a01333e08 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -208,6 +208,9 @@ function FLIGHTGROUP:New(group) return og end + -- First set FLIGHTGROUP. + self.isFlightgroup=true + -- Inherit everything from FSM class. local self=BASE:Inherit(self, OPSGROUP:New(group)) -- #FLIGHTGROUP @@ -215,7 +218,6 @@ function FLIGHTGROUP:New(group) self.lid=string.format("FLIGHTGROUP %s | ", self.groupname) -- Defaults - self.isFlightgroup=true self:SetFuelLowThreshold() self:SetFuelLowRTB() self:SetFuelCriticalThreshold() @@ -1853,6 +1855,9 @@ function FLIGHTGROUP:onafterArrived(From, Event, To) -- Check what to do. if airwing then + -- Debug info. + self:T(self.lid..string.format("Airwing asset group %s arrived ==> Adding asset back to stock of airwing %s", self.groupname, airwing.alias)) + -- Add the asset back to the airwing. airwing:AddAsset(self.group, 1) @@ -2018,6 +2023,9 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n) -- For patrol zone, we need to allow the update as we insert new waypoints. elseif task.dcstask.id=="ReconMission" then -- For recon missions, we need to allow the update as we insert new waypoints. + elseif task.description and task.description=="Task_Land_At" then + -- We allow this + env.info("FF allowing update route for Task_Land_At") else local taskname=task and task.description or "No description" self:E(self.lid..string.format("WARNING: Update route denied because taskcurrent=%d>0! Task description = %s", self.taskcurrent, tostring(taskname))) @@ -2075,9 +2083,9 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n) local waypointAction=COORDINATE.WaypointAction.TurningPoint if self:IsLanded() or self:IsLandedAt() or self:IsAirborne()==false then -- Had some issues with passing waypoint function of the next WP called too ealy when the type is TurningPoint. Setting it to TakeOff solved it! - waypointType=COORDINATE.WaypointType.TakeOff - env.info("FF takeoff type waypoint") - --waypointAction=COORDINATE.WaypointAction.FromParkingArea + --waypointType=COORDINATE.WaypointType.TakeOff + waypointType=COORDINATE.WaypointType.TakeOffGroundHot + waypointAction=COORDINATE.WaypointAction.FromGroundAreaHot end -- Set current waypoint or we get problem that the _PassingWaypoint function is triggered too early, i.e. right now and not when passing the next WP. @@ -2097,10 +2105,12 @@ function FLIGHTGROUP:onafterUpdateRoute(From, Event, To, n) self:T(self.lid..string.format("Updating route for WP #%d-%d [%s], homebase=%s destination=%s", n, #wp, self:GetState(), hb, db)) -- Print waypoints. + --[[ for i,w in pairs(wp) do env.info("FF waypoint index="..i) self:I(w) end + ]] if #wp>1 then @@ -2164,15 +2174,21 @@ end -- @param #number waittime Time to wait if group is done. function FLIGHTGROUP:_CheckGroupDone(delay, waittime) + -- FSM state. + local fsmstate=self:GetState() + if self:IsAlive() and self.isAI then if delay and delay>0 then + -- Debug info. + self:T(self.lid..string.format("Check FLIGHTGROUP [state=%s] done in %.3f seconds...", fsmstate, delay)) + -- Delayed call. self:ScheduleOnce(delay, FLIGHTGROUP._CheckGroupDone, self) else -- Debug info. - self:T(self.lid.."Check FLIGHTGROUP done?") + self:T(self.lid..string.format("Check FLIGHTGROUP [state=%s] done?", fsmstate)) -- First check if there is a paused mission that if self.missionpaused then @@ -2188,7 +2204,7 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime) -- Group is ordered to land at an airbase. if self.isLandingAtAirbase then - self:T(self.lid.."Landing at airbase! Group NOT done...") + self:T(self.lid..string.format("Landing at airbase %s! Group NOT done...", self.isLandingAtAirbase:GetName())) return end @@ -2211,7 +2227,7 @@ function FLIGHTGROUP:_CheckGroupDone(delay, waittime) self:T(self.lid..string.format("Remaining (final=%s): missions=%d, tasks=%d, transports=%d", tostring(self.passedfinalwp), nMissions, nTasks, nTransports)) -- Final waypoint passed? - if self.passedfinalwp then + if self:HasPassedFinalWaypoint() then --- -- Final Waypoint PASSED @@ -2445,6 +2461,7 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand) local text=string.format("Flight group set to hold at airbase %s. SpeedTo=%d, SpeedHold=%d, SpeedLand=%d", airbase:GetName(), SpeedTo, SpeedHold, SpeedLand) self:T(self.lid..text) + -- Holding altitude. local althold=self.isHelo and 1000+math.random(10)*100 or math.random(4,10)*1000 -- Holding points. @@ -2481,11 +2498,13 @@ function FLIGHTGROUP:_LandAtAirbase(airbase, SpeedTo, SpeedHold, SpeedLand) local h1=x1*math.tan(alpha) local h2=x2*math.tan(alpha) + -- Get active runway. local runway=airbase:GetActiveRunway() -- Set holding flag to 0=false. self.flaghold:Set(0) + -- Set holding time. local holdtime=2*60 if fc or self.airboss then holdtime=nil @@ -2557,14 +2576,14 @@ function FLIGHTGROUP:onbeforeWait(From, Event, To, Duration, Altitude, Speed) local Tsuspend=nil -- Check for a current task. - if self.taskcurrent>0 then + if self.taskcurrent>0 and not self:IsLandedAt() then self:I(self.lid..string.format("WARNING: Got current task ==> WAIT event is suspended for 30 sec!")) Tsuspend=-30 allowed=false end -- Check for a current transport assignment. - if self.cargoTransport then + if self.cargoTransport and not self:IsLandedAt() then self:I(self.lid..string.format("WARNING: Got current TRANSPORT assignment ==> WAIT event is suspended for 30 sec!")) Tsuspend=-30 allowed=false @@ -2604,14 +2623,6 @@ function FLIGHTGROUP:onafterWait(From, Event, To, Duration, Altitude, Speed) --TODO: set ROE passive. introduce roe event/state/variable. - -- Orbit task. - local TaskOrbit=self.group:TaskOrbit(Coord, UTILS.FeetToMeters(Altitude), UTILS.KnotsToMps(Speed)) - - -- Orbit task. - local TaskFunction=self.group:TaskFunction("FLIGHTGROUP._FinishedWaiting", self) - local DCSTasks=self.group:TaskCombo({TaskOrbit, TaskFunction}) - - -- Orbit until flaghold=1 (true) but max 5 min if no FC is giving the landing clearance. local TaskOrbit = self.group:TaskOrbit(Coord, UTILS.FeetToMeters(Altitude), UTILS.KnotsToMps(Speed)) local TaskStop = self.group:TaskCondition(nil, nil, nil, nil, Duration) @@ -2842,11 +2853,11 @@ end -- @param #string Event Event. -- @param #string To To state. -- @param Core.Point#COORDINATE Coordinate The coordinate where to land. Default is current position. --- @param #number Duration The duration in seconds to remain on ground. Default 600 sec (10 min). +-- @param #number Duration The duration in seconds to remain on ground. Default `nil` = forever. function FLIGHTGROUP:onafterLandAt(From, Event, To, Coordinate, Duration) -- Duration. - Duration=Duration or 600 + --Duration=Duration or 600 Coordinate=Coordinate or self:GetCoordinate() @@ -2855,7 +2866,7 @@ function FLIGHTGROUP:onafterLandAt(From, Event, To, Coordinate, Duration) local Task=self:NewTaskScheduled(DCStask, 1, "Task_Land_At", 0) self:TaskExecute(Task) - + end --- On after "FuelLow" event. @@ -3012,7 +3023,7 @@ function FLIGHTGROUP._FinishedWaiting(group, flightgroup) flightgroup.dTwait=nil -- Trigger Holding event. - flightgroup:_CheckGroupDone(1) + flightgroup:_CheckGroupDone(0.1) end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Ops/NavyGroup.lua b/Moose Development/Moose/Ops/NavyGroup.lua index f6b5f0058..ca2230f8c 100644 --- a/Moose Development/Moose/Ops/NavyGroup.lua +++ b/Moose Development/Moose/Ops/NavyGroup.lua @@ -114,6 +114,9 @@ function NAVYGROUP:New(group) return og end + -- First set NAVYGROUP. + self.isNavygroup=true + -- Inherit everything from FSM class. local self=BASE:Inherit(self, OPSGROUP:New(group)) -- #NAVYGROUP @@ -126,7 +129,6 @@ function NAVYGROUP:New(group) self:SetDefaultAlarmstate() self:SetPatrolAdInfinitum(true) self:SetPathfinding(false) - self.isNavygroup=true -- Add FSM transitions. -- From State --> Event --> To State diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index f396d4c29..1f31accd0 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -18,6 +18,7 @@ -- @field #string lid Class id string for output to DCS log file. -- @field #string groupname Name of the group. -- @field Wrapper.Group#GROUP group Group object. +-- @field DCS#Controller controller The DCS controller of the group. -- @field DCS#Template template Template table of the group. -- @field #boolean isLateActivated Is the group late activated. -- @field #boolean isUncontrolled Is the group uncontrolled. @@ -513,6 +514,10 @@ function OPSGROUP:New(group) -- Set the template. self:_SetTemplate() + -- Set DCS group and controller. + self.dcsgroup=self:GetDCSGroup() + self.controller=self.dcsgroup:getController() + -- Init set of detected units. self.detectedunits=SET_UNIT:New() @@ -521,6 +526,9 @@ function OPSGROUP:New(group) -- Init inzone set. self.inzones=SET_ZONE:New() + + -- Set Default altitude. + self:SetDefaultAltitude() -- Laser. self.spot={} @@ -555,7 +563,11 @@ function OPSGROUP:New(group) self:AddTransition("*", "Destroyed", "*") -- The whole group is dead. self:AddTransition("*", "Damaged", "*") -- Someone in the group took damage. - self:AddTransition("*", "UpdateRoute", "*") -- Update route of group. Only if airborne. + self:AddTransition("*", "UpdateRoute", "*") -- Update route of group. + + self:AddTransition("*", "PassingWaypoint", "*") -- Group passed a waypoint. + self:AddTransition("*", "PassedFinalWaypoint", "*") -- Group passed the waypoint. + self:AddTransition("*", "GotoWaypoint", "*") -- Group switches to a specific waypoint. self:AddTransition("*", "Wait", "*") -- Group will wait for further orders. @@ -569,9 +581,6 @@ function OPSGROUP:New(group) self:AddTransition("*", "DetectedGroupKnown", "*") -- A known unit is still detected. self:AddTransition("*", "DetectedGroupLost", "*") -- Group lost a detected target group. - self:AddTransition("*", "PassingWaypoint", "*") -- Group passed a waypoint. - self:AddTransition("*", "GotoWaypoint", "*") -- Group switches to a specific waypoint. - self:AddTransition("*", "OutOfAmmo", "*") -- Group is completely out of ammo. self:AddTransition("*", "OutOfGuns", "*") -- Group is out of gun shells. self:AddTransition("*", "OutOfRockets", "*") -- Group is out of rockets. @@ -744,7 +753,37 @@ end -- @param #OPSGROUP self -- @return #number Cruise speed (>0) in knots. function OPSGROUP:GetSpeedCruise() - return UTILS.KmphToKnots(self.speedCruise or self.speedMax*0.7) + local speed=UTILS.KmphToKnots(self.speedCruise or self.speedMax*0.7) + return speed +end + +--- Set default cruise altitude. +-- @param #OPSGROUP self +-- @param #number Altitude Altitude in feet. Default is 10,000 ft for airplanes and 1,000 feet for helicopters. +-- @return #OPSGROUP self +function OPSGROUP:SetDefaultAltitude(Altitude) + if Altitude then + self.altitudeCruise=UTILS.FeetToMeters(Altitude) + else + if self:IsFlightgroup() then + if self.isHelo then + self.altitudeCruise=UTILS.FeetToMeters(1000) + else + self.altitudeCruise=UTILS.FeetToMeters(10000) + end + else + self.altitudeCruise=0 + end + end + return self +end + +--- Get default cruise speed. +-- @param #OPSGROUP self +-- @return #number Cruise altitude in feet. +function OPSGROUP:GetCruiseAltitude() + local alt=UTILS.MetersToFeet(self.altitudeCruise) + return alt end --- Set detection on or off. @@ -2469,8 +2508,8 @@ function OPSGROUP:OnEventBirth(EventData) if element and element.status~=OPSGROUP.ElementStatus.SPAWNED then - -- Set element to spawned state. We need to delay this. - self:__ElementSpawned(0.05, element) + -- Set element to spawned state. + self:ElementSpawned(element) end @@ -2605,7 +2644,8 @@ function OPSGROUP:SetTask(DCSTask) end -- Set task. - self.group:SetTask(DCSTask) + --self.group:SetTask(DCSTask) + self.controller:setTask(DCSTask) -- Debug info. local text=string.format("SETTING Task %s", tostring(DCSTask.id)) @@ -2629,7 +2669,8 @@ function OPSGROUP:PushTask(DCSTask) if self:IsAlive() then -- Push task. - self.group:PushTask(DCSTask) + --self.group:PushTask(DCSTask) + self.controller:pushTask(DCSTask) -- Debug info. local text=string.format("PUSHING Task %s", tostring(DCSTask.id)) @@ -3165,8 +3206,8 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) -- NOTE: I am pushing the task instead of setting it as it seems to keep the mission task alive. -- There were issues that flights did not proceed to a later waypoint because the task did not finish until the fired missiles -- impacted (took rather long). Then the flight flew to the nearest airbase and one lost completely the control over the group. - --self:PushTask(TaskFinal) - self:SetTask(TaskFinal) + self:PushTask(TaskFinal) + --self:SetTask(TaskFinal) elseif Task.type==OPSGROUP.TaskType.WAYPOINT then @@ -3312,10 +3353,14 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task) if Task.description=="Engage_Target" then self:Disengage() end + + if Task.description=="Task_Land_At" then + self:Wait(60, 100) + else + self:T(self.lid.."Task Done but NO mission found ==> _CheckGroupDone in 0 sec") + self:_CheckGroupDone() + end - -- - self:T(self.lid.."Task Done but NO mission found ==> _CheckGroupDone in 0 sec") - self:_CheckGroupDone() end end @@ -3427,6 +3472,11 @@ function OPSGROUP:CountRemainingTransports() N=N+1 end end + + -- In case we directly set the cargo transport (not in queue). + if N==0 and self.cargoTransport then + N=1 + end return N end @@ -4295,6 +4345,19 @@ function OPSGROUP:_SetWaypointTasks(Waypoint) return #taskswp end +--- On after "PassedFinalWaypoint" event. +-- @param #OPSGROUP self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +function OPSGROUP:onafterPassedFinalWaypoint(From, Event, To) + self:T(self.lid..string.format("Group passed final waypoint")) + + -- Check if group is done? No tasks mission running. + self:_CheckGroupDone() + +end + --- On after "GotoWaypoint" event. Group will got to the given waypoint and execute its route from there. -- @param #OPSGROUP self -- @param #string From From state. @@ -5989,7 +6052,7 @@ function OPSGROUP:AddWeightCargo(UnitName, Weight) -- For airborne units, we set the weight in game. if self.isFlightgroup then - trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo + --trigger.action.setUnitInternalCargo(element.name, element.weightCargo) --https://wiki.hoggitworld.com/view/DCS_func_setUnitInternalCargo end end @@ -6202,8 +6265,8 @@ function OPSGROUP:onafterPickup(From, Event, To) if airbaseCurrent then -- Activate uncontrolled group. - if self:IsParking() then - self:StartUncontrolled() + if self:IsParking() and self:IsUncontrolled() then + self:StartUncontrolled(1) end else @@ -6220,14 +6283,13 @@ function OPSGROUP:onafterPickup(From, Event, To) --- -- Activate uncontrolled group. - if self:IsParking() then - self:StartUncontrolled() - end + if self:IsParking() and self:IsUncontrolled() then + self:StartUncontrolled(1) + end -- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone. - Coordinate:SetAltitude(200) - local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1 - + local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, 200, false) ; waypoint.detour=1 + else self:E(self.lid.."ERROR: Carrier aircraft cannot land in Pickup zone! Specify a ZONE_AIRBASE as pickup zone") end @@ -6486,12 +6548,6 @@ function OPSGROUP:onafterLoaded(From, Event, To) -- Debug info. self:T(self.lid.."Carrier Loaded ==> Transport") - -- Cancel landedAt task. - if self:IsFlightgroup() and self:IsLandedAt() then - local Task=self:GetTaskCurrent() - self:__TaskCancel(1, Task) - end - -- Order group to transport. self:__Transport(1) @@ -6588,7 +6644,7 @@ function OPSGROUP:onafterTransport(From, Event, To) if airbaseCurrent then -- Activate uncontrolled group. - if self:IsParking() then + if self:IsParking() and self:IsUncontrolled() then self:StartUncontrolled() end @@ -6597,16 +6653,22 @@ function OPSGROUP:onafterTransport(From, Event, To) self:LandAtAirbase(airbaseDeploy) end - elseif self.isHelo or self.isVTOL then + elseif self.isHelo then --- - -- Helo or VTOL can also land in a zone + -- Helo can also land in a zone --- -- If this is a helo and no ZONE_AIRBASE was given, we make the helo land in the pickup zone. - Coordinate:MarkToAll("landing",ReadOnly,Text) - env.info("FF helo add waypoint detour") - local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, 200) ; waypoint.detour=1 + local waypoint=FLIGHTGROUP.AddWaypoint(self, Coordinate, nil, self:GetWaypointCurrent().uid, 200, false) ; waypoint.detour=1 + + -- Cancel landedAt task. This should trigger Cruise once airborne. + if self:IsFlightgroup() and self:IsLandedAt() then + local Task=self:GetTaskCurrent() + --if Task and Task.description=="Task_Landed_At" then + self:__TaskCancel(5, Task) + --end + end else self:E(self.lid.."ERROR: Carrier aircraft cannot land in Deploy zone! Specify a ZONE_AIRBASE as deploy zone") @@ -7064,7 +7126,7 @@ function OPSGROUP:onafterBoard(From, Event, To, CarrierGroup, Carrier) self:ClearWaypoints(self.currentwp+1) if self.isArmygroup then - local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1 + local waypoint=ARMYGROUP.AddWaypoint(self, Coordinate, nil, nil, ENUMS.Formation.Vehicle.Diamond) ; waypoint.detour=1 self:Cruise() else local waypoint=NAVYGROUP.AddWaypoint(self, Coordinate) ; waypoint.detour=1 @@ -7344,7 +7406,7 @@ function OPSGROUP:_CheckGroupDone(delay) -- Finite Patrol --- - if self.passedfinalwp then + if self:HasPassedFinalWaypoint() then --- -- Passed FINAL waypoint @@ -7758,20 +7820,6 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax) self:_AddWaypoint(waypoint) - -- Add waypoint. - --[[ - if self:IsFlightgroup() then - FLIGHTGROUP.AddWaypoint(self, coordinate, speedknots, index-1, Altitude, false) - elseif self:IsArmygroup() then - ARMYGROUP.AddWaypoint(self, coordinate, speedknots, index-1, Formation, false) - elseif self:IsNavygroup() then - NAVYGROUP.AddWaypoint(self, coordinate, speedknots, index-1, Depth, false) - else - -- Should not happen! - self:AddWaypoint(coordinate, speedknots, index-1, nil, false) - end - ]] - end -- Debug info. @@ -7822,25 +7870,15 @@ function OPSGROUP:Route(waypoints, delay) if self:IsAlive() then - -- DCS task combo. - local Tasks={} - - self:ClearTasks(DCSTask) + -- Clear all DCS tasks. + --self:ClearTasks() -- Route (Mission) task. local TaskRoute=self.group:TaskRoute(waypoints) - table.insert(Tasks, TaskRoute) - - -- TaskCombo of enroute and mission tasks. - local TaskCombo=self.group:TaskCombo(Tasks) - - -- Set tasks. - if #Tasks>1 then - self:SetTask(TaskCombo) - else - self:SetTask(TaskRoute) - end + -- Set mission task. + self:SetTask(TaskRoute) + else self:E(self.lid.."ERROR: Group is not alive! Cannot route group.") end @@ -7947,6 +7985,10 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid) -- Trigger PassingWaypoint event. if waypoint.temp then + + --- + -- Temporary Waypoint + --- if opsgroup:IsNavygroup() or opsgroup:IsArmygroup() then --TODO: not sure if this works with FLIGHTGROUPS @@ -7955,11 +7997,19 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid) elseif waypoint.astar then + --- + -- Pathfinding Waypoint + --- + -- Cruise. opsgroup:Cruise() elseif waypoint.detour then + --- + -- Detour Waypoint + --- + if opsgroup:IsRearming() then -- Trigger Rearming event. @@ -7977,16 +8027,19 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid) elseif opsgroup:IsPickingup() then - if opsgroup.isFlightgroup then + if opsgroup:IsFlightgroup() then -- Land at current pos and wait for 60 min max. env.info("FF LandAt for Pickup") - opsgroup:LandAt(opsgroup:GetCoordinate(), 60*60) + --opsgroup:LandAt(opsgroup:GetCoordinate(), 60*60) + opsgroup:LandAt(opsgroup.cargoTransport.pickupzone:GetCoordinate(), 60*60) else + -- Wait and load cargo. opsgroup:FullStop() opsgroup:__Loading(-5) + end elseif opsgroup:IsTransporting() then @@ -8044,6 +8097,10 @@ function OPSGROUP._PassingWaypoint(group, opsgroup, uid) end else + + --- + -- Normal Route Waypoint + --- -- Check if the group is still pathfinding. if opsgroup.ispathfinding then @@ -8858,7 +8915,15 @@ function OPSGROUP:_AllSimilarStatus(status) -- ALIVE ---------- - if status==OPSGROUP.ElementStatus.SPAWNED then + if status==OPSGROUP.ElementStatus.INUTERO then + + -- Element INUTERO: Check that ALL others are also INUTERO + if element.status~=status then + return false + end + + + elseif status==OPSGROUP.ElementStatus.SPAWNED then -- Element SPAWNED: Check that others are not still IN UTERO if element.status~=status and @@ -9568,6 +9633,10 @@ function OPSGROUP:_PassedFinalWaypoint(final, comment) -- Debug info. self:T(self.lid..string.format("Passed final waypoint=%s [from %s]: comment \"%s\"", tostring(final), tostring(self.passedfinalwp), tostring(comment))) + if final==true and not self.passedfinalwp then + self:PassedFinalWaypoint() + end + -- Set value. self.passedfinalwp=final end