From 171af5a3c3e61e925b6760eaee579e7cabc3c0f0 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Wed, 11 Dec 2024 16:45:05 +0100 Subject: [PATCH 1/3] #AUFTRAG, #OPSGROUP - Better functionality for Ingress Points (used as IP Holding Point when combined with a push condition) --- Moose Development/Moose/Ops/Auftrag.lua | 46 ++++++++++++++++++++++-- Moose Development/Moose/Ops/OpsGroup.lua | 14 ++++++-- 2 files changed, 55 insertions(+), 5 deletions(-) diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 7f1a0ae44..6c4b2a2dd 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -162,6 +162,7 @@ -- @field #number missionRange Mission range in meters. Used by LEGION classes (AIRWING, BRIGADE, ...). -- @field Core.Point#COORDINATE missionWaypointCoord Mission waypoint coordinate. -- @field Core.Point#COORDINATE missionEgressCoord Mission egress waypoint coordinate. +-- @field Core.Point#COORDINATE missionIngressCoord Mission Ingress waypoint coordinate. -- @field #number missionWaypointRadius Random radius in meters. -- @field #boolean legionReturn If `true`, assets return to their legion (default). If `false`, they will stay alive. -- @@ -664,7 +665,7 @@ AUFTRAG.Category={ --- AUFTRAG class version. -- @field #string version -AUFTRAG.version="1.2.2" +AUFTRAG.version="1.2.3" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -1819,7 +1820,7 @@ end --- **[AIR]** Create a BOMBRUNWAY mission. -- @param #AUFTRAG self --- @param Wrapper.Airbase#AIRBASE Airdrome The airbase to bomb. This must be an airdrome (not a FARP or ship) as these to not have a runway. +-- @param Wrapper.Airbase#AIRBASE Airdrome The airbase to bomb. This must be an airdrome (not a FARP or ship) as these do not have a runway. -- @param #number Altitude Engage altitude in feet. Default 25000 ft. -- @return #AUFTRAG self function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude) @@ -4657,6 +4658,15 @@ function AUFTRAG:SetGroupWaypointCoordinate(opsgroup, coordinate) return self end +--- [Air] Set mission (ingress) waypoint coordinate for FLIGHT group. +-- @param #AUFTRAG self +-- @param Core.Point#COORDINATE coordinate Waypoint Coordinate. +-- @return #AUFTRAG self +function AUFTRAG:SetIngressCoordinate(coordinate) + self.missionIngressCoord = coordinate + return self +end + --- Get mission (ingress) waypoint coordinate of OPS group -- @param #AUFTRAG self -- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. @@ -5755,6 +5765,25 @@ function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude) end end +--- [Air] Set the mission ingress coordinate. This is the coordinate where the assigned group will fly before the actual mission coordinate. +-- @param #AUFTRAG self +-- @param Core.Point#COORDINATE Coordinate Ingrees coordinate. +-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate. +-- @return #AUFTRAG self +function AUFTRAG:SetMissionIngressCoord(Coordinate, Altitude) + + -- Obviously a zone was passed. We get the coordinate. + if Coordinate:IsInstanceOf("ZONE_BASE") then + Coordinate=Coordinate:GetCoordinate() + end + + self.missionIngressCoord=Coordinate + + if Altitude then + self.missionIngressCoord.y=UTILS.FeetToMeters(Altitude) + end +end + --- Get the mission egress coordinate if this was defined. -- @param #AUFTRAG self -- @return Core.Point#COORDINATE Coordinate Coordinate or nil. @@ -5762,6 +5791,13 @@ function AUFTRAG:GetMissionEgressCoord() return self.missionEgressCoord end +--- Get the mission ingress coordinate if this was defined. +-- @param #AUFTRAG self +-- @return Core.Point#COORDINATE Coordinate Coordinate or nil. +function AUFTRAG:GetMissionIngressCoord() + return self.missionIngressCoord +end + --- Get coordinate which was set as mission waypoint coordinate. -- @param #AUFTRAG self -- @return Core.Point#COORDINATE Coordinate where the mission is executed or `#nil`. @@ -5796,6 +5832,12 @@ function AUFTRAG:GetMissionWaypointCoord(group, randomradius, surfacetypes) end return coord end + + -- Check if a coord has been explicitly set. + if self.missionIngressCoord then + local coord=self.missionIngressCoord + return coord + end -- Create waypoint coordinate half way between us and the target. local waypointcoord=COORDINATE:New(0,0,0) diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index e1e148284..3fd37f26d 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -1041,7 +1041,7 @@ function OPSGROUP:SetReturnToLegion(Switch) else self.legionReturn=true end - self:T(self.lid..string.format("Setting ReturnToLetion=%s", tostring(self.legionReturn))) + self:T(self.lid..string.format("Setting ReturnToLegion=%s", tostring(self.legionReturn))) return self end @@ -4169,7 +4169,7 @@ function OPSGROUP:onbeforeTaskExecute(From, Event, To, Task) if self:IsWaiting() then -- Group is already waiting else - -- Wait indefinately. + -- Wait indefinitely. local alt=Mission.missionAltitude and UTILS.MetersToFeet(Mission.missionAltitude) or nil self:Wait(nil, alt) end @@ -6118,7 +6118,15 @@ function OPSGROUP:RouteToMission(mission, delay) -- Add mission execution (ingress) waypoint. local waypoint=nil --#OPSGROUP.Waypoint if self:IsFlightgroup() then - + + + local ingresscoord = mission:GetMissionIngressCoord() + + if ingresscoord and mission:IsReadyToPush() then + waypoint=FLIGHTGROUP.AddWaypoint(self, ingresscoord, SpeedToMission, uid, UTILS.MetersToFeet(self.altitudeCruise), false) + uid=waypoint.uid + end + waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) elseif self:IsArmygroup() then From 62dfb5b5ff3e7000216822994ec04c4c816871e6 Mon Sep 17 00:00:00 2001 From: Frank Date: Wed, 11 Dec 2024 22:49:40 +0100 Subject: [PATCH 2/3] OPS update - Set destination base to airwing base for flight groups - Restored setting of home, destination and current base in OPSGROUP - Fixed bug if no airbase associated with airwing in check rescuehelo - Added check that cohort names are unique - Removed InitWaypoints function from FLIGHTGROUP (obsolete) --- Moose Development/Moose/Ops/AirWing.lua | 26 +++++++----- Moose Development/Moose/Ops/Cohort.lua | 18 ++++++++- Moose Development/Moose/Ops/FlightGroup.lua | 45 --------------------- Moose Development/Moose/Ops/Legion.lua | 5 ++- Moose Development/Moose/Ops/OpsGroup.lua | 8 ++-- 5 files changed, 39 insertions(+), 63 deletions(-) diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index 1282c9193..f181b02ea 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -187,7 +187,7 @@ AIRWING = { --- AIRWING class version. -- @field #string version -AIRWING.version="0.9.5" +AIRWING.version="0.9.6" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -1365,16 +1365,20 @@ function AIRWING:CheckRescuhelo() local N=self:CountMissionsInQueue({AUFTRAG.Type.RESCUEHELO}) - local name=self.airbase:GetName() - - local carrier=UNIT:FindByName(name) - - for i=1,self.nflightsRescueHelo-N do - - local mission=AUFTRAG:NewRESCUEHELO(carrier) - - self:AddMission(mission) - + if self.airbase then + + local name=self.airbase:GetName() + + local carrier=UNIT:FindByName(name) + + for i=1,self.nflightsRescueHelo-N do + + local mission=AUFTRAG:NewRESCUEHELO(carrier) + + self:AddMission(mission) + + end + end return self diff --git a/Moose Development/Moose/Ops/Cohort.lua b/Moose Development/Moose/Ops/Cohort.lua index 5488c99cd..26f54e66d 100644 --- a/Moose Development/Moose/Ops/Cohort.lua +++ b/Moose Development/Moose/Ops/Cohort.lua @@ -88,7 +88,10 @@ COHORT = { --- COHORT class version. -- @field #string version -COHORT.version="0.3.5" +COHORT.version="0.3.6" + +--- Global variable to store the unique(!) cohort names +_COHORTNAMES={} ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -110,6 +113,17 @@ COHORT.version="0.3.5" -- @return #COHORT self function COHORT:New(TemplateGroupName, Ngroups, CohortName) + -- Name of the cohort. + local name=tostring(CohortName or TemplateGroupName) + + -- Cohort name has to be unique or we will get serious problems! + if UTILS.IsAnyInTable(_COHORTNAMES, name) then + env.error(string.format('ERROR: cannot create cohort "%s" because another cohort with that name already exists. Names must be unique!', name)) + return nil + else + table.insert(_COHORTNAMES, name) + end + -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #COHORT @@ -117,7 +131,7 @@ function COHORT:New(TemplateGroupName, Ngroups, CohortName) self.templatename=TemplateGroupName -- Cohort name. - self.name=tostring(CohortName or TemplateGroupName) + self.name=name -- Set some string id for output to DCS.log file. self.lid=string.format("COHORT %s | ", self.name) diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index 245cca698..c265e11d2 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -4189,51 +4189,6 @@ function FLIGHTGROUP:IsLandingAirbase(wp) return nil end ---- Initialize Mission Editor waypoints. --- @param #FLIGHTGROUP self --- @return #FLIGHTGROUP self -function FLIGHTGROUP:InitWaypoints() - - -- Template waypoints. - self.waypoints0=self.group:GetTemplateRoutePoints() - - -- Waypoints - self.waypoints={} - - for index,wp in pairs(self.waypoints0) do - - local waypoint=self:_CreateWaypoint(wp) - self:_AddWaypoint(waypoint) - - end - - -- Get home and destination airbases from waypoints. - self.homebase=self.homebase or self:GetHomebaseFromWaypoints() - self.destbase=self.destbase or self:GetDestinationFromWaypoints() - self.currbase=self:GetHomebaseFromWaypoints() - - -- Remove the landing waypoint. We use RTB for that. It makes adding new waypoints easier as we do not have to check if the last waypoint is the landing waypoint. - if self.destbase and #self.waypoints>1 then - table.remove(self.waypoints, #self.waypoints) - else - self.destbase=self.homebase - end - - -- Debug info. - self:T(self.lid..string.format("Initializing %d waypoints. Homebase %s ==> %s Destination", #self.waypoints, self.homebase and self.homebase:GetName() or "unknown", self.destbase and self.destbase:GetName() or "uknown")) - - -- Update route. - if #self.waypoints>0 then - - -- Check if only 1 wp? - if #self.waypoints==1 then - self:_PassedFinalWaypoint(true, "FLIGHTGROUP:InitWaypoints #self.waypoints==1") - end - - end - - return self -end --- Add an AIR waypoint to the flight plan. -- @param #FLIGHTGROUP self diff --git a/Moose Development/Moose/Ops/Legion.lua b/Moose Development/Moose/Ops/Legion.lua index ae675bc4a..6cc2ccb8c 100644 --- a/Moose Development/Moose/Ops/Legion.lua +++ b/Moose Development/Moose/Ops/Legion.lua @@ -53,7 +53,7 @@ LEGION.RandomAssetScore=1 --- LEGION class version. -- @field #string version -LEGION.version="0.5.0" +LEGION.version="0.5.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list @@ -1827,6 +1827,9 @@ function LEGION:_CreateFlightGroup(asset) -- Set home base. opsgroup.homebase=self.airbase + -- Set destination base + opsgroup.destbase=self.airbase + -- Set home zone. opsgroup.homezone=self.spawnzone diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 3fd37f26d..1c7fdbfba 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -11450,7 +11450,7 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax) self.homebase=self.homebase or self:GetHomebaseFromWaypoints() -- GetHomebaseFromWaypoints() returns carriers or destroyers if no airbase is found. local destbase=self:GetDestinationFromWaypoints() self.destbase=self.destbase or destbase - --self.currbase=self:GetHomebaseFromWaypoints() -- Skipped To fix RTB issue + self.currbase=self:GetHomebaseFromWaypoints() -- Skipped To fix RTB issue --env.info("FF home base "..(self.homebase and self.homebase:GetName() or "unknown")) --env.info("FF dest base "..(self.destbase and self.destbase:GetName() or "unknown")) @@ -11461,9 +11461,9 @@ function OPSGROUP:_InitWaypoints(WpIndexMin, WpIndexMax) end -- Set destination to homebase. - --if self.destbase==nil then -- Skipped To fix RTB issue - -- self.destbase=self.homebase - --end + if self.destbase==nil then -- Skipped To fix RTB issue + self.destbase=self.homebase + end end From 6025c05f335d9c69c5c1006dd98f814d9de092c9 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Thu, 12 Dec 2024 13:11:54 +0100 Subject: [PATCH 3/3] #AUFTRAG #OPSGROUP Handling of Ingress and Holding points for FlightGroups --- Moose Development/Moose/Ops/Auftrag.lua | 55 +++++++++++++++++++++--- Moose Development/Moose/Ops/OpsGroup.lua | 22 ++++++++-- 2 files changed, 68 insertions(+), 9 deletions(-) diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 6c4b2a2dd..93b9b27ef 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -665,7 +665,7 @@ AUFTRAG.Category={ --- AUFTRAG class version. -- @field #string version -AUFTRAG.version="1.2.3" +AUFTRAG.version="1.2.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -4664,6 +4664,7 @@ end -- @return #AUFTRAG self function AUFTRAG:SetIngressCoordinate(coordinate) self.missionIngressCoord = coordinate + self.missionIngressCoordAlt = UTILS.MetersToFeet(coordinate.y) or 10000 return self end @@ -5722,7 +5723,7 @@ function AUFTRAG:GetMissionTypesText(MissionTypes) return text end ---- Set the mission waypoint coordinate where the mission is executed. Note that altitude is set via `:SetMissionAltitude`. +--- [NON-AIR] Set the mission waypoint coordinate where the mission is executed. Note that altitude is set via `:SetMissionAltitude`. -- @param #AUFTRAG self -- @param Core.Point#COORDINATE Coordinate Coordinate where the mission is executed. -- @return #AUFTRAG self @@ -5762,6 +5763,7 @@ function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude) if Altitude then self.missionEgressCoord.y=UTILS.FeetToMeters(Altitude) + self.missionEgressCoordAlt = UTILS.FeetToMeters(Altitude) end end @@ -5781,6 +5783,29 @@ function AUFTRAG:SetMissionIngressCoord(Coordinate, Altitude) if Altitude then self.missionIngressCoord.y=UTILS.FeetToMeters(Altitude) + self.missionIngressCoordAlt = UTILS.FeetToMeters(Altitude or 10000) + end +end + +--- [Air] Set the mission holding coordinate. This is the coordinate where the assigned group will fly before the actual mission execution starts. Do not forget to add a push condition, too! +-- @param #AUFTRAG self +-- @param Core.Point#COORDINATE Coordinate Holding coordinate. +-- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate. +-- @param #number Duration (Optional) Duration in seconds on how long to hold, defaults to 15 minutes. Mission continues if either a push condition is met or the time is up. +-- @return #AUFTRAG self +function AUFTRAG:SetMissionHoldingCoord(Coordinate, Altitude, Duration) + + -- Obviously a zone was passed. We get the coordinate. + if Coordinate:IsInstanceOf("ZONE_BASE") then + Coordinate=Coordinate:GetCoordinate() + end + + self.missionHoldingCoord=Coordinate + self.missionHoldingDuration=Duration or 900 + + if Altitude then + self.missionHoldingCoord.y=UTILS.FeetToMeters(Altitude) + self.missionHoldingCoordAlt = UTILS.FeetToMeters(Altitude or 10000) end end @@ -5798,6 +5823,13 @@ function AUFTRAG:GetMissionIngressCoord() return self.missionIngressCoord end +--- Get the mission holding coordinate if this was defined. +-- @param #AUFTRAG self +-- @return Core.Point#COORDINATE Coordinate Coordinate or nil. +function AUFTRAG:GetMissionHoldingCoord() + return self.missionHoldingCoord +end + --- Get coordinate which was set as mission waypoint coordinate. -- @param #AUFTRAG self -- @return Core.Point#COORDINATE Coordinate where the mission is executed or `#nil`. @@ -5833,15 +5865,26 @@ function AUFTRAG:GetMissionWaypointCoord(group, randomradius, surfacetypes) return coord end - -- Check if a coord has been explicitly set. + local coord=group:GetCoordinate() + + -- Check if an ingress or holding coord has been explicitly set. + if self.missionHoldingCoord then + coord=self.missionHoldingCoord + if self.missionHoldingCoorddAlt then + coord:SetAltitude(self.missionHoldingCoordAlt, true) + end + end + if self.missionIngressCoord then - local coord=self.missionIngressCoord - return coord + coord=self.missionIngressCoord + if self.missionIngressCoordAlt then + coord:SetAltitude(self.missionIngressCoordAlt, true) + end end -- Create waypoint coordinate half way between us and the target. local waypointcoord=COORDINATE:New(0,0,0) - local coord=group:GetCoordinate() + if coord then waypointcoord=coord:GetIntermediateCoordinate(self:GetTargetCoordinate(), self.missionFraction) else diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 3fd37f26d..96adc32e7 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -6121,9 +6121,25 @@ function OPSGROUP:RouteToMission(mission, delay) local ingresscoord = mission:GetMissionIngressCoord() + local holdingcoord = mission:GetMissionHoldingCoord() - if ingresscoord and mission:IsReadyToPush() then - waypoint=FLIGHTGROUP.AddWaypoint(self, ingresscoord, SpeedToMission, uid, UTILS.MetersToFeet(self.altitudeCruise), false) + if holdingcoord then + waypoint=FLIGHTGROUP.AddWaypoint(self, holdingcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionHoldingCoordAlt or self.altitudeCruise), false) + uid=waypoint.uid + -- Orbit until flaghold=1 (true) but max 5 min + self.flaghold:Set(0) + local TaskOrbit = self.group:TaskOrbit(holdingcoord, mission.missionHoldingCoordAlt) + local TaskStop = self.group:TaskCondition(nil, self.flaghold.UserFlagName, 1, nil, mission.missionHoldingDuration or 900) + local TaskCntr = self.group:TaskControlled(TaskOrbit, TaskStop) + local TaskOver = self.group:TaskFunction("FLIGHTGROUP._FinishedWaiting", self) + local DCSTasks=self.group:TaskCombo({TaskCntr, TaskOver}) + -- Add waypoint task. UpdateRoute is called inside. + local waypointtask=self:AddTaskWaypoint(DCSTasks, waypoint, "Holding") + waypointtask.ismission=false + end + + if ingresscoord then + waypoint=FLIGHTGROUP.AddWaypoint(self, ingresscoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionIngressCoordAlt or self.altitudeCruise), false) uid=waypoint.uid end @@ -6165,7 +6181,7 @@ function OPSGROUP:RouteToMission(mission, delay) if egresscoord then local Ewaypoint=nil --#OPSGROUP.Waypoint if self:IsFlightgroup() then - Ewaypoint=FLIGHTGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) + Ewaypoint=FLIGHTGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionEgressCoordAlt or self.altitudeCruise), false) elseif self:IsArmygroup() then Ewaypoint=ARMYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, mission.optionFormation, false) elseif self:IsNavygroup() then