--- **Ops** - Auftrag (mission) for Ops. -- -- **Main Features:** -- -- * Create mission for ops. -- -- -- === -- -- ### Author: **funkyfranky** -- @module Ops.Auftrag -- @image OPS_Auftrag.png --- AUFTRAG class. -- @type AUFTRAG -- @field #string ClassName Name of the class. -- @field #boolean Debug Debug mode. Messages to all about status. -- @field #string lid Class id string for output to DCS log file. -- @field #number auftragsnummer Auftragsnummer. -- @field #string type Mission type. -- @field #string status Mission status. -- @field #table flightdata Flight specific data. -- @field #string name Mission name. -- @field #number prio Mission priority. -- @field #boolean urgent Mission is urgent. Running missions with lower prio might be cancelled. -- @field #number Tstart Mission start time in seconds. -- @field #number Tstop Mission stop time in seconds. -- @field #number duration Mission duration in seconds. -- @field #number marker F10 map marker ID. -- @field #table DCStask DCS task structure. -- -- @field Core.Point#COORDINATE waypointcoord Coordinate of the waypoint task. -- -- @field Core.Point#COORDINATE orbitCoord Coordinate where to orbit. -- @field #number orbitSpeed Orbit speed in m/s. -- @field #number orbitHeading Orbit heading in degrees. -- @field #number orbitLeg Length of orbit leg in meters. -- -- @field Core.Zone#ZONE_RADIUS engageZone *Circular* engagement zone. -- @field #table engageTargetTypes Table of target types that are engaged in the engagement zone. -- @field Core.Point#COORDINATE engageCoord Coordinate of target location. -- @field Core.Set#SET_GROUP engageTargetGroupset Set of target groups to attack. -- @field Core.Set#SET_GROUP engageTargetUnitset Set of target units to attack. -- @field #number engageAltitude Engagement altitude in meters. -- @field #number engageDirection Engagement direction in degrees. -- @field #number engageQuantity Number of times a target is engaged. -- @field #number engageWeaponType Weapon type used. -- @field #number engageWeaponExpend How many weapons are used. -- @field #boolean engageAsGroup Group attack. -- @field #number engageMaxDistance Max engage distance. -- -- @field Wrapper.Group#GROUP escortGroup The group to be escorted. -- @field DCS#Vec3 escortVec3 The 3D offset vector from the escorted group to the escort group. -- -- @field Ops.AirWing#AIRWING airwing The assigned airwing. -- @field #string squadname Name of the assigned Airwing squadron. -- @field #table assets Airwing Assets assigned for this mission. -- @field #number nassets Number of required assets by the Airwing. -- @field #number requestID The ID of the queued warehouse request. Necessary to cancel the request if the mission was cancelled before the request is processed. -- -- @field #number optionROE ROE. -- @field #number optionROT ROT. -- @field #number optionCM Counter measures. -- @field #number optionFormation Formation. -- @field #number optionRTBammo RTB on out-of-ammo. -- @field #number optionRTBfuel RTB on out-of-fuel. -- @field #number optionECM ECM. -- -- @extends Core.Fsm#FSM --- *A warrior's mission is to foster the success of others.* --- Morihei Ueshiba -- -- === -- -- ![Banner Image](..\Presentations\CarrierAirWing\AUFTRAG_Main.jpg) -- -- # The AUFTRAG Concept -- -- # Events -- -- -- # Missions -- -- -- # Examples -- -- -- -- -- -- @field #AUFTRAG AUFTRAG = { ClassName = "AUFTRAG", Debug = false, lid = nil, auftragsnummer = nil, flightdata = {}, } --- Global mission counter. _AUFTRAGSNR=0 --- Mission types. -- @type AUFTRAG.Type -- @param #string ANTISHIP Anti-ship mission. -- @param #string AWACS AWACS mission. -- @param #string BAI Battlefield Air Interdiction. -- @param #string BOMBING Bombing mission. -- @param #string CAP Combat Air Patrol. -- @param #string CAS Close Air Support. -- @param #string ESCORT Escort mission. -- @param #string FACA Forward AirController airborne mission. -- @param #string FERRY Ferry flight mission. -- @param #string INTERCEPT Intercept mission. -- @param #string ORBIT Orbit mission. -- @param #string RECON Recon mission. -- @param #string SEAD Suppression/destruction of enemy air defences. -- @param #string STRIKE Strike mission. -- @param #string TANKER Tanker mission. -- @param #string TRANSPORT Transport mission. AUFTRAG.Type={ ANTISHIP="Anti Ship", AWACS="AWACS", BAI="BAI", BOMBING="Bombing", CAP="CAP", CAS="CAS", ESCORT="Escort", FACA="FAC-A", FERRY="Ferry Flight", INTERCEPT="Intercept", ORBIT="Orbit", RECON="Recon", SEAD="SEAD", STRIKE="Strike", TANKER="Tanker", TRANSPORT="Transport", } --- Mission status. -- @type AUFTRAG.Status -- @field #string PLANNED Mission is at the early planning stage. -- @field #string QUEUED Mission is queued at an airwing. -- @field #string REQUESTED Mission assets were requested from the warehouse. -- @field #string ASSIGNED Mission was assigned to somebody. -- @field #string SCHEDULED Mission is scheduled in a FLIGHGROUP queue waiting to be started. -- @field #string STARTED Mission has started but is not executed yet. -- @field #string EXECUTING Mission is being executed. -- @field #string DONE Mission is over. -- @field #string CANCELLED Mission was cancelled. -- @field #string SUCCESS Mission was a success. -- @field #string FAILED Mission failed. AUFTRAG.Status={ PLANNED="planned", QUEUED="queued", REQUESTED="requested", ASSIGNED="assigned", SCHEDULED="scheduled", STARTED="started", EXECUTING="executing", DONE="done", CANCELLED="cancelled", SUCCESS="success", FAILED="failed", } --- FlightStatus -- @type AUFTRAG.FlightStatus -- @field #string SCHEDULED Mission is scheduled in a FLIGHGROUP queue waiting to be started. -- @field #string STARTED Flightgroup started this mission but it is not executed yet. -- @field #string EXECUTING Flightgroup is executing this mission. -- @field #string DONE Mission task of the flightgroup is done. -- @field #string CANCELLED Mission was cancelled. AUFTRAG.FlightStatus={ SCHEDULED="scheduled", STARTED="started", EXECUTING="executing", DONE="done", CANCELLED="cancelled", } --- Flight specific data. Each flight subscribed to this mission has different data for this. -- @type AUFTRAG.FlightData -- @field Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. -- @field Core.Point#COORDINATE waypointcoordinate Waypoint coordinate. -- @field #number waypointindex Waypoint index. -- @field Ops.FlightGroup#FLIGHTGROUP.Task waypointtask Waypoint task. -- @field #string status Flight mission status. --- AUFTRAG class version. -- @field #string version AUFTRAG.version="0.0.4" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO: Mission ROE and ROT -- TODO: Mission formation, etc. -- TODO: FSM events. -- TODO: F10 marker functions that are updated on Status event. -- TODO: Evaluate mission result ==> SUCCESS/FAILURE ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Constructor ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Create a new AUFTRAG object. -- @param #AUFTRAG self -- @param #string Type Mission type. -- @return #AUFTRAG self function AUFTRAG:New(Type) -- Inherit everything from FSM class. local self=BASE:Inherit(self, FSM:New()) -- #AUFTRAG -- Increase global counter. _AUFTRAGSNR=_AUFTRAGSNR+1 -- Mission type. self.type=Type -- Auftragsnummer. self.auftragsnummer=_AUFTRAGSNR -- Log id. self.lid=string.format("Auftrag #%d %s | ", self.auftragsnummer, tostring(self.type)) -- State is planned. self.status=AUFTRAG.Status.PLANNED -- Defaults self:SetName() self:SetPriority() self:SetMissionTime() -- FMS start state is PLANNED. self:SetStartState(self.status) -- PLANNED --> (QUEUED) --> (REQUESTED) --> SCHEDULED --> STARTED --> EXECUTING --> DONE self:AddTransition(AUFTRAG.Status.PLANNED, "Queued", AUFTRAG.Status.QUEUED) -- Mission is in queue of an AIRWING. self:AddTransition(AUFTRAG.Status.QUEUED, "Requested", AUFTRAG.Status.REQUESTED) -- Mission assets have been requested from the warehouse. self:AddTransition(AUFTRAG.Status.REQUESTED, "Scheduled", AUFTRAG.Status.SCHEDULED) -- Mission added to the first flight group queue. self:AddTransition(AUFTRAG.Status.PLANNED, "Scheduled", AUFTRAG.Status.SCHEDULED) -- From planned directly to scheduled. self:AddTransition(AUFTRAG.Status.SCHEDULED, "Started", AUFTRAG.Status.STARTED) -- First asset has started the mission self:AddTransition(AUFTRAG.Status.STARTED, "Executing", AUFTRAG.Status.EXECUTING) -- First asset is executing the mission. self:AddTransition("*", "Done", AUFTRAG.Status.DONE) -- All assets have reported that mission is done. self:AddTransition("*", "Cancel", AUFTRAG.Status.CANCELLED) -- Command to cancel the mission. self:AddTransition("*", "Accomplished", AUFTRAG.Status.SUCCESS) self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED) self:AddTransition("*", "Status", "*") self:__Status(-1) return self end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Create Missions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Create an ORBIT mission. -- @param #AUFTRAG self -- @param Core.Point#COORDINATE Coordinate Where to orbit. Altitude is also taken from the coordinate. -- @param #number Speed Orbit speed in knots. Default 350 kts. -- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West). -- @param #number Leg Length of race-track in NM. Default 10 NM. -- @return #AUFTRAG self function AUFTRAG:NewORBIT(Coordinate, Speed, Heading, Leg) local auftrag=AUFTRAG:New(AUFTRAG.Type.ORBIT) auftrag.orbitCoord = Coordinate auftrag.orbitHeading = Heading or 270 auftrag.orbitLeg = UTILS.NMToMeters(Leg or 10) auftrag.orbitSpeed = UTILS.KnotsToMps(Speed or 350) auftrag.DCStask=auftrag:GetDCSMissionTask() return auftrag end --- Create a CAP mission. -- @param #AUFTRAG self -- @param Core.Point#COORDINATE OrbitCoordinate Where to orbit. Altitude is also taken from the coordinate. -- @param #number OrbitSpeed Orbit speed in knots. Default 350 kts. -- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West). -- @param #number Leg Length of race-track in NM. Default 10 NM. -- @param Core.Zone#ZONE_RADIUS ZoneCAP Circular CAP zone. Detected targets in this zone will be engaged. -- @param #table TargetTypes Table of target types. Default {"Air"}. -- @return #AUFTRAG self function AUFTRAG:NewCAP(OrbitCoordinate, OrbitSpeed, Heading, Leg, ZoneCAP, TargetTypes) -- Ensure given TargetTypes parameter is a table. if TargetTypes then if type(TargetTypes)~="table" then TargetTypes={TargetTypes} end end -- Create ORBIT first. local mission=self:NewORBIT(OrbitCoordinate, OrbitSpeed, Heading, Leg) -- CAP paramters. mission.type=AUFTRAG.Type.CAP mission.engageZone=ZoneCAP or ZONE_RADIUS:New("CAP Zone", OrbitCoordinate:GetVec2(), mission.orbitLeg) mission.engageTargetTypes=TargetTypes or {"Air"} mission.DCStask=mission:GetDCSMissionTask() return mission end --- Create a CAS mission. -- @param #AUFTRAG self -- @param Core.Point#COORDINATE OrbitCoordinate Where to orbit. Altitude is also taken from the coordinate. -- @param #number OrbitSpeed Orbit speed in knots. Default 350 kts. -- @param #number Heading Heading of race-track pattern in degrees. Default 270 (East to West). -- @param #number Leg Length of race-track in NM. Default 10 NM. -- @param Core.Zone#ZONE_RADIUS ZoneCAS Circular CAS zone. Detected targets in this zone will be engaged. -- @param #table TargetTypes Table of target types. Default {"Helicopters", "Ground Units", "Light armed ships"}. -- @return #AUFTRAG self function AUFTRAG:NewCAS(OrbitCoordinate, OrbitSpeed, Heading, Leg, ZoneCAS, TargetTypes) -- Ensure given TargetTypes parameter is a table. if TargetTypes then if type(TargetTypes)~="table" then TargetTypes={TargetTypes} end end -- Create ORBIT first. local mission=self:NewORBIT(OrbitCoordinate, OrbitSpeed, Heading, Leg) -- CAS paramters. mission.type=AUFTRAG.Type.CAS mission.engageZone=ZoneCAS or ZONE_RADIUS:New("CAS Zone", OrbitCoordinate:GetVec2(), Leg) mission.engageTargetTypes=TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"} mission.DCStask=mission:GetDCSMissionTask() return mission end --- Create a STRIKE mission. Flight will attack a specified coordinate. -- @param #AUFTRAG self -- @param Core.Point#COORDINATE Coordinate Target Coordinate. -- @param #number Altitude Engage altitude in feet. Default 1000. -- @return #AUFTRAG self function AUFTRAG:NewSTRIKE(TargetCoordinate, Altitude) local mission=AUFTRAG:New(AUFTRAG.Type.STRIKE) mission.engageCoord=TargetCoordinate mission.engageAltitude=UTILS.FeetToMeters(Altitude or 1000) mission.DCStask=mission:GetDCSMissionTask() return mission end --- Create an INTERCEPT mission. -- @param #AUFTRAG self -- @param Core.Set#SET_GROUP TargetGroupSet The set of target groups to intercept. -- @return #AUFTRAG self function AUFTRAG:NewINTERCEPT(TargetGroupSet) if TargetGroupSet:IsInstanceOf("GROUP") then env.info("Converting group to set!") TargetGroupSet=SET_GROUP:New():AddGroup(TargetGroupSet) end local mission=AUFTRAG:New(AUFTRAG.Type.INTERCEPT) mission.engageTargetGroupset=TargetGroupSet mission.engageTargetGroupset:FilterDeads():FilterCrashes() mission.DCStask=mission:GetDCSMissionTask() return mission end --- Create a BAI mission. -- @param #AUFTRAG self -- @param Core.Set#SET_GROUP TargetGroupSet The set of target groups to attack. Instead of a SET an ordinary GROUP object can also be given if only a single group needs to be attacked. -- @return #AUFTRAG self function AUFTRAG:NewBAI(TargetGroupSet) if TargetGroupSet:IsInstanceOf("GROUP") then env.info("Converting group to set!") TargetGroupSet=SET_GROUP:New():AddGroup(TargetGroupSet) end local mission=AUFTRAG:New(AUFTRAG.Type.BAI) mission.engageTargetGroupset=TargetGroupSet mission.engageTargetGroupset:FilterDeads():FilterCrashes() mission.DCStask=mission:GetDCSMissionTask() return mission end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- User API Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Set mission start and stop time. -- @param #AUFTRAG self -- @param #string ClockStart Time the mission is started, e.g. "05:00" for 5 am. If specified as a #number, it will be relative (in seconds) to the current mission time. Default is 5 seconds after mission was added. -- @param #string ClockStop (Optional) Time the mission is stopped, e.g. "13:00" for 1 pm. If mission could not be started at that time, it will be removed from the queue. If specified as a #number it will be relative (in seconds) to the current mission time. -- @return #AUFTRAG self function AUFTRAG:SetMissionTime(ClockStart, ClockStop) -- Current mission time. local Tnow=timer.getAbsTime() -- Set start time. Default in 5 sec. local Tstart=Tnow+5 if ClockStart and type(ClockStart)=="number" then Tstart=Tnow+ClockStart elseif ClockStart and type(ClockStart)=="string" then Tstart=UTILS.ClockToSeconds(ClockStart) end -- Set stop time. Default nil. local Tstop=nil if ClockStop and type(ClockStop)=="number" then Tstop=Tnow+ClockStop elseif ClockStop and type(ClockStop)=="string" then Tstop=UTILS.ClockToSeconds(ClockStop) end self.Tstart=Tstart self.Tstop=Tstop if Tstop then self.duration=self.Tstop-self.Tstart end return self end --- Set mission priority and (optional) urgency. Urgent missions can cancel other running missions. -- @param #AUFTRAG self -- @param #number Prio Priority 1=high, 100=low. Default 50. -- @param #boolean Urgent If *true*, another running mission might be cancelled if it has a lower priority. -- @return #AUFTRAG self function AUFTRAG:SetPriority(Prio, Urgent) self.prio=Prio or 50 self.urgent=Urgent return self end --- Set mission name. -- @param #AUFTRAG self -- @param #string Name Name of the mission. -- @return #AUFTRAG self function AUFTRAG:SetName(Name) self.name=Name or string.format("Auftragsnummer %d", self.auftragsnummer) return self end --- Set weapon type used for the engagement. -- @param #AUFTRAG self -- @param #number WeaponType Weapon type. Default is ENUMS.WeaponFlag.Auto -- @return #AUFTRAG self function AUFTRAG:SetWeaponType(WeaponType) self.engageWeaponType=WeaponType or ENUMS.WeaponFlag.Auto -- Update the DCS task parameter. self.DCStask=self:GetDCSMissionTask() return self end --- Set Rules of Engagement for this mission. -- @param #AUFTRAG self -- @param #number roe ROE -- @return #AUFTRAG self function AUFTRAG:SetROE(roe) self.optionROE=roe return self end --- Add a flight group to the mission. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup The FLIGHTGROUP object. function AUFTRAG:AddFlightGroup(FlightGroup) self:I(self.lid..string.format("Adding flight group %s", FlightGroup.groupname)) local flightdata={} --#AUFTRAG.FlightData flightdata.flightgroup=FlightGroup flightdata.status=AUFTRAG.FlightStatus.SCHEDULED flightdata.waypointcoordinate=nil flightdata.waypointindex=nil flightdata.waypointtask=nil self.flightdata[FlightGroup.groupname]=flightdata end --- Check if mission is PLANNED. -- @param #AUFTRAG self -- @return #boolean If true, mission is in the planning state. function AUFTRAG:IsPlanned() return self.status==AUFTRAG.Status.PLANNED end --- Check if mission is QUEUED at an AIRWING mission queue. -- @param #AUFTRAG self -- @return #boolean If true, mission is queued. function AUFTRAG:IsQueued() return self.status==AUFTRAG.Status.QUEUED end --- Check if mission is REQUESTED, i.e. request for WAREHOUSE assets is done. -- @param #AUFTRAG self -- @return #boolean If true, mission is requested. function AUFTRAG:IsRequested() return self.status==AUFTRAG.Status.REQUESTED end --- Check if mission is SCHEDULED, i.e. request for WAREHOUSE assets is done. -- @param #AUFTRAG self -- @return #boolean If true, mission is queued. function AUFTRAG:IsScheduled() return self.status==AUFTRAG.Status.SCHEDULED end --- Check if mission is executing. -- @param #AUFTRAG self -- @return #boolean If true, mission is currently executing. function AUFTRAG:IsExecuting() return self.status==AUFTRAG.Status.EXECUTING end --- Check if mission was cancelled. -- @param #AUFTRAG self -- @return #boolean If true, mission was cancelled. function AUFTRAG:IsCancelled() return self.status==AUFTRAG.Status.CANCELLED end --- Check if mission is done. -- @param #AUFTRAG self -- @return #boolean If true, mission is done. function AUFTRAG:IsCancelled() return self.status==AUFTRAG.Status.DONE end --- Check if mission is over. This could be state DONE or CANCELLED. -- @param #AUFTRAG self -- @return #boolean If true, mission is currently executing. function AUFTRAG:IsOver() local over = self.status==AUFTRAG.Status.DONE or self.status==AUFTRAG.Status.CANCELLED or self.status==AUFTRAG.Status.SUCCESS or self.status==AUFTRAG.Status.FAILED return over end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Mission Status ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- On after "Status" event. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param Ops.AirWing#AIRWING Airwing The airwing. function AUFTRAG:onafterStatus(From, Event, To) local fsmstate=self:GetState() local Ntargets=self:CountMissionTargets() local Cstart=UTILS.SecondsToClock(self.Tstart, true) local Cstop=self.Tstop and UTILS.SecondsToClock(self.Tstop, true) or "INF" -- Info message. self:I(self.lid..string.format("FSM state %s (Mstatus=%s): T=%s-%s flights=%d, targets=%d", fsmstate, self.status, Cstart, Cstop, #self.flightdata, Ntargets)) self:__Status(-30) end --- Set flightgroup mission status. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. -- @param #string status New status. function AUFTRAG:SetFlightStatus(flightgroup, status) self.flightdata[flightgroup.groupname].status=status end --- Get flightgroup mission status. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. function AUFTRAG:GetFlightStatus(flightgroup) return self.flightdata[flightgroup.groupname].status end --- Set flightgroup waypoint coordinate. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. -- @param Core.Point#COORDINATE coordinate Waypoint Coordinate. function AUFTRAG:SetFlightWaypointCoordinate(flightgroup, coordinate) self.flightdata[flightgroup.groupname].waypointcoordinate=coordinate end --- Get flightgroup waypoint coordinate. -- @param #AUFTRAG self -- @return Core.Point#COORDINATE Waypoint Coordinate. function AUFTRAG:GetFlightWaypointCoordinate(flightgroup) return self.flightdata[flightgroup.groupname].waypointcoordinate end --- Set flightgroup waypoint task. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. -- @param Ops.FlightGroup#FLIGHTGROUP.Task task Waypoint task. function AUFTRAG:SetFlightWaypointTask(flightgroup, task) self:I(self.lid..string.format("Setting waypoint task %s", task and task.description or "WTF")) self.flightdata[flightgroup.groupname].waypointtask=task end --- Get flightgroup waypoint task. -- @param #AUFTRAG self -- @param Ops.FlightGroup#FLIGHTGROUP flightgroup The flight group. -- @return Ops.FlightGroup#FLIGHTGROUP.Task task Waypoint task. Waypoint task. function AUFTRAG:GetFlightWaypointTask(flightgroup) return self.flightdata[flightgroup.groupname].waypointtask end --- Get flightgroup mission status. -- @param #AUFTRAG self -- @return #boolean If true, all flights are done with the mission. function AUFTRAG:CheckFlightsDone() -- These are early stages, where we might not even have a flightgroup defined to be checked. if self:IsPlanned() or self:IsQueued() or self:IsRequested() then return false end local done=true for groupname,data in pairs(self.flightdata) do local flightdata=data --#AUFTRAG.FlightData if flightdata.status~=AUFTRAG.FlightStatus.DONE and flightdata.status~=AUFTRAG.FlightStatus.CANCELLED then done=false end end return done end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- FSM Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- On after "Queue" event. Mission is added to the mission queue of an AIRWING. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param Ops.AirWing#AIRWING Airwing The airwing. function AUFTRAG:onafterQueued(From, Event, To, Airwing) self.status=AUFTRAG.Status.QUEUED self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Requested" event. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterRequested(From, Event, TO) self.status=AUFTRAG.Status.REQUESTED self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Assign" event. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterAssign(From, Event, To) self.status=AUFTRAG.Status.ASSIGNED self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Schedule" event. Mission is added to the mission queue of a FLIGHTGROUP. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. -- @param Ops.FlightGroup#FLIGHTGROUP FlightGroup function AUFTRAG:onafterScheduled(From, Event, To, FlightGroup) self.status=AUFTRAG.Status.SCHEDULED self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Start" event. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterStarted(From, Event, To) self.status=AUFTRAG.Status.STARTED self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Execute" event. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterExecuting(From, Event, To) self.status=AUFTRAG.Status.EXECUTING self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Done" event. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterDone(From, Event, To) self.status=AUFTRAG.Status.DONE self:I(self.lid..string.format("New mission status=%s", self.status)) end --- On after "Cancel" event. Cancells the mission. -- @param #AUFTRAG self -- @param #string From From state. -- @param #string Event Event. -- @param #string To To state. function AUFTRAG:onafterCancel(From, Event, To) self.status=AUFTRAG.Status.CANCELLED self:I(self.lid..string.format("New mission status=%s", self.status)) if self.airwing then self.airwing:MissionCancel(self) else for _,_flightdata in pairs(self.flightdata) do local flightdata=_flightdata --#AUFTRAG.FlightData flightdata.flightgroup:MissionCancel(self) end end end ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- Misc Functions ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Count alive mission targets. -- @param #AUFTRAG self -- @return #number Number of alive targets. function AUFTRAG:CountMissionTargets() local N=0 if self.engageTargetGroupset then local n=self.engageTargetGroupset:CountAlive() N=N+n end if self.engageTargetUnitset then local n=self.engageTargetUnitset:CountAlive() N=N+n end return N end --- Get coordinate of target. First unit/group of the set is used. -- @param #AUFTRAG self -- @return Core.Point#COORDINATE The target coordinate or nil. function AUFTRAG:GetTargetCoordinate() if self.engageTargetGroupset then local group=self.engageTargetGroupset:GetFirst() --Wrapper.Group#GROUP return group:GetCoordinate() elseif self.engageTargetUnitset then local unit=self.engageTargetUnitset:GetFirst() --Wrapper.Unit#UNIT return unit:GetCoordinate() elseif self.engageCoord then return self.engageCoord elseif self.orbitCoord then return self.orbitCoord end return nil end --- Get DCS task table for the given mission. -- @param #AUFTRAG self -- @return DCS#Task The DCS task table. If multiple tasks are necessary, this is returned as a combo task. function AUFTRAG:GetDCSMissionTask() local DCStasks={} -- Create DCS task based on current self. if self.type==AUFTRAG.Type.ANTISHIP then ---------------------- -- ANTISHIP Mission -- ---------------------- for _,_unit in pairs(self.engageTargetUnitset:GetSet()) do local TargetUnit=_unit local DCStask=CONTROLLABLE.TaskAttackUnit(nil, TargetUnit, self.engageAltitude, self.WeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType) end elseif self.type==AUFTRAG.Type.AWACS then ------------------- -- AWACS Mission -- ------------------- local DCStask=CONTROLLABLE.EnRouteTaskAWACS(nil) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.BAI then ----------------- -- BAI Mission -- ----------------- for _,_group in pairs(self.engageTargetGroupset:GetSet()) do local TargetGroup=_group local DCStask=CONTROLLABLE.TaskAttackGroup(nil, TargetGroup, self.engageWeaponType, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude) table.insert(DCStasks, DCStask) end elseif self.type==AUFTRAG.Type.BOMBING then --------------------- -- BOMBING Mission -- --------------------- local Vec2=self.engageCoord:GetVec2() local DCStask=CONTROLLABLE.TaskBombing(self,Vec2, self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, Divebomb) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.CAP then ----------------- -- CAP Mission -- ----------------- local DCStask=CONTROLLABLE.EnRouteTaskEngageTargetsInZone(self.engageZone:GetVec2(), self.engageZone:GetRadius(), self.engageTargetTypes, Priority) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.CAS then ----------------- -- CAS Mission -- ----------------- local DCStask=CONTROLLABLE.EnRouteTaskEngageTargetsInZone(self.engageZone:GetVec2(), self.engageZone:GetRadius(), self.engageTargetTypes, Priority) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.ESCORT then -------------------- -- ESCORT Mission -- -------------------- local DCStask=CONTROLLABLE.TaskEscort(nil, self.escortGroup, self.escortVec3, LastWaypointIndex, self.engageMaxDistance, self.engageTargetTypes) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.FACA then ----------------- -- FAC Mission -- ----------------- local DCStask=CONTROLLABLE.TaskFAC_AttackGroup(nil, self.engageAsGroup, self.engageWeaponType, Designation, Datalink) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.FERRY then ------------------- -- FERRY Mission -- ------------------- elseif self.type==AUFTRAG.Type.INTERCEPT then ----------------------- -- INTERCEPT Mission -- ----------------------- for _,group in pairs(self.engageTargetGroupset:GetSet()) do local TargetGroup=group --Wrapper.Group#GROUP local DCStask=CONTROLLABLE.TaskAttackGroup(nil, TargetGroup, self.engageWeaponType, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude) table.insert(DCStasks, DCStask) end elseif self.type==AUFTRAG.Type.ORBIT then ------------------- -- ORBIT Mission -- ------------------- -- Done below as also other mission types use the orbit task. elseif self.type==AUFTRAG.Type.RECON then ------------------- -- RECON Mission -- ------------------- elseif self.type==AUFTRAG.Type.STRIKE then ------------------- -- STIKE Mission -- ------------------- local Vec2=self.engageCoord:GetVec2() local DCStask=CONTROLLABLE.TaskAttackMapObject(nil, Vec2, self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.TANKER then -------------------- -- TANKER Mission -- -------------------- local DCStask=CONTROLLABLE.EnRouteTaskTanker(nil) table.insert(DCStasks, DCStask) elseif self.type==AUFTRAG.Type.TRANSPORT then ----------------------- -- TRANSPORT Mission -- ----------------------- else self:E(self.lid..string.format("ERROR: Unknown mission task!")) return nil end -- Set ORBIT task. Also applies to other missions: AWACS, TANKER, CAP, CAS. if self.type==AUFTRAG.Type.ORBIT or self.type==AUFTRAG.Type.CAP or self.type==AUFTRAG.Type.CAS or self.type==AUFTRAG.Type.AWACS or self.type==AUFTRAG.Type.TANKER then ------------------- -- ORBIT Mission -- ------------------- local CoordRaceTrack=self.orbitCoord:Translate(self.orbitLeg, self.orbitHeading, true) local DCStask=CONTROLLABLE.TaskOrbit(nil, self.orbitCoord, self.orbitCoord.y, self.orbitSpeed, CoordRaceTrack) table.insert(DCStasks, DCStask) end -- Return the task. if #DCStasks==1 then return DCStasks[1] else return CONTROLLABLE.TaskCombo(nil, DCStasks) end end