Skyrim Special Edition

This article describes in more technical details how exactly NND distributes names and how you can create your own naming mod based on NND. So, without further ado, let's get into it.

Glossary
A short overview of the terminology used in this guide.
Spoiler:  
Show

  • Display Name: A final name that will be displayed on screen.
  • Original Name: A name that the game would've used by default.
  • Name: The primary segment of the display name that conveys a unique identity of an NPC.
  • Title: A secondary segment of the display name that is used to convey NPC's role or other auxiliary information about them.
  • Obscuring Name: An alternative display name which is used to describe an unknown NPCs by their looks.
  • Name Definition: A configuration file that contains Name Segments and defines how those segments are combined.
  • Name Segment: A part of the name that will be used to assemble a Full Name.
  • Names Variant: A list of possible names for a single Name Segment associated with a single condition. (For now - only male/female/any).
  • Adfix: A list of words/syllables or otherwise any text that can be appended to either end of the Name Segment.
  • Conjunctions: A list of any text that can be used to combine Name Segments. By default this is a whitespace (" ").
  • Scope: Defines where given Name Definition is applicable. There are 3 possible scopes: NameTitleObscuring.
  • Priority: Used to order multiple Name Definitions that are assigned to a single NPC.
  • Name Definition Keywords: Custom Keywords that match a file name of an associated Name Definition.
  • Behavior Keywords: Special Keywords reserved by NND. These are automatically created at the start of the game.
  • NNDUnique: Marks NPC as unique. Such NPCs don't get a Name distributed to them.
  • NNDNotUnique: Excludes NPC from getting NNDUnique. Effectively, forcing Name distribution.
  • NNDDisableDefaultTitle: Marks NPC that their original name cannot be used as a Title.
  • NNDEnableDefaultTitle: Excludes NPC from getting NNDDisableDefaultTitle. Effectively, forcing Title distribution.
  • NNDDisableDefaultObscurity: Marks NPC that their original name cannot be used as a Obscuring Name.
  • NNDEnableDefaultObscurity: Excludes NPC from getting NNDDisableDefaultObscurity. Effectively forcing Obscuring Name distribution.
  • NNDKnown: Marks NPC as known. Such NPCs never get an Obscuring Name.
  • NNDObscure: Excludes NPCs from getting NNDKnown. Effectively, forcing Obscurity.


Distribution

Distribution happens in two phases:

  • First, SPID distributes all NNDKeyword and Name Definition Keywords.
  • After that NND processes NPCs when they are loaded for the first and generates NameTitleObscuring Name according to preconfigured rules in Name Definitions, caches the results and uses it later when NPCs name should appear on screen.


Keywords

Keywords are fundamental element of the names distribution. Using Keywords you can both alter behavior of the NND and provide new Name Definitions to be used for specific NPCs.

Behavior Keywords

These are predefined Keywords that are created at the start of the game. They are used to tell NND how to treat a particular NPC.
With Behavior Keywords you create patches for other mods and/or tailor naming strategy to your preferences.

NNDUnique | -NNDNotUnique

NNDUnique is a Behavior Keyword that marks NPC as unique. NND will not create a Name for such NPCs and will forward NPC's original name untouched.

For example, NND by default distributes NNDUnique to all NPCs who've been marked as Unique by the game itself:

Keyword = NNDUnique|-NNDNotUnique|NONE|NONE|U
NNDNotUnique
 is a counterpart of NNDUnique and is used to negate the effect of the first one. In general it is used to add exceptions to NNDUnique. For example, NND uses it to exclude Unique NPCs who in fact doesn't have a name (as seen in the example above).

If you develop a naming mod that must target unique NPCs to modify their Names you'd want to exclude those NPCs from NNDUnique to be able to do that.

IMPORTANT:
 You should always distribute NNDUnique with -NNDNotUnique as the first filter.
This will make your distribution compatible with others, who might want to exclude certain NPCs.


NNDDisableDefaultTitle | -NNDEnableDefaultTitle

Migrating from NND 1:
Spoiler:  
Show

These keywords correspond to NNDTitleless and NNDExcludedTitleless from previous version.
NND 2 will automatically proxy these old keywords to new ones.


NNDDisableDefaultTitle is a Behavior Keyword that marks NPCs to hint NND that their original name should not be used as a Default Title.

For example, if you don't want a decent Nord guy Torvar Stormwall to be labeled "Torvar Stormwall - Nord" you can add this distribution:

Keyword = NNDDisableDefaultTitle|-NNDEnableDefaultTitle,Nord

NNDEnableDefaultTitle is a counterpart of NNDDisableDefaultTitle and is used to negate the effect of the first one.

IMPORTANT:
if you should always distribute NNDEnableDefaultTitle with -NNDDisableDefaultTitle as the first filter.
This will make your distribution compatible with others, who might want to exclude certain NPCs.


NNDDisableDefaultObscurity | -NNDEnableDefaultObscurity

NNDDisableDefaultObscurity is a Behavior Keyword that marks NPCs to hint NND that their original name should not be used as an Obscuring Name.

Similarly to Title-related keywords it allows you to exclude NPCs whose original name wouldn't make sense as Obscuring Name. For example, unique named NPCs who has real names as their original names would make Obscuring Name absolutely pointless.

To avoid this NND adds the following distribution:

Keyword = NNDDisableDefaultObscurity|-NNDEnableDefaultObscurity,NNDUnique
NNDEnableDefaultObscurity is a counterpart of NNDDisableDefaultObscurity and is used to negate the effect of the first one.

IMPORTANT:
You should always distribute NNDEnableDefaultObscurity with -NNDDisableDefaultObscurity as the first filter.
This will make your distribution compatible with others, who might want to exclude certain NPCs.

NNDKnown | -NNDObscure

NNDKnown is a Behavior Keyword that marks NPCs as excluded from Obscuring system. For example, to make Belethor's name known without speaking to him we can use the following distribution:

Keyword = NNDKnown|-NNDObscure,Belethor

NNDObscure is a counterpart of NNDKnown and is used to negate the effect of the first one.

IMPORTANT:
You should always distribute NNDKnown with -NNDObscure as the first filter.
This will make your distribution compatible with others, who might want to exclude certain NPCs.


Name Definition Keywords

All other Keywords that match a name of any existing Name Definitions are considered to be Name Definition Keywords. Such keywords indicate from which Name Definitions NND should pick a name for each NPC.

NPC can have multiple Name Definition Keywords distributed from different mods. NND will resolve the name by ordering corresponding Name Definitions by their priorities. More on that later.

If NPC doesn't have any Name Definition Keywords NND will skip them.

While you technically can have a Name Definition named exactly like one of the Behavior Keywords, you should avoid doing so :)

Migration from NND 1:
Spoiler:  
Show

Previously, these keywords could also have a custom priority added as a suffix (e.g. NNDForsworn_Faction).
In NND 2, priorities are defined directly in a Name Definition file, so all Name Definition Keywords should match the file names exactly, with no suffixes and excluding extension (e.g. for NNDForsworn.json a matching keyword is NNDForsworn).
NND 2 will automatically find usages of priorities in keywords and move them to corresponding Name Definitions.



Name Definition

Name Definition
 is a sort of configuration file, that contains a list of name segments for NND to assemble a name from.

Name Definitions are stored in folder at Data/SKSE/Plugins/NPCsNamesDistributor. Files will be read exactly once at game launch and be cached until the end of the current session.

Structure

Migration from NND 1:
Spoiler:  
Show

Most of the structure remains the same. There are a couple of notable changes, though:
  • All sections no longer have a "NND_" prefix: This was a necessity in NND 1 because those keys were passed to Papyrus, where strings are case insensitive and reusable, which could cause problems when getting sections by their keys.
  • Given/Family renamed to First/Last: For universal naming after addition of Middle segment.
  • Deleted Name Definition Chance: This one is redundant since top-level distribution chance can be controlled through SPID.
  • Flatten Behaviors sections: Those only provided redundant extra nesting with no benefit. All options from Behaviors were moved directly to where Behaviors previously were.
  • Combine renamed to Inherit: This should convey the meaning of this option clearer.


Name Definition at a gist is a JSON file that has a specific structure.

At the root there are 4 main sections:
  • First Name: Defines a pool of names and corresponding options for the First Name Segment.
  • Middle Name: Defines a pool of names and corresponding options for the Middle Name Segment.
  • Last Name: Defines a pool of names and corresponding options for the Last Name Segment.
  • Conjunctions: Defines how Name Segments should be combined together. By default, it's a simple whitespace, but you can configure it to be anything you want.

Related JSON structure:
Spoiler:  
Show

{
"First": {...},
"Middle": {...},
"Last": {...},
"Conjunctions": {...}
}


Each of these sections can be skipped, but you'd want to have at least one Name Segment so that Name Definition would make sense.

Name Segment section contains nested sections, where each describes a Names Variant:
  • MaleNames Variant suitable for male NPCs.
  • FemaleNames Variant suitable for female NPCs.
  • AnyNames Variant that fits either of the above.

Related JSON structure:

Spoiler:  
Show

{
"Male": {...},
"Female": {...},
"Any": {...}
}


Again, each of these is optional. If Male or Female Names Variant is missing NND will fall back to Any Names Variant.
So, for example, if Male Names Variant is not defined, then rules from Any Names Variant will apply for male NPCs. If both are missing, then no male NPCs will get a name from this particular Name Definition.

Names Variant section contains:
  • Names: An actual list of names from which NND will randomly pick one for each NPC.
  • Chance: A chance for any name to be chosen. 100 - A name will always be picked, 0 - no name will ever be picked from that Name Definition for this Names Variant.
  • Prefix: Also has Names/Chance values, that are used to define a list of prefixes and the chance for a prefix to be picked.
  • Suffix: Identical to Prefix, but is appended to the end of the Name Segment.

Related JSON structure:
Spoiler:  
Show

{
"Names": [],
"Chance": 100,
"Prefix": {
"Names": [],
"Chance": 100
},
"Suffix": {
"Names": [],
"Chance": 100
}
}


Lastly, Conjunctions. These are used to connect Name Segments if more than one was picked. Conjunctions can also be configured per each Names Variant with the same rules.

Related JSON structure:
Spoiler:  
Show

{
"Male": [],
"Female": [],
"Any": []
}


Name Resolution

When it's time for NND to pick a name for a particular NPC it fetches all Name Definition Keywords that were distributed to that NPC and builds a queue of corresponding Name Definitions. This queue is ordered based on Name Definitions' Priorities. If they have the same Priority then an alphabetical order is used.

NND then goes through that queue and queries each Name Definition to provide a name. By default, such query is considered to be successful if Name Definition returns at least one Name Segment, otherwise current Name Definition is skipped and NND moves on to the next. This process continues until either a name is found or no more Name Definitions present in the queue. In the latter case distribution will fail and NPC will use their original name.

Names might be skipped when any of the following scenarios happen (as well as any combination of them):

  • Name Definition defines a certain chance for a Name Segment to be picked.
  • Name Definition doesn't have Name Segments at all.
  • Name Definition contains Name Segments that doesn't have matching Names Variant.

Inheritance

The resolution process described above is quite strict. It will use the first minimal result and finish. But sometimes you'd want to define only one Name Segment or make your Name Segments have a chance to be skipped. Instead, you want to let other Name Definitions to pick missing Name Segments for you. In such cases you define Inheritance.

Inheritance allows you to specify which Name Segments you want to inherit from Name Definitions down the queue.

Note that Inheritance is not transitive, meaning that it only applies to the Name Definition that defines it. So, if one Name Definition with Inheritance passes control to another Name Definition that doesn't define Inheritance and it fails to pick a name then the final result will have only one part that was originally picked by the first Name Definition.

You can define Inheritance inside each Name Segment section.

Related JSON structure:
Spoiler:  
Show

{
"Male": {...},
"Female": {...},
"Any": {...},
"Inherit": true
}


Priorities

When processing a Queue of Name Definitions cases NND will process these Name Definitions in alphabetical order. It should be enough most of the times, however sometimes you'd want to ensure that one Name Definition is processed before another regardless of their names.

For that NPCs Names Distributor provides 5 priority levels, that are loosely based on certain traits of NPCs.
Here is the list of them from lowest to highest:
  • Race: Base names specific to races or otherwise a large group that shares an innate trait that cannot be changed. This is the default one and may be omitted.
  • Class: Names for a narrower group that shares an innate trait, which also cannot be changed
  • Faction: Names for a medium sized group that are united by some common idea or belief, that are scattered across the world.
  • Clan: Names for a small group that are united by some common idea or belief, but typically located in a single area.
  • Individual: Names for distinct individuals that are usually hand-picked.

The priority can be set at a top-level section of Name Definition.

Related JSON structure:
Spoiler:  
Show

{
"First": {...},
"Middle": {...},
"Last": {...},
"Conjunctions": {...},
"Priority": "Race"
}


Scopes

Scopes define where a Name Definition can be applied. There are 3 possible scopes:

  • NameName Definition is used to pick Names.
  • TitleName Definition is used to pick Titles.
  • ObscuringName Definition is used to pick Obscuring Names.

Scopes can be set at a top-level section of Name Definition. By default, all Name Definitions have a Name scope.

Related JSON structure:
Spoiler:  
Show

{
"First": {...},
"Middle": {...},
"Last": {...},
"Conjunctions": {...},
"Scopes": ["Name"]
}


Name Definitions
 can have multiple scopes, which make it an eligible pool of names for each scope. When a Name Definition has multiple scopes NND will chose separate names from that Name Definition for each scope.

There is one exception, however - Obscuring Titles. When a Name Definition declares exactly two scopes (Title and Obscuring) these two scopes will be linked. For linked scopes NND will pick only one name and will apply it for corresponding scopes.
NND picks names from each scope in the following order: NameTitleObscuring.


Short Names


Shortened list specifies which Name Segments can be used to form a Short Name. When not set, Name Definition won't allow Short Name and a Full Name will always be used.

Related JSON structure:
Spoiler:  
Show

{
"First": {...},
"Middle": {...},
"Last": {...},
"Conjunctions": {...},
"Shortened": ["First"]
}



Examples

There are three files under the misc files section that you can use to try out this mod as well as play around with it. Also, as a side effect, examples illustrate how multiple "mods" that use NND automatically resolve their conflicts based on priorities.


NNDEmptyExample


An empty Name Definition named NNDEmptyExample.json - It has all sections described above with comments and default values, so you could take a look at a complete structure or use it as a template to start creating your own definitions.


Lydia Impostors

You just realized that every female you meet is just a Lydia's impostor! You can only trust Gerda (one of the ladies in Dragonsreach) and the Lydia itself, who now has to tell everyone that she is the only true Lydia :) 

This example showcases
  • A simple name generation 
  • Distribution to specific category of NPCs (females),
  • Priorities
  • An exclusion of a single NPC
  • Disabling default Titles (original name).
  • Using Definition's "Skip" behavior that has a chance to not make someone an impostor.


Warrior Titles

Brave people who dedicate their lives to become great Warriors adopt a telling title to reflect their zeal, instead of their Last name. As such, you would meet notable warriors who call themselves "Rockbreaker", "Strong-Heart" and "Fireheart".

This example specifically features Inheritance option. It distributes a few random names to each and every NPC (First and Last). And creates a Name Definition that is specific to Warrior class (one-handed and two-handed). This Definition only provides Last names (with some customization applied through prefixes and suffixes). First names in this Definition are set to be inherited. As such NND uses specific Last names for Warriors and combines them with default First names from the default Definition.

Article information

Added on

Edited on

Written by

sasnikol

0 comments