diff --git a/Moose Development/Moose/Functional/Warehouse.lua b/Moose Development/Moose/Functional/Warehouse.lua index e8f169c06..613e02475 100644 --- a/Moose Development/Moose/Functional/Warehouse.lua +++ b/Moose Development/Moose/Functional/Warehouse.lua @@ -4391,9 +4391,16 @@ function WAREHOUSE:onafterAddRequest(From, Event, To, warehouse, AssetDescriptor -- Add request to queue. table.insert(self.queue, request) + + local descval="assetlist" + if request.assetdesc==WAREHOUSE.Descriptor.ASSETLIST then + + else + descval=tostring(request.assetdescval) + end - local text=string.format("Warehouse %s: New request from warehouse %s.\nDescriptor %s=%s, #assets=%s; Transport=%s, #transports =%s.", - self.alias, warehouse.alias, request.assetdesc, tostring(request.assetdescval), tostring(request.nasset), request.transporttype, tostring(request.ntransport)) + local text=string.format("Warehouse %s: New request from warehouse %s.\nDescriptor %s=%s, #assets=%s; Transport=%s, #transports=%s.", + self.alias, warehouse.alias, request.assetdesc, descval, tostring(request.nasset), request.transporttype, tostring(request.ntransport)) self:_DebugMessage(text, 5) end diff --git a/Moose Development/Moose/Ops/AirWing.lua b/Moose Development/Moose/Ops/AirWing.lua index cc7bc308f..a67e7ea64 100644 --- a/Moose Development/Moose/Ops/AirWing.lua +++ b/Moose Development/Moose/Ops/AirWing.lua @@ -3,10 +3,20 @@ -- **Main Features:** -- -- * Manage squadrons. +-- * Launch A2A and A2G missions (AUFTRAG) +-- +-- +-- === +-- +-- ## Example Missions: +-- +-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Airwing). -- -- === -- -- ### Author: **funkyfranky** +-- +-- === -- @module Ops.Airwing -- @image OPS_AirWing.png @@ -161,16 +171,16 @@ AIRWING = { --- AIRWING class version. -- @field #string version -AIRWING.version="0.9.0" +AIRWING.version="0.9.1" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +-- TODO: Check that airbase has enough parking spots if a request is BIG. -- TODO: Spawn in air ==> Needs WAREHOUSE update. -- DONE: Spawn hot. --- TODO: Make special request to transfer squadrons to anther airwing (or warehouse). --- TODO: Check that airbase has enough parking spots if a request is BIG. +-- DONE: Make special request to transfer squadrons to anther airwing (or warehouse). -- DONE: Add squadrons to warehouse. -- DONE: Build mission queue. -- DONE: Find way to start missions. @@ -355,6 +365,14 @@ function AIRWING:NewPayload(Unit, Npayloads, MissionTypes, Performance) capability.Performance=50 table.insert(payload.capabilities, capability) end + + -- Add RELOCATION for all. + if not AUFTRAG.CheckMissionType(AUFTRAG.Type.RELOCATECOHORT, MissionTypes) then + local capability={} --Ops.Auftrag#AUFTRAG.Capability + capability.MissionType=AUFTRAG.Type.RELOCATECOHORT + capability.Performance=50 + table.insert(payload.capabilities, capability) + end -- Info self:T(self.lid..string.format("Adding new payload from unit %s for aircraft type %s: ID=%d, N=%d (unlimited=%s), performance=%d, missions: %s", diff --git a/Moose Development/Moose/Ops/ArmyGroup.lua b/Moose Development/Moose/Ops/ArmyGroup.lua index 65b42d6e0..c022ab0af 100644 --- a/Moose Development/Moose/Ops/ArmyGroup.lua +++ b/Moose Development/Moose/Ops/ArmyGroup.lua @@ -65,7 +65,7 @@ ARMYGROUP = { --- Army Group version. -- @field #string version -ARMYGROUP.version="0.7.1" +ARMYGROUP.version="0.7.2" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 928e3d168..b1d1c90c4 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -367,7 +367,7 @@ _AUFTRAGSNR=0 -- @field #string CAS Close Air Support. -- @field #string ESCORT Escort mission. -- @field #string FACA Forward AirController airborne mission. --- @field #string FERRY Ferry flight mission. +-- @field #string FERRY Ferry mission. -- @field #string INTERCEPT Intercept mission. -- @field #string ORBIT Orbit mission. -- @field #string GCICAP Similar to CAP but no auto engage targets. @@ -392,6 +392,8 @@ _AUFTRAGSNR=0 -- @field #string HOVER Hover. -- @field #string GROUNDATTACK Ground attack. -- @field #string CARGOTRANSPORT Cargo transport. +-- @field #string RELOCATECOHORT Relocate a cohort from one legion to another. +-- @field #string NOTHING Nothing. AUFTRAG.Type={ ANTISHIP="Anti Ship", AWACS="AWACS", @@ -427,10 +429,12 @@ AUFTRAG.Type={ CASENHANCED="CAS Enhanced", HOVER="Hover", GROUNDATTACK="Ground Attack", - CARGOTRANSPORT="Cargo Transport" + CARGOTRANSPORT="Cargo Transport", + NOTHING="Nothing", + RELOCATECOHORT="Relocate Cohort", } ---- Mission status of an assigned group. +--- Special task description. -- @type AUFTRAG.SpecialTask -- @field #string PATROLZONE Patrol zone task. -- @field #string RECON Recon task @@ -442,6 +446,9 @@ AUFTRAG.Type={ -- @field #string BARRAGE Barrage. -- @field #string HOVER Hover. -- @field #string GROUNDATTACK Ground attack. +-- @field #string FERRY Ferry mission. +-- @field #string NOTHING Nothing. +-- @field #string RELOCATECOHORT Relocate cohort. AUFTRAG.SpecialTask={ PATROLZONE="PatrolZone", RECON="ReconMission", @@ -454,6 +461,9 @@ AUFTRAG.SpecialTask={ ARMORATTACK="AmorAttack", HOVER="Hover", GROUNDATTACK="Ground Attack", + FERRY="Ferry", + NOTHING="Nothing", + RELOCATECOHORT="Relocate Cohort", } --- Mission status. @@ -574,7 +584,7 @@ AUFTRAG.Category={ --- AUFTRAG class version. -- @field #string version -AUFTRAG.version="0.9.1" +AUFTRAG.version="0.9.2" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -1984,6 +1994,53 @@ function AUFTRAG:NewONGUARD(Coordinate) return mission end +--- **[PRIVATE, AIR, GROUND, NAVAL]** Create a mission to relocate assets to another LEGION. +-- @param #AUFTRAG self +-- @param Ops.Legion#LEGION Legion The new legion. +-- @param Ops.Cohort#COHORT Cohort The new cohort. +-- @return #AUFTRAG self +function AUFTRAG:_NewRELOCATECOHORT(Legion, Cohort) + + local mission=AUFTRAG:New(AUFTRAG.Type.RELOCATECOHORT) + + mission:_TargetFromObject(Legion.spawnzone) + + mission.optionROE=ENUMS.ROE.ReturnFire + mission.optionAlarm=ENUMS.AlarmState.Auto + + mission.missionFraction=0.0 + + mission.categories={AUFTRAG.Category.ALL} + + mission.DCStask=mission:GetDCSMissionTask() + + mission.DCStask.params.legion=Legion + mission.DCStask.params.cohort=Cohort + + return mission +end + +--- **[AIR, GROUND, NAVAL]** Create a mission to do NOTHING. +-- @param #AUFTRAG self +-- @return #AUFTRAG self +function AUFTRAG:NewNOTHING() + + local mission=AUFTRAG:New(AUFTRAG.Type.NOTHING) + + --mission:_TargetFromObject(Coordinate) + + mission.optionROE=ENUMS.ROE.ReturnFire + mission.optionAlarm=ENUMS.AlarmState.Auto + + mission.missionFraction=1.0 + + mission.categories={AUFTRAG.Category.ALL} + + mission.DCStask=mission:GetDCSMissionTask() + + return mission +end + --- **[GROUND]** Create an ARMORED ON GUARD mission. -- @param #AUFTRAG self -- @param Core.Point#COORDINATE Coordinate Coordinate, where to stand guard. @@ -4162,15 +4219,48 @@ function AUFTRAG:onafterDone(From, Event, To) -- Not executing any more. self.Texecuting=nil - - -- Set status for CHIEF, COMMANDER and LEGIONs + + -- Set status for CHIEF. self.statusChief=AUFTRAG.Status.DONE + + -- Set status for COMMANDER. self.statusCommander=AUFTRAG.Status.DONE + + -- Set status for LEGIONs. for _,_legion in pairs(self.legions) do local Legion=_legion --Ops.Legion#LEGION + self:SetLegionStatus(Legion, AUFTRAG.Status.DONE) + + -- Remove pending request from legion queue. + if self.type==AUFTRAG.Type.RELOCATECOHORT then + + -- Get request ID + local requestid=self.requestID[Legion.alias] + + if requestid then + + -- Debug info. + self:T(self.lid.."Removing request from pending queue") + + -- Remove request from pending queue. + Legion:_DeleteQueueItemByID(requestid, Legion.pending) + + -- Remove cohort from old legion. + local Cohort=self.DCStask.params.cohort --Ops.Cohort#COHORT + Legion:DelCohort(Cohort) + + else + self:E(self.lid.."WARNING: Could NOT remove relocation request from from pending queue (all assets were spawned?)") + end + end + end + + -- Trigger relocated event. + if self.type==AUFTRAG.Type.RELOCATECOHORT then + local cohort=self.DCStask.params.cohort --Ops.Cohort#COHORT + cohort:Relocated() end - end --- On after "Success" event. @@ -4637,6 +4727,19 @@ function AUFTRAG:AddAsset(Asset) return self end +--- Add asset to mission. +-- @param #AUFTRAG self +-- @param #table Assets List of assets. +-- @return #AUFTRAG self +function AUFTRAG:_AddAssets(Assets) + + for _,asset in pairs(Assets) do + self:AddAsset(asset) + end + + return self +end + --- Delete asset from mission. -- @param #AUFTRAG self -- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be removed. @@ -4941,8 +5044,32 @@ function AUFTRAG:GetDCSMissionTask(TaskControllable) -- FERRY Mission -- ------------------- - -- TODO: Ferry mission type. How? + local DCStask={} + DCStask.id=AUFTRAG.SpecialTask.FERRY + + -- We create a "fake" DCS task. + local param={} + DCStask.params=param + + table.insert(DCStasks, DCStask) + + elseif self.type==AUFTRAG.Type.RELOCATECOHORT then + + ---------------------- + -- RELOCATE Mission -- + ---------------------- + + local DCStask={} + + DCStask.id=AUFTRAG.SpecialTask.RELOCATECOHORT + + -- We create a "fake" DCS task. + local param={} + DCStask.params=param + + table.insert(DCStasks, DCStask) + elseif self.type==AUFTRAG.Type.INTERCEPT then ----------------------- diff --git a/Moose Development/Moose/Ops/Brigade.lua b/Moose Development/Moose/Ops/Brigade.lua index 54c884b3f..5fef5ac3d 100644 --- a/Moose Development/Moose/Ops/Brigade.lua +++ b/Moose Development/Moose/Ops/Brigade.lua @@ -5,11 +5,18 @@ -- * Manage platoons -- * Carry out ARTY and PATROLZONE missions (AUFTRAG) -- * Define rearming zones +-- +-- === -- +-- ## Example Missions: +-- +-- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Brigade). +-- -- === -- -- ### Author: **funkyfranky** -- +-- === -- @module Ops.Brigade -- @image OPS_Brigade.png @@ -29,7 +36,7 @@ -- -- # The BRIGADE Concept -- --- An BRIGADE consists of one or multiple PLATOONs. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed. +-- A BRIGADE consists of one or multiple PLATOONs. These platoons "live" in a WAREHOUSE that has a phyiscal struction (STATIC or UNIT) and can be captured or destroyed. -- -- -- @field #BRIGADE @@ -165,8 +172,6 @@ function BRIGADE:AddPlatoon(Platoon) return self end - - --- Add asset group(s) to platoon. -- @param #BRIGADE self -- @param Ops.Platoon#PLATOON Platoon The platoon object. diff --git a/Moose Development/Moose/Ops/Cohort.lua b/Moose Development/Moose/Ops/Cohort.lua index df1a3f284..486f7dec1 100644 --- a/Moose Development/Moose/Ops/Cohort.lua +++ b/Moose Development/Moose/Ops/Cohort.lua @@ -10,6 +10,8 @@ -- === -- -- ### Author: **funkyfranky** +-- +-- === -- @module Ops.Cohort -- @image OPS_Cohort.png @@ -81,7 +83,7 @@ COHORT = { --- COHORT class version. -- @field #string version -COHORT.version="0.2.0" +COHORT.version="0.3.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -186,6 +188,9 @@ function COHORT:New(TemplateGroupName, Ngroups, CohortName) self:AddTransition("OnDuty", "Pause", "Paused") -- Pause cohort. self:AddTransition("Paused", "Unpause", "OnDuty") -- Unpause cohort. + self:AddTransition("OnDuty", "Relocate", "Relocating") -- Relocate. + self:AddTransition("Relocating", "Relocated", "OnDuty") -- Relocated. + self:AddTransition("*", "Stop", "Stopped") -- Stop cohort. @@ -193,17 +198,17 @@ function COHORT:New(TemplateGroupName, Ngroups, CohortName) --- Pseudo Functions --- ------------------------ - --- Triggers the FSM event "Start". Starts the COHORT. Initializes parameters and starts event handlers. + --- Triggers the FSM event "Start". Starts the COHORT. -- @function [parent=#COHORT] Start -- @param #COHORT self - --- Triggers the FSM event "Start" after a delay. Starts the COHORT. Initializes parameters and starts event handlers. + --- Triggers the FSM event "Start" after a delay. Starts the COHORT. -- @function [parent=#COHORT] __Start -- @param #COHORT self -- @param #number delay Delay in seconds. - --- Triggers the FSM event "Stop". Stops the COHORT and all its event handlers. + --- Triggers the FSM event "Stop". -- @param #COHORT self --- Triggers the FSM event "Stop" after a delay. Stops the COHORT and all its event handlers. @@ -610,25 +615,31 @@ end --- Check if cohort is "OnDuty". -- @param #COHORT self --- @return #boolean If true, squdron is in state "OnDuty". +-- @return #boolean If true, cohort is in state "OnDuty". function COHORT:IsOnDuty() return self:Is("OnDuty") end --- Check if cohort is "Stopped". -- @param #COHORT self --- @return #boolean If true, squdron is in state "Stopped". +-- @return #boolean If true, cohort is in state "Stopped". function COHORT:IsStopped() return self:Is("Stopped") end --- Check if cohort is "Paused". -- @param #COHORT self --- @return #boolean If true, squdron is in state "Paused". +-- @return #boolean If true, cohort is in state "Paused". function COHORT:IsPaused() return self:Is("Paused") end +--- Check if cohort is "Relocating". +-- @param #COHORT self +-- @return #boolean If true, cohort is relocating. +function COHORT:IsRelocating() + return self:Is("Relocating") +end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Start & Status @@ -870,7 +881,6 @@ function COHORT:RecruitAssets(MissionType, Npayloads) --self:I("Not requested or reserved") -- Check if asset is currently on a mission (STARTED or QUEUED). if self.legion:IsAssetOnMission(asset) then - --self:I("But on a mission") --- -- Asset is already on a mission. --- @@ -892,13 +902,11 @@ function COHORT:RecruitAssets(MissionType, Npayloads) end else - --self:I("No current mission") --- -- Asset as NO current mission --- if asset.spawned then - --self:I("Is already spawned") --- -- Asset is already SPAWNED (could be uncontrolled on the airfield or inbound after another mission) --- diff --git a/Moose Development/Moose/Ops/FlightGroup.lua b/Moose Development/Moose/Ops/FlightGroup.lua index af59d7439..6dd769eb3 100644 --- a/Moose Development/Moose/Ops/FlightGroup.lua +++ b/Moose Development/Moose/Ops/FlightGroup.lua @@ -182,7 +182,7 @@ FLIGHTGROUP.RadioMessage = { --- FLIGHTGROUP class version. -- @field #string version -FLIGHTGROUP.version="0.7.1" +FLIGHTGROUP.version="0.7.2" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -1924,7 +1924,10 @@ function FLIGHTGROUP:onbeforeUpdateRoute(From, Event, To, n, N) self:T2(self.lid.."Allowing update route for Task: ReconMission") elseif task.dcstask.id=="Hover" then -- For recon missions, we need to allow the update as we insert new waypoints. - self:T2(self.lid.."Allowing update route for Task: Hover") + self:T2(self.lid.."Allowing update route for Task: Hover") + elseif task.dcstask.id==AUFTRAG.SpecialTask.RELOCATECOHORT then + -- For relocate + self:T2(self.lid.."Allowing update route for Task: Relocate Cohort") elseif task.description and task.description=="Task_Land_At" then -- We allow this self:T2(self.lid.."Allowing update route for Task: Task_Land_At") @@ -3393,7 +3396,7 @@ end --- Add an AIR waypoint to the flight plan. -- @param #FLIGHTGROUP self -- @param Core.Point#COORDINATE Coordinate The coordinate of the waypoint. Use COORDINATE:SetAltitude(altitude) to define the altitude. --- @param #number Speed Speed in knots. Default 350 kts. +-- @param #number Speed Speed in knots. Default is cruise speed. -- @param #number AfterWaypointWithID Insert waypoint after waypoint given ID. Default is to insert as last waypoint. -- @param #number Altitude Altitude in feet. Default is y-component of Coordinate. Note that these altitudes are wrt to sea level (barometric altitude). -- @param #boolean Updateroute If true or nil, call UpdateRoute. If false, no call. @@ -3407,7 +3410,7 @@ function FLIGHTGROUP:AddWaypoint(Coordinate, Speed, AfterWaypointWithID, Altitud local wpnumber=self:GetWaypointIndexAfterID(AfterWaypointWithID) -- Speed in knots. - Speed=Speed or self.speedCruise + Speed=Speed or self:GetSpeedCruise() -- Create air waypoint. local wp=coordinate:WaypointAir(COORDINATE.WaypointAltType.BARO, COORDINATE.WaypointType.TurningPoint, COORDINATE.WaypointAction.TurningPoint, UTILS.KnotsToKmph(Speed), true, nil, {}) diff --git a/Moose Development/Moose/Ops/Legion.lua b/Moose Development/Moose/Ops/Legion.lua index 8588fc0a4..132994e20 100644 --- a/Moose Development/Moose/Ops/Legion.lua +++ b/Moose Development/Moose/Ops/Legion.lua @@ -5,6 +5,8 @@ -- === -- -- ### Author: **funkyfranky** +-- +-- === -- @module Ops.Legion -- @image OPS_Legion.png @@ -45,13 +47,14 @@ LEGION = { --- LEGION class version. -- @field #string version -LEGION.version="0.2.1" +LEGION.version="0.3.0" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- ToDo list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO: Create FLEED class. +-- DONE: Relocate cohorts. -- DONE: Aircraft will not start hot on Alert5. -- DONE: OPS transport. -- DONE: Make general so it can be inherited by AIRWING and BRIGADE classes. @@ -389,6 +392,91 @@ function LEGION:AddOpsTransport(OpsTransport) return self end +--- Add cohort to cohort table of this legion. +-- @param #LEGION self +-- @param Ops.Cohort#COHORT Cohort The cohort to be added. +-- @return #LEGION self +function LEGION:AddCohort(Cohort) + + -- TODO: Check if this cohort is already part of the legion! + + -- Add cohort to legion. + table.insert(self.cohorts, Cohort) + + return self +end + +--- Remove cohort from cohor table of this legion. +-- @param #LEGION self +-- @param Ops.Cohort#COHORT Cohort The cohort to be added. +-- @return #LEGION self +function LEGION:DelCohort(Cohort) + + for i=#self.cohorts,1,-1 do + local cohort=self.cohorts[i] --Ops.Cohort#COHORT + if cohort.name==Cohort.name then + self:T(self.lid..string.format("Removing Cohort %s", tostring(cohort.name))) + table.remove(self.cohorts, i) + end + end + + return self +end + + +--- Relocate a cohort to another legion. +-- Assets in stock are spawned and routed to the new legion. +-- If assets are spawned, running missions will be cancelled. +-- Cohort assets will not be available until relocation is finished. +-- @param #LEGION self +-- @param Ops.Cohort#COHORT Cohort The cohort to be relocated. +-- @param Ops.Legion#LEGION Legion. +-- @param #number Delay Delay in seconds before relocation takes place. Default 0 sec. +-- @return #LEGION self +function LEGION:RelocateCohort(Cohort, Legion, Delay) + + if Delay and Delay>0 then + self:ScheduleOnce(Delay, LEGION.RelocateCohort, self, Cohort, Legion, 0) + else + + -- Add cohort to legion. + if Legion:IsCohort(Cohort.name) then + self:E(self.lid..string.format("ERROR: Cohort %s is already part of new legion %s ==> CANNOT Relocate!", Cohort.name, Legion.alias)) + return self + else + table.insert(Legion.cohorts, Cohort) + end + + -- Check that cohort is part of this legion + if not self:IsCohort(Cohort.name) then + self:E(self.lid..string.format("ERROR: Cohort %s is NOT part of this legion %s ==> CANNOT Relocate!", Cohort.name, self.alias)) + return self + end + + -- Check that legions are different. + if self.alias==Legion.alias then + self:E(self.lid..string.format("ERROR: old legion %s is same as new legion %s ==> CANNOT Relocate!", self.alias, Legion.alias)) + return self + end + + -- Trigger Relocate event. + Cohort:Relocate() + + -- Create a relocation mission. + local mission=AUFTRAG:_NewRELOCATECOHORT(Legion, Cohort) + + -- Add assets to mission. + mission:_AddAssets(Cohort.assets) + + -- Debug info. + self:I(self.lid..string.format("Relocating Cohort %s [nassets=%d] to legion %s", Cohort.name, #Cohort.assets, Legion.alias)) + + -- Assign mission to this legion. + self:MissionAssign(mission, {self}) + + end + +end --- Get cohort by name. -- @param #LEGION self @@ -408,6 +496,24 @@ function LEGION:_GetCohort(CohortName) return nil end +--- Check if cohort is part of this legion. +-- @param #LEGION self +-- @param #string CohortName Name of the platoon. +-- @return #boolean If `true`, cohort is part of this legion. +function LEGION:IsCohort(CohortName) + + for _,_cohort in pairs(self.cohorts) do + local cohort=_cohort --Ops.Cohort#COHORT + + if cohort.name==CohortName then + return true + end + + end + + return false +end + --- Get cohort of an asset. -- @param #LEGION self -- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset. @@ -667,6 +773,9 @@ end -- @param Ops.Auftrag#AUFTRAG Mission The requested mission. function LEGION:onafterMissionRequest(From, Event, To, Mission) + -- Debug info. + self:T(self.lid..string.format("MissionRequest for mission %s [%s]", Mission:GetName(), Mission:GetType())) + -- Set mission status from QUEUED to REQUESTED. Mission:Requested() @@ -688,6 +797,10 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission) if asset.wid==self.uid then if asset.spawned then + + --- + -- Spawned Assets + --- if asset.flightgroup then @@ -698,37 +811,67 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission) -- Special Missions --- + -- Get current mission. local currM=asset.flightgroup:GetMissionCurrent() + + if currM then + local cancel=false - -- Check if mission is INTERCEPT and asset is currently on GCI mission. If so, GCI is paused. - if Mission.type==AUFTRAG.Type.INTERCEPT then - if currM and currM.type==AUFTRAG.Type.GCICAP then + -- Check if mission is INTERCEPT and asset is currently on GCI mission. If so, GCI is paused. + if currM.type==AUFTRAG.Type.GCICAP and Mission.type==AUFTRAG.Type.INTERCEPT then self:T(self.lid..string.format("Pausing %s mission %s to send flight on intercept mission %s", currM.type, currM.name, Mission.name)) - asset.flightgroup:PauseMission() - end - end - - -- Cancel the current ALERT 5 mission. - if currM and currM.type==AUFTRAG.Type.ALERT5 then - asset.flightgroup:MissionCancel(currM) - end - - -- Cancel the current mission. - if asset.flightgroup:IsArmygroup() then - if currM and (currM.type==AUFTRAG.Type.ONGUARD or currM.type==AUFTRAG.Type.ARMOREDGUARD) then + asset.flightgroup:PauseMission() + end + + -- Cancel current ALERT5 mission + if currM.type==AUFTRAG.Type.ALERT5 then + cancel=true + end + + -- Cancel the current mission. + if currM.type==AUFTRAG.Type.ONGUARD or currM.type==AUFTRAG.Type.ARMOREDGUARD then + cancel=true + end + + if Mission.type==AUFTRAG.Type.RELOCATECOHORT then + cancel=true + + local requestID=currM.requestID[self.alias] + + -- Get request. + local request=self:GetRequestByID(requestID) + + if request then + self:T2(self.lid.."Removing group from cargoset") + request.cargogroupset:Remove(asset.spawngroupname, true) + else + self:E(self.lid.."ERROR: no request for spawned asset!") + end + end + + + if cancel then asset.flightgroup:MissionCancel(currM) end + end + -- Trigger event. self:__OpsOnMission(5, asset.flightgroup, Mission) else - self:E(self.lid.."ERROR: flight group for asset does NOT exist!") + self:E(self.lid.."ERROR: OPSGROUP for asset does NOT exist but it seems to be SPAWNED (asset.spawned=true)!") end else + + --- + -- Stock Assets + --- + -- These assets need to be requested and spawned. table.insert(Assetlist, asset) + end end @@ -750,18 +893,14 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission) asset.missionTask=Mission.missionTask end + -- Set takeoff type to parking for ALERT5 missions. We dont want them to take off without a proper mission if squadron start is hot. if Mission.type==AUFTRAG.Type.ALERT5 then asset.takeoffType=COORDINATE.WaypointType.TakeOffParking end end - -- Special for reloading brigade units - --local coordinate = nil - -- if Mission.specialCoordinate then - -- coordinate = Mission.specialCoordinate - -- end - + -- Set assignment. -- TODO: Get/set functions for assignment string. local assignment=string.format("Mission-%d", Mission.auftragsnummer) @@ -774,9 +913,13 @@ function LEGION:onafterMissionRequest(From, Event, To, Mission) -- Get request. local request=self:GetRequestByID(self.queueid) + -- Debug info. + self:T(self.lid..string.format("Mission %s [%s] got Request ID=%d", Mission:GetName(), Mission:GetType(), self.queueid)) + + -- Request ship. if request then if self:IsShip() then - self:T(self.lid.."Warehouse phyiscal structure is SHIP. Requestes assets will be late activated!") + self:T(self.lid.."Warehouse physical structure is SHIP. Requestes assets will be late activated!") request.lateActivation=true end end @@ -976,7 +1119,7 @@ end -- @param Ops.Auftrag#AUFTRAG Mission The requested mission. function LEGION:onafterOpsOnMission(From, Event, To, OpsGroup, Mission) -- Debug info. - self:T2(self.lid..string.format("Group %s on %s mission %s", OpsGroup:GetName(), Mission:GetType(), Mission:GetName())) + self:T2(self.lid..string.format("Group %s on mission %s [%s]", OpsGroup:GetName(), Mission:GetName(), Mission:GetType())) if self:IsAirwing() then -- Trigger event for Airwings. @@ -1031,7 +1174,7 @@ function LEGION:onafterNewAsset(From, Event, To, asset, assignment) local nunits=#asset.template.units -- Debug text. - local text=string.format("Adding asset to squadron %s: assignment=%s, type=%s, attribute=%s, nunits=%d ngroup=%s", cohort.name, assignment, asset.unittype, asset.attribute, nunits, tostring(cohort.ngrouping)) + local text=string.format("Adding asset to cohort %s: assignment=%s, type=%s, attribute=%s, nunits=%d ngroup=%s", cohort.name, assignment, asset.unittype, asset.attribute, nunits, tostring(cohort.ngrouping)) self:T(self.lid..text) -- Adjust number of elements in the group. @@ -1332,19 +1475,23 @@ end -- @param Functional.Warehouse#WAREHOUSE.Queueitem Request Information table of the request. function LEGION:onafterRequest(From, Event, To, Request) - -- Assets - local assets=Request.cargoassets + if Request.toself then - -- Get Mission - local Mission=self:GetMissionByID(Request.assignment) - - if Mission and assets then - - for _,_asset in pairs(assets) do - local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem - -- This would be the place to modify the asset table before the asset is spawned. + -- Assets + local assets=Request.cargoassets + + -- Get Mission + local Mission=self:GetMissionByID(Request.assignment) + + if Mission and assets then + + for _,_asset in pairs(assets) do + local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem + -- This would be the place to modify the asset table before the asset is spawned. + end + end - + end -- Call parent warehouse function after assets have been adjusted. @@ -1377,6 +1524,21 @@ function LEGION:onafterSelfRequest(From, Event, To, groupset, request) end +--- On after "RequestSpawned" event. +-- @param #LEGION self +-- @param #string From From state. +-- @param #string Event Event. +-- @param #string To To state. +-- @param #WAREHOUSE.Pendingitem Request Information table of the request. +-- @param Core.Set#SET_GROUP CargoGroupSet Set of cargo groups. +-- @param Core.Set#SET_GROUP TransportGroupSet Set of transport groups if any. +function LEGION:onafterRequestSpawned(From, Event, To, Request, CargoGroupSet, TransportGroupSet) + + -- Call parent warehouse function. + self:GetParent(self, LEGION).onafterRequestSpawned(self, From, Event, To, Request, CargoGroupSet, TransportGroupSet) + +end + ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Mission Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- diff --git a/Moose Development/Moose/Ops/OpsGroup.lua b/Moose Development/Moose/Ops/OpsGroup.lua index 92c5aba92..0ec1e2b9f 100644 --- a/Moose Development/Moose/Ops/OpsGroup.lua +++ b/Moose Development/Moose/Ops/OpsGroup.lua @@ -468,7 +468,7 @@ OPSGROUP.CargoStatus={ --- OpsGroup version. -- @field #string version -OPSGROUP.version="0.7.6" +OPSGROUP.version="0.7.7" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -481,9 +481,9 @@ OPSGROUP.version="0.7.6" -- TODO: Add pseudo function. -- TODO: Afterburner restrict. -- TODO: What more options? --- TODO: Damage? -- TODO: Shot events? -- TODO: Marks to add waypoints/tasks on-the-fly. +-- DONE: Damage? -- DONE: Options EPLRS ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- @@ -3867,6 +3867,38 @@ function OPSGROUP:onafterTaskExecute(From, Event, To, Task) local timer = TIMER:New(FlyOn,helo,Speed,CruiseAlt,Task) timer:Start(time) end + + elseif Task.dcstask.id==AUFTRAG.SpecialTask.RELOCATECOHORT then + + --- + -- Task "RelocateCohort" Mission. + --- + + -- Debug mission. + self:T(self.lid.."Executing task for relocation mission") + + -- The new legion. + local legion=Task.dcstask.params.legion --Ops.Legion#LEGION + + -- Get random coordinate in spawn zone of new legion. + local Coordinate=legion.spawnzone:GetRandomCoordinate() + + -- Get current waypoint ID. + local currUID=self:GetWaypointCurrent().uid + + local wp=nil --#OPSGROUP.Waypoint + if self.isArmygroup then + self:T2(self.lid.."Routing group to spawn zone of new legion") + wp=ARMYGROUP.AddWaypoint(self, Coordinate, Speed, currUID, Formation) + elseif self.isFlightgroup then + self:T2(self.lid.."Routing group to intermediate point near new legion") + Coordinate=self:GetCoordinate():GetIntermediateCoordinate(Coordinate, 0.8) + wp=FLIGHTGROUP.AddWaypoint(self, Coordinate, UTILS.KmphToKnots(self.speedCruise), currUID, UTILS.MetersToFeet(self.altitudeCruise)) + else + + end + + wp.missionUID=Mission and Mission.auftragsnummer or nil else @@ -4060,22 +4092,35 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task) local Mission=self:GetMissionByTaskID(Task.id) if Mission and Mission:IsNotOver() then - + + -- Get mission status of this group. local status=Mission:GetGroupStatus(self) + -- Check if mission is paused. if status~=AUFTRAG.GroupStatus.PAUSED then + --- + -- Mission is NOT over ==> trigger done + --- + + -- Get egress waypoint uid. local EgressUID=Mission:GetGroupEgressWaypointUID(self) + if EgressUID then + -- Egress coordinate given ==> wait until we pass that waypoint. self:T(self.lid..string.format("Task Done but Egress waypoint defined ==> Will call Mission Done once group passed waypoint UID=%d!", EgressUID)) else + -- Mission done! self:T(self.lid.."Task Done ==> Mission Done!") self:MissionDone(Mission) end else - --Mission paused. Do nothing! Just set the current mission to nil so we can launch a new one. + --- + -- Mission Paused: Do nothing! Just set the current mission to nil so we can launch a new one. + --- if self.currentmission and self.currentmission==Mission.auftragsnummer then self.currentmission=nil end + -- Remove mission waypoints. self:T(self.lid.."Remove mission waypoints") self:_RemoveMissionWaypoints(Mission, false) end @@ -4091,7 +4136,7 @@ function OPSGROUP:onafterTaskDone(From, Event, To, Task) 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) @@ -4685,12 +4730,41 @@ function OPSGROUP:onafterMissionDone(From, Event, To, Mission) self:_SwitchICLS() end - -- We add a 10 sec delay for ARTY. Found that they need some time to readjust the barrel of their gun. Not sure if necessary for all. Needs some more testing! + -- Delay before check if group is done. local delay=1 + + -- Special mission cases. if Mission.type==AUFTRAG.Type.ARTY then - delay=60 + -- We add a 10 sec delay for ARTY. Found that they need some time to readjust the barrel of their gun. Not sure if necessary for all. Needs some more testing! + delay=60 + elseif Mission.type==AUFTRAG.Type.RELOCATECOHORT then + + -- New legion. + local legion=Mission.DCStask.params.legion --Ops.Legion#LEGION + + -- Debug message. + self:T(self.lid..string.format("Asset relocated to new legion=%s",tostring(legion.alias))) + + -- Get asset and change its warehouse id. + local asset=Mission:GetAssetByName(self.groupname) + if asset then + asset.wid=legion.uid + end + + -- Set new legion. + self.legion=legion + + if self.isArmygroup then + self:T2(self.lid.."Adding asset via ReturnToLegion()") + self:ReturnToLegion() + elseif self.isFlightgroup then + self:T2(self.lid.."Adding asset via RTB to new legion airbase") + self:RTB(self.legion.airbase) + end + + return end - + -- Check if group is done. self:_CheckGroupDone(delay) @@ -4753,6 +4827,13 @@ function OPSGROUP:RouteToMission(mission, delay) waypointcoord=zone:GetRandomCoordinate(nil , nil, surfacetypes) elseif mission.type==AUFTRAG.Type.ONGUARD or mission.type==AUFTRAG.Type.ARMOREDGUARD then waypointcoord=mission:GetMissionWaypointCoord(self.group, nil, surfacetypes) + elseif mission.type==AUFTRAG.Type.RELOCATECOHORT then + local ToCoordinate=mission.DCStask.params.legion:GetCoordinate() + if self.isFlightgroup then + waypointcoord=self:GetCoordinate():GetIntermediateCoordinate(ToCoordinate, 0.2):SetAltitude(self.altitudeCruise) + else + waypointcoord=self:GetCoordinate():GetIntermediateCoordinate(ToCoordinate, 0.05) + end else waypointcoord=mission:GetMissionWaypointCoord(self.group, randomradius, surfacetypes) end @@ -4768,7 +4849,7 @@ function OPSGROUP:RouteToMission(mission, delay) end -- Speed to mission waypoint. - local SpeedToMission=mission.missionSpeed and UTILS.KmphToKnots(mission.missionSpeed) or self:GetSpeedCruise() --UTILS.KmphToKnots(self.speedCruise) + local SpeedToMission=mission.missionSpeed and UTILS.KmphToKnots(mission.missionSpeed) or self:GetSpeedCruise() -- Special for Troop transport. if mission.type==AUFTRAG.Type.TROOPTRANSPORT then @@ -4846,17 +4927,14 @@ function OPSGROUP:RouteToMission(mission, delay) end end - -- UID of this waypoint. - --local uid=self:GetWaypointCurrent().uid - -- Add waypoint. local waypoint=nil --#OPSGROUP.Waypoint if self:IsFlightgroup() then waypoint=FLIGHTGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) elseif self:IsArmygroup() then - waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.optionFormation, false) + waypoint=ARMYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.optionFormation, false) elseif self:IsNavygroup() then - waypoint=NAVYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, mission.missionAltitude or self.altitudeCruise, false) + waypoint=NAVYGROUP.AddWaypoint(self, waypointcoord, SpeedToMission, uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) end waypoint.missionUID=mission.auftragsnummer @@ -4879,9 +4957,9 @@ function OPSGROUP:RouteToMission(mission, delay) if self:IsFlightgroup() then Ewaypoint=FLIGHTGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) elseif self:IsArmygroup() then - Ewaypoint=ARMYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, mission.optionFormation, false) + Ewaypoint=ARMYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, mission.optionFormation, false) elseif self:IsNavygroup() then - Ewaypoint=NAVYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) + Ewaypoint=NAVYGROUP.AddWaypoint(self, egresscoord, SpeedToMission, waypoint.uid, UTILS.MetersToFeet(mission.missionAltitude or self.altitudeCruise), false) end Ewaypoint.missionUID=mission.auftragsnummer mission:SetGroupEgressWaypointUID(self, Ewaypoint.uid) @@ -5190,6 +5268,20 @@ function OPSGROUP:onafterPassingWaypoint(From, Event, To, Waypoint) end + elseif task and task.dcstask.id==AUFTRAG.SpecialTask.RELOCATECOHORT then + + --- + -- SPECIAL TASK: Relocate Mission + --- + + -- TARGET. + local legion=task.dcstask.params.legion --Ops.Legion#LEGION + + self:T(self.lid..string.format("Asset arrived at relocation task waypoint ==> Task Done!")) + + -- Final zone reached ==> task done. + self:TaskDone(task) + else --- @@ -8933,6 +9025,21 @@ function OPSGROUP:_CheckGroupDone(delay) return end end + + -- Number of tasks remaining. + local nTasks=self:CountRemainingTasks() + + -- Number of mission remaining. + local nMissions=self:CountRemainingMissison() + + -- Number of cargo transports remaining. + local nTransports=self:CountRemainingTransports() + + -- Number of remaining tasks/missions? + if nTasks>0 or nMissions>0 or nTransports>0 then + self:T(self.lid..string.format("Group still has tasks, missions or transports ==> NOT DONE")) + return + end if self.adinfinitum then @@ -9696,7 +9803,6 @@ function OPSGROUP._PassingWaypoint(opsgroup, uid) if opsgroup.cargoTZC.PickupAirbase then -- Pickup airbase specified. Land there. - --env.info(opsgroup.lid.."FF Land at Pickup Airbase") opsgroup:LandAtAirbase(opsgroup.cargoTZC.PickupAirbase) else -- Land somewhere in the pickup zone. Only helos can do that. @@ -9726,8 +9832,7 @@ function OPSGROUP._PassingWaypoint(opsgroup, uid) if opsgroup.cargoTZC then if opsgroup.cargoTZC.DeployAirbase then - -- Pickup airbase specified. Land there. - --env.info(opsgroup.lid.."FF Land at Deploy Airbase") + -- Deploy airbase specified. Land there. opsgroup:LandAtAirbase(opsgroup.cargoTZC.DeployAirbase) else -- Land somewhere in the pickup zone. Only helos can do that. @@ -10466,7 +10571,6 @@ function OPSGROUP:SwitchRadio(Frequency, Modulation) Modulation=Modulation or self.radioDefault.Modu if self:IsFlightgroup() and not self.radio.On then - --env.info("FF radio OFF") self.group:SetOption(AI.Option.Air.id.SILENCE, false) end