// Sets gender and display name // Has some logic to handle individual faction objects and certain flat limitations void AssignDisplayName() { // Witches and prostitutes only have female flats in Daggerfall if (factionData.type == (int)FactionFile.FactionTypes.WitchesCoven || factionData.id == 512) { npcGender = Genders.Female; } // Assign name - some types have their own individual name to use if ((factionData.type == (int)FactionFile.FactionTypes.Individual || factionData.type == (int)FactionFile.FactionTypes.Daedra) && factionData.id != 0) { // Use individual name displayName = factionData.name; } else { // Set a name seed if not configured if (nameSeed == -1) { nameSeed = DateTime.Now.Millisecond; } // Generate a random name based on gender and race name bank DFRandom.srand(nameSeed); displayName = DaggerfallUnity.Instance.NameHelper.FullName(nameBank, npcGender); } }
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); displayName = DaggerfallUnity.Instance.NameHelper.MonsterName(); return; } // TODO: Create a random humanoid foe name // Will get to this testing quests that assign player to defeat and return a class-based NPC Foe // Have more problems to solve before getting to name }
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); displayName = DaggerfallUnity.Instance.NameHelper.MonsterName(); return; } // Randomly assign a gender for humanoid foes humanoidGender = (UnityEngine.Random.Range(0.0f, 1.0f) < 0.5f) ? 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); }
// Sets gender and display name // Has some logic to handle individual faction objects and certain flat limitations void AssignDisplayName(string genderName) { // Set gender npcGender = GetGender(genderName); // Witches only have female flats if (factionData.type == (int)FactionFile.FactionTypes.WitchesCoven) { npcGender = Genders.Female; } // Get name bank NameHelper.BankTypes bankType = GameManager.Instance.PlayerGPS.GetNameBankOfCurrentRegion(); // Assign name - some types have their own individual name to use if (factionData.type == (int)FactionFile.FactionTypes.Individual || factionData.type == (int)FactionFile.FactionTypes.Daedra) { // Use individual name displayName = factionData.name; } else { // Set a name seed if not configured if (nameSeed == -1) { nameSeed = DateTime.Now.Millisecond; } // Generate a random name based on gender and race name bank DFRandom.srand(nameSeed); displayName = DaggerfallUnity.Instance.NameHelper.FullName(bankType, npcGender); } }
// Creates a career-based NPC like a Shopkeeper or Banker void SetupCareerAllianceNPC(string careerAllianceName) { // Special handling for Questor class // Will revisit this later when guilds are more integrated if (careerAllianceName.Equals("Questor", StringComparison.InvariantCultureIgnoreCase)) { if (SetupQuestorNPC()) { return; } } // Get faction data int factionID = GetCareerFactionID(careerAllianceName); if (factionID != -1) { FactionFile.FactionData factionData = GetFactionData(factionID); // Setup Person resource DFRandom.srand(Time.frameCount); this.factionData = factionData; } else { Debug.LogErrorFormat("SetupCareerAllianceNPC() failed to setup {0}", careerAllianceName); } }
// Sets gender and display name // Has some logic to handle individual faction objects and certain flat limitations void AssignDisplayName() { // Witches only have female flats if (factionData.type == (int)FactionFile.FactionTypes.WitchesCoven) { npcGender = Genders.Female; } // Get name bank - supports more races than are found in FACTION.TXT NameHelper.BankTypes bankType; switch (race) { case Races.Redguard: bankType = NameHelper.BankTypes.Redguard; break; case Races.Nord: bankType = NameHelper.BankTypes.Nord; break; case Races.DarkElf: bankType = NameHelper.BankTypes.DarkElf; break; case Races.HighElf: bankType = NameHelper.BankTypes.HighElf; break; case Races.WoodElf: bankType = NameHelper.BankTypes.WoodElf; break; case Races.Breton: default: bankType = NameHelper.BankTypes.Breton; break; } // Assign name - some types have their own individual name to use if (factionData.type == (int)FactionFile.FactionTypes.Individual || factionData.type == (int)FactionFile.FactionTypes.Daedra) { // Use individual name displayName = factionData.name; } else { // Set a name seed if not configured if (nameSeed == -1) { nameSeed = DateTime.Now.Millisecond; } // Generate a random name based on gender and race name bank DFRandom.srand(nameSeed); displayName = DaggerfallUnity.Instance.NameHelper.FullName(bankType, npcGender); } }
/// <summary> /// Gets display name of NPC as fixed individual or from random seed. /// </summary> string GetDisplayName() { FactionFile.FactionData factionData; bool foundFaction = GameManager.Instance.PlayerEntity.FactionData.GetFactionData(npcData.factionID, out factionData); if (foundFaction && factionData.type == (int)FactionFile.FactionTypes.Individual) { return(factionData.name); } else { DFRandom.srand(npcData.nameSeed); return(DaggerfallUnity.Instance.NameHelper.FullName(npcData.nameBank, npcData.gender)); } }
public TextFile.Token[] InitPaintingInfo(int paintingTextId = 250) { GetMacroDataSource(); if (ItemGroup == ItemGroups.Paintings && dataSource.paintingInfo == null) { DFRandom.srand(message); uint paintingIndex = DFRandom.rand() % 180; dataSource.paintingFileIdx = paintingIndex & 7; char paintingFileChar = (char)((paintingIndex >> 3) + 97); dataSource.paintingFilename = paintingFileChar + "paint.cif"; byte[] paintingRecord = DaggerfallUnity.Instance.ContentReader.PaintFileReader.Read(paintingIndex); Debug.LogFormat("painting file: {0}, index: {1}, cif idx: {2}, record: {3} {4} {5}", dataSource.paintingFilename, paintingIndex, dataSource.paintingFileIdx, paintingRecord[0], paintingRecord[1], paintingRecord[2]); dataSource.paintingSub = GetPaintingRecordPart(paintingRecord, 0, 9) + 6100; // for %sub macro dataSource.paintingAdj = GetPaintingRecordPart(paintingRecord, 10, 19) + 6200; // for %adj macro dataSource.paintingPp1 = GetPaintingRecordPart(paintingRecord, 20, 29) + 6300; // for %pp1 macro dataSource.paintingPp2 = GetPaintingRecordPart(paintingRecord, 30, 39) + 6400; // for %pp2 macro ITextProvider textProvider = DaggerfallUnity.Instance.TextProvider; dataSource.paintingInfo = textProvider.GetRandomTokens(paintingTextId, true); } return(dataSource.paintingInfo); }
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); }
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); }
public override string Name() { // Set seed to the quest UID before falling through to random name generation. (See t=2108) DFRandom.srand((int)parent.UID); return(null); }
void SelectCurrentSong() { if (currentPlaylist == null || currentPlaylist.Length == 0) { return; } int index = 0; // General MIDI song selection { uint gameMinutes = DaggerfallUnity.Instance.WorldTime.DaggerfallDateTime.ToClassicDaggerfallTime(); DFRandom.srand(gameMinutes / 1440); uint random = DFRandom.rand(); if (currentPlaylist == NightSongs) { index = (int)(random % NightSongs.Length); } else if (currentPlaylist == SunnySongs) { index = (int)(random % SunnySongs.Length); } else if (currentPlaylist == CloudySongs) { index = (int)(random % CloudySongs.Length); } else if (currentPlaylist == OvercastSongs) { index = (int)(random % OvercastSongs.Length); } else if (currentPlaylist == RainSongs) { index = (int)(random % RainSongs.Length); } else if (currentPlaylist == SnowSongs) { index = (int)(random % SnowSongs.Length); } else if (currentPlaylist == TempleSongs && playerEnterExit) { byte[] templeFactions = { 0x52, 0x54, 0x58, 0x5C, 0x5E, 0x62, 0x6A, 0x24 }; uint factionOfPlayerEnvironment = playerEnterExit.FactionID; index = Array.IndexOf(templeFactions, (byte)factionOfPlayerEnvironment); if (index < 0) { byte[] godFactions = { 0x15, 0x16, 0x18, 0x1A, 0x1B, 0x1D, 0x21, 0x23 }; index = Array.IndexOf(godFactions, (byte)factionOfPlayerEnvironment); } } else if (currentPlaylist == TavernSongs) { index = (int)(gameMinutes / 1440 % TavernSongs.Length); } else if (currentPlaylist == DungeonInteriorSongs) { PlayerGPS gps = GameManager.Instance.PlayerGPS; ushort unknown2 = 0; int region = 0; if (gps.HasCurrentLocation) { unknown2 = (ushort)gps.CurrentLocation.Dungeon.RecordElement.Header.Unknown2; region = gps.CurrentRegionIndex; } DFRandom.srand(unknown2 ^ ((byte)region << 8)); random = DFRandom.rand(); index = (int)(random % 15); } else if (currentPlaylist == SneakingSongs) { index = UnityEngine.Random.Range(0, SneakingSongs.Length); } } currentSong = currentPlaylist[index]; currentSongIndex = index; }
/// <summary> /// Generate a list of potential sites based on building type. /// This uses actual map layout and block data rather than the (often inaccurate) list of building in map data. /// Specify BuildingTypes.AllValid to find all valid building types /// </summary> SiteDetails[] CollectQuestSitesOfBuildingType(DFLocation location, DFLocation.BuildingTypes buildingType) { // Valid building types for valid search int[] validBuildingTypes = { 0, 2, 3, 5, 6, 8, 9, 11, 12, 13, 14, 15, 17, 18, 19, 20 }; List <SiteDetails> foundSites = new List <SiteDetails>(); // Iterate through all blocks DFBlock[] blocks; RMBLayout.GetLocationBuildingData(location, out blocks); int width = location.Exterior.ExteriorData.Width; int height = location.Exterior.ExteriorData.Height; for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { // Iterate through all buildings in this block int index = y * width + x; BuildingSummary[] buildingSummary = RMBLayout.GetBuildingData(blocks[index], x, y); for (int i = 0; i < buildingSummary.Length; i++) { // When enumAllValid is specified accept all valid building types bool forceAccept = false; if (buildingType == DFLocation.BuildingTypes.AllValid) { for (int j = 0; j < validBuildingTypes.Length; j++) { if (validBuildingTypes[j] == (int)buildingSummary[i].BuildingType) { forceAccept = true; break; } } } // Match building against required type if (buildingSummary[i].BuildingType == buildingType || forceAccept) { // Building must be a valid quest site QuestMarker[] questSpawnMarkers, questItemMarkers; EnumerateBuildingQuestMarkers(blocks[index], i, out questSpawnMarkers, out questItemMarkers); if (!ValidateQuestMarkers(questSpawnMarkers, questItemMarkers)) { continue; } // Get building name based on type string buildingName; if (RMBLayout.IsResidence(buildingType)) { // Generate a random surname for this residence DFRandom.srand(Time.renderedFrameCount); string surname = DaggerfallUnity.Instance.NameHelper.Surname(Utility.NameHelper.BankTypes.Breton); buildingName = HardStrings.theNamedResidence.Replace("%s", surname); } else { // Use fixed name buildingName = BuildingNames.GetName( buildingSummary[i].NameSeed, buildingSummary[i].BuildingType, buildingSummary[i].FactionId, location.Name, location.RegionName); } // Configure new site details SiteDetails site = new SiteDetails(); site.questUID = ParentQuest.UID; site.siteType = SiteTypes.Building; site.mapId = location.MapTableData.MapId; site.locationId = location.Exterior.ExteriorData.LocationId; site.regionName = location.RegionName; site.locationName = location.Name; site.buildingKey = buildingSummary[i].buildingKey; site.buildingName = buildingName; site.questSpawnMarkers = questSpawnMarkers; site.questItemMarkers = questItemMarkers; // Asssign markers only if available if (questSpawnMarkers != null) { siteDetails.selectedQuestSpawnMarker = UnityEngine.Random.Range(0, questSpawnMarkers.Length); } if (questItemMarkers != null) { siteDetails.selectedQuestItemMarker = UnityEngine.Random.Range(0, questItemMarkers.Length); } foundSites.Add(site); } } } } return(foundSites.ToArray()); }
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); }