From 23553f0f4c98d03dd8e3ecd4e8f193d120b71200 Mon Sep 17 00:00:00 2001 From: Applevangelist Date: Sat, 21 Jan 2023 15:40:18 +0100 Subject: [PATCH] #AUFTRAG * Added checking of bespoke conditions within the status call of AUFTRAG and not only when AUFTRAG is done already --- Moose Development/Moose/Ops/Auftrag.lua | 6317 +---------------------- 1 file changed, 29 insertions(+), 6288 deletions(-) diff --git a/Moose Development/Moose/Ops/Auftrag.lua b/Moose Development/Moose/Ops/Auftrag.lua index 5fec50121..b85fa6182 100644 --- a/Moose Development/Moose/Ops/Auftrag.lua +++ b/Moose Development/Moose/Ops/Auftrag.lua @@ -16,6289 +16,7 @@ -- -- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Auftrag). -- --- ===--- **Ops** - Auftrag (mission) for Ops. --- --- ## Main Features: --- --- * Simplifies defining and executing DCS tasks --- * Additional useful events --- * Set mission start/stop times --- * Set mission priority and urgency (can cancel running missions) --- * Specific mission options for ROE, ROT, formation, etc. --- * Compatible with OPS classes like FLIGHTGROUP, NAVYGROUP, ARMYGROUP, AIRWING, etc. --- * FSM events when a mission is done, successful or failed --- -- === --- --- ## Example Missions: --- --- Demo missions can be found on [github](https://github.com/FlightControl-Master/MOOSE_MISSIONS/tree/develop/OPS%20-%20Auftrag). --- --- === --- --- ### Author: **funkyfranky** --- --- === --- @module Ops.Auftrag --- @image OPS_Auftrag.png - - ---- AUFTRAG class. --- @type AUFTRAG --- @field #string ClassName Name of the class. --- @field #number verbose Verbosity level. --- @field #string lid Class id string for output to DCS log file. --- @field #number auftragsnummer Auftragsnummer. --- @field #string type Mission type. --- @field #table categories Mission categories. --- @field #string status Mission status. --- @field #table legions Assigned legions. --- @field #table statusLegion Mission status of all assigned LEGIONs. --- @field #string statusCommander Mission status of the COMMANDER. --- @field #string statusChief Mission status of the CHIEF. --- @field #table groupdata Group 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 importance Importance. --- @field #number Tstart Mission start time in abs. seconds. --- @field #number Tstop Mission stop time in abs. seconds. --- @field #number duration Mission duration in seconds. --- @field #number durationExe Mission execution time in seconds. --- @field #number Texecuting Time stamp (abs) when mission is executing. Is `#nil` on start. --- @field #number Tpush Mission push/execute time in abs. seconds. --- @field #number Tstarted Time stamp (abs) when mission is started. --- @field Wrapper.Marker#MARKER marker F10 map marker. --- @field #boolean markerOn If true, display marker on F10 map with the AUFTRAG status. --- @field #number markerCoaliton Coalition to which the marker is dispayed. --- @field #table DCStask DCS task structure. --- @field #number Ncasualties Number of own casualties during mission. --- @field #number Nkills Number of (enemy) units killed by assets of this mission. --- @field #number Nelements Number of elements (units) assigned to mission. --- @field #number dTevaluate Time interval in seconds before the mission result is evaluated after mission is over. --- @field #number Tover Mission abs. time stamp, when mission was over. --- @field #boolean updateDCSTask If `true`, DCS task is updated at every status update of the assigned groups. --- @field #table conditionStart Condition(s) that have to be true, before the mission will be started. --- @field #table conditionSuccess If all conditions are true, the mission is cancelled. --- @field #table conditionFailure If all conditions are true, the mission is cancelled. --- @field #table conditionPush If all conditions are true, the mission is executed. Before, the group(s) wait at the mission execution waypoint. --- --- @field #number orbitSpeed Orbit speed in m/s. --- @field #number orbitAltitude Orbit altitude in meters. --- @field #number orbitHeading Orbit heading in degrees. --- @field #number orbitLeg Length of orbit leg in meters. --- @field DCS#Vec2 orbitOffsetVec2 2D offset vector. --- @field DCS#Vec2 orbitVec2 2D orbit vector. --- @field #number orbitDeltaR Distance threshold in meters for moving orbit targets. --- --- @field Ops.Target#TARGET engageTarget Target data to engage. --- @field #number targetHeading Heading of target in degrees. --- --- @field Ops.Operation#OPERATION operation Operation this mission is part of. --- --- @field #boolean teleport Groups are teleported to the mission ingress waypoint. --- --- @field Core.Zone#ZONE_RADIUS engageZone *Circular* engagement zone. --- @field #table engageTargetTypes Table of target types that are engaged in the engagement zone. --- @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 #number refuelSystem Refuel type (boom or probe) for TANKER missions. --- --- @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 #number facDesignation FAC designation type. --- @field #boolean facDatalink FAC datalink enabled. --- @field #number facFreq FAC radio frequency in MHz. --- @field #number facModu FAC radio modulation 0=AM 1=FM. --- --- @field Core.Set#SET_GROUP transportGroupSet Groups to be transported. --- @field Core.Point#COORDINATE transportPickup Coordinate where to pickup the cargo. --- @field Core.Point#COORDINATE transportDropoff Coordinate where to drop off the cargo. --- @field #number transportPickupRadius Radius in meters for pickup zone. Default 500 m. --- --- @field Ops.OpsTransport#OPSTRANSPORT opstransport OPS transport assignment. --- @field #number NcarriersMin Min number of required carrier assets. --- @field #number NcarriersMax Max number of required carrier assets. --- @field Core.Zone#ZONE transportDeployZone Deploy zone of an OPSTRANSPORT. --- @field Core.Zone#ZONE transportDisembarkZone Disembark zone of an OPSTRANSPORT. --- --- @field #number artyRadius Radius in meters. --- @field #number artyShots Number of shots fired. --- @field #number artyAltitude Altitude in meters. Can be used for a Barrage. --- @field #number artyHeading Heading in degrees (for Barrage). --- @field #number artyAngle Shooting angle in degrees (for Barrage). --- --- @field #string alert5MissionType Alert 5 mission type. This is the mission type, the alerted assets will be able to carry out. --- --- @field #table attributes Generalized attribute(s) of assets. --- @field #table properties DCS attribute(s) of assets. --- --- @field Ops.Chief#CHIEF chief The CHIEF managing this mission. --- @field Ops.Commander#COMMANDER commander The COMMANDER managing this mission. --- @field #table assets Warehouse assets assigned for this mission. --- @field #number NassetsMin Min. number of required warehouse assets. --- @field #number NassetsMax Max. number of required warehouse assets. --- @field #number NescortMin Min. number of required escort assets for each group the mission is assigned to. --- @field #number NescortMax Max. number of required escort assets for each group the mission is assigned to. --- @field #string escortMissionType Escort mission type. --- @field #table escortTargetTypes Target types that will be engaged. --- @field #number escortEngageRange Engage range in nautical miles (NM). --- @field #number Nassets Number of requested warehouse assets. --- @field #table NassetsLegMin Number of required warehouse assets for each assigned legion. --- @field #table NassetsLegMax Number of required warehouse assets for each assigned legion. --- @field #table requestID The ID of the queued warehouse request. Necessary to cancel the request if the mission was cancelled before the request is processed. --- @field #table payloads User specified airwing payloads for this mission. Only these will be considered for the job! --- @field Ops.AirWing#AIRWING.PatrolData patroldata Patrol data. --- --- @field #table specialLegions User specified legions assigned for this mission. Only these will be considered for the job! --- @field #table specialCohorts User specified cohorts assigned for this mission. Only these will be considered for the job! --- @field #table transportLegions Legions explicitly requested for providing transport carrier assets. --- @field #table transportCohorts Cohorts explicitly requested for providing transport carrier assets. --- @field #table escortLegions Legions explicitly requested for providing escorting assets. --- @field #table escortCohorts Cohorts explicitly requested for providing escorting assets. --- --- @field #string missionTask Mission task. See `ENUMS.MissionTask`. --- @field #number missionAltitude Mission altitude in meters. --- @field #number missionSpeed Mission speed in km/h. --- @field #number missionFraction Mission coordiante fraction. Default is 0.5. --- @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 #number missionWaypointRadius Random radius in meters. --- --- @field #table enrouteTasks Mission enroute tasks. --- --- @field #number repeated Number of times mission was repeated. --- @field #number repeatedSuccess Number of times mission was repeated after a success. --- @field #number repeatedFailure Number of times mission was repeated after a failure. --- @field #number Nrepeat Number of times the mission is repeated. --- @field #number NrepeatFailure Number of times mission is repeated if failed. --- @field #number NrepeatSuccess Number of times mission is repeated if successful. --- --- @field Ops.OpsGroup#OPSGROUP.Radio radio Radio freq and modulation. --- @field Ops.OpsGroup#OPSGROUP.Beacon tacan TACAN setting. --- @field Ops.OpsGroup#OPSGROUP.Beacon icls ICLS setting. --- --- @field #number optionROE ROE. --- @field #number optionROT ROT. --- @field #number optionAlarm Alarm state. --- @field #number optionFormation Formation. --- @field #boolean optionEPLRS EPLRS datalink. --- @field #number optionCM Counter measures. --- @field #number optionRTBammo RTB on out-of-ammo. --- @field #number optionRTBfuel RTB on out-of-fuel. --- @field #number optionECM ECM. --- @field #boolean optionEmission Emission is on or off. --- @field #boolean optionInvisible Invisible is on/off. --- @field #boolean optionImmortal Immortal is on/off. --- --- @extends Core.Fsm#FSM - ---- *A warrior's mission is to foster the success of others.* -- Morihei Ueshiba --- --- === --- --- # The AUFTRAG Concept --- --- The AUFTRAG class significantly simplifies the workflow of using DCS tasks. --- --- You can think of an AUFTRAG as document, which contains the mission briefing, i.e. information about the target location, mission altitude, speed and various other parameters. --- This document can be handed over directly to a pilot (or multiple pilots) via the @{Ops.FlightGroup#FLIGHTGROUP} class. The pilots will then execute the mission. --- --- The AUFTRAG document can also be given to an AIRWING. The airwing will then determine the best assets (pilots and payloads) available for the job. --- --- Similarly, an AUFTRAG can be given to ground or navel groups via the @{Ops.ArmyGroup#ARMYGROUP} or @{Ops.NavyGroup#NAVYGROUP} classes, respectively. These classes have also --- AIRWING analouges, which are called BRIGADE and FLEET. Brigades and fleets will likewise select the best assets they have available and pass on the AUFTRAG to them. --- --- --- One more up the food chain, an AUFTRAG can be passed to a COMMANDER. The commander will recruit the best assets of AIRWINGs, BRIGADEs and/or FLEETs and pass the job over to it. --- --- --- # Airborne Missions --- --- Several mission types are supported by this class. --- --- ## Anti-Ship --- --- An anti-ship mission can be created with the @{#AUFTRAG.NewANTISHIP}() function. --- --- ## AWACS --- --- An AWACS mission can be created with the @{#AUFTRAG.NewAWACS}() function. --- --- ## BAI --- --- A BAI mission can be created with the @{#AUFTRAG.NewBAI}() function. --- --- ## Bombing --- --- A bombing mission can be created with the @{#AUFTRAG.NewBOMBING}() function. --- --- ## Bombing Runway --- --- A bombing runway mission can be created with the @{#AUFTRAG.NewBOMBRUNWAY}() function. --- --- ## Bombing Carpet --- --- A carpet bombing mission can be created with the @{#AUFTRAG.NewBOMBCARPET}() function. --- --- ## CAP --- --- A CAP mission can be created with the @{#AUFTRAG.NewCAP}() function. --- --- ## CAS --- --- A CAS mission can be created with the @{#AUFTRAG.NewCAS}() function. --- --- ## Escort --- --- An escort mission can be created with the @{#AUFTRAG.NewESCORT}() function. --- --- ## FACA --- --- An FACA mission can be created with the @{#AUFTRAG.NewFACA}() function. --- --- ## Ferry --- --- Not implemented yet. --- --- ## Intercept --- --- An intercept mission can be created with the @{#AUFTRAG.NewINTERCEPT}() function. --- --- ## Orbit --- --- An orbit mission can be created with the @{#AUFTRAG.NewORBIT}() function. --- --- ## GCICAP --- --- An patrol mission can be created with the @{#AUFTRAG.NewGCICAP}() function. --- --- ## RECON --- --- An reconnaissance mission can be created with the @{#AUFTRAG.NewRECON}() function. --- --- ## RESCUE HELO --- --- An rescue helo mission can be created with the @{#AUFTRAG.NewRESCUEHELO}() function. --- --- ## SEAD --- --- An SEAD mission can be created with the @{#AUFTRAG.NewSEAD}() function. --- --- ## STRIKE --- --- An strike mission can be created with the @{#AUFTRAG.NewSTRIKE}() function. --- --- ## Tanker --- --- A refueling tanker mission can be created with the @{#AUFTRAG.NewTANKER}() function. --- --- ## TROOPTRANSPORT --- --- A troop transport mission can be created with the @{#AUFTRAG.NewTROOPTRANSPORT}() function. --- --- ## CARGOTRANSPORT --- --- A cargo transport mission can be created with the @{#AUFTRAG.NewCARGOTRANSPORT}() function. --- --- ## HOVER --- --- A mission for a helicoptre or VSTOL plane to Hover at a point for a certain amount of time can be created with the @{#AUFTRAG.NewHOVER}() function. --- --- # Ground Missions --- --- ## ARTY --- --- An arty mission can be created with the @{#AUFTRAG.NewARTY}() function. --- --- ## GROUNDATTACK --- --- A ground attack mission can be created with the @{#AUFTRAG.NewGROUNDATTACK}() function. --- --- # Assigning Missions --- --- An AUFTRAG can be assigned to groups (FLIGHTGROUP, ARMYGROUP, NAVYGROUP), legions (AIRWING, BRIGADE, FLEET) or to a COMMANDER. --- --- ## Group Level --- --- ### Flight Group --- --- Assigning an AUFTRAG to a flight group is done via the @{Ops.FlightGroup#FLIGHTGROUP.AddMission} function. See FLIGHTGROUP docs for details. --- --- ### Army Group --- --- Assigning an AUFTRAG to an army group is done via the @{Ops.ArmyGroup#ARMYGROUP.AddMission} function. See ARMYGROUP docs for details. --- --- ### Navy Group --- --- Assigning an AUFTRAG to a navy group is done via the @{Ops.NavyGroup#NAVYGROUP.AddMission} function. See NAVYGROUP docs for details. --- --- ## Legion Level --- --- Adding an AUFTRAG to an airwing is done via the @{Ops.AirWing#AIRWING.AddMission} function. See AIRWING docs for further details. --- Similarly, an AUFTRAG can be added to a brigade via the @{Ops.Brigade#BRIGADE.AddMission} function. --- --- ## Commander Level --- --- Assigning an AUFTRAG to a commander is done via the @{Ops.Commander#COMMANDER.AddMission} function. --- The commander will select the best assets available from all the legions under his command. See COMMANDER docs for details. --- --- ## Chief Level --- --- Assigning an AUFTRAG to a commander is done via the @{Ops.Chief#CHIEF.AddMission} function. The chief will simply pass on the mission to his/her commander. --- --- # Transportation --- --- TODO --- --- --- # Events --- --- The AUFTRAG class creates many useful (FSM) events, which can be used in the mission designers script. --- --- TODO --- --- --- # Examples --- --- TODO --- --- --- @field #AUFTRAG -AUFTRAG = { - ClassName = "AUFTRAG", - verbose = 0, - lid = nil, - auftragsnummer = nil, - groupdata = {}, - legions = {}, - statusLegion = {}, - requestID = {}, - assets = {}, - NassetsLegMin = {}, - NassetsLegMax = {}, - missionFraction = 0.5, - enrouteTasks = {}, - marker = nil, - markerOn = nil, - markerCoalition = nil, - conditionStart = {}, - conditionSuccess = {}, - conditionFailure = {}, - conditionPush = {}, -} - ---- Global mission counter. -_AUFTRAGSNR=0 - - ---- Mission types. --- @type AUFTRAG.Type --- @field #string ANTISHIP Anti-ship mission. --- @field #string AWACS AWACS mission. --- @field #string BAI Battlefield Air Interdiction. --- @field #string BOMBING Bombing mission. --- @field #string BOMBRUNWAY Bomb runway of an airbase. --- @field #string BOMBCARPET Carpet bombing. --- @field #string CAP Combat Air Patrol. --- @field #string CAS Close Air Support. --- @field #string ESCORT Escort mission. --- @field #string FACA Forward AirController airborne 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. --- @field #string RECON Recon mission. --- @field #string RECOVERYTANKER Recovery tanker mission. Not implemented yet. --- @field #string RESCUEHELO Rescue helo. --- @field #string SEAD Suppression/destruction of enemy air defences. --- @field #string STRIKE Strike mission. --- @field #string TANKER Tanker mission. --- @field #string TROOPTRANSPORT Troop transport mission. --- @field #string ARTY Fire at point. --- @field #string PATROLZONE Patrol a zone. --- @field #string OPSTRANSPORT Ops transport. --- @field #string AMMOSUPPLY Ammo supply. --- @field #string FUELSUPPLY Fuel supply. --- @field #string ALERT5 Alert 5. --- @field #string ONGUARD On guard. --- @field #string ARMOREDGUARD On guard - with armored groups. --- @field #string BARRAGE Barrage. --- @field #string ARMORATTACK Armor attack. --- @field #string CASENHANCED Enhanced CAS. --- @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 AIRDEFENSE Air defense. --- @field #string EWR Early Warning Radar. --- @field #string RECOVERYTANKER Recovery tanker. --- @filed #string REARMING Rearming mission. --- @field #string NOTHING Nothing. -AUFTRAG.Type={ - ANTISHIP="Anti Ship", - AWACS="AWACS", - BAI="BAI", - BOMBING="Bombing", - BOMBRUNWAY="Bomb Runway", - BOMBCARPET="Carpet Bombing", - CAP="CAP", - CAS="CAS", - ESCORT="Escort", - FACA="FAC-A", - FERRY="Ferry Flight", - INTERCEPT="Intercept", - ORBIT="Orbit", - GCICAP="Ground Controlled CAP", - RECON="Recon", - RECOVERYTANKER="Recovery Tanker", - RESCUEHELO="Rescue Helo", - SEAD="SEAD", - STRIKE="Strike", - TANKER="Tanker", - TROOPTRANSPORT="Troop Transport", - ARTY="Fire At Point", - PATROLZONE="Patrol Zone", - OPSTRANSPORT="Ops Transport", - AMMOSUPPLY="Ammo Supply", - FUELSUPPLY="Fuel Supply", - ALERT5="Alert5", - ONGUARD="On Guard", - ARMOREDGUARD="Armored Guard", - BARRAGE="Barrage", - ARMORATTACK="Armor Attack", - CASENHANCED="CAS Enhanced", - HOVER="Hover", - GROUNDATTACK="Ground Attack", - CARGOTRANSPORT="Cargo Transport", - RELOCATECOHORT="Relocate Cohort", - AIRDEFENSE="Air Defence", - EWR="Early Warning Radar", - RECOVERYTANKER="Recovery Tanker", - REARMING="Rearming", - NOTHING="Nothing", -} - ---- Special task description. --- @type AUFTRAG.SpecialTask --- @field #string FORMATION AI formation task. --- @field #string PATROLZONE Patrol zone task. --- @field #string RECON Recon task. --- @field #string AMMOSUPPLY Ammo Supply. --- @field #string FUELSUPPLY Fuel Supply. --- @field #string ALERT5 Alert 5 task. --- @field #string ONGUARD On guard. --- @field #string ARMOREDGUARD On guard with armor. --- @field #string BARRAGE Barrage. --- @field #string HOVER Hover. --- @field #string GROUNDATTACK Ground attack. --- @field #string FERRY Ferry mission. --- @field #string RELOCATECOHORT Relocate cohort. --- @field #string AIRDEFENSE Air defense. --- @field #string EWR Early Warning Radar. --- @field #string RECOVERYTANKER Recovery tanker. --- @field #string REARMING Rearming. --- @field #string NOTHING Nothing. -AUFTRAG.SpecialTask={ - FORMATION="Formation", - PATROLZONE="PatrolZone", - RECON="ReconMission", - AMMOSUPPLY="Ammo Supply", - FUELSUPPLY="Fuel Supply", - ALERT5="Alert5", - ONGUARD="On Guard", - ARMOREDGUARD="ArmoredGuard", - BARRAGE="Barrage", - ARMORATTACK="AmorAttack", - HOVER="Hover", - GROUNDATTACK="Ground Attack", - FERRY="Ferry", - RELOCATECOHORT="Relocate Cohort", - AIRDEFENSE="Air Defense", - EWR="Early Warning Radar", - RECOVERYTANKER="Recovery Tanker", - REARMING="Rearming", - NOTHING="Nothing", -} - ---- Mission status. --- @type AUFTRAG.Status --- @field #string PLANNED Mission is at the early planning stage and has not been added to any queue. --- @field #string QUEUED Mission is queued at a LEGION. --- @field #string REQUESTED Mission assets were requested from the warehouse. --- @field #string SCHEDULED Mission is scheduled in an OPSGROUP 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", - SCHEDULED="scheduled", - STARTED="started", - EXECUTING="executing", - DONE="done", - CANCELLED="cancelled", - SUCCESS="success", - FAILED="failed", -} - ---- Mission status of an assigned group. --- @type AUFTRAG.GroupStatus --- @field #string SCHEDULED Mission is scheduled in a FLIGHGROUP queue waiting to be started. --- @field #string STARTED Ops group started this mission but it is not executed yet. --- @field #string EXECUTING Ops group is executing this mission. --- @field #string PAUSED Ops group has paused this mission, e.g. for refuelling. --- @field #string DONE Mission task of the Ops group is done. --- @field #string CANCELLED Mission was cancelled. -AUFTRAG.GroupStatus={ - SCHEDULED="scheduled", - STARTED="started", - EXECUTING="executing", - PAUSED="paused", - DONE="done", - CANCELLED="cancelled", -} - ---- Target type. --- @type AUFTRAG.TargetType --- @field #string GROUP Target is a GROUP object. --- @field #string UNIT Target is a UNIT object. --- @field #string STATIC Target is a STATIC object. --- @field #string COORDINATE Target is a COORDINATE. --- @field #string AIRBASE Target is an AIRBASE. --- @field #string SETGROUP Target is a SET of GROUPs. --- @field #string SETUNIT Target is a SET of UNITs. -AUFTRAG.TargetType={ - GROUP="Group", - UNIT="Unit", - STATIC="Static", - COORDINATE="Coordinate", - AIRBASE="Airbase", - SETGROUP="SetGroup", - SETUNIT="SetUnit", -} - ---- Mission category. --- @type AUFTRAG.Category --- @field #string AIRCRAFT Airplanes and helicopters. --- @field #string AIRPLANE Airplanes. --- @field #string HELICOPTER Helicopter. --- @field #string GROUND Ground troops. --- @field #string NAVAL Naval grous. -AUFTRAG.Category={ - ALL="All", - AIRCRAFT="Aircraft", - AIRPLANE="Airplane", - HELICOPTER="Helicopter", - GROUND="Ground", - NAVAL="Naval", -} - ---- Target data. --- @type AUFTRAG.TargetData --- @field Wrapper.Positionable#POSITIONABLE Target Target Object. --- @field #string Type Target type: "Group", "Unit", "Static", "Coordinate", "Airbase", "SetGroup", "SetUnit". --- @field #string Name Target name. --- @field #number Ninital Number of initial targets. --- @field #number Lifepoints Total life points. --- @field #number Lifepoints0 Inital life points. - ---- Mission capability. --- @type AUFTRAG.Capability --- @field #string MissionType Type of mission. --- @field #number Performance Number describing the performance level. The higher the better. - ---- Mission success. --- @type AUFTRAG.Success --- @field #string SURVIVED Group did survive. --- @field #string ENGAGED Target was engaged. --- @field #string DAMAGED Target was damaged. --- @field #string DESTROYED Target was destroyed. - ---- Generic mission condition. --- @type AUFTRAG.Condition --- @field #function func Callback function to check for a condition. Should return a #boolean. --- @field #table arg Optional arguments passed to the condition callback function. - ---- Group specific data. Each ops group subscribed to this mission has different data for this. --- @type AUFTRAG.GroupData --- @field Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @field Core.Point#COORDINATE waypointcoordinate Ingress waypoint coordinate. --- @field #number waypointindex Mission (ingress) Waypoint UID. --- @field #number waypointEgressUID Egress Waypoint UID. --- @field Core.Point#COORDINATE wpegresscoordinate Egress waypoint coordinate. --- --- @field Ops.OpsGroup#OPSGROUP.Task waypointtask Waypoint task. --- @field #string status Group mission status. --- @field Functional.Warehouse#WAREHOUSE.Assetitem asset The warehouse asset. - - ---- AUFTRAG class version. --- @field #string version -AUFTRAG.version="0.9.7" - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- TODO list -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - --- TODO: Replace engageRange by missionRange. Here and in other classes. CTRL+H is your friend! --- TODO: Mission success options damaged, destroyed. --- TODO: F10 marker to create new missions. --- DONE: Add orbit mission for moving anker points. --- DONE: Add recovery tanker mission for boat ops. --- DONE: Added auftrag category. --- DONE: Missions can be assigned to multiple legions. --- DONE: Option to assign a specific payload for the mission (requires an AIRWING). --- NOPE: Clone mission. How? Deepcopy? ==> Create a new auftrag. --- DONE: Recon mission. What input? Set of coordinates? --- DONE: Option to assign mission to specific squadrons (requires an AIRWING). --- DONE: Add mission start conditions. --- DONE: Add rescue helo mission for boat ops. --- DONE: Mission ROE and ROT. --- DONE: Mission frequency and TACAN. --- DONE: Mission formation, etc. --- DONE: FSM events. --- DONE: F10 marker functions that are updated on Status event. --- DONE: Evaluate mission result ==> SUCCESS/FAILURE --- DONE: NewAUTO() NewA2G NewA2A --- DONE: Transport mission. --- DONE: Set mission coalition, e.g. for F10 markers. Could be derived from target if target has a coalition. - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Constructor -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- Create a new generic 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:_SetLogID() - - -- State is planned. - self.status=AUFTRAG.Status.PLANNED - - -- Defaults . - self:SetName() - self:SetPriority() - self:SetTime() - self:SetRequiredAssets() - self.engageAsGroup=true - self.dTevaluate=5 - - -- Init counters and stuff. - self.repeated=0 - self.repeatedSuccess=0 - self.repeatedFailure=0 - self.Nrepeat=0 - self.NrepeatFailure=0 - self.NrepeatSuccess=0 - self.Ncasualties=0 - self.Nkills=0 - self.Nelements=0 - self.Ngroups=0 - self.Nassigned=nil - self.Ndead=0 - - -- FMS start state is PLANNED. - self:SetStartState(self.status) - - -- PLANNED --> (QUEUED) --> (REQUESTED) --> SCHEDULED --> STARTED --> EXECUTING --> DONE - self:AddTransition("*", "Planned", AUFTRAG.Status.PLANNED) -- Mission is in planning stage. Could be in the queue of a COMMANDER or CHIEF. - self:AddTransition(AUFTRAG.Status.PLANNED, "Queued", AUFTRAG.Status.QUEUED) -- Mission is in queue of a LEGION. - 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 ops 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("*", "Success", AUFTRAG.Status.SUCCESS) - self:AddTransition("*", "Failed", AUFTRAG.Status.FAILED) - - self:AddTransition("*", "Status", "*") - self:AddTransition("*", "Stop", "*") - - self:AddTransition("*", "Repeat", AUFTRAG.Status.PLANNED) - - self:AddTransition("*", "ElementDestroyed", "*") - self:AddTransition("*", "GroupDead", "*") - self:AddTransition("*", "AssetDead", "*") - - ------------------------ - --- Pseudo Functions --- - ------------------------ - - --- Triggers the FSM event "Status". - -- @function [parent=#AUFTRAG] Status - -- @param #AUFTRAG self - - --- Triggers the FSM event "Status" after a delay. - -- @function [parent=#AUFTRAG] __Status - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- Triggers the FSM event "Stop". - -- @function [parent=#AUFTRAG] Stop - -- @param #AUFTRAG self - - --- Triggers the FSM event "Stop" after a delay. - -- @function [parent=#AUFTRAG] __Stop - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - - --- Triggers the FSM event "Planned". - -- @function [parent=#AUFTRAG] Planned - -- @param #AUFTRAG self - - --- Triggers the FSM event "Planned" after a delay. - -- @function [parent=#AUFTRAG] __Planned - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Planned" event. - -- @function [parent=#AUFTRAG] OnAfterPlanned - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Queued". - -- @function [parent=#AUFTRAG] Queued - -- @param #AUFTRAG self - - --- Triggers the FSM event "Queued" after a delay. - -- @function [parent=#AUFTRAG] __Queued - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Queued" event. - -- @function [parent=#AUFTRAG] OnAfterQueued - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Requested". - -- @function [parent=#AUFTRAG] Requested - -- @param #AUFTRAG self - - --- Triggers the FSM event "Requested" after a delay. - -- @function [parent=#AUFTRAG] __Requested - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Requested" event. - -- @function [parent=#AUFTRAG] OnAfterRequested - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Scheduled". - -- @function [parent=#AUFTRAG] Scheduled - -- @param #AUFTRAG self - - --- Triggers the FSM event "Scheduled" after a delay. - -- @function [parent=#AUFTRAG] __Scheduled - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Scheduled" event. - -- @function [parent=#AUFTRAG] OnAfterScheduled - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Started". - -- @function [parent=#AUFTRAG] Started - -- @param #AUFTRAG self - - --- Triggers the FSM event "Started" after a delay. - -- @function [parent=#AUFTRAG] __Started - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Started" event. - -- @function [parent=#AUFTRAG] OnAfterStarted - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Executing". - -- @function [parent=#AUFTRAG] Executing - -- @param #AUFTRAG self - - --- Triggers the FSM event "Executing" after a delay. - -- @function [parent=#AUFTRAG] __Executing - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Executing" event. - -- @function [parent=#AUFTRAG] OnAfterExecuting - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Cancel". - -- @function [parent=#AUFTRAG] Cancel - -- @param #AUFTRAG self - - --- Triggers the FSM event "Cancel" after a delay. - -- @function [parent=#AUFTRAG] __Cancel - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Cancel" event. - -- @function [parent=#AUFTRAG] OnAfterCancel - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Done". - -- @function [parent=#AUFTRAG] Done - -- @param #AUFTRAG self - - --- Triggers the FSM event "Done" after a delay. - -- @function [parent=#AUFTRAG] __Done - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Done" event. - -- @function [parent=#AUFTRAG] OnAfterDone - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - - --- Triggers the FSM event "Success". - -- @function [parent=#AUFTRAG] Success - -- @param #AUFTRAG self - - --- Triggers the FSM event "Success" after a delay. - -- @function [parent=#AUFTRAG] __Success - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Success" event. - -- @function [parent=#AUFTRAG] OnAfterSuccess - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - --- Triggers the FSM event "Failed". - -- @function [parent=#AUFTRAG] Failed - -- @param #AUFTRAG self - - --- Triggers the FSM event "Failed" after a delay. - -- @function [parent=#AUFTRAG] __Failed - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Failed" event. - -- @function [parent=#AUFTRAG] OnAfterFailed - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - --- Triggers the FSM event "Repeat". - -- @function [parent=#AUFTRAG] Repeat - -- @param #AUFTRAG self - - --- Triggers the FSM event "Repeat" after a delay. - -- @function [parent=#AUFTRAG] __Repeat - -- @param #AUFTRAG self - -- @param #number delay Delay in seconds. - - --- On after "Repeat" event. - -- @function [parent=#AUFTRAG] OnAfterRepeat - -- @param #AUFTRAG self - -- @param #string From From state. - -- @param #string Event Event. - -- @param #string To To state. - - -- Init status update. - self:__Status(-1) - - return self -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Create Missions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- **[AIR]** Create an ANTI-SHIP mission. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be passed as a @{Wrapper.Group#GROUP} or @{Wrapper.Unit#UNIT} object. --- @param #number Altitude Engage altitude in feet. Default 2000 ft. --- @return #AUFTRAG self -function AUFTRAG:NewANTISHIP(Target, Altitude) - - local mission=AUFTRAG:New(AUFTRAG.Type.ANTISHIP) - - mission:_TargetFromObject(Target) - - -- DCS task parameters: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 2000) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.ANTISHIPSTRIKE - mission.missionAltitude=mission.engageAltitude - mission.missionFraction=0.4 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR ROTARY]** Create an HOVER mission. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Where to hover. --- @param #number Altitude Hover altitude in feet AGL. Default is 50 feet above ground. --- @param #number Time Time in seconds to hold the hover. Default 300 seconds. --- @param #number Speed Speed in knots to fly to the target coordinate. Default 150kn. --- @param #number MissionAlt Altitide to fly towards the mission in feet AGL. Default 1000ft. --- @return #AUFTRAG self -function AUFTRAG:NewHOVER(Coordinate, Altitude, Time, Speed, MissionAlt) - - local mission=AUFTRAG:New(AUFTRAG.Type.HOVER) - - -- Altitude. - if Altitude then - mission.hoverAltitude=Coordinate:GetLandHeight()+UTILS.FeetToMeters(Altitude) - else - mission.hoverAltitude=Coordinate:GetLandHeight()+UTILS.FeetToMeters(50) - end - - mission:_TargetFromObject(Coordinate) - - mission.hoverSpeed = 0.1 -- the DCS Task itself will shortly be build with this so MPS - mission.hoverTime = Time or 300 - self:SetMissionSpeed(Speed or 150) - self:SetMissionAltitude(MissionAlt or 1000) - - -- Mission options: - mission.missionFraction=0.9 - mission.optionROE=ENUMS.ROE.ReturnFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.HELICOPTER} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create an ORBIT mission, which can be either a circular orbit or a race-track pattern. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Where to orbit. --- @param #number Altitude Orbit altitude in feet above sea level. Default is y component of `Coordinate`. --- @param #number Speed Orbit speed in knots. Default 350 KIAS. --- @param #number Heading Heading of race-track pattern in degrees. If not specified, a circular orbit is performed. --- @param #number Leg Length of race-track in NM. If not specified, a circular orbit is performed. --- @return #AUFTRAG self -function AUFTRAG:NewORBIT(Coordinate, Altitude, Speed, Heading, Leg) - - local mission=AUFTRAG:New(AUFTRAG.Type.ORBIT) - - -- Target. - mission:_TargetFromObject(Coordinate) - - -- Set Altitude. - if Altitude then - mission.orbitAltitude=UTILS.FeetToMeters(Altitude) - else - mission.orbitAltitude=Coordinate.y - end - - -- Orbit speed in m/s. - mission.orbitSpeed = UTILS.KnotsToMps(UTILS.KnotsToAltKIAS(Speed or 350, UTILS.MetersToFeet(mission.orbitAltitude))) - - -- Mission speed in km/h. - mission.missionSpeed = UTILS.KnotsToKmph(Speed or 350) - - if Leg then - mission.orbitLeg=UTILS.NMToMeters(Leg) - - -- Relative heading - if Heading and Heading<0 then - mission.orbitHeadingRel=true - Heading=-Heading - end - - -- Heading if given. - mission.orbitHeading=Heading - end - - -- Mission options: - mission.missionAltitude=mission.orbitAltitude*0.9 - mission.missionFraction=0.9 - mission.optionROE=ENUMS.ROE.ReturnFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create an ORBIT mission, where the aircraft will go in a circle around the specified coordinate. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Position where to orbit around. --- @param #number Altitude Orbit altitude in feet. Default is y component of `Coordinate`. --- @param #number Speed Orbit speed in knots. Default 350 KIAS. --- @return #AUFTRAG self -function AUFTRAG:NewORBIT_CIRCLE(Coordinate, Altitude, Speed) - - local mission=AUFTRAG:NewORBIT(Coordinate, Altitude, Speed) - - return mission -end - ---- **[AIR]** Create an ORBIT mission, where the aircraft will fly a race-track pattern. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Where to orbit. --- @param #number Altitude Orbit altitude in feet. Default is y component of `Coordinate`. --- @param #number Speed Orbit speed in knots. Default 350 KIAS. --- @param #number Heading Heading of race-track pattern in degrees. Default random in [0, 360) degrees. --- @param #number Leg Length of race-track in NM. Default 10 NM. --- @return #AUFTRAG self -function AUFTRAG:NewORBIT_RACETRACK(Coordinate, Altitude, Speed, Heading, Leg) - - Heading = Heading or math.random(360) - Leg = Leg or 10 - - local mission=AUFTRAG:NewORBIT(Coordinate, Altitude, Speed, Heading, Leg) - - return mission -end - ---- **[AIR]** Create an ORBIT mission, where the aircraft will fly a circular or race-track pattern over a given group or unit. --- @param #AUFTRAG self --- @param Wrapper.Group#GROUP Group Group where to orbit around. Can also be a UNIT object. --- @param #number Altitude Orbit altitude in feet. Default is 6,000 ft. --- @param #number Speed Orbit speed in knots. Default 350 KIAS. --- @param #number Leg Length of race-track in NM. Default nil. --- @param #number Heading Heading of race-track pattern in degrees. Default is heading of the group. --- @param DCS#Vec2 OffsetVec2 Offset 2D-vector {x=0, y=0} in NM with respect to the group. Default directly overhead. Can also be given in polar coordinates `{r=5, phi=45}`. --- @param #number Distance Threshold distance in NM before orbit pattern is updated. Default 5 NM. --- @return #AUFTRAG self -function AUFTRAG:NewORBIT_GROUP(Group, Altitude, Speed, Leg, Heading, OffsetVec2, Distance) - - -- Set default altitude. - Altitude = Altitude or 6000 - - -- Create orbit mission. - local mission=AUFTRAG:NewORBIT(Group, Altitude, Speed, Heading, Leg) - - -- DCS tasks needs to be updated from time to time. - mission.updateDCSTask=true - - -- Convert offset vector to meters. - if OffsetVec2 then - if OffsetVec2.x then - OffsetVec2.x=UTILS.NMToMeters(OffsetVec2.x) - end - if OffsetVec2.y then - OffsetVec2.y=UTILS.NMToMeters(OffsetVec2.y) - end - if OffsetVec2.r then - OffsetVec2.r=UTILS.NMToMeters(OffsetVec2.r) - end - end - - -- Offset vector. - mission.orbitOffsetVec2=OffsetVec2 - - -- Pattern update distance. - mission.orbitDeltaR=UTILS.NMToMeters(Distance or 5) - - -- Update task with offset etc. - mission:GetDCSMissionTask() - - return mission -end - - ---- **[AIR]** Create a Ground Controlled CAP (GCICAP) mission. Flights with this task are considered for A2A INTERCEPT missions by the CHIEF class. They will perform a compat air patrol but not engage by --- themselfs. They wait for the CHIEF to tell them whom to engage. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Where to orbit. --- @param #number Altitude Orbit altitude in feet. Default is y component of `Coordinate`. --- @param #number Speed Orbit speed in knots. Default 350 kts. --- @param #number Heading Heading of race-track pattern in degrees. Default random in [0, 360) degrees. --- @param #number Leg Length of race-track in NM. Default 10 NM. --- @return #AUFTRAG self -function AUFTRAG:NewGCICAP(Coordinate, Altitude, Speed, Heading, Leg) - - -- Create ORBIT first. - local mission=AUFTRAG:NewORBIT_RACETRACK(Coordinate, Altitude, Speed, Heading, Leg) - - -- Mission type GCICAP. - mission.type=AUFTRAG.Type.GCICAP - - mission:_SetLogID() - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.INTERCEPT - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - return mission -end - ---- **[AIR]** Create a TANKER mission. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Where to orbit. --- @param #number Altitude Orbit altitude in feet. Default is y component of `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. --- @param #number RefuelSystem Refueling system (0=boom, 1=probe). This info is *only* for AIRWINGs so they launch the right tanker type. --- @return #AUFTRAG self -function AUFTRAG:NewTANKER(Coordinate, Altitude, Speed, Heading, Leg, RefuelSystem) - - -- Create ORBIT first. - local mission=AUFTRAG:NewORBIT_RACETRACK(Coordinate, Altitude, Speed, Heading, Leg) - - -- Mission type TANKER. - mission.type=AUFTRAG.Type.TANKER - - mission:_SetLogID() - - mission.refuelSystem=RefuelSystem - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.REFUELING - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a AWACS mission. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Where to orbit. Altitude is also taken from the coordinate. --- @param #number Altitude Orbit altitude in feet. Default is y component of `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:NewAWACS(Coordinate, Altitude, Speed, Heading, Leg) - - -- Create ORBIT first. - local mission=AUFTRAG:NewORBIT_RACETRACK(Coordinate, Altitude, Speed, Heading, Leg) - - -- Mission type AWACS. - mission.type=AUFTRAG.Type.AWACS - - mission:_SetLogID() - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.AWACS - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - - ---- **[AIR]** Create an INTERCEPT mission. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Target The target to intercept. Can also be passed as simple @{Wrapper.Group#GROUP} or @{Wrapper.Unit#UNIT} object. --- @return #AUFTRAG self -function AUFTRAG:NewINTERCEPT(Target) - - local mission=AUFTRAG:New(AUFTRAG.Type.INTERCEPT) - - mission:_TargetFromObject(Target) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.INTERCEPT - mission.missionFraction=0.1 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a CAP mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE_RADIUS ZoneCAP Circular CAP zone. Detected targets in this zone will be engaged. --- @param #number Altitude Altitude at which to orbit in feet. Default is 10,000 ft. --- @param #number Speed Orbit speed in knots. Default 350 kts. --- @param Core.Point#COORDINATE Coordinate Where to orbit. Default is the center of the CAP zone. --- @param #number Heading Heading of race-track pattern in degrees. If not specified, a simple circular orbit is performed. --- @param #number Leg Length of race-track in NM. If not specified, a simple circular orbit is performed. --- @param #table TargetTypes Table of target types. Default {"Air"}. --- @return #AUFTRAG self -function AUFTRAG:NewCAP(ZoneCAP, Altitude, Speed, Coordinate, Heading, Leg, 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=AUFTRAG:NewORBIT(Coordinate or ZoneCAP:GetCoordinate(), Altitude or 10000, Speed or 350, Heading, Leg) - - -- Mission type CAP. - mission.type=AUFTRAG.Type.CAP - mission:_SetLogID() - - -- DCS task parameters: - mission.engageZone=ZoneCAP - mission.engageTargetTypes=TargetTypes or {"Air"} - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.CAP - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - mission.missionSpeed = UTILS.KnotsToKmph(UTILS.KnotsToAltKIAS(Speed or 350, Altitude)) - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a CAP mission on a group. --- @param #AUFTRAG self --- @param Wrapper.Group#GROUP Grp. --- @param #number Altitude Orbit altitude in feet. Default is 6,000 ft. --- @param #number Speed Orbit speed in knots. Default 250 KIAS. --- @param #number RelHeading Relative heading [0, 360) of race-track pattern in degrees wrt heading of the carrier. Default is heading of the carrier. --- @param #number Leg Length of race-track in NM. Default 14 NM. --- @param #number OffsetDist Relative distance of the first race-track point wrt to the carrier. Default 6 NM. --- @param #number OffsetAngle Relative angle of the first race-track point wrt. to the carrier. Default 180 (behind the boat). --- @param #number UpdateDistance Threshold distance in NM before orbit pattern is updated. Default 5 NM. --- @param #table TargetTypes (Optional) Table of target types. Default `{"Helicopters", "Ground Units", "Light armed ships"}`. --- @param #number EngageRange Max range in nautical miles that the escort group(s) will engage enemies. Default 32 NM (60 km). --- @return #AUFTRAG self -function AUFTRAG:NewCAPGROUP(Grp, Altitude, Speed, RelHeading, Leg, OffsetDist, OffsetAngle, UpdateDistance, TargetTypes, EngageRange) - - -- Ensure given TargetTypes parameter is a table. - if TargetTypes then - if type(TargetTypes)~="table" then - TargetTypes={TargetTypes} - end - end - -- Six NM astern. - local OffsetVec2={r=OffsetDist or 6, phi=OffsetAngle or 180} - - -- Default leg. - Leg=Leg or 14 - - local Heading=nil - if RelHeading then - Heading=-math.abs(RelHeading) - end - - -- Create orbit mission. - local mission=AUFTRAG:NewORBIT_GROUP(Grp, Altitude, Speed, Leg, Heading, OffsetVec2, UpdateDistance) - -- Mission type CAP. - mission.type=AUFTRAG.Type.CAP - mission:_SetLogID() - - -- DCS task parameters: - local engage = EngageRange or 32 - local zoneCAPGroup = ZONE_GROUP:New("CAPGroup", Grp, UTILS.NMToMeters(engage)) - mission.engageZone=zoneCAPGroup - mission.engageTargetTypes=TargetTypes or {"Air"} - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.CAP - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a CAS mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE_RADIUS ZoneCAS Circular CAS zone. Detected targets in this zone will be engaged. --- @param #number Altitude Altitude at which to orbit. Default is 10,000 ft. --- @param #number Speed Orbit speed in knots. Default 350 KIAS. --- @param Core.Point#COORDINATE Coordinate Where to orbit. Default is the center of the CAS zone. --- @param #number Heading Heading of race-track pattern in degrees. If not specified, a simple circular orbit is performed. --- @param #number Leg Length of race-track in NM. If not specified, a simple circular orbit is performed. --- @param #table TargetTypes (Optional) Table of target types. Default `{"Helicopters", "Ground Units", "Light armed ships"}`. --- @return #AUFTRAG self -function AUFTRAG:NewCAS(ZoneCAS, Altitude, Speed, Coordinate, Heading, Leg, 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=AUFTRAG:NewORBIT(Coordinate or ZoneCAS:GetCoordinate(), Altitude or 10000, Speed, Heading, Leg) - - -- Mission type CAS. - mission.type=AUFTRAG.Type.CAS - mission:_SetLogID() - - -- DCS Task options: - mission.engageZone=ZoneCAS - mission.engageTargetTypes=TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"} - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.CAS - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a CASENHANCED mission. Group(s) will go to the zone and patrol it randomly. --- @param #AUFTRAG self --- @param Core.Zone#ZONE CasZone The CAS zone. --- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL. --- @param #number Speed Speed in knots. --- @param #number RangeMax Max range in NM. Only detected targets within this radius from the group will be engaged. Default is 25 NM. --- @param Core.Set#SET_ZONE NoEngageZoneSet Set of zones in which targets are *not* engaged. Default is nowhere. --- @param #table TargetTypes Types of target attributes that will be engaged. See [DCS enum attributes](https://wiki.hoggitworld.com/view/DCS_enum_attributes). Default `{"Helicopters", "Ground Units", "Light armed ships"}`. --- @return #AUFTRAG self -function AUFTRAG:NewCASENHANCED(CasZone, Altitude, Speed, RangeMax, NoEngageZoneSet, TargetTypes) - - local mission=AUFTRAG:New(AUFTRAG.Type.CASENHANCED) - - -- Ensure we got a ZONE and not just the zone name. - if type(CasZone)=="string" then - CasZone=ZONE:New(CasZone) - end - - mission:_TargetFromObject(CasZone) - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.CASENHANCED) - - mission:SetEngageDetected(RangeMax, TargetTypes or {"Helicopters", "Ground Units", "Light armed ships"}, CasZone, NoEngageZoneSet) - - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - - mission.missionFraction=1.0 - mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil - mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - ---- **[AIR]** Create a FACA mission. --- @param #AUFTRAG self --- @param Wrapper.Group#GROUP Target Target group. Must be a GROUP object. --- @param #string Designation Designation of target. See `AI.Task.Designation`. Default `AI.Task.Designation.AUTO`. --- @param #boolean DataLink Enable data link. Default `true`. --- @param #number Frequency Radio frequency in MHz the FAC uses for communication. Default is 133 MHz. --- @param #number Modulation Radio modulation band. Default 0=AM. Use 1 for FM. See radio.modulation.AM or radio.modulaton.FM. --- @return #AUFTRAG self -function AUFTRAG:NewFACA(Target, Designation, DataLink, Frequency, Modulation) - - local mission=AUFTRAG:New(AUFTRAG.Type.FACA) - - mission:_TargetFromObject(Target) - - -- TODO: check that target is really a group object! - - -- DCS Task options: - mission.facDesignation=Designation --or AI.Task.Designation.AUTO - mission.facDatalink=true - mission.facFreq=Frequency or 133 - mission.facModu=Modulation or radio.modulation.AM - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.AFAC - mission.missionAltitude=nil - mission.missionFraction=0.5 - mission.optionROE=ENUMS.ROE.ReturnFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - ---- **[AIR]** Create a BAI mission. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object. --- @param #number Altitude Engage altitude in feet. Default 5000 ft. --- @return #AUFTRAG self -function AUFTRAG:NewBAI(Target, Altitude) - - local mission=AUFTRAG:New(AUFTRAG.Type.BAI) - - mission:_TargetFromObject(Target) - - -- DCS Task options: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 5000) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.GROUNDATTACK - mission.missionAltitude=mission.engageAltitude - mission.missionFraction=0.75 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a SEAD mission. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP or UNIT object. --- @param #number Altitude Engage altitude in feet. Default 25000 ft. --- @return #AUFTRAG self -function AUFTRAG:NewSEAD(Target, Altitude) - - local mission=AUFTRAG:New(AUFTRAG.Type.SEAD) - - mission:_TargetFromObject(Target) - - -- DCS Task options: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.SEAD - mission.missionAltitude=mission.engageAltitude - mission.missionFraction=0.2 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.EvadeFire - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a STRIKE mission. Flight will attack the closest map object to the specified coordinate. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Target The target coordinate. Can also be given as a GROUP, UNIT, STATIC or TARGET object. --- @param #number Altitude Engage altitude in feet. Default 2000 ft. --- @return #AUFTRAG self -function AUFTRAG:NewSTRIKE(Target, Altitude) - - local mission=AUFTRAG:New(AUFTRAG.Type.STRIKE) - - mission:_TargetFromObject(Target) - - -- DCS Task options: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 2000) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.GROUNDATTACK - mission.missionAltitude=mission.engageAltitude - mission.missionFraction=0.75 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a BOMBING mission. Flight will drop bombs a specified coordinate. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT, STATIC or TARGET object. --- @param #number Altitude Engage altitude in feet. Default 25000 ft. --- @return #AUFTRAG self -function AUFTRAG:NewBOMBING(Target, Altitude) - - local mission=AUFTRAG:New(AUFTRAG.Type.BOMBING) - - mission:_TargetFromObject(Target) - - -- DCS task options: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.GROUNDATTACK - mission.missionAltitude=mission.engageAltitude*0.8 - mission.missionFraction=0.5 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.NoReaction -- No reaction is better. - - -- Evaluate result after 5 min. We might need time until the bombs have dropped and targets have been detroyed. - mission.dTevaluate=5*60 - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - -- Get DCS task. - mission.DCStask=mission:GetDCSMissionTask() - - return mission -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 #number Altitude Engage altitude in feet. Default 25000 ft. --- @return #AUFTRAG self -function AUFTRAG:NewBOMBRUNWAY(Airdrome, Altitude) - - if type(Airdrome)=="string" then - Airdrome=AIRBASE:FindByName(Airdrome) - end - - local mission=AUFTRAG:New(AUFTRAG.Type.BOMBRUNWAY) - - mission:_TargetFromObject(Airdrome) - - -- DCS task options: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.RUNWAYATTACK - mission.missionAltitude=mission.engageAltitude*0.8 - mission.missionFraction=0.75 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - -- Evaluate result after 5 min. - mission.dTevaluate=5*60 - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - -- Get DCS task. - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR]** Create a CARPET BOMBING mission. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Target Target coordinate. Can also be specified as a GROUP, UNIT or STATIC object. --- @param #number Altitude Engage altitude in feet. Default 25000 ft. --- @param #number CarpetLength Length of bombing carpet in meters. Default 500 m. --- @return #AUFTRAG self -function AUFTRAG:NewBOMBCARPET(Target, Altitude, CarpetLength) - - local mission=AUFTRAG:New(AUFTRAG.Type.BOMBCARPET) - - mission:_TargetFromObject(Target) - - -- DCS task options: - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - mission.engageWeaponExpend=AI.Task.WeaponExpend.ALL - mission.engageAltitude=UTILS.FeetToMeters(Altitude or 25000) - mission.engageCarpetLength=CarpetLength or 500 - mission.engageAsGroup=false -- Looks like this must be false or the task is not executed. It is not available in the ME anyway but in the task of the mission file. - mission.engageDirection=nil -- This is also not available in the ME. - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.GROUNDATTACK - mission.missionAltitude=mission.engageAltitude*0.8 - mission.missionFraction=0.5 - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.NoReaction - - -- Evaluate result after 5 min. - mission.dTevaluate=5*60 - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - -- Get DCS task. - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - ---- **[AIR]** Create an ESCORT (or FOLLOW) mission. Flight will escort another group and automatically engage certain target types. --- @param #AUFTRAG self --- @param Wrapper.Group#GROUP EscortGroup The group to escort. --- @param DCS#Vec3 OffsetVector A table with x, y and z components specifying the offset of the flight to the escorted group. Default {x=-100, y=0, z=200} for z=200 meters to the right, same alitude (y=0), x=-100 meters behind. --- @param #number EngageMaxDistance Max engage distance of targets in nautical miles. Default auto 32 NM. --- @param #table TargetTypes Types of targets to engage automatically. Default is {"Air"}, i.e. all enemy airborne units. Use an empty set {} for a simple "FOLLOW" mission. --- @return #AUFTRAG self -function AUFTRAG:NewESCORT(EscortGroup, OffsetVector, EngageMaxDistance, TargetTypes) - - local mission=AUFTRAG:New(AUFTRAG.Type.ESCORT) - - -- If only a string is passed we set a variable and check later if the group exists. - if type(EscortGroup)=="string" then - mission.escortGroupName=EscortGroup - mission:_TargetFromObject() - else - mission:_TargetFromObject(EscortGroup) - end - - -- DCS task parameters: - mission.escortVec3=OffsetVector or {x=-100, y=0, z=200} - mission.engageMaxDistance=EngageMaxDistance and UTILS.NMToMeters(EngageMaxDistance) or UTILS.NMToMeters(32) - mission.engageTargetTypes=TargetTypes or {"Air"} - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.ESCORT - mission.missionFraction=0.1 - mission.missionAltitude=1000 - mission.optionROE=ENUMS.ROE.OpenFire -- TODO: what's the best ROE here? Make dependent on ESCORT or FOLLOW! - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR ROTARY]** Create a RESCUE HELO mission. --- @param #AUFTRAG self --- @param Wrapper.Unit#UNIT Carrier The carrier unit. --- @return #AUFTRAG self -function AUFTRAG:NewRESCUEHELO(Carrier) - - local mission=AUFTRAG:New(AUFTRAG.Type.RESCUEHELO) - - mission:_TargetFromObject(Carrier) - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.NOTHING - mission.missionFraction=0.5 - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionROT=ENUMS.ROT.NoReaction - - mission.categories={AUFTRAG.Category.HELICOPTER} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIRPANE]** Create a RECOVERY TANKER mission. --- @param #AUFTRAG self --- @param Wrapper.Unit#UNIT Carrier The carrier unit. --- @param #number Altitude Orbit altitude in feet. Default is 6,000 ft. --- @param #number Speed Orbit speed in knots. Default 250 KIAS. --- @param #number Leg Length of race-track in NM. Default 14 NM. --- @param #number RelHeading Relative heading [0, 360) of race-track pattern in degrees wrt heading of the carrier. Default is heading of the carrier. --- @param #number OffsetDist Relative distance of the first race-track point wrt to the carrier. Default 6 NM. --- @param #number OffsetAngle Relative angle of the first race-track point wrt. to the carrier. Default 180 (behind the boat). --- @param #number UpdateDistance Threshold distance in NM before orbit pattern is updated. Default 5 NM. --- @return #AUFTRAG self -function AUFTRAG:NewRECOVERYTANKER(Carrier, Altitude, Speed, Leg, RelHeading, OffsetDist, OffsetAngle, UpdateDistance) - - -- Six NM astern. - local OffsetVec2={r=OffsetDist or 6, phi=OffsetAngle or 180} - - -- Default leg. - Leg=Leg or 14 - - -- Default Speed. - Speed=Speed or 250 - - local Heading=nil - if RelHeading then - Heading=-math.abs(RelHeading) - end - - -- Create orbit mission. - local mission=AUFTRAG:NewORBIT_GROUP(Carrier, Altitude, Speed, Leg, Heading, OffsetVec2, UpdateDistance) - - -- Set the type. - mission.type=AUFTRAG.Type.RECOVERYTANKER - - -- Mission options: - mission.missionTask=ENUMS.MissionTask.REFUELING - mission.missionFraction=0.9 - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionROT=ENUMS.ROT.NoReaction - - mission.categories={AUFTRAG.Category.AIRPLANE} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - ---- **[AIR ROTARY, GROUND]** Create a TROOP TRANSPORT mission. --- @param #AUFTRAG self --- @param Core.Set#SET_GROUP TransportGroupSet The set group(s) to be transported. --- @param Core.Point#COORDINATE DropoffCoordinate Coordinate where the helo will land drop off the the troops. --- @param Core.Point#COORDINATE PickupCoordinate Coordinate where the helo will land to pick up the the cargo. Default is the first transport group. --- @param #number PickupRadius Radius around the pickup coordinate in meters. Default 100 m. --- @return #AUFTRAG self -function AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet, DropoffCoordinate, PickupCoordinate, PickupRadius) - - local mission=AUFTRAG:New(AUFTRAG.Type.TROOPTRANSPORT) - - if TransportGroupSet:IsInstanceOf("GROUP") then - mission.transportGroupSet=SET_GROUP:New() - mission.transportGroupSet:AddGroup(TransportGroupSet) - elseif TransportGroupSet:IsInstanceOf("SET_GROUP") then - mission.transportGroupSet=TransportGroupSet - else - mission:E(mission.lid.."ERROR: TransportGroupSet must be a GROUP or SET_GROUP object!") - return nil - end - - mission:_TargetFromObject(mission.transportGroupSet) - - mission.transportPickup=PickupCoordinate or mission:GetTargetCoordinate() - mission.transportDropoff=DropoffCoordinate - - mission.transportPickupRadius=PickupRadius or 100 - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.TROOPTRANSPORT) - - -- Debug. - --mission.transportPickup:MarkToAll("Pickup Transport") - --mission.transportDropoff:MarkToAll("Drop off") - - -- TODO: what's the best ROE here? - mission.optionROE=ENUMS.ROE.ReturnFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.HELICOPTER, AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR ROTARY]** Create a CARGO TRANSPORT mission. --- **Important Note:** --- The dropoff zone has to be a zone defined in the Mission Editor. This is due to a restriction in the used DCS task, which takes the zone ID as input. --- Only ME zones have an ID that can be referenced. --- @param #AUFTRAG self --- @param Wrapper.Static#STATIC StaticCargo Static cargo object. --- @param Core.Zone#ZONE DropZone Zone where to drop off the cargo. **Has to be a zone defined in the ME!** --- @return #AUFTRAG self -function AUFTRAG:NewCARGOTRANSPORT(StaticCargo, DropZone) - - local mission=AUFTRAG:New(AUFTRAG.Type.CARGOTRANSPORT) - - mission:_TargetFromObject(StaticCargo) - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.CARGOTRANSPORT) - - -- Set ROE and ROT. - mission.optionROE=ENUMS.ROE.ReturnFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.HELICOPTER} - - mission.DCStask=mission:GetDCSMissionTask() - - mission.DCStask.params.groupId=StaticCargo:GetID() - mission.DCStask.params.zoneId=DropZone.ZoneID - mission.DCStask.params.zone=DropZone - mission.DCStask.params.cargo=StaticCargo - - return mission -end - ---[[ - ---- **[AIR, GROUND, NAVAL]** Create a OPS TRANSPORT mission. --- @param #AUFTRAG self --- @param Core.Set#SET_GROUP CargoGroupSet The set group(s) to be transported. --- @param Core.Zone#ZONE PickupZone Pick up zone --- @param Core.Zone#ZONE DeployZone Deploy zone --- @return #AUFTRAG self -function AUFTRAG:NewOPSTRANSPORT(CargoGroupSet, PickupZone, DeployZone) - - local mission=AUFTRAG:New(AUFTRAG.Type.OPSTRANSPORT) - - mission.transportGroupSet=CargoGroupSet - - mission:_TargetFromObject(mission.transportGroupSet) - - mission.opstransport=OPSTRANSPORT:New(CargoGroupSet, PickupZone, DeployZone) - - function mission.opstransport:OnAfterExecuting(From, Event, To) - mission:Executing() - end - - function mission.opstransport:OnAfterDelivered(From, Event, To) - mission:Done() - end - - -- TODO: what's the best ROE here? - mission.optionROE=ENUMS.ROE.ReturnFire - mission.optionROT=ENUMS.ROT.PassiveDefense - - mission.categories={AUFTRAG.Category.ALL} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - -]] - ---- **[GROUND, NAVAL]** Create an ARTY mission. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Target Center of the firing solution. --- @param #number Nshots Number of shots to be fired. Default `#nil`. --- @param #number Radius Radius of the shells in meters. Default 100 meters. --- @param #number Altitude Altitude in meters. Can be used to setup a Barrage. Default `#nil`. --- @return #AUFTRAG self -function AUFTRAG:NewARTY(Target, Nshots, Radius, Altitude) - - local mission=AUFTRAG:New(AUFTRAG.Type.ARTY) - - mission:_TargetFromObject(Target) - - mission.artyShots=Nshots or nil - mission.artyRadius=Radius or 100 - mission.artyAltitude=Altitude - - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - - mission.optionROE=ENUMS.ROE.OpenFire -- Ground/naval need open fire! - mission.optionAlarm=0 - - mission.missionFraction=0.0 - - -- Evaluate after 8 min. - mission.dTevaluate=8*60 - - mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[GROUND, NAVAL]** Create an BARRAGE mission. Assigned groups will move to a random coordinate within a given zone and start firing into the air. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone The zone where the unit will go. --- @param #number Heading Heading in degrees. Default random heading [0, 360). --- @param #number Angle Shooting angle in degrees. Default random [45, 85]. --- @param #number Radius Radius of the shells in meters. Default 100 meters. --- @param #number Altitude Altitude in meters. Default 500 m. --- @param #number Nshots Number of shots to be fired. Default is until ammo is empty (`#nil`). --- @return #AUFTRAG self -function AUFTRAG:NewBARRAGE(Zone, Heading, Angle, Radius, Altitude, Nshots) - - local mission=AUFTRAG:New(AUFTRAG.Type.BARRAGE) - - mission:_TargetFromObject(Zone) - - mission.artyShots=Nshots - mission.artyRadius=Radius or 100 - mission.artyAltitude=Altitude - mission.artyHeading=Heading - mission.artyAngle=Angle - - mission.engageWeaponType=ENUMS.WeaponFlag.Auto - - mission.optionROE=ENUMS.ROE.OpenFire -- Ground/naval need open fire! - mission.optionAlarm=0 - - mission.missionFraction=0.0 - - -- Evaluate after instantly. - mission.dTevaluate=10 - - mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[AIR, GROUND, NAVAL]** Create a PATROLZONE mission. Group(s) will go to the zone and patrol it randomly. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone The patrol zone. --- @param #number Speed Speed in knots. --- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL. --- @param #string Formation Formation used by ground units during patrol. Default "Off Road". --- @return #AUFTRAG self -function AUFTRAG:NewPATROLZONE(Zone, Speed, Altitude, Formation) - - local mission=AUFTRAG:New(AUFTRAG.Type.PATROLZONE) - - -- Ensure we got a ZONE and not just the zone name. - if type(Zone)=="string" then - Zone=ZONE:New(Zone) - end - - mission:_TargetFromObject(Zone) - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.PATROLZONE) - - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionROT=ENUMS.ROT.PassiveDefense - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil - mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil - - mission.categories={AUFTRAG.Category.ALL} - - mission.DCStask=mission:GetDCSMissionTask() - - mission.DCStask.params.formation=Formation or "Off Road" - - return mission -end - - ---- **[OBSOLETE]** Create a ARMORATTACK mission. --- ** Note that this is actually creating a GROUNDATTACK mission!** --- @param #AUFTRAG self --- @param Ops.Target#TARGET Target The target to attack. Can be a GROUP, UNIT or STATIC object. --- @param #number Speed Speed in knots. --- @param #string Formation The attack formation, e.g. "Wedge", "Vee" etc. --- @return #AUFTRAG self -function AUFTRAG:NewARMORATTACK(Target, Speed, Formation) - - local mission=AUFTRAG:NewGROUNDATTACK(Target, Speed, Formation) - - -- Mission type. - mission.type=AUFTRAG.Type.ARMORATTACK - - return mission -end - ---- **[GROUND]** Create a GROUNDATTACK mission. Ground group(s) will go to a target object and attack. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Target The target to attack. Can be a GROUP, UNIT or STATIC object. --- @param #number Speed Speed in knots. Default max. --- @param #string Formation The attack formation, e.g. "Wedge", "Vee" etc. Default `ENUMS.Formation.Vehicle.Vee`. --- @return #AUFTRAG self -function AUFTRAG:NewGROUNDATTACK(Target, Speed, Formation) - - local mission=AUFTRAG:New(AUFTRAG.Type.GROUNDATTACK) - - mission:_TargetFromObject(Target) - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.GROUNDATTACK) - - -- Defaults. - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionAlarm=ENUMS.AlarmState.Auto - mission.optionFormation="On Road" - mission.missionFraction=0.70 - mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - mission.DCStask.params.speed=Speed - mission.DCStask.params.formation=Formation or ENUMS.Formation.Vehicle.Vee - - return mission -end - ---- **[AIR, GROUND, NAVAL]** Create a RECON mission. --- @param #AUFTRAG self --- @param Core.Set#SET_ZONE ZoneSet The recon zones. --- @param #number Speed Speed in knots. --- @param #number Altitude Altitude in feet. Only for airborne units. Default 2000 feet ASL. --- @param #boolean Adinfinitum If `true`, the group will start over again after reaching the final zone. --- @param #boolean Randomly If `true`, the group will select a random zone. --- @param #string Formation Formation used during recon route. --- @return #AUFTRAG self -function AUFTRAG:NewRECON(ZoneSet, Speed, Altitude, Adinfinitum, Randomly, Formation) - - local mission=AUFTRAG:New(AUFTRAG.Type.RECON) - - mission:_TargetFromObject(ZoneSet) - - mission.missionTask=mission:GetMissionTaskforMissionType(AUFTRAG.Type.RECON) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionROT=ENUMS.ROT.PassiveDefense - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=0.5 - mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil - mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or UTILS.FeetToMeters(2000) - - mission.categories={AUFTRAG.Category.ALL} - - mission.DCStask=mission:GetDCSMissionTask() - mission.DCStask.params.adinfinitum=Adinfinitum - mission.DCStask.params.randomly=Randomly - mission.DCStask.params.formation=Formation - - return mission -end - ---- **[GROUND]** Create a AMMO SUPPLY mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone The zone, where supply units go. --- @return #AUFTRAG self -function AUFTRAG:NewAMMOSUPPLY(Zone) - - local mission=AUFTRAG:New(AUFTRAG.Type.AMMOSUPPLY) - - mission:_TargetFromObject(Zone) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.missionWaypointRadius=0 - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[GROUND]** Create a FUEL SUPPLY mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone The zone, where supply units go. --- @return #AUFTRAG self -function AUFTRAG:NewFUELSUPPLY(Zone) - - local mission=AUFTRAG:New(AUFTRAG.Type.FUELSUPPLY) - - mission:_TargetFromObject(Zone) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[GROUND]** Create a REARMING mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone The zone, where units go and look for ammo supply. --- @return #AUFTRAG self -function AUFTRAG:NewREARMING(Zone) - - local mission=AUFTRAG:New(AUFTRAG.Type.REARMING) - - mission:_TargetFromObject(Zone) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.missionWaypointRadius=0 - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - ---- **[AIR]** Create an ALERT 5 mission. Aircraft will be spawned uncontrolled and wait for an assignment. You must specify **one** mission type which is performed. --- This determines the payload and the DCS mission task which are used when the aircraft is spawned. --- @param #AUFTRAG self --- @param #string MissionType Mission type `AUFTRAG.Type.XXX`. Determines payload and mission task (intercept, ground attack, etc.). --- @return #AUFTRAG self -function AUFTRAG:NewALERT5(MissionType) - - local mission=AUFTRAG:New(AUFTRAG.Type.ALERT5) - - mission.missionTask=self:GetMissionTaskforMissionType(MissionType) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionROT=ENUMS.ROT.NoReaction - - mission.alert5MissionType=MissionType - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.AIRCRAFT} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[GROUND, NAVAL]** Create an ON GUARD mission. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Coordinate, where to stand guard. --- @return #AUFTRAG self -function AUFTRAG:NewONGUARD(Coordinate) - - local mission=AUFTRAG:New(AUFTRAG.Type.ONGUARD) - - mission:_TargetFromObject(Coordinate) - - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[GROUND, NAVAL]** Create an AIRDEFENSE mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone Zone where the air defense group(s) should be stationed. --- @return #AUFTRAG self -function AUFTRAG:NewAIRDEFENSE(Zone) - - local mission=AUFTRAG:New(AUFTRAG.Type.AIRDEFENSE) - - mission:_TargetFromObject(Zone) - - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- **[GROUND]** Create an EWR mission. --- @param #AUFTRAG self --- @param Core.Zone#ZONE Zone Zone where the Early Warning Radar group(s) should be stationed. --- @return #AUFTRAG self -function AUFTRAG:NewEWR(Zone) - - local mission=AUFTRAG:New(AUFTRAG.Type.EWR) - - mission:_TargetFromObject(Zone) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - - ---- **[PRIVATE, AIR, GROUND, NAVAL]** Create a mission to relocate all cohort assets to another LEGION. --- @param #AUFTRAG self --- @param Ops.Legion#LEGION Legion The new legion. --- @param Ops.Cohort#COHORT Cohort The cohort to be relocated. --- @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() - - if Cohort.isGround then - mission.optionFormation=ENUMS.Formation.Vehicle.OnRoad - end - - mission.DCStask.params.legion=Legion - mission.DCStask.params.cohort=Cohort - - return mission -end - ---- **[GROUND, NAVAL]** Create a mission to do NOTHING. --- @param #AUFTRAG self --- @param Core.Zone#ZONE RelaxZone Zone where the assets are supposed to do nothing. --- @return #AUFTRAG self -function AUFTRAG:NewNOTHING(RelaxZone) - - local mission=AUFTRAG:New(AUFTRAG.Type.NOTHING) - - mission:_TargetFromObject(RelaxZone) - - mission.optionROE=ENUMS.ROE.WeaponHold - mission.optionAlarm=ENUMS.AlarmState.Auto - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.GROUND, AUFTRAG.Category.NAVAL} - - 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. --- @param #string Formation Formation to take, e.g. "On Road", "Vee" etc. --- @return #AUFTRAG self -function AUFTRAG:NewARMOREDGUARD(Coordinate,Formation) - - local mission=AUFTRAG:New(AUFTRAG.Type.ARMOREDGUARD) - - mission:_TargetFromObject(Coordinate) - - mission.optionROE=ENUMS.ROE.OpenFire - mission.optionAlarm=ENUMS.AlarmState.Auto - mission.optionFormation=Formation or "On Road" - - mission.missionFraction=1.0 - - mission.categories={AUFTRAG.Category.GROUND} - - mission.DCStask=mission:GetDCSMissionTask() - - return mission -end - ---- Create a mission to attack a TARGET object. --- @param #AUFTRAG self --- @param Ops.Target#TARGET Target The target. --- @param #string MissionType The mission type. --- @return #AUFTRAG self -function AUFTRAG:NewFromTarget(Target, MissionType) - - local mission=nil --#AUFTRAG - - if MissionType==AUFTRAG.Type.ANTISHIP then - mission=self:NewANTISHIP(Target, Altitude) - elseif MissionType==AUFTRAG.Type.ARTY then - mission=self:NewARTY(Target, Nshots, Radius) - elseif MissionType==AUFTRAG.Type.BAI then - mission=self:NewBAI(Target, Altitude) - elseif MissionType==AUFTRAG.Type.BOMBCARPET then - mission=self:NewBOMBCARPET(Target, Altitude, CarpetLength) - elseif MissionType==AUFTRAG.Type.BOMBING then - mission=self:NewBOMBING(Target, Altitude) - elseif MissionType==AUFTRAG.Type.BOMBRUNWAY then - mission=self:NewBOMBRUNWAY(Target, Altitude) - elseif MissionType==AUFTRAG.Type.CAS then - mission=self:NewCAS(ZONE_RADIUS:New(Target:GetName(),Target:GetVec2(),1000),Altitude,Speed,Target:GetAverageCoordinate(),Heading,Leg,TargetTypes) - elseif MissionType==AUFTRAG.Type.CASENHANCED then - mission=self:NewCASENHANCED(ZONE_RADIUS:New(Target:GetName(),Target:GetVec2(),1000),Altitude,Speed,RangeMax,NoEngageZoneSet,TargetTypes) - elseif MissionType==AUFTRAG.Type.INTERCEPT then - mission=self:NewINTERCEPT(Target) - elseif MissionType==AUFTRAG.Type.SEAD then - mission=self:NewSEAD(Target, Altitude) - elseif MissionType==AUFTRAG.Type.STRIKE then - mission=self:NewSTRIKE(Target, Altitude) - elseif MissionType==AUFTRAG.Type.ARMORATTACK then - mission=self:NewARMORATTACK(Target, Speed) - elseif MissionType==AUFTRAG.Type.GROUNDATTACK then - mission=self:NewGROUNDATTACK(Target, Speed, Formation) - else - return nil - end - - return mission -end - - ---- Create a mission to attack a group. Mission type is automatically chosen from the group category. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Target Target object. --- @return #string Auftrag type, e.g. `AUFTRAG.Type.BAI` (="BAI"). -function AUFTRAG:_DetermineAuftragType(Target) - - local group=nil --Wrapper.Group#GROUP - local airbase=nil --Wrapper.Airbase#AIRBASE - local scenery=nil --Wrapper.Scenery#SCENERY - local coordinate=nil --Core.Point#COORDINATE - local auftrag=nil - - if Target:IsInstanceOf("GROUP") then - group=Target --Target is already a group. - elseif Target:IsInstanceOf("UNIT") then - group=Target:GetGroup() - elseif Target:IsInstanceOf("AIRBASE") then - airbase=Target - elseif Target:IsInstanceOf("SCENERY") then - scenery=Target - end - - if group then - - local category=group:GetCategory() - local attribute=group:GetAttribute() - - if category==Group.Category.AIRPLANE or category==Group.Category.HELICOPTER then - - --- - -- A2A: Intercept - --- - - auftrag=AUFTRAG.Type.INTERCEPT - - elseif category==Group.Category.GROUND or category==Group.Category.TRAIN then - - --- - -- GROUND - --- - - if attribute==GROUP.Attribute.GROUND_SAM then - - -- SEAD/DEAD - - auftrag=AUFTRAG.Type.SEAD - - elseif attribute==GROUP.Attribute.GROUND_AAA then - - auftrag=AUFTRAG.Type.BAI - - elseif attribute==GROUP.Attribute.GROUND_ARTILLERY then - - auftrag=AUFTRAG.Type.BAI - - elseif attribute==GROUP.Attribute.GROUND_INFANTRY then - - auftrag=AUFTRAG.Type.CAS - - elseif attribute==GROUP.Attribute.GROUND_TANK then - - auftrag=AUFTRAG.Type.BAI - - else - - auftrag=AUFTRAG.Type.BAI - - end - - - elseif category==Group.Category.SHIP then - - --- - -- NAVAL - --- - - auftrag=AUFTRAG.Type.ANTISHIP - - else - self:T(self.lid.."ERROR: Unknown Group category!") - end - - elseif airbase then - auftrag=AUFTRAG.Type.BOMBRUNWAY - elseif scenery then - auftrag=AUFTRAG.Type.STRIKE - elseif coordinate then - auftrag=AUFTRAG.Type.BOMBING - end - - return auftrag -end - ---- Create a mission to attack a group. Mission type is automatically chosen from the group category. --- @param #AUFTRAG self --- @param Wrapper.Group#GROUP EngageGroup Group to be engaged. --- @return #AUFTRAG self -function AUFTRAG:NewAUTO(EngageGroup) - - local mission=nil --#AUFTRAG - - local Target=EngageGroup - - local auftrag=self:_DetermineAuftragType(EngageGroup) - - if auftrag==AUFTRAG.Type.ANTISHIP then - mission=AUFTRAG:NewANTISHIP(Target) - elseif auftrag==AUFTRAG.Type.ARTY then - mission=AUFTRAG:NewARTY(Target) - elseif auftrag==AUFTRAG.Type.AWACS then - mission=AUFTRAG:NewAWACS(Coordinate, Altitude,Speed,Heading,Leg) - elseif auftrag==AUFTRAG.Type.BAI then - mission=AUFTRAG:NewBAI(Target,Altitude) - elseif auftrag==AUFTRAG.Type.BOMBING then - mission=AUFTRAG:NewBOMBING(Target,Altitude) - elseif auftrag==AUFTRAG.Type.BOMBRUNWAY then - mission=AUFTRAG:NewBOMBRUNWAY(Airdrome,Altitude) - elseif auftrag==AUFTRAG.Type.BOMBCARPET then - mission=AUFTRAG:NewBOMBCARPET(Target,Altitude,CarpetLength) - elseif auftrag==AUFTRAG.Type.CAP then - mission=AUFTRAG:NewCAP(ZoneCAP,Altitude,Speed,Coordinate,Heading,Leg,TargetTypes) - elseif auftrag==AUFTRAG.Type.CAS then - mission=AUFTRAG:NewCAS(ZoneCAS,Altitude,Speed,Coordinate,Heading,Leg,TargetTypes) - elseif auftrag==AUFTRAG.Type.ESCORT then - mission=AUFTRAG:NewESCORT(EscortGroup,OffsetVector,EngageMaxDistance,TargetTypes) - elseif auftrag==AUFTRAG.Type.FACA then - mission=AUFTRAG:NewFACA(Target,Designation,DataLink,Frequency,Modulation) - elseif auftrag==AUFTRAG.Type.FERRY then - -- Not implemented yet. - elseif auftrag==AUFTRAG.Type.GCICAP then - mission=AUFTRAG:NewGCICAP(Coordinate,Altitude,Speed,Heading,Leg) - elseif auftrag==AUFTRAG.Type.INTERCEPT then - mission=AUFTRAG:NewINTERCEPT(Target) - elseif auftrag==AUFTRAG.Type.ORBIT then - mission=AUFTRAG:NewORBIT(Coordinate,Altitude,Speed,Heading,Leg) - elseif auftrag==AUFTRAG.Type.RECON then - -- Not implemented yet. - elseif auftrag==AUFTRAG.Type.RESCUEHELO then - mission=AUFTRAG:NewRESCUEHELO(Carrier) - elseif auftrag==AUFTRAG.Type.SEAD then - mission=AUFTRAG:NewSEAD(Target,Altitude) - elseif auftrag==AUFTRAG.Type.STRIKE then - mission=AUFTRAG:NewSTRIKE(Target,Altitude) - elseif auftrag==AUFTRAG.Type.TANKER then - mission=AUFTRAG:NewTANKER(Coordinate,Altitude,Speed,Heading,Leg,RefuelSystem) - elseif auftrag==AUFTRAG.Type.TROOPTRANSPORT then - mission=AUFTRAG:NewTROOPTRANSPORT(TransportGroupSet,DropoffCoordinate,PickupCoordinate) - else - - end - - if mission then - mission:SetPriority(10, true) - end - - 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:SetTime(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 time how long the mission is executed. Once this time limit has passed, the mission is cancelled. --- @param #AUFTRAG self --- @param #number Duration Duration in seconds. --- @return #AUFTRAG self -function AUFTRAG:SetDuration(Duration) - self.durationExe=Duration - return self -end - ---- Set that mission assets are teleported to the mission execution waypoint. --- @param #AUFTRAG self --- @param #boolean Switch If `true` or `nil`, teleporting is on. If `false`, teleporting is off. --- @return #AUFTRAG self -function AUFTRAG:SetTeleport(Switch) - if Switch==nil then - Switch=true - end - self.teleport=Switch - return self -end - - ---- Set mission push time. This is the time the mission is executed. If the push time is not passed, the group will wait at the mission execution waypoint. --- @param #AUFTRAG self --- @param #string ClockPush Time the mission is executed, e.g. "05:00" for 5 am. Can also be given as a `#number`, where it is interpreted as relative push time in seconds. --- @return #AUFTRAG self -function AUFTRAG:SetPushTime(ClockPush) - - if ClockPush then - if type(ClockPush)=="string" then - self.Tpush=UTILS.ClockToSeconds(ClockPush) - elseif type(ClockPush)=="number" then - self.Tpush=timer.getAbsTime()+ClockPush - end - 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. --- @param #number Importance Number 1-10. If missions with lower value are in the queue, these have to be finished first. Default is `nil`. --- @return #AUFTRAG self -function AUFTRAG:SetPriority(Prio, Urgent, Importance) - self.prio=Prio or 50 - self.urgent=Urgent - self.importance=Importance - return self -end - ---- **[LEGION, COMMANDER, CHIEF]** Set how many times the mission is repeated. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level. --- @param #AUFTRAG self --- @param #number Nrepeat Number of repeats. Default 0. --- @return #AUFTRAG self -function AUFTRAG:SetRepeat(Nrepeat) - self.Nrepeat=Nrepeat or 0 - return self -end - ---- **[LEGION, COMMANDER, CHIEF]** Set how many times the mission is repeated if it fails. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level. --- @param #AUFTRAG self --- @param #number Nrepeat Number of repeats. Default 0. --- @return #AUFTRAG self -function AUFTRAG:SetRepeatOnFailure(Nrepeat) - self.NrepeatFailure=Nrepeat or 0 - return self -end - ---- **[LEGION, COMMANDER, CHIEF]** Set how many times the mission is repeated if it was successful. Only valid if the mission is handled by a LEGION (AIRWING, BRIGADE, FLEET) or higher level. --- @param #AUFTRAG self --- @param #number Nrepeat Number of repeats. Default 0. --- @return #AUFTRAG self -function AUFTRAG:SetRepeatOnSuccess(Nrepeat) - self.NrepeatSuccess=Nrepeat or 0 - return self -end - ---- **[LEGION, COMMANDER, CHIEF]** Define how many assets are required to do the job. Only used if the mission is handled by a **LEGION** (AIRWING, BRIGADE, ...) or higher level. --- @param #AUFTRAG self --- @param #number NassetsMin Minimum number of asset groups. Default 1. --- @param #number NassetsMax Maximum Number of asset groups. Default is same as `NassetsMin`. --- @return #AUFTRAG self -function AUFTRAG:SetRequiredAssets(NassetsMin, NassetsMax) - - self.NassetsMin=NassetsMin or 1 - - self.NassetsMax=NassetsMax or self.NassetsMin - - -- Ensure that max is at least equal to min. - if self.NassetsMaxself.Tstop then - return false - end - - -- All start conditions true? - local startme=self:EvalConditionsAll(self.conditionStart) - - if not startme then - return false - end - - - -- We're good to go! - return true -end - ---- Check if mission is ready to be started. --- * Mission stop already passed. --- * Any stop condition is true. --- @param #AUFTRAG self --- @return #boolean If true, mission should be cancelled. -function AUFTRAG:IsReadyToCancel() - - local Tnow=timer.getAbsTime() - - -- Stop time already passed. - if self.Tstop and Tnow>=self.Tstop then - return true - end - - -- Evaluate failure condition. One is enough. - local failure=self:EvalConditionsAny(self.conditionFailure) - - if failure then - self.failurecondition=true - return true - end - - -- Evaluate success consitions. One is enough. - local success=self:EvalConditionsAny(self.conditionSuccess) - - if success then - self.successcondition=true - return true - end - - -- No criterion matched. - return false -end - ---- Check if mission is ready to be pushed. --- * Mission push time already passed. --- * **All** push conditions are true. --- @param #AUFTRAG self --- @return #boolean If true, mission groups can push. -function AUFTRAG:IsReadyToPush() - - local Tnow=timer.getAbsTime() - - -- Push time passed? - if self.Tpush and Tnow<=self.Tpush then - return false - end - - -- Evaluate push condition(s) if any. All need to be true. - local push=self:EvalConditionsAll(self.conditionPush) - - return push -end - ---- Check if all given condition are true. --- @param #AUFTRAG self --- @param #table Conditions Table of conditions. --- @return #boolean If true, all conditions were true. Returns false if at least one condition returned false. -function AUFTRAG:EvalConditionsAll(Conditions) - - -- Any stop condition must be true. - for _,_condition in pairs(Conditions or {}) do - local condition=_condition --#AUFTRAG.Condition - - -- Call function. - local istrue=condition.func(unpack(condition.arg)) - - -- Any false will return false. - if not istrue then - return false - end - - end - - -- All conditions were true. - return true -end - - ---- Check if any of the given conditions is true. --- @param #AUFTRAG self --- @param #table Conditions Table of conditions. --- @return #boolean If true, at least one condition is true. -function AUFTRAG:EvalConditionsAny(Conditions) - - -- Any stop condition must be true. - for _,_condition in pairs(Conditions or {}) do - local condition=_condition --#AUFTRAG.Condition - - -- Call function. - local istrue=condition.func(unpack(condition.arg)) - - -- Any true will return true. - if istrue then - return true - end - - end - - -- No condition was true. - return false -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Mission Status -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- On after "Status" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterStatus(From, Event, To) - - -- Current abs. mission time. - local Tnow=timer.getAbsTime() - - -- ESCORT: Check if only the group NAME of an escort had been specified. - if self.escortGroupName then - -- Try to find the group. - local group=GROUP:FindByName(self.escortGroupName) - if group and group:IsAlive() then - - -- Debug info. - self:T(self.lid..string.format("ESCORT group %s is now alive. Updating DCS task and adding group to TARGET", tostring(self.escortGroupName))) - - -- Add TARGET object. - self.engageTarget:AddObject(group) - - -- Update DCS task with the known group ID. - self.DCStask=self:GetDCSMissionTask() - - -- Set value to nil so we do not do this again in the next cycle. - self.escortGroupName=nil - end - end - - -- Number of alive mission targets. - local Ntargets=self:CountMissionTargets() - local Ntargets0=self:GetTargetInitialNumber() - - -- Number of alive groups attached to this mission. - local Ngroups=self:CountOpsGroups() - - -- Check if mission is not OVER yet. - if self:IsNotOver() then - - if self:CheckGroupsDone() then - - -- All groups have reported MISSON DONE. - self:Done() - - elseif (self.Tstop and Tnow>self.Tstop+10) then - - -- Cancel mission if stop time passed. - self:Cancel() - - elseif self.durationExe and self.Texecuting and Tnow-self.Texecuting>self.durationExe then - - -- Backup repeat values - local Nrepeat=self.Nrepeat - local NrepeatS=self.NrepeatSuccess - local NrepeatF=self.NrepeatFailure - - -- Cancel mission if stop time passed. - self:Cancel() - - self.Nrepeat=Nrepeat - self.NrepeatSuccess=NrepeatS - self.NrepeatFailure=NrepeatF - - elseif (Ntargets0>0 and Ntargets==0) then - - -- Cancel mission if mission targets are gone (if there were any in the beginning). - -- TODO: I commented this out for some reason but I forgot why... - self:T(self.lid.."No targets left cancelling mission!") - self:Cancel() - - elseif self:IsExecuting() then - - -- Had the case that mission was in state Executing but all assigned groups were dead. - -- TODO: might need to loop over all assigned groups - if Ngroups==0 then - self:Done() - else - local done=true - for groupname,data in pairs(self.groupdata or {}) do - local groupdata=data --#AUFTRAG.GroupData - local opsgroup=groupdata.opsgroup - if opsgroup:IsAlive() then - done=false - end - end - if done then - self:Done() - end - end - - end - - end - - -- Current FSM state. - local fsmstate=self:GetState() - - -- Check for error. - if fsmstate~=self.status then - self:T(self.lid..string.format("ERROR: FSM state %s != %s mission status!", fsmstate, self.status)) - end - - -- General info. - if self.verbose>=1 then - - -- Mission start stop time. - local Cstart=UTILS.SecondsToClock(self.Tstart, true) - local Cstop=self.Tstop and UTILS.SecondsToClock(self.Tstop, true) or "INF" - - local targetname=self:GetTargetName() or "unknown" - - local Nlegions=#self.legions - local commander=self.commander and self.statusCommander or "N/A" - local chief=self.chief and self.statusChief or "N/A" - - -- Info message. - self:T(self.lid..string.format("Status %s: Target=%s, T=%s-%s, assets=%d, groups=%d, targets=%d, legions=%d, commander=%s, chief=%s", - self.status, targetname, Cstart, Cstop, #self.assets, Ngroups, Ntargets, Nlegions, commander, chief)) - end - - -- Group info. - if self.verbose>=2 then - -- Data on assigned groups. - local text="Group data:" - for groupname,_groupdata in pairs(self.groupdata) do - local groupdata=_groupdata --#AUFTRAG.GroupData - text=text..string.format("\n- %s: status mission=%s opsgroup=%s", groupname, groupdata.status, groupdata.opsgroup and groupdata.opsgroup:GetState() or "N/A") - end - self:I(self.lid..text) - end - - -- Ready to evaluate mission outcome? - local ready2evaluate=self.Tover and Tnow-self.Tover>=self.dTevaluate or false - - -- Check if mission is OVER (done or cancelled) and enough time passed to evaluate the result. - if self:IsOver() and ready2evaluate then - -- Evaluate success or failure of the mission. - self:Evaluate() - else - self:__Status(-30) - end - - -- Update F10 marker. - if self.markerOn then - self:UpdateMarker() - end - -end - ---- Evaluate mission outcome - success or failure. --- @param #AUFTRAG self --- @return #AUFTRAG self -function AUFTRAG:Evaluate() - - -- Assume success and check if any failed condition applies. - local failed=false - - -- Target damage in %. - local targetdamage=self:GetTargetDamage() - - -- Own damage in %. - local owndamage=self.Ncasualties/self.Nelements*100 - - -- Current number of mission targets. - local Ntargets=self:CountMissionTargets() - local Ntargets0=self:GetTargetInitialNumber() - - local Life=self:GetTargetLife() - local Life0=self:GetTargetInitialLife() - - - if Ntargets0>0 then - - --- - -- Mission had targets - --- - - -- Check if failed. - if self.type==AUFTRAG.Type.TROOPTRANSPORT or self.type==AUFTRAG.Type.ESCORT then - - -- Transported or escorted groups have to survive. - if Ntargets0 then - failed=true - end - - end - - else - - --- - -- Mission had NO targets - --- - - -- No targets and everybody died ==> mission failed. Well, unless success condition is true. - if self.Nelements==self.Ncasualties then - failed=true - end - - end - - - -- Any success condition true? - local successCondition=self:EvalConditionsAny(self.conditionSuccess) - - -- Any failure condition true? - local failureCondition=self:EvalConditionsAny(self.conditionFailure) - - if failureCondition then - failed=true - elseif successCondition then - failed=false - end - - -- Debug text. - if self.verbose > 0 then - local text=string.format("Evaluating mission:\n") - text=text..string.format("Own casualties = %d/%d\n", self.Ncasualties, self.Nelements) - text=text..string.format("Own losses = %.1f %%\n", owndamage) - text=text..string.format("Killed units = %d\n", self.Nkills) - text=text..string.format("--------------------------\n") - text=text..string.format("Targets left = %d/%d\n", Ntargets, Ntargets0) - text=text..string.format("Targets life = %.1f/%.1f\n", Life, Life0) - text=text..string.format("Enemy losses = %.1f %%\n", targetdamage) - text=text..string.format("--------------------------\n") - text=text..string.format("Success Cond = %s\n", tostring(successCondition)) - text=text..string.format("Failure Cond = %s\n", tostring(failureCondition)) - text=text..string.format("--------------------------\n") - text=text..string.format("Final Success = %s\n", tostring(not failed)) - text=text..string.format("=========================") - self:I(self.lid..text) - end - - -- Trigger events. - if failed then - self:I(self.lid..string.format("Mission %d [%s] failed!", self.auftragsnummer, self.type)) - if self.chief then - self.chief.Nfailure=self.chief.Nfailure+1 - end - self:Failed() - else - self:I(self.lid..string.format("Mission %d [%s] success!", self.auftragsnummer, self.type)) - if self.chief then - self.chief.Nsuccess=self.chief.Nsuccess+1 - end - self:Success() - end - - return self -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Asset Data -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- Get all OPS groups. --- @param #AUFTRAG self --- @return #table Table of Ops.OpsGroup#OPSGROUP or {}. -function AUFTRAG:GetOpsGroups() - local opsgroups={} - for _,_groupdata in pairs(self.groupdata or {}) do - local groupdata=_groupdata --#AUFTRAG.GroupData - table.insert(opsgroups, groupdata.opsgroup) - end - return opsgroups -end - ---- Get asset data table. --- @param #AUFTRAG self --- @param #string AssetName Name of the asset. --- @return #AUFTRAG.GroupData Group data or *nil* if OPS group does not exist. -function AUFTRAG:GetAssetDataByName(AssetName) - return self.groupdata[tostring(AssetName)] -end - ---- Get flight data table. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The flight group. --- @return #AUFTRAG.GroupData Flight data or nil if opsgroup does not exist. -function AUFTRAG:GetGroupData(opsgroup) - if opsgroup and self.groupdata then - return self.groupdata[opsgroup.groupname] - end - return nil -end - ---- Set opsgroup mission status. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The flight group. --- @param #string status New status. --- @return #AUFTRAG self -function AUFTRAG:SetGroupStatus(opsgroup, status) - - -- Current status. - local oldstatus=self:GetGroupStatus(opsgroup) - - -- Debug info. - self:T(self.lid..string.format("Setting OPSGROUP %s to status %s-->%s", opsgroup and opsgroup.groupname or "nil", tostring(oldstatus), tostring(status))) - - if oldstatus==AUFTRAG.GroupStatus.CANCELLED and status==AUFTRAG.GroupStatus.DONE then - -- Do not overwrite a CANCELLED status with a DONE status. - else - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - groupdata.status=status - else - self:T(self.lid.."WARNING: Could not SET flight data for flight group. Setting status to DONE") - end - end - - -- Check if mission is NOT over. - local isNotOver=self:IsNotOver() - - -- Check if all assigned groups are done. - local groupsDone=self:CheckGroupsDone() - - -- Debug info. - self:T2(self.lid..string.format("Setting OPSGROUP %s status to %s. IsNotOver=%s CheckGroupsDone=%s", opsgroup.groupname, self:GetGroupStatus(opsgroup), tostring(self:IsNotOver()), tostring(groupsDone))) - - -- Check if ALL flights are done with their mission. - if isNotOver and groupsDone then - self:T3(self.lid.."All assigned OPSGROUPs done ==> mission DONE!") - self:Done() - else - self:T3(self.lid.."Mission NOT DONE yet!") - end - - return self -end - ---- Get ops group mission status. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @return #string The group status. -function AUFTRAG:GetGroupStatus(opsgroup) - self:T3(self.lid..string.format("Trying to get Flight status for flight group %s", opsgroup and opsgroup.groupname or "nil")) - - local groupdata=self:GetGroupData(opsgroup) - - if groupdata then - return groupdata.status - else - - self:T(self.lid..string.format("WARNING: Could not GET groupdata for opsgroup %s. Returning status DONE.", opsgroup and opsgroup.groupname or "nil")) - return AUFTRAG.GroupStatus.DONE - - end -end - ---- Add LEGION to mission. --- @param #AUFTRAG self --- @param Ops.Legion#LEGION Legion The legion. --- @return #AUFTRAG self -function AUFTRAG:AddLegion(Legion) - - -- Debug info. - self:T(self.lid..string.format("Adding legion %s", Legion.alias)) - - -- Add legion to table. - table.insert(self.legions, Legion) - - return self -end - ---- Remove LEGION from mission. --- @param #AUFTRAG self --- @param Ops.Legion#LEGION Legion The legion. --- @return #AUFTRAG self -function AUFTRAG:RemoveLegion(Legion) - - -- Loop over legions - for i=#self.legions,1,-1 do - local legion=self.legions[i] --Ops.Legion#LEGION - - if legion.alias==Legion.alias then - - -- Debug info. - self:T(self.lid..string.format("Removing legion %s", Legion.alias)) - table.remove(self.legions, i) - - -- Set legion status to nil. - self.statusLegion[Legion.alias]=nil - - return self - end - - end - - self:T(self.lid..string.format("ERROR: Legion %s not found and could not be removed!", Legion.alias)) - return self -end - ---- Set LEGION mission status. --- @param #AUFTRAG self --- @param Ops.Legion#LEGION Legion The legion. --- @param #string Status New status. --- @return #AUFTRAG self -function AUFTRAG:SetLegionStatus(Legion, Status) - - -- Old status - local status=self:GetLegionStatus(Legion) - - -- Debug info. - self:T(self.lid..string.format("Setting LEGION %s to status %s-->%s", Legion.alias, tostring(status), tostring(Status))) - - -- New status. - self.statusLegion[Legion.alias]=Status - - return self -end - ---- Get LEGION mission status. --- @param #AUFTRAG self --- @param Ops.Legion#LEGION Legion The legion. --- @return #string status Current status. -function AUFTRAG:GetLegionStatus(Legion) - - -- New status. - local status=self.statusLegion[Legion.alias] or "unknown" - - return status -end - - ---- Set mission (ingress) waypoint coordinate for OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @param Core.Point#COORDINATE coordinate Waypoint Coordinate. --- @return #AUFTRAG self -function AUFTRAG:SetGroupWaypointCoordinate(opsgroup, coordinate) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - groupdata.waypointcoordinate=coordinate - end - return self -end - ---- Get mission (ingress) waypoint coordinate of OPS group --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @return Core.Point#COORDINATE Waypoint Coordinate. -function AUFTRAG:GetGroupWaypointCoordinate(opsgroup) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - return groupdata.waypointcoordinate - end -end - - ---- Set mission waypoint task for OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @param Ops.OpsGroup#OPSGROUP.Task task Waypoint task. -function AUFTRAG:SetGroupWaypointTask(opsgroup, task) - self:T2(self.lid..string.format("Setting waypoint task %s", task and task.description or "WTF")) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - groupdata.waypointtask=task - end -end - ---- Get mission waypoint task of OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @return Ops.OpsGroup#OPSGROUP.Task task Waypoint task. Waypoint task. -function AUFTRAG:GetGroupWaypointTask(opsgroup) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - return groupdata.waypointtask - end -end - ---- Set mission (ingress) waypoint UID for OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @param #number waypointindex Waypoint UID. --- @return #AUFTRAG self -function AUFTRAG:SetGroupWaypointIndex(opsgroup, waypointindex) - self:T2(self.lid..string.format("Setting Mission waypoint UID=%d", waypointindex)) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - groupdata.waypointindex=waypointindex - end - return self -end - ---- Get mission (ingress) waypoint UID of OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @return #number Waypoint UID. -function AUFTRAG:GetGroupWaypointIndex(opsgroup) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - return groupdata.waypointindex - end -end - ---- Set Egress waypoint UID for OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @param #number waypointindex Waypoint UID. --- @return #AUFTRAG self -function AUFTRAG:SetGroupEgressWaypointUID(opsgroup, waypointindex) - self:T2(self.lid..string.format("Setting Egress waypoint UID=%d", waypointindex)) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - groupdata.waypointEgressUID=waypointindex - end - return self -end - ---- Get Egress waypoint UID of OPS group. --- @param #AUFTRAG self --- @param Ops.OpsGroup#OPSGROUP opsgroup The OPS group. --- @return #number Waypoint UID. -function AUFTRAG:GetGroupEgressWaypointUID(opsgroup) - local groupdata=self:GetGroupData(opsgroup) - if groupdata then - return groupdata.waypointEgressUID - end -end - - - ---- Check if all flights are done with their mission (or dead). --- @param #AUFTRAG self --- @return #boolean If true, all flights are done with the mission. -function AUFTRAG:CheckGroupsDone() - - -- Check status of all OPS groups. - for groupname,data in pairs(self.groupdata) do - local groupdata=data --#AUFTRAG.GroupData - if groupdata then - if not (groupdata.status==AUFTRAG.GroupStatus.DONE or groupdata.status==AUFTRAG.GroupStatus.CANCELLED) then - -- At least this flight is not DONE or CANCELLED. - self:T2(self.lid..string.format("CheckGroupsDone: OPSGROUP %s is not DONE or CANCELLED but in state %s. Mission NOT DONE!", groupdata.opsgroup.groupname, groupdata.status:upper())) - return false - end - end - end - - -- Check status of all LEGIONs. - for _,_legion in pairs(self.legions) do - local legion=_legion --Ops.Legion#LEGION - local status=self:GetLegionStatus(legion) - if not status==AUFTRAG.Status.CANCELLED then - -- At least one LEGION has not CANCELLED. - self:T2(self.lid..string.format("CheckGroupsDone: LEGION %s is not CANCELLED but in state %s. Mission NOT DONE!", legion.alias, status)) - return false - end - end - - -- Check commander status. - if self.commander then - if not self.statusCommander==AUFTRAG.Status.CANCELLED then - self:T2(self.lid..string.format("CheckGroupsDone: COMMANDER is not CANCELLED but in state %s. Mission NOT DONE!", self.statusCommander)) - return false - end - end - - -- Check chief status. - if self.chief then - if not self.statusChief==AUFTRAG.Status.CANCELLED then - self:T2(self.lid..string.format("CheckGroupsDone: CHIEF is not CANCELLED but in state %s. Mission NOT DONE!", self.statusChief)) - return false - end - end - - -- These are early stages, where we might not even have a opsgroup defined to be checked. If there were any groups, we checked above. - if self:IsPlanned() or self:IsQueued() or self:IsRequested() then - self:T2(self.lid..string.format("CheckGroupsDone: Mission is still in state %s [FSM=%s] (PLANNED or QUEUED or REQUESTED). Mission NOT DONE!", self.status, self:GetState())) - return false - end - - -- It could be that all flights were destroyed on the way to the mission execution waypoint. - -- TODO: would be better to check if everybody is dead by now. - if self:IsStarted() and self:CountOpsGroups()==0 then - self:T(self.lid..string.format("CheckGroupsDone: Mission is STARTED state %s [FSM=%s] but count of alive OPSGROUP is zero. Mission DONE!", self.status, self:GetState())) - return true - end - - return true -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- EVENT Functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- Unit lost event. --- @param #AUFTRAG self --- @param Core.Event#EVENTDATA EventData Event data. -function AUFTRAG:OnEventUnitLost(EventData) - - -- Check that this is the right group. - if EventData and EventData.IniGroup and EventData.IniUnit then - local unit=EventData.IniUnit - local group=EventData.IniGroup - local unitname=EventData.IniUnitName - - for _,_groupdata in pairs(self.groupdata) do - local groupdata=_groupdata --#AUFTRAG.GroupData - if groupdata and groupdata.opsgroup and groupdata.opsgroup.groupname==EventData.IniGroupName then - self:T(self.lid..string.format("UNIT LOST event for opsgroup %s unit %s", groupdata.opsgroup.groupname, EventData.IniUnitName)) - end - end - - end - -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- FSM Functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - - ---- On after "Planned" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterPlanned(From, Event, To) - self.status=AUFTRAG.Status.PLANNED - self:T(self.lid..string.format("New mission status=%s", self.status)) -end - ---- On after "Queue" event. Mission is added to the mission queue of a LEGION. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterQueued(From, Event, To, Airwing) - self.status=AUFTRAG.Status.QUEUED - self:T(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:T(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:T(self.lid..string.format("New mission status=%s", self.status)) -end - ---- On after "Schedule" event. Mission is added to the mission queue of an OPSGROUP. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterScheduled(From, Event, To) - self.status=AUFTRAG.Status.SCHEDULED - self:T(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.Tstarted=timer.getAbsTime() - self:T(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.Texecuting=timer.getAbsTime() - self:T(self.lid..string.format("New mission status=%s", self.status)) -end - ---- On after "ElementDestroyed" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. --- @param Ops.OpsGroup#OPSGROUP OpsGroup The ops group to which the element belongs. --- @param Ops.OpsGroup#OPSGROUP.Element Element The element that got destroyed. -function AUFTRAG:onafterElementDestroyed(From, Event, To, OpsGroup, Element) - -- Increase number of own casualties. - self.Ncasualties=self.Ncasualties+1 -end - ---- On after "GroupDead" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. --- @param Ops.OpsGroup#OPSGROUP OpsGroup The ops group that is dead now. -function AUFTRAG:onafterGroupDead(From, Event, To, OpsGroup) - - local asset=self:GetAssetByName(OpsGroup.groupname) - if asset then - self:AssetDead(asset) - end - - -- Number of dead groups. - self.Ndead=self.Ndead+1 - -end - ---- On after "AssetDead" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. --- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset. -function AUFTRAG:onafterAssetDead(From, Event, To, Asset) - - -- Number of groups alive. - local N=self:CountOpsGroups() - - self:T(self.lid..string.format("Asset %s dead! Number of ops groups remaining %d", tostring(Asset.spawngroupname), N)) - - -- All assets dead? - if N==0 then - - if self:IsNotOver() then - - -- Cancel mission. Wait for next mission update to evaluate SUCCESS or FAILURE. - self:Cancel() - - else - - --self:E(self.lid.."ERROR: All assets are dead not but mission was already over... Investigate!") - -- Now this can happen, because when a opsgroup dies (sometimes!), the mission is DONE - - end - end - - -- Delete asset from mission. - self:DelAsset(Asset) - -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) - - -- Number of OPSGROUPS assigned and alive. - local Ngroups = self:CountOpsGroups() - - -- Debug info. - self:T(self.lid..string.format("CANCELLING mission in status %s. Will wait for %d groups to report mission DONE before evaluation", self.status, Ngroups)) - - -- Time stamp. - self.Tover=timer.getAbsTime() - - -- No more repeats. - self.Nrepeat=self.repeated - self.NrepeatFailure=self.repeatedFailure - self.NrepeatSuccess=self.repeatedSuccess - - -- Not necessary to delay the evaluaton?! - self.dTevaluate=0 - - if self.chief then - - -- Debug info. - self:T(self.lid..string.format("CHIEF will cancel the mission. Will wait for mission DONE before evaluation!")) - - -- CHIEF will cancel the mission. - self.chief:MissionCancel(self) - - elseif self.commander then - - -- Debug info. - self:T(self.lid..string.format("COMMANDER will cancel the mission. Will wait for mission DONE before evaluation!")) - - -- COMMANDER will cancel the mission. - self.commander:MissionCancel(self) - - elseif self.legions and #self.legions>0 then - - -- Loop over all LEGIONs. - for _,_legion in pairs(self.legions or {}) do - local legion=_legion --Ops.Legion#LEGION - - -- Debug info. - self:T(self.lid..string.format("LEGION %s will cancel the mission. Will wait for mission DONE before evaluation!", legion.alias)) - - -- Legion will cancel all flight missions and remove queued request from warehouse queue. - legion:MissionCancel(self) - - end - - else - - -- Debug info. - self:T(self.lid..string.format("No legion, commander or chief. Attached groups will cancel the mission on their own. Will wait for mission DONE before evaluation!")) - - -- Loop over all groups. - for _,_groupdata in pairs(self.groupdata or {}) do - local groupdata=_groupdata --#AUFTRAG.GroupData - groupdata.opsgroup:MissionCancel(self) - end - - end - - -- Special mission states. - if self:IsPlanned() or self:IsQueued() or self:IsRequested() or Ngroups==0 then - self:T(self.lid..string.format("Cancelled mission was in %s stage with %d groups assigned and alive. Call it done!", self.status, Ngroups)) - self:Done() - end - -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:T(self.lid..string.format("New mission status=%s", self.status)) - - -- Set time stamp. - self.Tover=timer.getAbsTime() - - -- Not executing any more. - self.Texecuting=nil - - -- 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. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterSuccess(From, Event, To) - - self.status=AUFTRAG.Status.SUCCESS - self:T(self.lid..string.format("New mission status=%s", self.status)) - - -- Set status for CHIEF, COMMANDER and LEGIONs - self.statusChief=self.status - self.statusCommander=self.status - for _,_legion in pairs(self.legions) do - local Legion=_legion --Ops.Legion#LEGION - self:SetLegionStatus(Legion, self.status) - end - - local repeatme=self.repeatedSuccess Repeat mission!", self.repeated+1, N)) - self:Repeat() - - else - - -- Stop mission. - self:T(self.lid..string.format("Mission SUCCESS! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1)) - self:Stop() - - end - -end - ---- On after "Failed" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterFailed(From, Event, To) - - self.status=AUFTRAG.Status.FAILED - self:T(self.lid..string.format("New mission status=%s", self.status)) - - -- Set status for CHIEF, COMMANDER and LEGIONs - self.statusChief=self.status - self.statusCommander=self.status - for _,_legion in pairs(self.legions) do - local Legion=_legion --Ops.Legion#LEGION - self:SetLegionStatus(Legion, self.status) - end - - local repeatme=self.repeatedFailure Repeat mission!", self.repeated+1, N)) - self:Repeat() - - else - - -- Stop mission. - self:T(self.lid..string.format("Mission FAILED! Number of max repeats %d reached ==> Stopping mission!", self.repeated+1)) - self:Stop() - - end - -end - ---- On before "Repeat" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onbeforeRepeat(From, Event, To) - - if not (self.chief or self.commander or #self.legions>0) then - self:E(self.lid.."ERROR: Mission can only be repeated by a CHIEF, COMMANDER or LEGION! Stopping AUFTRAG") - self:Stop() - return false - end - - return true -end - ---- On after "Repeat" event. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterRepeat(From, Event, To) - - -- Set mission status to PLANNED. - self.status=AUFTRAG.Status.PLANNED - - -- Debug info. - self:T(self.lid..string.format("New mission status=%s (on Repeat)", self.status)) - - -- Set status for CHIEF, COMMANDER and LEGIONs - self.statusChief=self.status - self.statusCommander=self.status - for _,_legion in pairs(self.legions) do - local Legion=_legion --Ops.Legion#LEGION - self:SetLegionStatus(Legion, self.status) - end - - -- Increase repeat counter. - self.repeated=self.repeated+1 - - if self.chief then - - -- Set status for chief. - self.statusChief=AUFTRAG.Status.PLANNED - - -- Remove mission from wingcommander because Chief will assign it again. - if self.commander then - self.statusCommander=AUFTRAG.Status.PLANNED - end - - -- Remove mission from legions because commander will assign it again but maybe to different legion(s). - for _,_legion in pairs(self.legions) do - local legion=_legion --Ops.Legion#LEGION - legion:RemoveMission(self) - end - - elseif self.commander then - - -- Set status for commander. - self.statusCommander=AUFTRAG.Status.PLANNED - - -- Remove mission from legion(s) because commander will assign it again but maybe to different legion(s). - for _,_legion in pairs(self.legions) do - local legion=_legion --Ops.Legion#LEGION - legion:RemoveMission(self) - self:SetLegionStatus(legion, AUFTRAG.Status.PLANNED) - end - - elseif #self.legions>0 then - - -- Remove mission from airwing because WC will assign it again but maybe to a different wing. - for _,_legion in pairs(self.legions) do - local legion=_legion --Ops.Legion#LEGION - legion:RemoveMission(self) - self:SetLegionStatus(legion, AUFTRAG.Status.PLANNED) - legion:AddMission(self) - end - - else - self:E(self.lid.."ERROR: Mission can only be repeated by a CHIEF, COMMANDER or LEGION! Stopping AUFTRAG") - self:Stop() - return - end - - - -- No mission assets. - self.assets={} - - - -- Remove OPS groups. This also removes the mission from the OPSGROUP mission queue. - for groupname,_groupdata in pairs(self.groupdata) do - local groupdata=_groupdata --#AUFTRAG.GroupData - local opsgroup=groupdata.opsgroup - if opsgroup then - self:DelOpsGroup(opsgroup) - end - - end - -- No flight data. - self.groupdata={} - - -- Reset casualties and units assigned. - self.Ncasualties=0 - self.Nelements=0 - self.Ngroups=0 - self.Nassigned=nil - self.Ndead=0 - - -- Update DCS mission task. Could be that the initial task (e.g. for bombing) was destroyed. Then we need to update the coordinate. - self.DCStask=self:GetDCSMissionTask() - - -- Call status again. - self:__Status(-30) - -end - ---- On after "Stop" event. Remove mission from AIRWING and FLIGHTGROUP mission queues. --- @param #AUFTRAG self --- @param #string From From state. --- @param #string Event Event. --- @param #string To To state. -function AUFTRAG:onafterStop(From, Event, To) - - -- Debug info. - self:T(self.lid..string.format("STOPPED mission in status=%s. Removing missions from queues. Stopping CallScheduler!", self.status)) - - -- TODO: Mission should be OVER! we dont want to remove running missions from any queues. - - -- Remove mission from CHIEF queue. - if self.chief then - self.chief:RemoveMission(self) - end - - -- Remove mission from WINGCOMMANDER queue. - if self.commander then - self.commander:RemoveMission(self) - end - - -- Remove mission from LEGION queues. - if #self.legions>0 then - for _,_legion in pairs(self.legions) do - local legion=_legion --Ops.Legion#LEGION - legion:RemoveMission(self) - end - end - - -- Remove mission from OPSGROUP queue - for _,_groupdata in pairs(self.groupdata) do - local groupdata=_groupdata --#AUFTRAG.GroupData - groupdata.opsgroup:RemoveMission(self) - end - - -- No mission assets. - self.assets={} - - -- No flight data. - self.groupdata={} - - -- Clear pending scheduler calls. - self.CallScheduler:Clear() - -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Target Functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- Create target data from a given object. --- @param #AUFTRAG self --- @param Wrapper.Positionable#POSITIONABLE Object The target GROUP, UNIT, STATIC. -function AUFTRAG:_TargetFromObject(Object) - - if not self.engageTarget then - - if Object and Object:IsInstanceOf("TARGET") then - - self.engageTarget=Object - - else --if Object then - - self.engageTarget=TARGET:New(Object) - - end - - else - - -- Target was already specified elsewhere. - - end - - -- Debug info. - --self:T2(self.lid..string.format("Mission Target %s Type=%s, Ntargets=%d, Lifepoints=%d", self.engageTarget.lid, self.engageTarget.lid, self.engageTarget.N0, self.engageTarget:GetLife())) - - return self -end - - ---- Count alive mission targets. --- @param #AUFTRAG self --- @return #number Number of alive target units. -function AUFTRAG:CountMissionTargets() - - local N=0 - - if self.engageTarget then - N=self.engageTarget:CountTargets() - end - - return N -end - ---- Get initial number of targets. --- @param #AUFTRAG self --- @return #number Number of initial life points when mission was planned. -function AUFTRAG:GetTargetInitialNumber() - local target=self:GetTargetData() - if target then - return target.N0 - else - return 0 - end -end - - ---- Get target life points. --- @param #AUFTRAG self --- @return #number Number of initial life points when mission was planned. -function AUFTRAG:GetTargetInitialLife() - local target=self:GetTargetData() - if target then - return target.life0 - else - return 0 - end -end - ---- Get target damage. --- @param #AUFTRAG self --- @return #number Damage in percent. -function AUFTRAG:GetTargetDamage() - local target=self:GetTargetData() - if target then - return target:GetDamage() - else - return 0 - end -end - - ---- Get target life points. --- @param #AUFTRAG self --- @return #number Life points of target. -function AUFTRAG:GetTargetLife() - local target=self:GetTargetData() - if target then - return target:GetLife() - else - return 0 - end -end - ---- Get target. --- @param #AUFTRAG self --- @return Ops.Target#TARGET The target object. Could be many things. -function AUFTRAG:GetTargetData() - return self.engageTarget -end - ---- Get mission objective object. Could be many things depending on the mission type. --- @param #AUFTRAG self --- @return Wrapper.Positionable#POSITIONABLE The target object. Could be many things. -function AUFTRAG:GetObjective() - local objective=self:GetTargetData():GetObject() - return objective -end - ---- Get type of target. --- @param #AUFTRAG self --- @return #string The target type. -function AUFTRAG:GetTargetType() - local target=self.engageTarget - if target then - local to=target:GetObjective() - if to then - return to.Type - else - return "Unknown" - end - else - return "Unknown" - end -end - ---- Get 2D vector of target. --- @param #AUFTRAG self --- @return DCS#VEC2 The target 2D vector or *nil*. -function AUFTRAG:GetTargetVec2() - local coord=self:GetTargetCoordinate() - if coord then - local vec2=coord:GetVec2() - return vec2 - end - return nil -end - ---- Get coordinate of target. --- @param #AUFTRAG self --- @return Core.Point#COORDINATE The target coordinate or *nil*. -function AUFTRAG:GetTargetCoordinate() - - if self.transportPickup then - - -- Special case where we defined a - return self.transportPickup - - elseif self.engageTarget then - - local coord=self.engageTarget:GetCoordinate() - return coord - - elseif self.type==AUFTRAG.Type.ALERT5 then - - -- For example, COMMANDER will not assign a coordiante. This will be done later, when the mission is assigned to an airwing. - return nil - - else - self:T(self.lid.."ERROR: Cannot get target coordinate!") - end - - return nil -end - ---- Get heading of target. --- @param #AUFTRAG self --- @return #number Heading of target in degrees. -function AUFTRAG:GetTargetHeading() - if self.engageTarget then - local heading=self.engageTarget:GetHeading() - return heading - end - return nil -end - ---- Get name of the target. --- @param #AUFTRAG self --- @return #string Name of the target or "N/A". -function AUFTRAG:GetTargetName() - - if self.engageTarget then - local name=self.engageTarget:GetName() - return name - end - - return "N/A" -end - - ---- Get distance to target. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE FromCoord The coordinate from which the distance is measured. --- @return #number Distance in meters or 0. -function AUFTRAG:GetTargetDistance(FromCoord) - - local TargetCoord=self:GetTargetCoordinate() - - if TargetCoord and FromCoord then - return TargetCoord:Get2DDistance(FromCoord) - else - self:T(self.lid.."ERROR: TargetCoord or FromCoord does not exist in AUFTRAG:GetTargetDistance() function! Returning 0") - end - - return 0 -end - - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Misc Functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- Add asset to mission. --- @param #AUFTRAG self --- @param Functional.Warehouse#WAREHOUSE.Assetitem Asset The asset to be added to the mission. --- @return #AUFTRAG self -function AUFTRAG:AddAsset(Asset) - - -- Debug info - self:T(self.lid..string.format("Adding asset \"%s\" to mission", tostring(Asset.spawngroupname))) - - -- Add to table. - self.assets=self.assets or {} - - -- Add to table. - table.insert(self.assets, Asset) - - self.Nassigned=self.Nassigned or 0 - - self.Nassigned=self.Nassigned+1 - - return self -end - ---- Add assets 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. --- @return #AUFTRAG self -function AUFTRAG:DelAsset(Asset) - - for i,_asset in pairs(self.assets or {}) do - local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem - - if asset.uid==Asset.uid then - self:T(self.lid..string.format("Removing asset \"%s\" from mission", tostring(Asset.spawngroupname))) - table.remove(self.assets, i) - return self - end - - end - - return self -end - ---- Get asset by its spawn group name. --- @param #AUFTRAG self --- @param #string Name Asset spawn group name. --- @return Functional.Warehouse#WAREHOUSE.Assetitem Asset. -function AUFTRAG:GetAssetByName(Name) - - for i,_asset in pairs(self.assets or {}) do - local asset=_asset --Functional.Warehouse#WAREHOUSE.Assetitem - - if asset.spawngroupname==Name then - return asset - end - - end - - return nil -end - ---- Count alive OPS groups assigned for this mission. --- @param #AUFTRAG self --- @return #number Number of alive OPS groups. -function AUFTRAG:CountOpsGroups() - local N=0 - for _,_groupdata in pairs(self.groupdata) do - local groupdata=_groupdata --#AUFTRAG.GroupData - if groupdata and groupdata.opsgroup and groupdata.opsgroup:IsAlive() and not groupdata.opsgroup:IsDead() then - N=N+1 - end - end - return N -end - ---- Count OPS groups in a certain status. --- @param #AUFTRAG self --- @param #string Status Status of group, e.g. `AUFTRAG.GroupStatus.EXECUTING`. --- @return #number Number of alive OPS groups. -function AUFTRAG:CountOpsGroupsInStatus(Status) - local N=0 - for _,_groupdata in pairs(self.groupdata) do - local groupdata=_groupdata --#AUFTRAG.GroupData - if groupdata and groupdata.status==Status then - N=N+1 - end - end - return N -end - - - ---- Get coordinate of target. First unit/group of the set is used. --- @param #AUFTRAG self --- @param #table MissionTypes A table of mission types. --- @return #string Comma separated list of mission types. -function AUFTRAG:GetMissionTypesText(MissionTypes) - - local text="" - for _,missiontype in pairs(MissionTypes) do - text=text..string.format("%s, ", missiontype) - end - - return text -end - ---- 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 -function AUFTRAG:SetMissionWaypointCoord(Coordinate) - - -- Obviously a zone was passed. We get the coordinate. - if Coordinate:IsInstanceOf("ZONE_BASE") then - Coordinate=Coordinate:GetCoordinate() - end - - self.missionWaypointCoord=Coordinate - return self -end - ---- Set randomization of the mission waypoint coordinate. Each assigned group will get a random ingress coordinate, where the mission is executed. --- @param #AUFTRAG self --- @param #number Radius Distance in meters. Default `#nil`. --- @return #AUFTRAG self -function AUFTRAG:SetMissionWaypointRandomization(Radius) - self.missionWaypointRadius=Radius - return self -end - ---- Set the mission egress coordinate. This is the coordinate where the assigned group will go once the mission is finished. --- @param #AUFTRAG self --- @param Core.Point#COORDINATE Coordinate Egrees coordinate. --- @param #number Altitude (Optional) Altitude in feet. Default is y component of coordinate. --- @return #AUFTRAG self -function AUFTRAG:SetMissionEgressCoord(Coordinate, Altitude) - - -- Obviously a zone was passed. We get the coordinate. - if Coordinate:IsInstanceOf("ZONE_BASE") then - Coordinate=Coordinate:GetCoordinate() - end - - self.missionEgressCoord=Coordinate - - if Altitude then - self.missionEgressCoord.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. -function AUFTRAG:GetMissionEgressCoord() - return self.missionEgressCoord -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`. -function AUFTRAG:_GetMissionWaypointCoordSet() - - -- Check if a coord has been explicitly set. - if self.missionWaypointCoord then - local coord=self.missionWaypointCoord - if self.missionAltitude then - coord.y=self.missionAltitude - end - - - return coord - end - -end - ---- Get coordinate of target. First unit/group of the set is used. --- @param #AUFTRAG self --- @param Wrapper.Group#GROUP group Group. --- @param #number randomradius Random radius in meters. --- @param #table surfacetypes Surface types of random zone. --- @return Core.Point#COORDINATE Coordinate where the mission is executed. -function AUFTRAG:GetMissionWaypointCoord(group, randomradius, surfacetypes) - - -- Check if a coord has been explicitly set. - if self.missionWaypointCoord then - local coord=self.missionWaypointCoord - if self.missionAltitude then - coord.y=self.missionAltitude - end - return coord - end - - -- Create waypoint coordinate half way between us and the target. - local waypointcoord=group:GetCoordinate():GetIntermediateCoordinate(self:GetTargetCoordinate(), self.missionFraction) - local alt=waypointcoord.y - - -- Add some randomization. - if randomradius then - waypointcoord=ZONE_RADIUS:New("Temp", waypointcoord:GetVec2(), randomradius):GetRandomCoordinate(nil, nil, surfacetypes):SetAltitude(alt, false) - end - - -- Set altitude of mission waypoint. - if self.missionAltitude then - waypointcoord:SetAltitude(self.missionAltitude, true) - end - - return waypointcoord -end - - ---- Set log ID string. --- @param #AUFTRAG self --- @return #AUFTRAG self -function AUFTRAG:_SetLogID() - self.lid=string.format("Auftrag #%d %s | ", self.auftragsnummer, tostring(self.type)) - return self -end - - ---- Update DCS task. --- @param #AUFTRAG self --- @return #AUFTRAG self -function AUFTRAG:_UpdateTask() - - - - return self -end - ---- Update mission F10 map marker. --- @param #AUFTRAG self --- @return #AUFTRAG self -function AUFTRAG:UpdateMarker() - - -- Marker text. - local text=string.format("%s %s: %s", self.name, self.type:upper(), self.status:upper()) - text=text..string.format("\n%s", self:GetTargetName()) - text=text..string.format("\nTargets %d/%d, Life Points=%d/%d", self:CountMissionTargets(), self:GetTargetInitialNumber(), self:GetTargetLife(), self:GetTargetInitialLife()) - text=text..string.format("\nOpsGroups %d/%d", self:CountOpsGroups(), self:GetNumberOfRequiredAssets()) - - if not self.marker then - - -- Get target coordinates. Can be nil! - local targetcoord=self:GetTargetCoordinate() - - if self.markerCoaliton and self.markerCoaliton>=0 then - self.marker=MARKER:New(targetcoord, text):ReadOnly():ToCoalition(self.markerCoaliton) - else - self.marker=MARKER:New(targetcoord, text):ReadOnly():ToAll() - end - - else - - if self.marker:GetText()~=text then - self.marker:UpdateText(text) - end - - end - - return self -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 -- - ---------------------- - - -- Add enroute anti-ship task. - local DCStask=CONTROLLABLE.EnRouteTaskAntiShip(nil) - table.insert(self.enrouteTasks, DCStask) - - self:_GetDCSAttackTask(self.engageTarget, DCStasks) - - elseif self.type==AUFTRAG.Type.AWACS then - - ------------------- - -- AWACS Mission -- - ------------------- - - local DCStask=CONTROLLABLE.EnRouteTaskAWACS(nil) - - table.insert(self.enrouteTasks, DCStask) - - elseif self.type==AUFTRAG.Type.BAI then - - ----------------- - -- BAI Mission -- - ----------------- - - self:_GetDCSAttackTask(self.engageTarget, DCStasks) - - elseif self.type==AUFTRAG.Type.BOMBING then - - --------------------- - -- BOMBING Mission -- - --------------------- - - local DCStask=CONTROLLABLE.TaskBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, Divebomb) - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.BOMBRUNWAY then - - ------------------------ - -- BOMBRUNWAY Mission -- - ------------------------ - - local DCStask=CONTROLLABLE.TaskBombingRunway(nil, self.engageTarget:GetObject(), self.engageWeaponType, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAsGroup) - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.BOMBCARPET then - - ------------------------ - -- BOMBCARPET Mission -- - ------------------------ - - local DCStask=CONTROLLABLE.TaskCarpetBombing(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType, self.engageCarpetLength) - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.CAP then - - ----------------- - -- CAP Mission -- - ----------------- - - local DCStask=CONTROLLABLE.EnRouteTaskEngageTargetsInZone(nil, self.engageZone:GetVec2(), self.engageZone:GetRadius(), self.engageTargetTypes, Priority) - - table.insert(self.enrouteTasks, DCStask) - - elseif self.type==AUFTRAG.Type.CAS then - - ----------------- - -- CAS Mission -- - ----------------- - - local DCStask=CONTROLLABLE.EnRouteTaskEngageTargetsInZone(nil, self.engageZone:GetVec2(), self.engageZone:GetRadius(), self.engageTargetTypes, Priority) - - table.insert(self.enrouteTasks, DCStask) - - elseif self.type==AUFTRAG.Type.ESCORT then - - -------------------- - -- ESCORT Mission -- - -------------------- - - local DCStask=CONTROLLABLE.TaskEscort(nil, self.engageTarget:GetObject(), 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.engageTarget:GetObject(), self.engageWeaponType, self.facDesignation, self.facDatalink, self.facFreq, self.facModu, CallsignName, CallsignNumber) - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.FERRY then - - ------------------- - -- FERRY Mission -- - ------------------- - - 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 - - ----------------------- - -- INTERCEPT Mission -- - ----------------------- - - self:_GetDCSAttackTask(self.engageTarget, DCStasks) - - 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.GCICAP then - - -------------------- - -- GCICAP Mission -- - -------------------- - - -- Done below as also other mission types use the orbit task. - - elseif self.type==AUFTRAG.Type.RECON then - - ------------------- - -- RECON Mission -- - ------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.RECON - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.target=self.engageTarget - param.altitude=self.missionAltitude - param.speed=self.missionSpeed - param.lastindex=nil - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.SEAD then - - ------------------ - -- SEAD Mission -- - ------------------ - - --[[ - local DCStask=CONTROLLABLE.EnRouteTaskEngageTargets(nil, nil ,{"Air Defence"} , 0) - table.insert(self.enrouteTasks, DCStask) - DCStask.key="SEAD" - ]] - - self:_GetDCSAttackTask(self.engageTarget, DCStasks) - - elseif self.type==AUFTRAG.Type.STRIKE then - - -------------------- - -- STRIKE Mission -- - -------------------- - - local DCStask=CONTROLLABLE.TaskAttackMapObject(nil, self:GetTargetVec2(), self.engageAsGroup, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType) - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.TANKER or self.type==AUFTRAG.Type.RECOVERYTANKER then - - -------------------- - -- TANKER Mission -- - -------------------- - - local DCStask=CONTROLLABLE.EnRouteTaskTanker(nil) - - table.insert(self.enrouteTasks, DCStask) - - elseif self.type==AUFTRAG.Type.TROOPTRANSPORT then - - ---------------------------- - -- TROOPTRANSPORT Mission -- - ---------------------------- - - -- Task to embark the troops at the pick up point. - local TaskEmbark=CONTROLLABLE.TaskEmbarking(TaskControllable, self.transportPickup, self.transportGroupSet, self.transportWaitForCargo) - - -- Task to disembark the troops at the drop off point. - local TaskDisEmbark=CONTROLLABLE.TaskDisembarking(TaskControllable, self.transportDropoff, self.transportGroupSet) - - table.insert(DCStasks, TaskEmbark) - table.insert(DCStasks, TaskDisEmbark) - - elseif self.type==AUFTRAG.Type.OPSTRANSPORT then - - -------------------------- - -- OPSTRANSPORT Mission -- - -------------------------- - - local DCStask={} - - DCStask.id="OpsTransport" - - -- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP. - local param={} - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.CARGOTRANSPORT then - - ---------------------------- - -- CARGOTRANSPORT Mission -- - ---------------------------- - - -- Task to transport cargo. - local TaskCargoTransportation={ - id = "CargoTransportation", - params = {} - } - - table.insert(DCStasks, TaskCargoTransportation) - - elseif self.type==AUFTRAG.Type.RESCUEHELO then - - ------------------------- - -- RESCUE HELO Mission -- - ------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.FORMATION - - -- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP. - local param={} - param.unitname=self:GetTargetName() - param.offsetX=200 - param.offsetZ=240 - param.altitude=70 - param.dtFollow=1.0 - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.ARTY then - - ------------------ - -- ARTY Mission -- - ------------------ - - - if self.artyShots==1 or self.artyRadius<10 or true then - - local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, self:GetTargetVec2(), self.artyRadius, self.artyShots, self.engageWeaponType, self.artyAltitude) - table.insert(DCStasks, DCStask) - - else - - local Vec2=self:GetTargetVec2() - - local zone=ZONE_RADIUS:New("temp", Vec2, self.artyRadius) - - for i=1,self.artyShots do - - local vec2=zone:GetRandomVec2() - - local DCStask=CONTROLLABLE.TaskFireAtPoint(nil, vec2, 0, 1, self.engageWeaponType, self.artyAltitude) - table.insert(DCStasks, DCStask) - - end - - end - - elseif self.type==AUFTRAG.Type.BARRAGE then - - --------------------- - -- BARRAGE Mission -- - --------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.BARRAGE - - -- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP. - local param={} - param.zone=self:GetObjective() - param.altitude=self.artyAltitude - param.radius=self.artyRadius - param.heading=self.artyHeading - param.angle=self.artyAngle - param.shots=self.artyShots - param.weaponTypoe=self.engageWeaponType - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.PATROLZONE then - - ------------------------- - -- PATROL ZONE Mission -- - ------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.PATROLZONE - - -- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP. - local param={} - param.zone=self:GetObjective() - param.altitude=self.missionAltitude - param.speed=self.missionSpeed - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.CASENHANCED then - - ------------------------- - -- CAS ENHANCED Mission -- - ------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.PATROLZONE - - -- We create a "fake" DCS task and pass the parameters to the FLIGHTGROUP. - local param={} - param.zone=self:GetObjective() - param.altitude=self.missionAltitude - param.speed=self.missionSpeed - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.GROUNDATTACK then - - --------------------------- - -- GROUND ATTACK Mission -- - --------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.GROUNDATTACK - - -- We create a "fake" DCS task and pass the parameters to the ARMYGROUP. - local param={} - param.target=self:GetTargetData() - param.action="Wedge" - param.speed=self.missionSpeed - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.AMMOSUPPLY then - - ------------------------- - -- AMMO SUPPLY Mission -- - ------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.AMMOSUPPLY - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.zone=self:GetObjective() - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.FUELSUPPLY then - - ------------------------- - -- FUEL SUPPLY Mission -- - ------------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.FUELSUPPLY - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.zone=self:GetObjective() - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.AMMOSUPPLY then - - ---------------------- - -- REARMING Mission -- - ---------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.REARMING - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.zone=self:GetObjective() - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.ALERT5 then - - --------------------- - -- ALERT 5 Mission -- - --------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.ALERT5 - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.NOTHING then - - --------------------- - -- NOTHING Mission -- - --------------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.NOTHING - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.HOVER then - - --------------------- - -- HOVER Mission -- - --------------------- - - local DCStask={} - DCStask.id=AUFTRAG.SpecialTask.HOVER - - local param={} - - param.hoverAltitude=self.hoverAltitude - param.hoverTime = self.hoverTime - param.missionSpeed = self.missionSpeed - param.missionAltitude = self.missionAltitude - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.ONGUARD or self.type==AUFTRAG.Type.ARMOREDGUARD then - - ---------------------- - -- ON GUARD Mission -- - ---------------------- - - local DCStask={} - - DCStask.id= self.type==AUFTRAG.Type.ONGUARD and AUFTRAG.SpecialTask.ONGUARD or AUFTRAG.SpecialTask.ARMOREDGUARD - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.coordinate=self:GetObjective() - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.AIRDEFENSE then - - ------------------------ - -- AIRDEFENSE Mission -- - ------------------------ - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.AIRDEFENSE - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.zone=self:GetObjective() - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - elseif self.type==AUFTRAG.Type.EWR then - - ----------------- - -- EWR Mission -- - ----------------- - - local DCStask={} - - DCStask.id=AUFTRAG.SpecialTask.EWR - - -- We create a "fake" DCS task and pass the parameters to the OPSGROUP. - local param={} - param.zone=self:GetObjective() - - DCStask.params=param - - table.insert(DCStasks, DCStask) - - -- EWR is an enroute task - local Enroutetask=CONTROLLABLE.EnRouteTaskEWR() - table.insert(self.enrouteTasks, Enroutetask) - - else - self:T(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.GCICAP or - self.type==AUFTRAG.Type.AWACS or - self.type==AUFTRAG.Type.TANKER or - self.type==AUFTRAG.Type.RECOVERYTANKER then - - ------------------- - -- ORBIT Mission -- - ------------------- - - -- Get/update orbit vector. - self.orbitVec2=self:GetTargetVec2() - - if self.orbitVec2 then - - -- Heading of the target. - self.targetHeading=self:GetTargetHeading() - - local OffsetVec2=nil --DCS#Vec2 - if (self.orbitOffsetVec2~=nil) then - OffsetVec2=UTILS.DeepCopy(self.orbitOffsetVec2) - end - - if OffsetVec2 then - - if self.orbitOffsetVec2.r then - -- Polar coordinates - local r=self.orbitOffsetVec2.r - local phi=(self.orbitOffsetVec2.phi or 0) + self.targetHeading - - OffsetVec2.x=r*math.cos(math.rad(phi)) - OffsetVec2.y=r*math.sin(math.rad(phi)) - else - -- Cartesian coordinates - OffsetVec2.x=self.orbitOffsetVec2.x - OffsetVec2.y=self.orbitOffsetVec2.y - end - - end - - -- Actual orbit position with possible offset. - local orbitVec2=OffsetVec2 and UTILS.Vec2Add(self.orbitVec2, OffsetVec2) or self.orbitVec2 - - -- Check for race-track pattern. - local orbitRaceTrack=nil --DCS#Vec2 - if self.orbitLeg then - - -- Default heading is due North. - local heading=0 - - -- Check if specific heading was specified. - if self.orbitHeading then - - -- Is heading realtive to target? - if self.orbitHeadingRel then - -- Relative heading wrt target. - heading=self.targetHeading+self.orbitHeading - else - -- Take given heading. - heading=self.orbitHeading - end - - else - -- Not specific heading specified ==> Take heading of target. - heading=self.targetHeading or 0 - end - - -- Race-track vector. - orbitRaceTrack=UTILS.Vec2Translate(orbitVec2, self.orbitLeg, heading) - end - - local orbitRaceTrackCoord = nil - if orbitRaceTrack then - orbitRaceTrackCoord = COORDINATE:NewFromVec2(orbitRaceTrack) - end - - -- Create orbit task. - local DCStask=CONTROLLABLE.TaskOrbit(nil, COORDINATE:NewFromVec2(orbitVec2), self.orbitAltitude, self.orbitSpeed, orbitRaceTrackCoord) - - -- Add DCS task. - table.insert(DCStasks, DCStask) - - end - - end - - -- Debug info. - self:T3({missiontask=DCStasks}) - - -- Return the task. - if #DCStasks==1 then - return DCStasks[1] - else - return CONTROLLABLE.TaskCombo(nil, DCStasks) - end - -end - ---- Get DCS task table for an attack group or unit task. --- @param #AUFTRAG self --- @param Ops.Target#TARGET Target Target data. --- @param #table DCStasks DCS DCS tasks table to which the task is added. --- @return DCS#Task The DCS task table. -function AUFTRAG:_GetDCSAttackTask(Target, DCStasks) - - DCStasks=DCStasks or {} - - for _,_target in pairs(Target.targets) do - local target=_target --Ops.Target#TARGET.Object - - if target.Type==TARGET.ObjectType.GROUP then - - local DCStask=CONTROLLABLE.TaskAttackGroup(nil, target.Object, self.engageWeaponType, self.engageWeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageAsGroup) - - table.insert(DCStasks, DCStask) - - elseif target.Type==TARGET.ObjectType.UNIT or target.Type==TARGET.ObjectType.STATIC then - - local DCStask=CONTROLLABLE.TaskAttackUnit(nil, target.Object, self.engageAsGroup, self.WeaponExpend, self.engageQuantity, self.engageDirection, self.engageAltitude, self.engageWeaponType) - - table.insert(DCStasks, DCStask) - - end - - end - - return DCStasks -end - ---- Get DCS task table for an attack group or unit task. --- @param #AUFTRAG self --- @param #string MissionType Mission (AUFTAG) type. --- @return #string DCS mission task for the auftrag type. -function AUFTRAG:GetMissionTaskforMissionType(MissionType) - - local mtask=ENUMS.MissionTask.NOTHING - - if MissionType==AUFTRAG.Type.ANTISHIP then - mtask=ENUMS.MissionTask.ANTISHIPSTRIKE - elseif MissionType==AUFTRAG.Type.AWACS then - mtask=ENUMS.MissionTask.AWACS - elseif MissionType==AUFTRAG.Type.BAI then - mtask=ENUMS.MissionTask.GROUNDATTACK - elseif MissionType==AUFTRAG.Type.BOMBCARPET then - mtask=ENUMS.MissionTask.GROUNDATTACK - elseif MissionType==AUFTRAG.Type.BOMBING then - mtask=ENUMS.MissionTask.GROUNDATTACK - elseif MissionType==AUFTRAG.Type.BOMBRUNWAY then - mtask=ENUMS.MissionTask.RUNWAYATTACK - elseif MissionType==AUFTRAG.Type.CAP then - mtask=ENUMS.MissionTask.CAP - elseif MissionType==AUFTRAG.Type.GCICAP then - mtask=ENUMS.MissionTask.CAP - elseif MissionType==AUFTRAG.Type.CAS then - mtask=ENUMS.MissionTask.CAS - elseif MissionType==AUFTRAG.Type.PATROLZONE then - mtask=ENUMS.MissionTask.CAS - elseif MissionType==AUFTRAG.Type.CASENHANCED then - mtask=ENUMS.MissionTask.CAS - elseif MissionType==AUFTRAG.Type.ESCORT then - mtask=ENUMS.MissionTask.ESCORT - elseif MissionType==AUFTRAG.Type.FACA then - mtask=ENUMS.MissionTask.AFAC - elseif MissionType==AUFTRAG.Type.FERRY then - mtask=ENUMS.MissionTask.NOTHING - elseif MissionType==AUFTRAG.Type.INTERCEPT then - mtask=ENUMS.MissionTask.INTERCEPT - elseif MissionType==AUFTRAG.Type.RECON then - mtask=ENUMS.MissionTask.RECONNAISSANCE - elseif MissionType==AUFTRAG.Type.SEAD then - mtask=ENUMS.MissionTask.SEAD - elseif MissionType==AUFTRAG.Type.STRIKE then - mtask=ENUMS.MissionTask.GROUNDATTACK - elseif MissionType==AUFTRAG.Type.TANKER then - mtask=ENUMS.MissionTask.REFUELING - elseif MissionType==AUFTRAG.Type.TROOPTRANSPORT then - mtask=ENUMS.MissionTask.TRANSPORT - elseif MissionType==AUFTRAG.Type.CARGOTRANSPORT then - mtask=ENUMS.MissionTask.TRANSPORT - elseif MissionType==AUFTRAG.Type.ARMORATTACK then - mtask=ENUMS.MissionTask.NOTHING - elseif MissionType==AUFTRAG.Type.HOVER then - mtask=ENUMS.MissionTask.NOTHING - end - - return mtask -end - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --- Global Functions -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - ---- Checks if a mission type is contained in a table of possible types. --- @param #string MissionType The requested mission type. --- @param #table PossibleTypes A table with possible mission types. --- @return #boolean If true, the requested mission type is part of the possible mission types. -function AUFTRAG.CheckMissionType(MissionType, PossibleTypes) - - if type(PossibleTypes)=="string" then - PossibleTypes={PossibleTypes} - end - - for _,canmission in pairs(PossibleTypes) do - if canmission==MissionType then - return true - end - end - - return false -end - ---- Check if a mission type is contained in a list of possible capabilities. --- @param #table MissionTypes The requested mission type. Can also be passed as a single mission type `#string`. --- @param #table Capabilities A table with possible capabilities `Ops.Auftrag#AUFTRAG.Capability`. --- @param #boolean All If `true`, given mission type must be includedin ALL capabilities. If `false` or `nil`, it must only match one. --- @return #boolean If true, the requested mission type is part of the possible mission types. -function AUFTRAG.CheckMissionCapability(MissionTypes, Capabilities, All) - - -- Ensure table. - if type(MissionTypes)~="table" then - MissionTypes={MissionTypes} - end - - for _,cap in pairs(Capabilities) do - local capability=cap --Ops.Auftrag#AUFTRAG.Capability - for _,MissionType in pairs(MissionTypes) do - if All==true then - if capability.MissionType~=MissionType then - return false - end - else - if capability.MissionType==MissionType then - return true - end - end - end - end - - if All==true then - return true - else - return false - end -end - - ---- Check if a mission type is contained in a list of possible capabilities. --- @param #table MissionTypes The requested mission type. Can also be passed as a single mission type `#string`. --- @param #table Capabilities A table with possible capabilities `Ops.Auftrag#AUFTRAG.Capability`. --- @return #boolean If true, the requested mission type is part of the possible mission types. -function AUFTRAG.CheckMissionCapabilityAny(MissionTypes, Capabilities) - - local res=AUFTRAG.CheckMissionCapability(MissionTypes, Capabilities, false) - - return res -end - - ---- Check if a mission type is contained in a list of possible capabilities. --- @param #table MissionTypes The requested mission type. Can also be passed as a single mission type `#string`. --- @param #table Capabilities A table with possible capabilities `Ops.Auftrag#AUFTRAG.Capability`. --- @return #boolean If true, the requested mission type is part of the possible mission types. -function AUFTRAG.CheckMissionCapabilityAll(MissionTypes, Capabilities) - - local res=AUFTRAG.CheckMissionCapability(MissionTypes, Capabilities, true) - - return res -end - - - -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -- -- ### Author: **funkyfranky** -- @@ -6348,6 +66,8 @@ end -- @field #table conditionSuccess If all conditions are true, the mission is cancelled. -- @field #table conditionFailure If all conditions are true, the mission is cancelled. -- @field #table conditionPush If all conditions are true, the mission is executed. Before, the group(s) wait at the mission execution waypoint. +-- @field #boolean conditionSuccessSet +-- @field #boolean conditionFailureSet -- -- @field #number orbitSpeed Orbit speed in m/s. -- @field #number orbitAltitude Orbit altitude in meters. @@ -6660,6 +380,8 @@ AUFTRAG = { conditionSuccess = {}, conditionFailure = {}, conditionPush = {}, + conditionSuccessSet = false, + conditionFailureSet = false, } --- Global mission counter. @@ -6917,7 +639,7 @@ AUFTRAG.Category={ --- AUFTRAG class version. -- @field #string version -AUFTRAG.version="0.9.9" +AUFTRAG.version="0.9.10" ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -- TODO list @@ -7732,10 +1454,14 @@ function AUFTRAG:NewCASENHANCED(CasZone, Altitude, Speed, RangeMax, NoEngageZone mission.missionFraction=1.0 mission.missionSpeed=Speed and UTILS.KnotsToKmph(Speed) or nil mission.missionAltitude=Altitude and UTILS.FeetToMeters(Altitude) or nil - + + -- Evaluate result after x secs. We might need time until targets have been detroyed. + mission.dTevaluate=15 + mission.categories={AUFTRAG.Category.AIRCRAFT} mission.DCStask=mission:GetDCSMissionTask() + return mission end @@ -9714,7 +3440,9 @@ function AUFTRAG:AddConditionSuccess(ConditionFunction, ...) end table.insert(self.conditionSuccess, condition) - + + self.conditionSuccessSet = true + return self end @@ -9734,7 +3462,9 @@ function AUFTRAG:AddConditionFailure(ConditionFunction, ...) end table.insert(self.conditionFailure, condition) - + + self.conditionFailureSet = true + return self end @@ -10027,7 +3757,7 @@ function AUFTRAG:IsReadyToGo() return true end ---- Check if mission is ready to be started. +--- Check if mission is ready to be cancelled. -- * Mission stop already passed. -- * Any stop condition is true. -- @param #AUFTRAG self @@ -10284,7 +4014,18 @@ function AUFTRAG:onafterStatus(From, Event, To) end self:I(self.lid..text) end - + + -- check conditions if set + if self.conditionFailureSet then + local failed = self:EvalConditionsAny(self.conditionFailure) + if failed then self:__Failed(-1) end + end + + if self.conditionSuccessSet then + local success = self:EvalConditionsAny(self.conditionSuccess) + if success then self:__Success(-1) end + end + -- Ready to evaluate mission outcome? local ready2evaluate=self.Tover and Tnow-self.Tover>=self.dTevaluate or false