DCS Mission Editing Tools and Discussion

So I need to get a bit more familiar with the Lua part of the DCS Mission editing areas to make missions that are, hopefully, more immersive and dynamic. To do that, I’m a gonna need resources. So, I thought to myself, it might be an idea to start a thread on MudSpike where like minded crazy people could discuss and share these resources.

Please share any resources that you might have for DCS Mission Editing, Tools and Lua related scripts. I will try to turn this post into a wiki and keep the main page up to date.

And, of course, discussions.

DCS Mission Editor:

Lua:

Lua Code/Libraries:

7 Likes

Nice one!

I am re-learning all that ME stuff in DCSW again after I quit making complex missions in 2011 or so.
Back then I wanted to wait a few weeks or maybe months until they fix a few things, especially the ATC. So here I am five years later with the same old stuff… :disappointed:
So this comes in useful.

Not sure where it would fit, but I’ve been keeping an eye on the Mission Object Oriented Scripting Environment (MOOSE). Looks like it’s got potential to provide some interesting dynamically generated missions.

I’d love to use it, I just can’t get past their documentation videos. Is an actual document so much to ask?

Documentation?

Bro, do you even Devops?

Nope

EDIT:
But seriously. Right now I can’t really tell what all MOOSE is going to end up being, which means I can’t slot in what I want to use it for. That combined with the means by which they’re documenting things makes it likely I will leave it be for the time being. I’m rather a novice at DCS scripting anyways, so I’m trying to pick up the finer points of lua and the scripting engine.

1 Like

I’ve spent a lot of time in Lua (not LUA, BTW. It’s not an acronym, it’s the Portuguese word for “moon” ) and in the DCS environment. There are some new changes to the user API that are pretty exciting and open up a lot of new possibilities.

Remember that the SSE interface is just one way to get into the guts. Check out …\Eagle Dynamics\DCS World\API\DCS_ControlAPI.txt for another way in. The readme is old and needs some updating, and doesn’t include all the descriptions of ALL the functions you can get access to, but it’s really powerful, and simple to deploy - just copy a .lua file to your scripts directory.

1 Like

Question. If I execute a “do script” command in a waypoint, is there a way to return which group the waypoint belongs to?

Short answer … as far as I know, no.

There is no ‘ownership’ of the code by the waypoint … meaning, that when the script executes, it executes independant of any information on what triggered it … I think. I could not find anything (or any code example that let me check for a calling object/parent/whatever.

On the other hand, I think that you could pass an argument/set a ‘global’ variable with some soft of waypoint number and the name/country/pilot and that information could look up the waypoint list. I think. Just make sure to unset or clear that variable when you are done, in case the game decides to run that code at some other moment. Know what I mean?

Is this through the Advanced (Waypoint Actions) → Preform Command → Run Script call? That seems to be the only way I can think of, at the moment, to attach code to a waypoint.

It is. I was just hopping there was an inherited self variable, which would save me from editing 54 instances of a function. c’est la vie. group:this.firezemissile() is much easier than bombergrp54.firezemissile()

Yes. Yes it is :slight_smile:

See the Mission Editor Resources page over at my Projects site for the latest versions of these two documents –
WC’s Mist Examples.txt (19.7 KB)
WC’s Flags.txt (12.0 KB)

1 Like

First in a series of posts detailing my implementation of a training flight mission in DCS World.

Please note that this is a work in progress. I welcome comments and suggestions!


Part 1: Introduction and Design

TLDR; An example at doing something a little more complex in the mission editor.

I have been working on some missions for the Mirage 2000C lately as part of a multiplayer campaign for us Mudspike flyers. It is coming along … slowly. As part of that effort, I thought I would share any nuggets of information I might find or discover, giving back to the mission building community.

What I wanted was something more than just adding units to the battlefield and giving players a limited time slot to play in. I wanted something that could be fairly dynamic, or at least semi rigid. I wanted to avoid CAP patrols or tankers that would expire or ground units that would get to their destination before the players had corralled themselves into the air. I wanted to make use of all of the available community tools in as much as they did not either over complicate things or fall into a trap where they were never updated.

Part 1: Introduction and Design;
Part 2: Implementation of the Escort Target C-17;
Part 3: Random AI Enemy Fighters in a Position to Threaten the Corridor;
Part 4: Random AI Enemy Fighter Intercept;


Background

TLDR: Adding a unit that could be escorted;

The first task that I encountered was with community training. One of the challenges with a multi-player campaign revolves around the missions that virtual pilots (who I will refer to as clients for the rest of this post) will be expected to perform. That means having a mission that provides a means for pilots to practice what they might have to do during the campaign. And that lead me to the escort mission.

First ingredient in an escort mission is something to escort. Being that this would occur in a training mission, I realized that I needed to allow clients to perform an escort mission when they are ready and not at a prescribed time. Here is how I went about adding an escort-able AI that could be launched when the clients were ready (or, at least, close to ready).

Requirement #1: Allow for dynamic launch time;

The Escort mission, in my mind, revolves around a corridor within which clients would have to provide adequate security. Clients would need to patrol and control the corridor and let the escort target know when to proceed or when to abort.

Requirement #2: Allow clients to let the escort target know when it was ok to proceed;
Requirement #3: Allow clients to request that the escort target abort;

Communication between the escort and escort target is, as usual, a two way street. There are three methods that can be used by mission designers: a) recording voice segments that can be played at relevant times; b) text messages that can be displayed on-screen for a set duration when an event occurs; c) listening to the AI traffic calls. For this mission I intended to use both b & c (since no one needs weird calls recorded using my voice). I chose both b & c because text messages can be missed and because the radio calls can also be missed and misunderstood. That all comes in to the training and the simulator capabilities.

Design

TLDR: C-17 w/ route plus triggers;

Lets get down to the mission bits. First I placed a C-17 on the ramp at Nellis and checked the box for ‘Late Activation’. I then gave a way-point (WP #1) and altitude far enough away from the airfield as a suitable ‘Rejoin’/‘Form-up’ way-point - where the C-17 would orbit waiting for a command from the clients to push. Push, in this instance, means to begin it’s pre-planned course. This allows the clients to work with the AI, knowing when, and from where, the C-17 is going to work from and knowing that it would be following the briefed flight plan on the push command. Then I placed the second (WP #2) and third (WP #3) way-points for the C-17 at the target altitude FL025 along the path of the corridor. I added a fifth (WP #5) way-point (number four crept in there during mission editing) that would represent the C-17 continuing on after the escort mission - pretending that the C-17 had some place it needed to be after the escort. I added a sixth (WP #6) way-pointthat would circumvent any enemy CAP/OCA and a seventh (WP #7) way-point back at Nellis. I do not intend that the C-17 would RTB after the escort but I needed those way-points in case it had to abort.

I also needed some trigger zones that I could use to notify me when the escort target C-17 hit it’s assigned points: TZ #1 at WP #1 to detect that the C-17 was at it’s Rejoin point, TZ #2 to detect when the C-17 was at the end of the escort zone and TZ #3 to remove the C-17 when it had completed it’s required task and was ‘on it’s way’ out of the zone.

Design Choices Impact Implementation

TLDR: mission requirements can complicate what you are trying to accomplish;

Before we get into the complicated bits there is one design choice that needs to be made at this point. There are two ways that this mission can be implemented: 1) via the trigger commands in the mission editor and 2) via Lua scripting independant of the trigger commands. One would make use of the flags (mission editor) while the other would make use of event listeners or timed function calls.

The problem I was starting to over-engineer a solution for was related to a fourth requirement that I wanted to implement: having this entire system callable any time and any number of times. For that I needed a way that I could ‘reset’ the escort target after it had completed it’s task and there were two ways I can think of to do that in DCS … maybe. One is to let get DCS to reset the escort target back to it’s starting state, on the Nellis airfield with the ‘Late Activation’ flag set and the flight’s prior history ‘forgotten’. Or, method two, I could clone the escort target and spawn the clone when I needed to and then destroy it when it had completed it’s task leaving me free to clone/spawn another whenever I wanted. The problem was in choosing to use the mission editor trigger flags section as it would mean that the trigger commands created in the mission editor would refer to the flight that would be cloned, meaning that the triggers would refer to the incorrect flight or that I would have to set up the triggers with a flight that did not exist at mission start.

The tools available for this mission example (Mission Editor only) lead me to dropping the fourth requirement and it would delay … everything. Scope creep at the mission design level :slight_smile:

I included this to make a point: choices early in the mission design can have unintended consequences later and it gets much harder to change this once you start implementation - certainly if that means complete re-implementation. This is often a thing many people complaining about on the flight sim forums when deadlines are missed. And this is only in mission design which can mean a weeks worth of work needs to be completely redone and no where near the complexity and scope of the flight sim itself.

2 Likes

Part 2: Implementation

Here is the route as intended with the trigger areas moved away from the way-points for readability. Each of those trigger areas will sit (when moved back into place) directly on top of their assigned way-points.

The escort flight of M2000C fighters will have a route that overlays the escort route, allowing the clients to be properly briefed on their mission and to be able to understand the calls from the C-17.

Both units are tied to the 251 UHF Guard frequency to facilitate ‘communication’. Now we need to do the complicated parts and get all the behaviour ‘coded’.

There is (will be) a chart at the end of the steps that attempts to illustrate the process of using flags as triggers and states.


Step 1

TLDR: Set the Escort Target Options;

Add an ‘abort’ option to the escort target. For this, we add a ‘Triggered Action’ to the escort target. This will allow us to ‘call’ this operation via the communication menu. This triggered action instructs the escort target to switch to WP #6 - the RTB way-point.

Instruct the escort target to ‘Orbit’ at (WP #1). We will use the communication menu, in the steps below, to instruct the escort target to leave this orbit by setting Flag 154.

Note: Make the way-point speeds above 380. Way-point speeds in DCS are in ‘ground speed’ and not air speed. If, as in the screen shot above, you set the speed to something around 300, the unit may have a difficult time matching that speed.

Flag 150 Request: Spawn C-17;

Step 2

TLDR: Add Initial Communication Menu Item to Spawn the C-17;

Add an item to the communication menu, allowing clients to request that the C-17 depart from Nellis;

This radio message will appear in the communications menu at the bottom (F10). It will, when executed (ie: called by a client by selecting the appropriate communication radio item, set Flag 150 to true (any non-zero value). We make this available at the start of the mission as part of a single execution trigger.

Step 3

TLDR: Process the Flag 150 ‘event’;

This step responds to the setting of Flag 150 and spawns the C-17 which will start it’s route toward the Orbit/Hold area of WP #1.

This trigger will spend a small bit of CPU time, each second, checking to see if Flag 150 is true. Upon detecting it we will:

  1. Turn off the Flag 150;
  2. Set Flag 151;
  3. Remove the radio menu item we added in Step 2 (preventing it from being called again);
  4. Activate the C-17;
  5. Send a message to the players - in this instance a text message;
Flag 150 Request: Spawn C-17;
Flag 151 State: C-17 En Route to Orbit/Hold Area;

Step 04

TLDR: Detect the Escort Target Entering the Orbit/Hold Area (TZ #1);

This step is a little more complicated. We are detecting that the escort target is entering the orbit area in order to add the ‘Push’ radio message to the communication menu. At this point, the escort target is ready to ‘Push’ to and through the escort corridor.

To do this we want to detect the C-17 entering TZ #1 while Flag 151 is set. This translates into the escort target entering TZ #1 while it is in the C-17 En Route to Orbit/Hold Area state. When those conditions are met:

  1. Turn off Flag 151;
  2. Set Flag 152;
  3. Add a radio item to the communication menu to instruct the C-17 to ‘Push’ - set Flag 153;
  4. Send a message to the players - in this instance a text message;

There is an implied communication happening here. When the escort target C-17 arrives at WP #1 and starts to orbit, it will announce this on it’s assigned UHF communication channel as a call from Springfield 1. Clients can/should be listening for this call as the text message sent to players is acting as a visible notification, rather than audio … if the clients are turned in properly.

The escort target will now proceed to orbit WP #1 (as instructed in Step 1) waiting for the clients to ask it to ‘Push’ via a communication radio item.

Flag 151 State: C-17 En Route to Orbit/Hold Area;
Flag 152 State: C-17 Orbiting;
Flag 153 Request: Push;

Step 05

TLDR: Receive Request to Push;

Here, we wait on Flag 153 being set to true to trigger our next state change. Once it is detected, we set Flag 154 which, you may remember from Step 1 above, allows/instructs the C-17 to end the Orbit task at WP #1.

When Flag 153 is detected (set to true but the communication radio item call):

  1. Turn Flag 152 off;
  2. Turn Flag 153 off;
  3. Set Flag 154;
  4. Remove the ‘Push’ request communication radio item;
  5. Send a message to the players - in this instance a text message;
  6. Add a radio item to the communication menu to instruct the C-17 to ‘Abort’ - set Flag 155;

During this period, the escort target will push from WP #1 to WP #2 and continue through the route it has been assigned. While doing this, a communication radio item will exist that will allow clients to request that the escort target abort.

There is an implied communication happening here. When the escort target C-17 departs from WP #1 and starts to push, it will announce this on it’s assigned UHF communication channel as a call from Springfield 1. Clients can/should be listening for this call as the text message sent to players is acting as a visible notification, rather than audio. Also, as the escort target passes each assigned waypoint, there will be an audio call out … if the clients are turned in properly.

Flag 152 State: C-17 Orbiting;
Flag 153 Request: Push;
Flag 154 State: C-17 Pushing;
Flag 155 Request: Abort;

Step 06

TLDR: Detect the Escort Target ‘Completing’ the Assigned Task;

To do this we want to detect the C-17 entering TZ #2 while Flag 154 is set. This translates into the escort target entering TZ #2 while it is in the C-17 Pushing through the escort corridor. When those conditions are met:

  1. Turn off Flag 154;
  2. Send a message to the players - in this instance a text message;
  3. Remove the ‘Abort’ request communication radio item;
Flag 154 State: C-17 Pushing;

Step 07

TLDR: Detect and Process the Abort Call from the Clients;

A little more complicated as we are calling a ‘Triggered Action’ for the C-17. For this we are ‘listening’ for Flag 155 to be set. This is set through execution of the communication radio item by a client established in Step 6.

To execute this:

  1. Turn off Flag 155;
  2. Remove the ‘Abort’ radio item;
  3. Order the C-17 execute the ‘Switch Waypoint’ triggered action;
  4. Send a message to the players - in this instance a text message;

At this point, the escort target will depart it’s current course and head to the RTB point at WP #6.

Flag 155 Request: Abort;

Step 08

TLDR: Cleanup;

Last step. Promise. When the escort target enters TZ #3, we remove it from the game. Here we clean up a little as a design choice. In this case I did not want to C-17 to circle around ‘out of sight’ and back to Nellis. Well, at least if the Abort call did not get made. In my mind, as mission designer, this represents the C-17 heading off on it’s own mysterious task.

This would have been the point where, with Lua scripting and MiST, it may be possible to reset the escort target back to it’s initial state and allow it to be triggered again. Maybe. Maybe.


Flag Trigger/State Diagram

And, after all of that, a flow chart that attempts to visually describe what is happening.

4 Likes

The Continuous Action Types should be used sparingly. Use Switched Condition if you expect the condition can repeat; the Continuous Actions will fire every second, for instance Step 04 I’d expect it to do the Actions every second as long as the group is in the zone.
I recommend making the Pilot name the same as the Group; dash it off for multiple units. It will make it easier if/when you make events that are Unit based. You could extend that name to the associated zone, especially for Unit In Zone conditions.
Step 07 can be a Type: Once.

1 Like

I agree. I am trying to stay away from those or, at the minimum, make them fire once. For instance, in Step 04 the ‘In Zone’ condition is paired with a flag so it will fire when both are set and, upon firing, the flag is immediately unset … so the condition should only fire once and during execution, make sure it does not fire again. I probably should have the flag at the top as checking it is a much faster and simpler test which, if it fails, should mean that the more complicated ‘In Zone’ test does not need to be executed.

I will take another look at the trigger types when I get back to my PC on Sunday/Monday.

Yep, you’re right. I was looking at the preceding event, and soo many Continuous Actions had me in a mental loop :slight_smile: I keep wanting to click on the events in your screenshots to open them up. Be aware there is a bug with Messages right now in v154. This thread may have the Mist script you want in order to respawn; the event types would then be Switched Conditions.

Part 3: Modifying the Escort and Adding AWACS#

To increase immersion I thought it would be a great idea to add a couple of elements to the mission. First, I wanted to add an AWACS to the mission in order to facilitate having to parse BRA/BullsEye Calls to develop a mental picture of what was happening. Second, I wanted to add a ‘close in’ escort for the C-17 target. This escort would more serve as eye candy and, maybe, a last ditch defensive mechanism if the main escort flight was distracted hunting down bandits.

At the same, a post describing a method that would have the AI aircraft waiting for task calls to sit on the airfield. In Part 2 (above), the C-17 escort was set to ‘Late Activation’ with a trigger to Group Activate. This would spawn the unit on upon receiving the radio call. The new method has them sit on the airfield until they are needed.


Step 1

TLDR: Adding the Awacs;

Relatively simple. Adding an AWACS to launch from Nellis and head out over the desert to the east of the intended flight path. I added an Advanced Waypoint Action at WP #2 to direct the AWACS into a Race-Track orbit between WP #2 and WP #3. In hindsight, the speed assigned to the AWACS is way too slow, showing 300kts ground speed while having them at FL035 - this means they will be crawling in a high AoA the entire time.

I also assigned the AWACS to a frequency off of the default Guard frequency: 251 MHz. Since the M2000C has two radios capable of receiving this, wingmen who were annoyed at the continuous stream of calls from the AWACS could tune it out.


Step 2

TLDR: Re-kajiggering the AI Start Mechanism;

This post is pretty cool, describing how to have the AI aircraft sit on the airfield until they are called.

From feefifofum:

Make sure they are set as take off from ramp.
Check “uncontrolled”

Open the advanced waypoint actions

Select triggered actions tab

Add-》 perform command -》 start

Use AI TASK PUSH to trigger your startup.

Nice! Let’s make the changes!

First I modified the C-17 Escort, turning off the ‘Late Activation’ and checking the box for ‘Uncontrolled’.

Next, we added the ‘Triggered Action’ to Start the AI. I gave it a name to help me identify it in the trigger logic GUI but it was not hard to figure out.

Last, I modified the trigger logic to call the ‘Triggered Action’ and removed the previous calls to GROUP ACTIVATE.


Step 3

TLDR: Adding the Close-In Escort;

This was a little tricky and @near_blind helped me figure out what was necessary.

I added an F-14 to Nellis with the same setup as the C-17: checked the ‘Uncontrolled’ box. Since the F-14 would only ‘activate’ at the same time as the C-17, I did not have to worry too much about the initial setup. I gave the F-14 an appropriate loadout and set it’s first waypoint to the same ‘rejoin’/orbit location that the C-17 was heading to. This is key: do not give the escort fighter a ‘Follow’ command in it’s initial waypoint. Instead, give it a place to meet up with the target and then follow. In this instance, the F-14 will head to WP #1, where it will be ordered to find and follow BLUE Transp #001.

The ‘LAST WPT’ box is checked to cover the ‘Abort Mission’ radio call to the C-17. Throughout the C-17s flight plan, the F-14 will attempt to tag along. If the C-17 is ordered to ‘Abort’, it immediately sets it’s destination to WP #7 and, once there, will continue on to land at Nellis (WP #8). We want the F-14 to do the same thing, and by having it end it’s mission at the C-17 WP #7, it will then continue on to it’s own internal next waypoint, WP #2, and ‘separate’ from the C-17. We then set WP #3 to Nellis so that it, too, will land when the mission is aborted.

Last, we have to handle the C-17 completing it’s mission. That happens with the Escort Destroy trigger: when the C-17 enters the ‘BLUE ESCORT CLEAR’ trigger zone. Easy enough, we just destroy the escort at this point as well.

2 Likes

Added an updated link to DCS Witchcraft (LUA interaction with a live DCS instance). It still works with DCS 1.5 and 2.0.

Necro thread!

Some helper code for DCS World 2.1+

So DCS World 2.1+ has a bug in it where ‘Late Activation’ units actually move but are hidden. This is not, as I understand it, the intended behaviour and there is a case opened for it somewhere in the DCS bug tracker.

To work around this, and allow me to work on missions in the new maps I am taking advantage of MOOSE to scan the positions of the units at mission start and store those initial states.

To start, I have data like this in Lua. This is how my data looks. The names (RED-Ar Route #001) refers to a group (ie: a DCS Group name). I have it as both the row index and as a value just because I am an Lua idiot and it was easier at different points to refer to different bits. Anyway. Look here…

	Routes_Data = {
		["RED-Ar Route #001"] = { Name="RED-Ar Route #001", GroupRef=nil, TaskRoute=nil, StartVec3=nil },
		["RED-Ar Route #002"] = { Name="RED-Ar Route #002", GroupRef=nil, TaskRoute=nil, StartVec3=nil },

So what I do is loop though this list like this:

	for rgrp_idx,rgrp_val in pairs (Routes_Data) do
		SpawnControl_processroutes ( rgrp_idx, rgrp_val )
	end

Which calls this code to fill out the rest of that table above. It’s a little verbose because I tend to leave debug statements lying around so I can monitor the log live on my second monitor:

	local function SpawnControl_processroutes ( _idx, _route_structure )
		-- Expects to get rows of data like this:
		-- Routes_Data = {
		--    "RED-Ar Route #001"] = { Name="RED-Ar Route #001", GroupRef=nil, TaskRoute=nil, StartVec3=nil },
		-- }
		local status_txt = "Group " .. _idx .. " (" .. _route_structure.Name .. ") "

		_route_structure.GroupRef = GROUP:FindByName( _route_structure.Name )
		if _route_structure.GroupRef ~= nil then
			status_txt = status_txt .. ", GroupRef stored"
			if _route_structure.GroupRef:GetUnit(1) == nil then
				env.error ( "SpawnControl_processroutes:  No Unit ref from Route Group:" .. _route_structure.Name .. ". Skipping!" )
				return
			else
				_route_structure.TaskRoute = _route_structure.GroupRef:GetTaskRoute()
				if _route_structure.TaskRoute == nil then
					env.error ( "SpawnControl_processroutes:  No Task Route from Route Group:" .. _route_structure.Name .. ". Skipping!" )
				else
					status_txt = status_txt .. ", TaskRoute stored"
				end
				_route_structure.StartVec3 = _route_structure.GroupRef:GetUnit(1):GetVec3()
				if _route_structure.StartVec3 == nil then
					env.error ( "SpawnControl_processroutes:  No Start Pos from Route Group:" .. _route_structure.Name .. ". Skipping!" )
				else
					status_txt = status_txt .. ", StartVec3 stored"
				end

				env.info( "SpawnControl_processroutes:  " .. status_txt )
			end
		else
			env.error ( "SpawnControl_processroutes:  No Group ref from Route Group:" .. _route_structure.Name .. ". Skipping!" )
			return
		end
	end

So what I do at the start of a mission is run through all of my groups that are ‘position sensitive’ (ie: I expect them to start at pos A and travel a route). I grab a reference to the group (stored in GroupRef) and then grab the Route and the Vec3 position. This allows me reference them at a later time in their initial state (well, everything except the GroupRef).

So if you try spawning an aircraft and it starts off somewhere you do not expect (like landed at an airfield) then it might be related to this.

As I write this, @near_blind has prompted me to take a look at the SPAWN:Spawn() where the behaviour I was seeing with Late Activation units was not happening. In my case, what I am trying to achieve is a training mission where the commander can chose from an array of potential adversaries that will get assigned to a random route … which means I can’t use that functionality. :slight_smile: