From 2ebce9fd03b5256d996da6543d60f4b376b46b1c Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 10 Feb 2026 22:17:22 +0100 Subject: [PATCH 1/3] AUFTRAG - New FREIGHTTRANSPORT (internal cargo transportation) WIP --- Moose Development/Moose/Ops/Auftrag.lua | 64 +++++++++++++++++++++++- Moose Development/Moose/Ops/OpsGroup.lua | 5 ++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 4b49a2842..04978cb6e 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -458,6 +458,7 @@ _AUFTRAGSNR=0 -- @field #string NOTHING Nothing. -- @field #string PATROLRACETRACK Patrol Racetrack. -- @field #string STRAFING Strafing run. +-- @field #string FREIGHTTRANSPORT Freight transport. AUFTRAG.Type={ ANTISHIP="Anti Ship", AWACS="AWACS", @@ -506,6 +507,7 @@ AUFTRAG.Type={ NOTHING="Nothing", PATROLRACETRACK="Patrol Racetrack", STRAFING="Strafing", + FREIGHTTRANSPORT="FREIGHTTRANSPORT", } --- Special task description. @@ -2172,6 +2174,33 @@ function AUFTRAG:NewCARGOTRANSPORT(StaticCargo, DropZone) return mission end +--- **[AIR]** Create a FREIGHT TRANSPORT mission. +-- @param #AUFTRAG self +-- @param Wrapper.Static#STATIC StaticCargo Static cargo object. +-- @param Wrapper.Airbase#AIRBASE Destination Destination airbase, where the cargo is unloaded. +-- @return #AUFTRAG self +function AUFTRAG:NewFREIGHTTRANSPORT(StaticCargo, Destination) + + local mission=AUFTRAG:New(AUFTRAG.Type.FREIGHTTRANSPORT) + + mission:_TargetFromObject(StaticCargo) + + mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.FREIGHTTRANSPORT) + + -- Set ROE and ROT. + mission.optionROE=ENUMS.ROE.ReturnFire + mission.optionROT=ENUMS.ROT.PassiveDefense + + mission.categories={AUFTRAG.Category.HELICOPTER, AUFTRAG.Category.AIRCRAFT} + + mission.DCStask=mission:GetDCSMissionTask() + + mission.DCStask.params.groupId=StaticCargo:GetID() + mission.DCStask.params.cargo=StaticCargo + + return mission +end + --[[ --- **[AIR, GROUND, NAVAL]** Create a OPS TRANSPORT mission. @@ -6201,8 +6230,9 @@ end --- Get DCS task table for the given mission. -- @param #AUFTRAG self +-- @param Wrapper.Group#GROUP MissionGroup (Optional) Group that is supposed to carry out the mission. This might not exist when the AUFTRAG is created but only when the AUFTRAG is passed to a certain group. -- @return DCS#Task The DCS task table. If multiple tasks are necessary, this is returned as a combo task. -function AUFTRAG:GetDCSMissionTask() +function AUFTRAG:GetDCSMissionTask(MissionGroup) local DCStasks={} @@ -6545,6 +6575,36 @@ function AUFTRAG:GetDCSMissionTask() table.insert(DCStasks, TaskCargoTransportation) + elseif self.type==AUFTRAG.Type.FREIGHTTRANSPORT then + + ------------------------------ + -- FREIGHTTRANSPORT Mission -- + ------------------------------ + + local x=nil; local y=nil; local unitIdTransport=nil + if MissionGroup then + local vec2=MissionGroup:GetVec2() + x=vec2.x + y=vec2.y + unitIdTransport=MissionGroup:GetFirstUnit():GetID() + end + + local static=self.engageTarget:GetObject() --Wrapper.Static#STATIC + + -- Task to transport cargo. + local TaskCargoTransportation={ + id = "CargoTransportationPlane", + params = { + x=x, + y=y, + unitIdTransport=nil, + groupId=static:GetID(), + unitId=static:GetID(), + } + } + + table.insert(DCStasks, TaskCargoTransportation) + elseif self.type==AUFTRAG.Type.RESCUEHELO then ------------------------- @@ -7109,6 +7169,8 @@ function AUFTRAG:GetMissionTaskforMissionType(MissionType) mtask=ENUMS.MissionTask.TRANSPORT elseif MissionType==AUFTRAG.Type.CARGOTRANSPORT then mtask=ENUMS.MissionTask.TRANSPORT + elseif MissionType==AUFTRAG.Type.FREIGHTTRANSPORT then + mtask=ENUMS.MissionTask.TRANSPORT elseif MissionType==AUFTRAG.Type.ARMORATTACK then mtask=ENUMS.MissionTask.NOTHING elseif MissionType==AUFTRAG.Type.HOVER then diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 7a1d8d3df..a2457a00f 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -6150,6 +6150,11 @@ function OPSGROUP:RouteToMission(mission, delay) end end + + elseif mission.type==AUFTRAG.Type.FREIGHTTRANSPORT then + + -- Refresh DCS task with the known controllable. + mission.DCStask=mission:GetDCSMissionTask(self.group) elseif mission.type==AUFTRAG.Type.ARTY then From 52986ce8deb7238ff5a7cf94ce034b71601c7f87 Mon Sep 17 00:00:00 2001 From: Frank Date: Fri, 13 Feb 2026 12:01:34 +0100 Subject: [PATCH 2/3] AUFTRAG --- Moose Development/Moose/Ops/Auftrag.lua | 1 + Moose Development/Moose/Ops/OpsGroup.lua | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 04978cb6e..c284b1ffe 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -2197,6 +2197,7 @@ function AUFTRAG:NewFREIGHTTRANSPORT(StaticCargo, Destination) mission.DCStask.params.groupId=StaticCargo:GetID() mission.DCStask.params.cargo=StaticCargo + mission.DCStask.params.destination=Destination return mission end diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index a2457a00f..50c69626e 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -6153,9 +6153,24 @@ function OPSGROUP:RouteToMission(mission, delay) elseif mission.type==AUFTRAG.Type.FREIGHTTRANSPORT then + --- + -- FREIGHTTRANSPORT + --- + + local destination=mission.DCStask.params.destination + local cargo=mission.DCStask.params.cargo + + -- Set the waypoint coordinate directly above the airbase. + -- The only way to ensure the cargo is delivered there, because when the task is executed, the cargo is delivered to the closest airbase. + -- Hopefully, ED will change the behaviour of this task but at the moment, it is what it is. + waypointcoord=destination:GetCoordinate() + -- Refresh DCS task with the known controllable. mission.DCStask=mission:GetDCSMissionTask(self.group) - + + mission.DCStask.params.destination=destination + mission.DCStask.params.cargo=cargo + elseif mission.type==AUFTRAG.Type.ARTY then --- From 1ac0249fe5a3236780ea8c466f6a2e0d8282a558 Mon Sep 17 00:00:00 2001 From: Frank Date: Sun, 15 Feb 2026 22:44:39 +0100 Subject: [PATCH 3/3] AUFTRAG - improved FREIGHTTRANSPORT mission type --- Moose Development/Moose/Core/Fsm.lua | 10 ++++ Moose Development/Moose/Ops/Auftrag.lua | 70 ++++++++++++++++-------- Moose Development/Moose/Ops/OpsGroup.lua | 51 +++++++++++++++-- 3 files changed, 102 insertions(+), 29 deletions(-) diff --git a/Moose Development/Moose/Core/Fsm.lua b/Moose Development/Moose/Core/Fsm.lua index e86b88267..a4448d4af 100644 --- a/Moose Development/Moose/Core/Fsm.lua +++ b/Moose Development/Moose/Core/Fsm.lua @@ -833,6 +833,16 @@ do -- FSM return self._handler( self, EventName, ... ) end end + + --- Clear scheduled FSM event. + -- @param #FSM self + -- @param #string EventName Event name. + function FSM:_ClearFSMEvent( EventName ) + if self._EventSchedules[EventName] then + self.CallScheduler:Remove( self._EventSchedules[EventName] ) + self._EventSchedules[EventName]=nil + end + end --- Go sub. -- @param #FSM self diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index c284b1ffe..f219083b2 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -2175,12 +2175,37 @@ function AUFTRAG:NewCARGOTRANSPORT(StaticCargo, DropZone) end --- **[AIR]** Create a FREIGHT TRANSPORT mission. +-- This mission type can be used to transport cargo items internally via suitable transport aircraft (planes and helicopters), e.g. C-130 or CH-47. +-- It supports transporting one or multiple cargos (weight limits are not checked). -- @param #AUFTRAG self --- @param Wrapper.Static#STATIC StaticCargo Static cargo object. +-- @param Wrapper.Static#STATIC StaticCargo Static cargo object. Can also be passed as a `SET_STATIC` object. -- @param Wrapper.Airbase#AIRBASE Destination Destination airbase, where the cargo is unloaded. -- @return #AUFTRAG self function AUFTRAG:NewFREIGHTTRANSPORT(StaticCargo, Destination) + -- Check if Destination is given + if Destination==nil then + self:E(self.lid..string.format("ERROR: Destination is nil for AUFTRAG:NewFREIGHTTRANSPORT! You must specify the destination airbase")) + return nil + elseif type(Destination)=="string" then + Destination=AIRBASE:FindByName(Destination) + end + + -- Check if Cargo is given + if StaticCargo==nil then + self:E(self.lid..string.format("ERROR: StaticCargo is nil for AUFTRAG:NewFREIGHTTRANSPORT! You must specify the static object that represents the cargo")) + return nil + elseif type(StaticCargo)=="string" then + StaticCargo=STATIC:FindByName(StaticCargo) + end + + -- Convert static to a set if necessary + if StaticCargo:IsInstanceOf("STATIC") then + local StaticCargoSet=SET_STATIC:New() --Core.Set#SET_STATIC + StaticCargoSet:AddCargo(StaticCargo) + StaticCargo=StaticCargoSet + end + local mission=AUFTRAG:New(AUFTRAG.Type.FREIGHTTRANSPORT) mission:_TargetFromObject(StaticCargo) @@ -2195,7 +2220,6 @@ function AUFTRAG:NewFREIGHTTRANSPORT(StaticCargo, Destination) mission.DCStask=mission:GetDCSMissionTask() - mission.DCStask.params.groupId=StaticCargo:GetID() mission.DCStask.params.cargo=StaticCargo mission.DCStask.params.destination=Destination @@ -6581,30 +6605,28 @@ function AUFTRAG:GetDCSMissionTask(MissionGroup) ------------------------------ -- FREIGHTTRANSPORT Mission -- ------------------------------ + + local statics=self.engageTarget:GetObjects() - local x=nil; local y=nil; local unitIdTransport=nil - if MissionGroup then - local vec2=MissionGroup:GetVec2() - x=vec2.x - y=vec2.y - unitIdTransport=MissionGroup:GetFirstUnit():GetID() + for _, StaticObject in pairs(statics) do + local static=StaticObject --Wrapper.Static#STATIC + + self:T(static) + + -- Task to unload the cargo + local TaskCargoUnload={ + ["id"] = "CargoUnloadPlane", + ["params"] = + { + ["groupId"] = static:GetID(), + ["unitId"] = static:GetID(), + } + } + + + table.insert(DCStasks, TaskCargoUnload) + end - - local static=self.engageTarget:GetObject() --Wrapper.Static#STATIC - - -- Task to transport cargo. - local TaskCargoTransportation={ - id = "CargoTransportationPlane", - params = { - x=x, - y=y, - unitIdTransport=nil, - groupId=static:GetID(), - unitId=static:GetID(), - } - } - - table.insert(DCStasks, TaskCargoTransportation) elseif self.type==AUFTRAG.Type.RESCUEHELO then diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 50c69626e..c5617c94c 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -5946,6 +5946,9 @@ function OPSGROUP:RouteToMission(mission, delay) -- Debug info. self:T(self.lid..string.format("Route To Mission")) + + -- Delay in seconds before cruise or updateroute is called. + local delayGo=-1 -- Catch dead or stopped groups. if self:IsDead() or self:IsStopped() then @@ -6164,13 +6167,51 @@ function OPSGROUP:RouteToMission(mission, delay) -- The only way to ensure the cargo is delivered there, because when the task is executed, the cargo is delivered to the closest airbase. -- Hopefully, ED will change the behaviour of this task but at the moment, it is what it is. waypointcoord=destination:GetCoordinate() + + -- Get additional parameters + mission.DCStask.params.destination=destination --Wrapper.Airbase#AIRBASE + mission.DCStask.params.cargo=cargo --Core.Set#SET_STATIC - -- Refresh DCS task with the known controllable. - mission.DCStask=mission:GetDCSMissionTask(self.group) + -- Get transport unit + local unit=self.group:GetFirstUnit() + local unitIdTransport=unit:GetID() + local vec2=unit:GetVec2() - mission.DCStask.params.destination=destination - mission.DCStask.params.cargo=cargo + -- Create tasks to load/transport statics cargos + local tasks={} + for StaticName, StaticObject in pairs(cargo:GetSet()) do + local static=StaticObject --Wrapper.Static#STATIC + + -- Task to transport cargo. + local TaskCargoTransportation={ + id = "CargoTransportationPlane", + params = { + x=vec2.x, + y=vec2.y, + unitIdTransport=unitIdTransport, + groupId=static:GetID(), + unitId=static:GetID(), + } + } + + table.insert(tasks, TaskCargoTransportation) + end + -- If we have multiple tasks, we create a combo task + local TaskCargo=nil + if #tasks==1 then + TaskCargo=tasks[1] + else + TaskCargo=CONTROLLABLE.TaskCombo(nil, tasks) + end + + -- We set the task to load the cargo into the aircraft. + -- We must be careful when calling updateroute because there the task is overwritten. + -- We also clear present "UpdateRoute" FSM events + self:_ClearFSMEvent( "UpdateRoute" ) + delayGo=-30 + self.group:SetTask(TaskCargo) + elseif mission.type==AUFTRAG.Type.ARTY then --- @@ -6329,7 +6370,7 @@ function OPSGROUP:RouteToMission(mission, delay) elseif self:IsNavygroup() then self:Cruise(SpeedToMission) elseif self:IsFlightgroup() then - self:UpdateRoute() + self:__UpdateRoute(delayGo) end end