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 “Serfoss scaling” (also known as “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 such an implementation would be if that is indeed the case, 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, but has been stripped of the helpful descriptions included in ED's original file — for the full default file built into DCS, you can look in your DCS install directory to find DCS World\Config\View\labels.lua. 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

Skipping over a first bit of boolean logic that will be used much later, the Labels.lua file opens up with some very basic settings: what should actually show and what should not.

  7. AirOn                 = true
  8. GroundOn              = true
  9. NavyOn                = true
 10. WeaponOn              = true
 11. 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

In the default DCS lables.lua file, you can find 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. In the Even Lamer Goons file linked above, this has been removed because… well, you are reading this description, and it is more thorough so it doesn't need to be in the file itself.

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 variations of what the text label will actually show.

 13. local NAME                 = "%N"
 14. local NAME_DISTANCE_PLAYER = "%N%n %D%n %P"
 15. local NAME_DISTANCE        = "%N%n %D"
 16. local DISTANCE             = "%n %D "
 17. local PLAYER               = " %D - %P "
 18. local EMPTY                = {"", "LeftBottom", 1, 1, 0, 0}

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. Beyond that, no value in particular should be attributed to the specific names — they are all “local,” meaning they only matter within the context of this exact file, and as long as the right name is referenced in later definitions, these presets can be added, removed, or renamed as the label designer chooses. Indeed, some of the presets in the file are not even used, but are rather left in in case someone at a later stage just quickly want to change to a different preset without having to (re)define or introduce new things.

Note also that in DCS's standard labels file, there are also definitions of the text_shadow_color and text_blur_color variables mixed in there. 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, and as such they have been stripped from the Even Lamer Goons file.

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:

 20. 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, in this illustration 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.

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.

 22. local near_symbol        = "⌜" --U+231C
 23. local aircraft_symbol    = "˄" --U+02C4
 24. local ground_symbol      = "ˉ" --U+02C9
 25. local navy_symbol        = "ʷ" --U+02B7
 26. local weapon_symbol_near = "*" --U+002A
 27. local weapon_symbol_far  = "ˈ" --U+02C8
 28. local function dot_symbol(blending, opacity)
 29.    return {"˙","CenterBottom", blending or 1.0 , opacity  or 0.1} --U+02D9
 30. end

Here, each unit category gets a near and a far symbol according to whatever is inside the quotation marks — note that depending on your text editor (or web browser) these may show up in some peculiar ways, either as “missing character” blocks, or as some strange alteration of the subsequent character. For the most part, though, it will show up correctly in-game, and the method to pick and preview the exact character will be described further down (spoiler: you use the Character Map).

Note that the names here are almost completely arbitrary. While there are separate “weapon_symbol_near” and “weapon_symbol_far” definitions, these in no way decide that one should be shown at close range and the other farther away, or indeed that these symbols will be used for weapons. The name is simply there to make it easy for the label designer to remember what's what. The exact parameters for what will show when are defined in a later code block. This also means that you can set up a very granular set of symbols to denote ever-closer objects, maybe different series of dots such as ˑ ˇ ▾ ▼ that are named really_far_aircraft, far_aircraft, closer_aircraft, too_close_aircraft, and then the code blocks below define different ranges where those are applicable.

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. This is also commonly the symbol that is then used for (surprise) the dot-label display setting, if one prefers not to run with full labels.

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…

Range definition arrays

The range 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. Skipping over a bunch of lines that relate to more complex setups, we can see the following:

139.    AirFormat = {
140.        [305]   = EMPTY,
141.        [5556]  = {near_symbol..PLAYER,       "LeftBottom"   ,1    , 0, 2, -2}, -- 3nm
142.        [9260]  = {aircraft_symbol..DISTANCE, "CenterBottom" ,0.75 ,0},         -- 5nm
143.        [18520] = {aircraft_symbol,           "CenterBottom" ,0.25 ,0},         -- 10nm
144.        [27780] = dot_symbol(0,0),                                              -- 15nm
145.    }
146.
147.    GroundFormat = {
[…]
152.    }
153.
154.    NavyFormat = {
[…]
160.    }
161.
162.    NavyFormat = {
[…]
167.    }

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.

Again, we are dealing with Lua arrays, and the general format for these definitions is this:
[ range in meters ] = label string , " alignment ", colour blending (0-1) , shadow opacity (0-1) , position shift left in pixels , position shift up in pixels

The first line simply says that, within 305 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, out to 3nm (5556m), the label will show the “near_symbol” character defined earlier (a ‘⌜’ symbol), append the PLAYER preset to that (so in this case the distance and the pilot name). The lines will be left-justified below the unit. The label will have a 100% colour blend and the shadow will have a 0% opacity (but since we defined the shadow to sit right underneath the text in the font definition earlier, this does not particularly matter). To adjust the final position, the whole label is moved 2 pixels left, and 2 pixels down. And finally, a comment to remind ourselves that this line is for a 5nm distance.

The next two lines say that, out to 5nm (9260m), the label will instead be the aircraft_symbol (˄) followed by the DISTANCE preset (a newline and then the distance) centred below the unit, and then that out to 10nm (18520m), we lose the distance display and just retain the aircraft symbol. The colour blending first goes down to 75% and then to 25%, making the text increasingly dark as range increases. Note that no x- or y-shift is provided — the newline and the centred alignment puts the label right where it should be so no further adjustment is needed.

Finally, the last line says that out to 15nm (27780m), 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 and opacity of 0%. Since nothing more is defined, air units outside of 15nm 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. In DCS' default, built-in label file there is a deprecated code snipppet that defines 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. As such, only this more detailed colour setup is present in the Even Lamer label file.

169.    ColorAliesSide   = {192, 96, 48}
170.    ColorEnemiesSide = {48, 96, 192}
171.    ColorUnknown     = {48, 48, 48}
172.
173.    ShadowColorNeutralSide = {192,192,192,32 }
174.    ShadowColorAliesSide   = {96 ,48 ,24 ,32 }
175.    ShadowColorEnemiesSide = {24 ,48 ,96 ,32 }
176.    ShadowColorUnknown     = {25 ,25 ,25 ,32 }
177.
178.    BlurColorNeutralSide   = {255,255,255,0  }
179.    BlurColorAliesSide     = {48 ,0  ,0  ,0  }
180.    BlurColorEnemiesSide   = {0  ,0  ,48 ,0  }
181.    BlurColorUnknown       = {48 ,48 ,48 ,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 default 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

As the astute reader may have noticed, especially if they followed along in the Labels.lua file, a significant portion of the file content was skipped. This has to do with the functionality introduced in DCS 2.5 that offers three different layers of labels: full, abbreviated, and dot-labels. All of these can be defined individually in the Labels.lua file, and each can effectively completely change how everything looks.

The label parameter

It all starts with two odd lines at the very beginning of the file:

  4. local IS_DOT         = labels and labels ==  3
  5. local IS_ABBREVIATED = labels and labels ==  2

This is a bit of Lua logic trickery that sets the IS_DOT variable to “true” if the player uses the dot-labels setting, and the IS_ABBREVIATED to true if they have set their labels to be abbreviated.

These two variables can then be used in standard if/else conditional code blocks to define or redefine how things should look depending on what the player's label setting is. Any and all definitions can be put into these conditional blocks, depending on how much or how little commonality you want between different label styles. For instance, if the colour scheme should always be the same no matter what, the Color, ShadowColor, and BlurColor definitions mentioned earlier can be set outside of the conditional block(s) and will then apply universally. Conversely, if you want every label style to come with its own colour scheme — maybe full labels are very colourful and each coalition is at all times clearly distinct from the others, whereas in the abbreviated style, the difference is more subdued and the dot-label style offers no colour differentiation whatsoever.

Thus, each of the following can be set globally or individually for a specific label style:

  • Which units have labels and which do not (the AirOn, GroundOn etc. variables).
  • What font is used for the labels.
  • The contents of the label presets (eg. maybe all styles have the same format, but each style defines a different PLAYER preset that shows the player name in different ways).
  • The symbols used for the different unit types, including the appearance of the “dot symbol.”
  • The range bands and label styles for each unit type (the AirFormat, GroundFormat etc. blocks).
  • Each separate part of the colour schemes.

In short, interpreting the label parameter allows for an insane amount of flexibility in terms of deciding how unit labels should show up for the player depending on what label setting they use.

But how?

The exact method of creating these different label styles is the most basic of Lua conditional statements. In the Even Lamer labels file, we find the following lines of code:

 36. if IS_DOT then
[…]
 76. elseif IS_ABBREVIATED then 
[…]
137. else
[…]
183. end

Between each line, a different style of label is defined, based on (and in some case overwriting) what has already been set in earlier sections.

Even a fairly shallow understanding of pseudo-English should make it clear what is going on here: on lines 36, we check the variable IS_DOT — in other words, whether the player is using dot labels. Then follows a definition of air, ground, navy, and weapon formats that are all based on various types of dots. In this label file, there is even an additional “big dot” symbol definition that is being used for particularly up-close objects:

 32. local function big_dot_symbol(blending, opacity)
 33.    return {"·","CenterCenter", blending or 1.0 , opacity  or 0.1} --U+00B7
 34. end

On line 76, if IS_DOT was not set (if the player was not using dot labels), we check if IS_ABBREVIATED is set instead. If it is, the subsequent lines set up how abbreviated labels should look. It actually redefines a couple of earlier settings and variables, and once again set up the standard range definition arrays. By request from the Even Lamer Goon players, this setup replicates hoggits GAW server settings, which is why some earlier definitions (notably GroundOn and WeaponOn, as well as a couple of symbols) are redefined, and why the font is reset to not have any blur. The “full” label definition used in this file is already quite terse, so this abbreviated format simply consists of sets of symbols with no additional text, but ones that are bigger and more noticeable than pure dot labels.

The last block, from line 137 on, is simply if neither of the previous ones happen to be true: the player has either set no labels, or full labels. If they have no labels, then we do not have to deal with that because DCS handles it internally by… simply not showing any labels. So the whole block is about defining range arrays and colours for the full label setup — the one described in the earlier Distance definition arrays segment. The “end” on line 183 closes out the whole conditional logic block.

For bonus points, there is then a mystery PointFormat definition that no-one has any idea what it does.

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