Пример #1
0
        // Gets random Redguard name which follows 0+1+2+3 (male), 0+1+2+4 (female) pattern
        string GetRandomRedguardName(NameBank nameBank, Genders gender)
        {
            // Get set parts
            string[] partsA, partsB, partsC, partsD;
            if (gender == Genders.Male)
            {
                partsA = nameBank.sets[0].parts;
                partsB = nameBank.sets[1].parts;
                partsC = nameBank.sets[2].parts;
                partsD = nameBank.sets[3].parts;
            }
            else
            {
                partsA = nameBank.sets[0].parts;
                partsB = nameBank.sets[1].parts;
                partsC = nameBank.sets[2].parts;
                partsD = nameBank.sets[4].parts;
            }

            // Generate strings
            string stringA = partsA[DFRandom.random_range(partsA.Length)];
            string stringB = partsB[DFRandom.random_range(partsB.Length)];
            string stringC = partsC[DFRandom.random_range(partsC.Length)];
            string stringD = partsD[DFRandom.random_range(partsD.Length)];

            return(stringA + stringB + stringC + stringD);
        }
Пример #2
0
        void SetFoeName()
        {
            // Set type name with fallback
            MobileEnemy enemy;

            if (EnemyBasics.GetEnemy(foeType, out enemy))
            {
                typeName = enemy.Name;
            }
            else
            {
                typeName = foeType.ToString();
            }

            // Monster types get a random monster name
            // Always treating monsters as male for now as they don't have any gender in game files
            if ((int)foeType < 128)
            {
                DFRandom.srand(DateTime.Now.Millisecond + DFRandom.random_range(1, 1000000));
                displayName = DaggerfallUnity.Instance.NameHelper.MonsterName();
                return;
            }

            // Randomly assign a gender for humanoid foes
            humanoidGender = (UnityEngine.Random.Range(0.0f, 1.0f) < 0.55f) ? Genders.Male : Genders.Female;

            // Create a random display name for humanoid foes
            DFRandom.srand(DateTime.Now.Millisecond);
            NameHelper.BankTypes nameBank = GameManager.Instance.PlayerGPS.GetNameBankOfCurrentRegion();
            displayName = DaggerfallUnity.Instance.NameHelper.FullName(nameBank, humanoidGender);
        }
Пример #3
0
        // Gets random surname for names that follow 4+5 pattern
        string GetRandomSurname(NameBank nameBank)
        {
            // Get set parts
            string[] partsA, partsB;
            partsA = nameBank.sets[4].parts;
            partsB = nameBank.sets[5].parts;

            // Generate strings
            string stringA = partsA[DFRandom.random_range(partsA.Length)];
            string stringB = partsB[DFRandom.random_range(partsB.Length)];

            return(stringA + stringB);
        }
Пример #4
0
        // Get random monster name which follows 0+1 (50% +2)
        string GetRandomMonsterName(Genders gender)
        {
            NameBank nameBank = bankDict[BankTypes.MonsterName];

            // Get set parts
            string[] partsA, partsB, partsC;
            partsA = nameBank.sets[0].parts;
            partsB = nameBank.sets[1].parts;
            partsC = nameBank.sets[2].parts;

            // Generate strings
            string stringA = partsA[DFRandom.random_range(partsA.Length)];
            string stringB = partsB[DFRandom.random_range(partsB.Length)];
            string stringC = (UnityEngine.Random.Range(0f, 1f) < 0.5f) ? partsC[DFRandom.random_range(partsC.Length)] : string.Empty;

            return(stringA + stringB + stringC);
        }
Пример #5
0
        //
        // -= Rules For Name Generation, By Bank =-
        //
        // Breton:
        //  Male FirstName          : Sets 0 + 1
        //  Female FirstName        : Sets 2 + 3
        //  Surname                 : Sets 4 + 5
        //
        // Redguard:
        //  Male FullName           : Sets 0 + 1 + 2 + 3
        //  Female FullName         : Sets 0 + 1 + 2 + 4
        //
        // Nord:
        //  Male FirstName          : Sets 0 + 1
        //  Female FirstName        : Sets 2 + 3
        //  Surname (Use Breton)    : Sets 4 + 5
        //
        // Noble:
        //  Title                   : Sets 0
        //  FullName                : Sets 1 + 2 + 3
        //
        // Imperial:
        //  Male FirstName          : Sets 0 + 1
        //  Female FirstName        : Sets 2 + 3
        //  Surname                 : Sets 4 + 5
        //
        // DarkElf:
        //  Male FirstName          : Sets 0 + 1
        //  Female FirstName        : Sets 2 + 3
        //  Surname                 : Sets 4 + 5
        //
        // HighElf:
        //  Male FirstName          : Sets 0 + 1
        //  Female FirstName        : Sets 2 + 3
        //  Surname                 : Sets 4 + 5
        //
        // WoodElf:
        //  Male FirstName          : Sets 0 + 1
        //  Female FirstName        : Sets 2 + 3
        //  Surname                 : Sets 4 + 5
        //
        // Location1:
        //  Masculine FirstName     : Sets 0 + 1
        //  Feminine FirstName      : Sets 2 + 3
        //  Surname                 : Sets 4 + 5
        //
        // Location2:
        //  FullName                : Sets 0 + 1 + 2
        //
        // Location3:
        //  Masculine FullName      : Sets 0 + 1 + 2
        //  Feminine FullName       : Sets 0 + 1 + 2 + 3
        //
        // -= END =-
        //

        // Gets random first name by gender for names that follow 0+1 (male), 2+3 (female) pattern
        string GetRandomFirstName(NameBank nameBank, Genders gender)
        {
            // Get set parts
            string[] partsA, partsB;
            if (gender == Genders.Male)
            {
                partsA = nameBank.sets[0].parts;
                partsB = nameBank.sets[1].parts;
            }
            else
            {
                partsA = nameBank.sets[2].parts;
                partsB = nameBank.sets[3].parts;
            }

            // Generate strings
            string stringA = partsA[DFRandom.random_range(partsA.Length)];
            string stringB = partsB[DFRandom.random_range(partsB.Length)];

            return(stringA + stringB);
        }
Пример #6
0
        // Get random monster name which follows 0+(random 1 or 2) + 3 (if feminine)
        string GetRandomMonsterName(Genders gender)
        {
            NameBank nameBank = bankDict[BankTypes.MonsterName];

            // Get set parts
            string[] partsA, partsB;
            partsA = nameBank.sets[0].parts;
            partsB = (UnityEngine.Random.Range(0f, 1f) < 0.5f) ? nameBank.sets[1].parts : nameBank.sets[2].parts;

            // Generate strings
            string stringA = partsA[DFRandom.random_range(partsA.Length)];
            string stringB = partsB[DFRandom.random_range(partsB.Length)];

            // Attach femimine suffix
            string stringC = string.Empty;

            if (gender == Genders.Female)
            {
                string[] partsC = nameBank.sets[3].parts;
                stringC = partsC[DFRandom.random_range(partsC.Length)];
            }

            return(stringA + stringB + stringC);
        }
        public static string GetName(int seed, DFLocation.BuildingTypes type, int factionID, string locationName, string regionName)
        {
            const string firstNameTitleVar = "%ef";
            const string cityNameTitleVar  = "%cn";
            const string royalTitleVar     = "%rt";

            string a = string.Empty, b = string.Empty;
            string result = string.Empty;

            bool singleton = false;

            FactionFile.FactionData factionData;
            DFRandom.srand(seed);
            switch (type)
            {
            case DFLocation.BuildingTypes.HouseForSale:
                return("House for sale");

            case DFLocation.BuildingTypes.Tavern:
                b = TavernsB[DFRandom.random_range(0, TavernsB.Length)];
                a = TavernsA[DFRandom.random_range(0, TavernsA.Length)];
                break;

            case DFLocation.BuildingTypes.GeneralStore:
                b = GeneralStoresB[DFRandom.random_range(0, GeneralStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.WeaponSmith:
                b = WeaponStoresB[DFRandom.random_range(0, WeaponStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Armorer:
                b = ArmorStoresB[DFRandom.random_range(0, ArmorStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Bookseller:
                b = BookStoresB[DFRandom.random_range(0, BookStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.ClothingStore:
                b = ClothingStoresB[DFRandom.random_range(0, ClothingStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Alchemist:
                b = AlchemyStoresB[DFRandom.random_range(0, AlchemyStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.GemStore:
                b = GemStoresB[DFRandom.random_range(0, GemStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.PawnShop:
                b = PawnStoresB[DFRandom.random_range(0, PawnStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.FurnitureStore:
                b = FurnitureStoresB[DFRandom.random_range(0, FurnitureStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Library:
                b = LibraryStoresB[DFRandom.random_range(0, LibraryStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Bank:
                // Banks always appear to be named "The Bank of RegionName"
                b = regionName;
                a = "The Bank of";
                break;

            case DFLocation.BuildingTypes.GuildHall:
                // Guild halls get the name from faction data
                if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionID, out factionData))
                {
                    a         = factionData.name;
                    singleton = true;
                }
                break;

            case DFLocation.BuildingTypes.Temple:
                // Temples get name from faction data - always seem to be first child of factionID
                if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionID, out factionData))
                {
                    if (factionData.children.Count > 0)
                    {
                        FactionFile.FactionData firstChild;
                        if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionData.children[0], out firstChild))
                        {
                            a         = firstChild.name;
                            singleton = true;
                        }
                    }
                }
                break;

            case DFLocation.BuildingTypes.Palace:
                // Main palace names come from TEXT.RSC (e.g. "Castle Daggerfall")
                // Other palaces are just named "Palace" (still need to confirm behaviour)
                int textId = 0;
                if (locationName == "Daggerfall")
                {
                    textId = 475;
                }
                else if (locationName == "Wayrest")
                {
                    textId = 476;
                }
                else if (locationName == "Sentinel")
                {
                    textId = 477;
                }

                if (textId > 0)
                {
                    TextFile.Token[] nameTokens = DaggerfallUnity.Instance.TextProvider.GetRSCTokens(textId);
                    foreach (TextFile.Token token in nameTokens)
                    {
                        if (token.formatting == TextFile.Formatting.Text)
                        {
                            a = token.text;
                            break;
                        }
                    }
                    a = a.TrimEnd('.');     // remove character '.' from castle text record entry if it is last character
                }
                else
                {
                    a = "Palace";
                }
                singleton = true;
                break;

            default:
                // Do nothing for unknown/unsupported building type
                // Houses can actually change names based on active quests
                return(string.Empty);
            }

            // Replace %cn
            a = a.Replace(cityNameTitleVar, locationName);

            // Replace %ef
            if (a.Contains(firstNameTitleVar))
            {
                // Need to burn a rand() for %ef roll to be correct
                // What is Daggerfall rolling here?
                DFRandom.rand();

                // Observation finds nameplates only seem to use male Breton namebank
                string firstName = DaggerfallUnity.Instance.NameHelper.FirstName(NameHelper.BankTypes.Breton, Game.Entity.Genders.Male);
                a = a.Replace(firstNameTitleVar, firstName);
            }

            // Replace %rt based on faction ruler
            if (a.Contains(royalTitleVar))
            {
                a = a.Replace(royalTitleVar, MacroHelper.RegentTitle(null));
            }

            // Final text is "{a} {b}" for two-part names or just "{a}" for singleton names
            if (!singleton)
            {
                result = string.Format("{0} {1}", a, b);
            }
            else
            {
                result = a;
            }

            return(result);
        }
Пример #8
0
        public static string GetName(int seed, DFLocation.BuildingTypes type, int factionID, string locationName, string regionName)
        {
            const string firstNameTitleVar = "%ef";
            const string cityNameTitleVar  = "%cn";
            const string royalTitleVar     = "%rt";

            string a = string.Empty, b = string.Empty;
            string result = string.Empty;

            bool singleton = false;

            FactionFile.FactionData factionData;
            DFRandom.srand(seed);
            switch (type)
            {
            case DFLocation.BuildingTypes.HouseForSale:
                return("House for sale");

            case DFLocation.BuildingTypes.Tavern:
                b = TavernsB[DFRandom.random_range(0, TavernsB.Length)];
                a = TavernsA[DFRandom.random_range(0, TavernsA.Length)];
                break;

            case DFLocation.BuildingTypes.GeneralStore:
                b = GeneralStoresB[DFRandom.random_range(0, GeneralStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.WeaponSmith:
                b = WeaponStoresB[DFRandom.random_range(0, WeaponStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Armorer:
                b = ArmorStoresB[DFRandom.random_range(0, ArmorStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Bookseller:
                b = BookStoresB[DFRandom.random_range(0, BookStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.ClothingStore:
                b = ClothingStoresB[DFRandom.random_range(0, ClothingStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Alchemist:
                b = AlchemyStoresB[DFRandom.random_range(0, AlchemyStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.GemStore:
                b = GemStoresB[DFRandom.random_range(0, GemStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.PawnShop:
                b = PawnStoresB[DFRandom.random_range(0, PawnStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.FurnitureStore:
                b = FurnitureStoresB[DFRandom.random_range(0, FurnitureStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Library:
                b = LibraryStoresB[DFRandom.random_range(0, LibraryStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Bank:
                // Banks always appear to be named "The Bank of RegionName"
                b = regionName;
                a = "The Bank of";
                break;

            case DFLocation.BuildingTypes.GuildHall:
                // Guild halls get the name from faction data
                if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionID, out factionData))
                {
                    a         = factionData.name;
                    singleton = true;
                }
                break;

            case DFLocation.BuildingTypes.Temple:
                // Temples get name from faction data - always seem to be first child of factionID
                if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionID, out factionData))
                {
                    if (factionData.children.Count > 0)
                    {
                        FactionFile.FactionData firstChild;
                        if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionData.children[0], out firstChild))
                        {
                            a         = firstChild.name;
                            singleton = true;
                        }
                    }
                }
                break;

            case DFLocation.BuildingTypes.Palace:
                // Main palace names (e.g. "Castle Daggerfall" appear to be hardcoded in FALL.EXE
                // Other palaces are just named "Palace"
                // Need to confirm behaviour before implementing
                // Just calling everything "Palace" for now.
                a         = "Palace";
                singleton = true;
                break;

            default:
                // Do nothing for unknown/unsupported building type
                // Houses can actually change names based on active quests
                return(string.Empty);
            }

            // Replace %cn
            a = a.Replace(cityNameTitleVar, locationName);

            // Replace %ef
            if (a.Contains(firstNameTitleVar))
            {
                // Need to burn a rand() for %ef roll to be correct
                // What is Daggerfall rolling here?
                DFRandom.rand();

                // Observation finds nameplates only seem to use male Breton namebank
                string firstName = DaggerfallUnity.Instance.NameHelper.FirstName(NameHelper.BankTypes.Breton, Game.Entity.Genders.Male);
                a = a.Replace(firstNameTitleVar, firstName);
            }

            // Replace %rt based on faction ruler
            if (a.Contains(royalTitleVar))
            {
                // Get factionID of this region
                FactionFile factionFile       = DaggerfallUnity.Instance.ContentReader.FactionFileReader;
                int         regionalFactionID = factionFile.GetFactionID(regionName);
                if (regionalFactionID != -1)
                {
                    // Get faction data
                    if (factionFile.GetFactionData(factionID, out factionData))
                    {
                        // Get ruler title for this region
                        string royalTile = RoyalTitles[factionData.ruler];
                        a = a.Replace(royalTitleVar, royalTile);
                    }
                }
            }

            // Final text is "{a} {b}" for two-part names or just "{a}" for singleton names
            if (!singleton)
            {
                result = string.Format("{0} {1}", a, b);
            }
            else
            {
                result = a;
            }

            return(result);
        }
Пример #9
0
        public static string GetName(int seed, DFLocation.BuildingTypes type, int factionID, string locationName, string regionName)
        {
            const string firstNameTitleVar = "%ef";
            const string cityNameTitleVar  = "%cn";
            const string royalTitleVar     = "%rt";

            string a = string.Empty, b = string.Empty;
            string result = string.Empty;

            bool singleton = false;

            FactionFile.FactionData factionData;
            DFRandom.srand(seed);
            switch (type)
            {
            case DFLocation.BuildingTypes.HouseForSale:
                return("House for sale");

            case DFLocation.BuildingTypes.Tavern:
                b = TavernsB[DFRandom.random_range(0, TavernsB.Length)];
                a = TavernsA[DFRandom.random_range(0, TavernsA.Length)];
                break;

            case DFLocation.BuildingTypes.GeneralStore:
                b = GeneralStoresB[DFRandom.random_range(0, GeneralStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.WeaponSmith:
                b = WeaponStoresB[DFRandom.random_range(0, WeaponStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Armorer:
                b = ArmorStoresB[DFRandom.random_range(0, ArmorStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Bookseller:
                b = BookStoresB[DFRandom.random_range(0, BookStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.ClothingStore:
                b = ClothingStoresB[DFRandom.random_range(0, ClothingStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Alchemist:
                b = AlchemyStoresB[DFRandom.random_range(0, AlchemyStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.GemStore:
                b = GemStoresB[DFRandom.random_range(0, GemStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.PawnShop:
                b = PawnStoresB[DFRandom.random_range(0, PawnStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.FurnitureStore:
                b = FurnitureStoresB[DFRandom.random_range(0, FurnitureStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Library:
                b = LibraryStoresB[DFRandom.random_range(0, LibraryStoresB.Length)];
                a = StoresA[DFRandom.random_range(0, StoresA.Length)];
                break;

            case DFLocation.BuildingTypes.Bank:
                // Banks always appear to be named "The Bank of RegionName"
                b = regionName;
                a = "The Bank of";
                break;

            case DFLocation.BuildingTypes.GuildHall:
                // Guild halls get the name from faction data
                if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionID, out factionData))
                {
                    a         = factionData.name;
                    singleton = true;
                }
                break;

            case DFLocation.BuildingTypes.Temple:
                // Temples get name from faction data - always seem to be first child of factionID
                if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionID, out factionData))
                {
                    if (factionData.children.Count > 0)
                    {
                        FactionFile.FactionData firstChild;
                        if (DaggerfallUnity.Instance.ContentReader.FactionFileReader.GetFactionData(factionData.children[0], out firstChild))
                        {
                            a         = firstChild.name;
                            singleton = true;
                        }
                    }
                }
                break;

            case DFLocation.BuildingTypes.Palace:
                // Main palace names come from TEXT.RSC (e.g. "Castle Daggerfall")
                // Other palaces are just named "Palace" (still need to confirm behaviour)
                int textId = 0;
                if (locationName == "Daggerfall")
                {
                    textId = 475;
                }
                else if (locationName == "Wayrest")
                {
                    textId = 476;
                }
                else if (locationName == "Sentinel")
                {
                    textId = 477;
                }

                if (textId > 0)
                {
                    TextFile.Token[] nameTokens = DaggerfallUnity.Instance.TextProvider.GetRSCTokens(textId);
                    foreach (TextFile.Token token in nameTokens)
                    {
                        if (token.formatting == TextFile.Formatting.Text)
                        {
                            a = token.text;
                            break;
                        }
                    }
                    a = a.TrimEnd('.');     // remove character '.' from castle text record entry if it is last character
                }
                else
                {
                    a = "Palace";
                }
                singleton = true;
                break;

            default:
                // Do nothing for unknown/unsupported building type
                // Houses can actually change names based on active quests
                return(string.Empty);
            }

            // Replace %cn
            a = a.Replace(cityNameTitleVar, locationName);

            // Replace %ef
            if (a.Contains(firstNameTitleVar))
            {
                // Need to burn a rand() for %ef roll to be correct.
                // Classic is always doing this when expanding a macro.
                DFRandom.rand();

                // In classic, the function expanding the %ef macro uses a global variable containing the current
                // region race. However, this variable is never updated when the character travels
                // and remains at 0. This explains why the Breton name bank is always used for shops.
                // This global variable is probably a leftover from Daggerfall early development as,
                // with the exception of %lp, which presents a similar issue and always returns
                // "High Rock", all naming functions use a global array of 62 fixed race values, one for each region.
                // As with %lp, we choose to fix the original bug in DFU and use this array, meaning that
                // all shops in Hammerfell now use Redguard names.
                NameHelper.BankTypes nameBank = (NameHelper.BankTypes)MapsFile.RegionRaces[GameManager.Instance.PlayerGPS.CurrentRegionIndex];
                string firstName = DaggerfallUnity.Instance.NameHelper.FirstName(nameBank, Game.Entity.Genders.Male);
                a = a.Replace(firstNameTitleVar, firstName);
            }

            // Replace %rt based on faction ruler
            if (a.Contains(royalTitleVar))
            {
                a = a.Replace(royalTitleVar, MacroHelper.RegentTitle(null));
            }

            // Final text is "{a} {b}" for two-part names or just "{a}" for singleton names
            if (!singleton)
            {
                result = string.Format("{0} {1}", a, b);
            }
            else
            {
                result = a;
            }

            return(result);
        }