Airgoons
CE2goons.jpg BMS.png
DCS.png

DCS Reference: Labels

From Airgoons
Jump to navigation Jump to search

DCS's visual model is… quirky. It uses a rather naive system for drawing units that has the unfortunate side-effect of making things harder to see on better hardware. Higher resolutions make units appear as smaller pixels, and fancy post-processing and anti-aliasing make them indistinct against the background. In BMS such tendencies are counteracted, and other visual cues compensated for, through a system of “smart scaling” that actually provides a better simulation of visual perception.

DCS does not have that. Indeed, according to the developers, it cannot possibly have that since that would create problems with radar (and other sensor) detection. The less said about how hilariously broken and backwards this implementation is, the better.

What DCS has instead is the label system. They're the big ugly things that clutter up your view with tons of overlapping text when all you want is an indication of what's out there at a range where a pilot would be able to identify those details. For spotting, you can turn them into just simple dots, but that still isn't a very neat solution. As luck would have it, you can actually get the benefits of that without any (or at least most) of the downsides by creating your own Labels.lua file.

Labels.lua

The Labels.lua file is where DCS sets up how labels appear on-screen. Like kneeboard images, this file can show up in a number of places but only two actually matter:

  • In the %USERPROFILE%\Saved Games\DCS\Config\View directory.
  • In a Config\View directory stored in a mission (.miz) file.

The first is used to define how labels will appear to you, unless something else is specified elsewhere. If a Labels.lua file exists here, it will override the default label settings used in DCS. The default can also be changed, but there's never any real reason to do so since the userprofile file exists for the exact reason of letting you personalise labels in an easier way without outright modding.

The second is used to define how labels will appear to everyone playing that mission. It will override any personal labels you might have defined in the aforementioned userprofile directory. Of course, on top of this, a mission can also categorically enforce labels to use a specific setting (full, dots, or completely off). This file and its directories can be added using any regular zip manipulation tool since that's exactly what .miz files are.

This page will dissect the Labels.lua file commonly used on the Even Lamer Goon Server, to explain and provide examples of how you can create your own setup. The original file can be found here, and retains the helpful descriptions included in ED's original file. Note that order of the sections described here does not necessarily match the order in the file.

When editing this file, use something sensible, such as Notepad++ or BBEdit — something that does not try to be clever and interpretative, but rather simply stores exactly what you type and nothing else.

Basic settings

The Labels.lua file opens up with some very basic settings: what should actually show and what should not.

  4. AirOn                 = true
  5. GroundOn              = true
  6. NavyOn                = true
  7. WeaponOn              = true
  8. labels_format_version = 1 -- labels format vesrion

To turn a specific set of labels on or off, simply change the respective category value to “true” or “false”. Here, everything is left on. A common request is to turn weapons off — simply change line 8 to say WeaponOn = false.

The last line is what it says on the tin: the version of the labels file format. Leave it at 1.

Formatting and string variables

Next follows a lengthy description of string formatting variables and rules, which will help anyone familiar with Lua strings to formulate pretty much everything else in the file.

Variable What it means What it does
%N Object name Displays the object/unit type (not to be confused with pilot name), eg. “Su-27” or “T-80”
%D Distance to object Displays (surprise) the distance to the object, eg. “8.5nm”
%P Pilot name Displays the name of the pilot (or callsign for AI pilots — not to be confused with object name), eg. “Tippis” or “Enfield 1-1”
%n New line A manual line break (in case you want to have lots of info but short lines)
%% The ‘%’ symbol The % sign is usually used to denote other variables so this is used to actually display a % sign.
%x To display any other ‘x’ symbol …and the above can be generalised to show any symbol, eg. %& to show an ‘&’ or %= to show an ‘=’.
%C Extended info Various weapon system data

The file also enumerates the various alignment options available when you position text relative to the unit: RightBottom, LeftTop, RightTop, LeftCenter, RightCenter, CenterBottom, CenterTop, CenterCenter, and LeftBottom. These work pretty much exactly the same as the alignment options in an MS Office table.

In other words, RightBottom means the text will be right aligned (i.e. expand to the left from the unit) and will sit below the unit (i.e. expand down). CenterTop means the text will be centred (i.e expand to both the left and right) and be on top (i.e. expand up). CenterCenter will put the label exactly on top of the unit and expand in every direction from there — this may seem like an immediately obvious “right” choice, but will actually misalign the unit symbol in most cases. See Aligning the symbols, below for an illustration of where the text appears.

Label text presets

The file sets up a number of text presets and you can simply define your own suit your needs. The presets use the aforementioned string variables to set up what the text label will actually show.

 61. local NAME_DISTANCE_PLAYER = "%N%n %D%n %P"
 62. local NAME_DISTANCE        = "%N%n %D"
 63. local DISTANCE             =   "%n %D"
 64. local DISTANCE_PLAYER      =   "%n %D%n %P"
 65. local PLAYER               =        "%n %P"
 […]
 72. local EMPTY = {"", "LeftBottom", 1, 1, 0, 0}

So, for instance, the NAME_DISTANCE preset consists of the [unit name] [new line] [distance] variables, and will thus print the unit name on one line and the distance on a second line. The DISTANCE_PLAYER preset consists of [new line] [distance][new line] [pilot name/callsign]. Starting out with a new line generally means that the unit symbol ends up separated from the label text, which is important if any of the centred alignment options are used, or the symbol will end up offset from where the unit actually is.

The EMPTY preset is exactly that: a preset that shows nothing, which can be handy if you want to remove the label at very close distances. It's simply a pre-defined Lua array that pre-empts the more complex label definitions we will see later on. Its meaning is less important than the fact that it just has an empty string in it.

Nested in here, the file also defines the text_shadow_color and text_blur_color variables. They are completely pointless since they have been replaced with a more granular method of defining colours, and can safely be left out and ignored.

Symbol definitions

The symbol definitions is where you set up exactly what character (because it is all character based) you want the unit to be marked with. While you can conceivably enter any unicode character, the actual end result is obviously limited by what is provided by the font.

If you want emoji aircraft, you need to change to a font that has emoji characters, and then take responsibility for all the breakage that will ensue.

 45. local aircraft_symbol_near =  "˄" --U+02C4
 46. local aircraft_symbol_far  =  "˄" --U+02C4
 47. 
 48. local ground_symbol_near   = "ˉ"  --U+02C9
 49. local ground_symbol_far    = "ˉ"  --U+02C9
 50.
 51. local navy_symbol_near     = "˜"  --U+02DC
 52. local navy_symbol_far      = "˜"  --U+02DC
 53. 
 54. local weapon_symbol_near   = "*"  --U+02C8
 55. local weapon_symbol_far    = "ˈ"  --U+02C8
 56. 
 57. local function dot_symbol(blending, opacity)
 58.    return {"˙","CenterBottom", blending or 1.0 , opacity  or 0.1} --U+02D9
 59. end

Here, each unit category gets a near and a far symbol according to whatever is inside the quotation marks — exactly what qualifies as “near” and “far” is defined later on and can vary with each unit category. This lets you set up differently apparent symbols for different ranges, which is particularly handy if you do not want to provide any more on-screen information than the symbol itself or, perhaps more obviously, you want a larger symbol to show up at close range than at longer range.

For various historical reasons in how this file was created, the standard setup is retained even though there is a lot of duplication. It is not strictly necessary to keep these duplicates, nor is there anything that limits the label designer to only having two symbols for different ranges. You can just as easily define, say, an aircraft_symbol_middle and aircraft_symbol_hideouslyclose and use those in the range bands defined below.

The “--U+ [etc]” at the end of each line is a Lua comment (denoted by the double minus) that explains which Unicode character is actually being used (denoted by the U+ hexadecimal code). This is not necessary — indeed, being a comment, it's outright ignored by DCS — but is obviously a helpful memory aid if you want to explain or recreate the same look elsewhere.

The last couple of lines define the “dot symbol” — a default character that you can fall back on if nothing else is suitable. It follows standard Lua function definition syntax: if you provide (optionally) two values, it returns an pre-defined array describing what this default dot should look like.

The array itself is the interesting bit. It consists of: a character to be used (just like with the ones defined for different units), a text alignment for that character, a default bending value, and a default opacity value. We'll get to those…

Font definition

The font_properties variable sets up 5 things, in order, in a regular comma-separated Lua array:

  1. The file name of the font to be used (change this with due caution and dread)
  2. Font size (in pixels)
  3. X-axis (horizontal) shadow offset
  4. Y-axis (vertical) shadow offset
  5. Blur type

The blur type can be one of 3 values:

  1. No shadow
  2. A 3×3 pixel blur
  3. A 5×5 pixel blur

Rather than actually blurring the text, the blur acts more like an outer glow around the text, and can be particularly effective in changing how large (or small) just the single dot of a label will appear.

For instance:

 43. font_properties =  {"DejaVuLGCSans.ttf", 13, 0, 0, 2}

The Even Lamer server setup uses the default font, at 13px size, with the shadow placed right behind the text (no offset) and thus invisible, but with a 5-pixel blur to make it bloat a bit. And yes, this means you can set labels to be in Comic Sans if you are in desperate need of a free long-sleeved white jacket.

The colour and opacity of the text, shadow, and blur are defined further down in the file. To achieve more of a true blur-like effect, the blur and text colour need to match closely.

Shadow and blur variations

The differences between having shadow and blur is illustrated below. To distinguish the three more clearly, the base text label is in red, the shadow portion of the label is in green, and the blur effect is in yellow. Note that the blur effect also muddles the shadow underneath it.

Shadow and blur variations

In practice, blur is generally set in grey or in a similar colour, but perhaps darker shade, to the label itself, whereas the shadow is set in some shade of grey.

Distance definition arrays

The distance definitions is the real meat of the label setup, and where all the previous components come together. Each unit category (air, ground, navy, and weapons) get their own array consisting of a range limit and a definition of how labels will appear inside that range.

 74. AirFormat = {
 75. --[distance] = {format, alignment, color_blending_k, opacity, shift_x, shift_y}
 76. [10]    = EMPTY,
 77. [9260]  = {aircraft_symbol_near..PLAYER, "CenterBottom", 0.75, 0.7}, -- 5nm
 78. [18520] = {aircraft_symbol_near,         "CenterBottom", 0.75, 0.5}, -- 10nm
 79. [27780] = {aircraft_symbol_far,          "CenterBottom", 0.25, 0.3}, -- 15nm
 80. [55560] = dot_symbol(0,0.1),                                         -- 30nm
 81. }
 82.
 83. GroundFormat = {
 […]
 89. }
 90.
 91. NavyFormat = {
 […]
 97. }
 98.
 99. WeaponFormat = {
 […]
105. }

All four category arrays work the same, only for different units as the names suggest, so we will only take a closer look at the air units here, one line at a time.

First of all, there is a Lua comment that describes the general format for the array, in case you forget while editing.

Then there is a line that says that, within 10 meters, the EMPTY preset will be used — something that close needs no label according to this setup. This also allows us to do close-up screen shots without having to fiddle with turning labels off and on again.

Next, within 5nm (9260m), the label will show the “near” aircraft symbol as defined earlier (a ‘^’ symbol), append the PLAYER preset to that (so in this case a newline and then the pilot name). The lines will be centred and will sit below the unit. The label will have a 75% colour blend and the shadow will have a 70% opacity (but since we defined the shadow to sit right underneath the text in the font definition earlier, this does not particularly matter). Notice that no x- or y-shift is provided, so the label anchor point will sit right on top of the unit centre point — depending on what characters and font sizes you use, you might want to move the label text around, especially if it is right- or left-aligned. And finally, a comment to remind ourselves that this line is for a 5nm distance.

The next line follows the same pattern, but we have now dropped the PLAYER preset so only the near symbol will show out to 10nm (18520m). Beyond that, out to 27780m (15nm), the next line applies, and we are now using the “far” aircraft symbol (which in this particular setup makes little difference since both the near and far aircraft symbols defined earlier are the same). The colour blend is now 25%.

Finally, the last line says that out to 30nm (55560m), we will invoke the dot symbol defined earlier. If we look back at that definition, we notice that it provides its own alignment, colour blend, and opacity values but we overwrite the latter two with a blend of 0% and an opacity of 10%. Since nothing more is defined, air units outside of 30nm have no label.

These definitions can be made as granular as one would like, with different layers of information appearing at different distances, and using any extra symbol definitions you care to add as discussed earlier. Note, however, that DCS will automatically apply smoothing from one range segment to the next as far as the colour blend and opacity values go.

Colour definitions

The last part of the Labels.lua file is the colour definitions. Earlier we came across a deprecated code snipppet that defined shadow and blur colour, but it has been replaced with a much wider array of colour selections that can be applied depending on what side a unit is on.

109. ColorAliesSide   = {192, 96,  48 }
110. ColorEnemiesSide = {48,  96,  192}
111. ColorUnknown     = {50,  50,  50 } -- will be blend at distance with coalition color
112.
113.
114.
115. ShadowColorNeutralSide = {0,   0,   0,   0  }
116. ShadowColorAliesSide   = {0,   0,   0,   0  }
117. ShadowColorEnemiesSide = {0,   0,   0,   0  }
118. ShadowColorUnknown     = {0,   0,   0,   0  }
119.
120. BlurColorNeutralSide   = {255, 255, 255, 0  }
121. BlurColorAliesSide     = {50,  0,   0,   0  }
122. BlurColorEnemiesSide   = {0,   0,   50,  0  }
123. BlurColorUnknown       = {50,  50,  50,  128}

This section uses RGB arrays to define colours for the coalitions and RGBA (alpha) values to define their respective shadow and blur colours. In a sense, the labels used for this example do not show this off to the full extent, since almost all opacities are set to 0, but that has its own curious effects.

The first three — allied, enemy, and unknown colours are easy enough. Just note that the naming scheme is a bit of a left-over from older versions (and games), so “allies” means Red coalition, “enemies” means Blue coalition. Unknown is still unknown, though.

The shadow and blur colours follow the same pattern, but also allows for a pre-set opacity so that they naturally blend in with their background. This lets you set up different kinds of glows for the different coalitions (or have them differently blurred, if the colours are used that way as mentioned earlier) to make them more distinct. Note, however, that separate to the label range definitions made earlier, DCS also applies colour cross-blending at longer distances to make it difficult to determine sides from colour alone. As a unit comes close, text, shadow and blur will all fade from the neutral setting to their correct coalition colours.

Colour blend and opacity

We can finally get a sense of what the two parameters mentioned earlier do: colour blend and opacity. Colour blend — or as the Label file itself calls it, “color_blending_k”, i.e. colour blended with black — acts on the base label text colour to make it fade to black as the blend value approaches 0%. Opacity acts on the shadow colour to make it less opaque as the value approaches 0%. This shadow transparency is applied on top of the alpha value assigned in the ShadowColor arrays described above.

The differences between 100% blend and opacity, 50% opacity, 50% blend, 10% opacity, and 10% opacity and blend look like this, again using red text, green shadow, and yellow blur for the sake of clarity: Opacity and colour blend variations

To sum up, the different colours change according to the following rules:

  • Text colour shifts from neutral to the specific coalition as range decreases.
  • Text colour also fades to black depending on the colour blend value defined for the different range bands.
  • Text opacity is fixed at 100%.
  • Shadow colour and opacity shifts from neutral to the specific coalition as range decreases.
  • Shadow opacity also fades between the different opacity values defined for the different range bands.
  • Shadow base opacity depends on the coalition shadow colour definitions.
  • Blur colour and opacity shifts from neutral to the specific coalition as range decreases.
  • Blur base opacity depends on the coalition shadow colour definitions.

Note that blur only changes as a sliding value depending on DCS's own determination of when coalition can be determined — the range band definitions have no impact.

This explains why, even though the shadow and blur colours are mostly set to be completely transparent in the example Labels.lua file, the label setup still generates a blur: the “BlurColorAliesSide” values (20% red, completely transparent) only hold fully true if the game has determined that a unit can be 100% identified as belonging to the Red team. If not, some blending occurs with the “BlurColorUnknown” values (20% grey, 50% transparent), so it's more of a greyish red, with some low:ish level of transparency, and that half-way blur colour is used for the 5x5 blur setting set up in the font definition earlier in the file.

Designing a label setup

The label setup begins with the font definition, and its three main questions:

  • What size do you want? Large is easier to spot and read, but also gets bloated and cluttered very quickly.
  • Do you want a shadow at all? If you are using bright text, having a dark shadow at a 1–2px offset may help it stand out against brighter backgrounds, and as the text is faded to a dark colour at distance, the shadow can be made more transparent so as not to bloat everything up too much. A 0/0px offset means the shadow is hidden behind the text.
  • How much blur do you want? Blur makes distant targets appear more easily, but will (as the label suggests) make things blurry up close. Depending on which colours are then chosen, the blur can either be used to create a bright (but generally pretty ugly) outline to contrast against dark text, or be used to simply enlarge darker symbols. Remember that blur is always present unless its colour setup sets 0% opacity and distances are so close that the coalition is 100% clear.

Picking the symbols

Character Map.exe

Time to break out the trusty old Character Map.exe. Old and clunky as it may be, it is still the best tool available for figuring out what symbols are available in a font and finding one that would work well as a unit marker. The status bar will show the code place of the currently selected symbol, which is why noting them down in a comment in the Lua file is so handy.

The default font (Deja Vu LGC Sans Mono) can be found in the DCS\Bazar\Fonts directory — installing it directly obviously makes it easier to see exactly how various symbols are represented.

In general, you want to find symbols that are close to the edge where the unit will be, so a symbol placed low if you are aligning the label on top; one placed high if you intend to align below. A larger symbol obviously makes it easier to see, but a small one will be less intrusive (and with a sensibly defined blur will still be visible enough). Then use local variable definitions like aircraft_symbol_near, weapon_symbol_far or whatever else seems needed to store those symbols for later use in the range definitions.

Aligning the symbols

Alignment modes and text shifts

The tricky part in designing a label is in figuring out how to align it properly. The alignment depends on the total size of the text box, including any line breaks and extra spaces you might include. Since most characters will be designed to be useful as text rather than as game UI bits, they will not fully stick to the edges of that box. With very few exceptions, unless you only use a single character, some kind of x/y shift will be required to make the marker point to the actual unit.

One thing to note in particular is that the origo for the coordinate system sits in the lower left side of the screen. Thus, y-shift is inverted from what one might expect: negative numbers move the text down; positive numbers move the text up.

If all you want is a single simple character to just overlap and highlight the unit, it is a bit simpler: a CenterCenter alignment with a simple dot or bullet character will do the trick, or some sort of umlaut with a CenterBottom alignment.

Expect that fine-tuning the alignment will require multiple tries, and the easiest way of doing this without starting all of DCS is to include the Labels.lua file in a mission and just repackage new versions for every adjustment. The mission can then quickly be reloaded though the missions menu, and if all it contains is one unit of every type, it will not take long to load.

Picking the colours

As hinted at, there are three main considerations when picking colours for the coalitions, the shadow, and the blur:

  • How distinct should the two coalition colours be? If all you want is something to make spotting easier, setting everything to black does that but makes positive ID:ing a necessity.
  • How much shadow do you want (if one is defined)? Unless the shadow is meant to contrast the main text, you generally want a darker grey with a low:ish (<128) alpha value. Remember that the alpha value can then be modified depending on range.
  • Do you want the blur to blur or to make spotting easier? Setting blur colour to the same as the label colour makes things hard to read, whereas setting it to a darker grey with a low:ish alpha similar to a shadow, helps with spotting. A dark blur also means you can use the colour blend value to make symbols dissolve into distinct black-grey blobs at longer distances.

Picking the ranges

Deciding what the range bands should be is probably the easiest part. Calculate (or use the conversion table below to figure out) how many meters your preferred range is and set up the AirFormat, GroundFormat, NavyFormat and WeaponFormat arrays as described above.

As a general rule, as range increases, you want to use:

  • Smaller symbols, if defined.
  • Lower colour blend values to make text fade to black and blend in with a dark blur.
  • Lower opacity values to make shadows fade away.
  • The dot_symbol() function to define the farthest range at which any label at all should be visible.
  • As few range bands as possible not to make a mess of everything, but enough to create the different steps in visibility you want — 2–3 bands should be plenty for most uses.

Advanced label setups

Assigning different labels to different user settings.

The label parameter

Distance conversions

Metric Imperial Nautical Metric Imperial Nautical
305m 1,000' 0.16nm 9,260m 30,381' 5nm
1km 3,281' 0.54nm 10km 32,808' 5.4nm
1,524m 5,000' 0.82nm 15,240m 50,000' 8.23nm
1,852m 6,076' 1nm 18,520m 60,761' 10nm
2.5km 8,202' 1.35nm 20km 65,617' 10.8nm
3,048m 10,000' 1.65nm 27,780m 91,142' 15nm
3,658m 12,000' 1.97nm 30km 98,425' 16.2nm
4,630m 15,190' 2.5nm 30,480m 100,000' 16.46nm
5km 16,404' 2.7nm 37,040m 121,522' 20nm