LTR files are used to generate random names, and are referenced in racialtypes.2da.

You can also generate new names in game with nwscript; RandomName, although these use a predefined "default 6 races" and animal companion/familiar list.

LTR files

LTR files use markov chains to generate random names from a source list of words. It doesn't just output the same source names back, but randomly takes bits of them.

LTR files are named depending on their purpose. There are two entirely hardcoded ones for familiars and animal companions and the others references in racialtypes.2da.

It's not known (someone please test!) if you need one, two or all 3 of these files for the racialtypes.2da reference.

Pstemarie 03/25/2023 - You do not need all the __l.ltr file; although if it's not included, the game will sometimes use the human table to generate a last name.  

File NameSignifying LetterExample (Human)Purpose
___m.ltrMhumanm.ltrMale forename
___f.ltrFhumanf.ltrFemale forename
___l.ltrLhumanl.ltrLast name

Familiar names

Animal companion names

Presumably used for NAME_FIRST_GENERIC_MALE since it's the only one that makes sense for this with RandomName.


The file is a binary file, the easiest way to edit it is to use the NWNLTR tool:

You can find an updated version of the tool with fixes here:

On Windows it's recommended to use PowerShell so you can easily pipe in data. Obviously shell is fine on Linux.

NWN name generator tool
Usage: nwnltr [OPTION] <LTRFILE>
 -p, --print         Print Markov chain tables for <LTRFILE> in a human readable format
 -b, --build         Build Markov chain tables using words from stdin and store in <LTRFILE>
 -g, --generate=NUM  Generate NUM names from <LTRFILE> and print to stdout. NUM=100 by default
 -s, --seed=NUM      Set the RNG seed to NUM. time(NULL) by default

Looking at Existing Files

LTR files are available in the game bifs. Search nwnexplorer for .ltr

The names.ltr looks to be built using a very old 26 character set, instead of 28 and is not openable by the nwnltr tool (unless the tool is manually recompiled) but the other .ltr files can be - you can generate some names or view the entire markov chain tables, eg: to generate 100 names from the file:

.\nwnltr.exe -g 100 .\dwarff.ltr


Generated Names

Generated names seem to be:

  • Between 4 and 13 letters
  • Always capitalized at the start
  • Can contain ' and - if the LTR has them
  • Is built from parts of the names that were previously split up into the table
  • Will compare the output to the swear filter 2da file and reject them

A writeup from Lord Nightmare:

It generates the first 3 characters by looking at the singles(start) then doubles(start) then triples(start) tables, then enters a loop for all subsequent letters, rolling on the triples(middle) table and simultaneously rolling a number between 1 and 12 and comparing to the current number of letters. If it find a letter (some of the triples(middle) tables are empty due to hand-editing!) and if the name length roll of 1-12 is less than or equal to the current number of letters, it ends the name with the next letter, rolling on the triples(end) table to find that letter.

Generating LTR Files

The easiest way to generate a new LTR file is to have a text file with one name per line to input.

The requirements for a name are in the source of the tool:

  • 3 characters
  • A-Z (the case doesn't seem to matter, the generated names have the first letter capitalised)
  • Dash - and apostrophe ' are valid but depending on the tool downloaded (see above) it might not work. The versions downloadable on this page should work with these characters.

For instance this could be dragon_input.txt


Run the command to generate the markov file:

more dragon_input.txt | .\nwnltr.exe -b dragon.ltr

Test the generation:

.\nwnltr.exe -g 10 .\dragon.ltr

As you can see having only a few names generates...not much randomness.


  • At least 100+ names input of various lengths
  • Do generations of 100 at a time to look and see if some names don't appear much or at all, and tune them

SQLite Names

Since RandomName can't specify a LTR file to use dynamically, you miss out on your fancy new files in nwscript! Oh no!

The easiest way around this is to generate the file, output 10000 entries and throw them in an sqlite database, then retrieve a random entry in nwscript.

  • No labels