// 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); } }
public virtual TextFile.Token[] GetRandomTokens(int id, bool dfRand = false) { TextFile.Token[] sourceTokens = GetRSCTokens(id); // Build a list of token subrecords List <TextFile.Token> currentStream = new List <TextFile.Token>(); List <TextFile.Token[]> tokenStreams = new List <TextFile.Token[]>(); for (int i = 0; i < sourceTokens.Length; i++) { // If we're at end of subrecord then start a new stream if (sourceTokens[i].formatting == TextFile.Formatting.SubrecordSeparator) { tokenStreams.Add(currentStream.ToArray()); currentStream.Clear(); continue; } // Otherwise keep adding to current stream currentStream.Add(sourceTokens[i]); } // Complete final stream tokenStreams.Add(currentStream.ToArray()); // Select a random token stream int index = dfRand ? (int)(DFRandom.rand() % tokenStreams.Count) : UnityEngine.Random.Range(0, tokenStreams.Count); // Select the next to last item from the array if the length of the last one is zero index = (tokenStreams[index].Length == 0 ? index - 1 : index); return(tokenStreams[index]); }
// 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); }
// 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 FixedUpdate() { // Unable to attack if AI disabled or paralyzed if (GameManager.Instance.DisableAI || entityBehaviour.Entity.IsParalyzed) { return; } // Countdown to next melee attack MeleeTimer -= Time.deltaTime; if (MeleeTimer < 0) { MeleeTimer = 0; } EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; int speed = entity.Stats.LiveSpeed; // Note: Speed comparison here is reversed from classic. Classic's way makes fewer attack // attempts at higher speeds, so it seems backwards. if (GameManager.ClassicUpdate && (DFRandom.rand() % speed >= (speed >> 3) + 6 && MeleeTimer == 0)) { if (!MeleeAnimation()) { return; } ResetMeleeTimer(); } }
public override string PaintingPrefix2() { // %pp2 DFRandom.rand(); // Classic uses every other value. TextFile.Token[] tokens = DaggerfallUnity.Instance.TextProvider.GetRandomTokens(paintingPp2, true); MacroHelper.ExpandMacros(ref tokens); return((tokens.Length > 0) ? tokens[0].text : "%pp2[idxError]"); }
// 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); } }
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); }
void ReadHeader(bool randomPrice = true) { BinaryReader reader = bookFile.GetReader(); header = new BookHeader(); header.Title = FileProxy.ReadCStringSkip(reader, 0, 64); header.Author = FileProxy.ReadCStringSkip(reader, 0, 64); header.IsNaughty = (FileProxy.ReadCStringSkip(reader, 0, 8) == naughty); header.NullValues = reader.ReadBytes(88); header.Price = reader.ReadUInt32(); header.Unknown1 = reader.ReadUInt16(); header.Unknown2 = reader.ReadUInt16(); header.Unknown3 = reader.ReadUInt16(); header.PageCount = reader.ReadUInt16(); header.PageOffsets = new UInt32[header.PageCount]; for (int i = 0; i < header.PageCount; i++) { header.PageOffsets[i] = reader.ReadUInt32(); } if (randomPrice) { // Overwrite price field using random seeded with first 4 bytes. // (See https://forums.dfworkshop.net/viewtopic.php?f=23&t=1576) reader.BaseStream.Position = 0; DFRandom.Seed = reader.ReadUInt32(); // first 4 bytes of book file as a uint header.Price = (uint)DFRandom.random_range_inclusive(300, 800); } }
public override string ImperialName() { // %imp string[] names = { "Pelagius", "Cephorus", "Uriel", "Cassynder", "Voragiel", "Trabbatus" }; DFRandom.Seed = (uint)parent.GetHashCode(); uint rand = DFRandom.rand() % 6; return(names[rand]); }
void Update() { // If a melee attack has reached the damage frame we can run a melee attempt if (mobile.DoMeleeDamage) { MeleeDamage(); mobile.DoMeleeDamage = false; } // If a bow attack has reached the shoot frame we can shoot an arrow else if (mobile.ShootArrow) { BowDamage(); // TODO: Shoot 3D projectile instead of doing an instant hit mobile.ShootArrow = false; DaggerfallAudioSource dfAudioSource = GetComponent <DaggerfallAudioSource>(); if (dfAudioSource) { dfAudioSource.PlayOneShot((int)SoundClips.ArrowShoot, 1, 1.0f); } } // Countdown to next melee attack meleeTimer -= Time.deltaTime; if (meleeTimer < 0) { meleeTimer = 0; } EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; int speed = entity.Stats.LiveSpeed; // Note: Speed comparison here is reversed from classic. Classic's way makes fewer attack // attempts at higher speeds, so it seems backwards. if (classicUpdate && (DFRandom.rand() % speed >= (speed >> 3) + 6 && meleeTimer == 0)) { MeleeAnimation(); meleeTimer = Random.Range(1500, 3001); meleeTimer -= 50 * (GameManager.Instance.PlayerEntity.Level - 10); // Note: In classic, what happens here is // meleeTimer += 450 * (enemydata[130] - 2); // Apparently this was meant to reference the game reflexes setting, // which is stored in playerentitydata[130]. // Instead enemydata[130] seems to instead always be 0, the equivalent of // "very high" reflexes, regardless of what the game reflexes are. // Here, we use the reflexes data as was intended. meleeTimer += 450 * ((int)GameManager.Instance.PlayerEntity.Reflexes - 2); if (meleeTimer > 100000 || meleeTimer < 0) { meleeTimer = 1500; } meleeTimer /= 980; // Approximates classic frame update } }
// 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); } }
public override string ImperialName() { // %imp string[] names = { "Pelagius", "Cephorus", "Uriel", "Cassynder", "Voragiel", "Trabbatus" }; System.Random random = new System.Random(); DFRandom.Seed = (uint)random.Next(); uint rand = DFRandom.rand() % 6; return(names[rand]); }
private int GetPaintingRecordPart(byte[] paintingRecord, int start, int end) { int i = start; while (i <= end && paintingRecord[i] != 0xFF) { i++; } return((i - start == 1) ? paintingRecord[i - 1] : paintingRecord[DFRandom.random_range_inclusive(start, i - 1)]); }
public override string ArtistName() { // %an DFRandom.rand(); // Classic uses every other value. uint rand = DFRandom.rand() & 1; Genders gender = (Genders)rand; rand = DFRandom.rand(); NameHelper.BankTypes race = (NameHelper.BankTypes)(rand & 7); return(DaggerfallUnity.Instance.NameHelper.FullName(race, gender)); }
// 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); }
public bool SetNewRulerData(int factionID) { if (factionDict.ContainsKey(factionID)) { FactionFile.FactionData faction = factionDict[factionID]; faction.rulerPowerBonus = DFRandom.random_range_inclusive(0, 50) + 20; uint random = DFRandom.rand() << 16; faction.rulerNameSeed = DFRandom.rand() | random; return(true); } return(false); }
void Update() { if (GameManager.Instance.DisableAI) { return; } // If a melee attack has reached the damage frame we can run a melee attempt if (mobile.DoMeleeDamage) { MeleeDamage(); mobile.DoMeleeDamage = false; } // If a bow attack has reached the shoot frame we can shoot an arrow else if (mobile.ShootArrow) { ShootBow(); mobile.ShootArrow = false; DaggerfallAudioSource dfAudioSource = GetComponent <DaggerfallAudioSource>(); if (dfAudioSource) { dfAudioSource.PlayOneShot((int)SoundClips.ArrowShoot, 1, 1.0f); } } // Countdown to next melee attack MeleeTimer -= Time.deltaTime; if (MeleeTimer < 0) { MeleeTimer = 0; } EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; int speed = entity.Stats.LiveSpeed; // Note: Speed comparison here is reversed from classic. Classic's way makes fewer attack // attempts at higher speeds, so it seems backwards. if (GameManager.ClassicUpdate && (DFRandom.rand() % speed >= (speed >> 3) + 6 && MeleeTimer == 0)) { if (!MeleeAnimation()) { return; } ResetMeleeTimer(); } }
void FixedUpdate() { const int speedFloor = 8; // Unable to attack if AI disabled or paralyzed if (GameManager.Instance.DisableAI || entityBehaviour.Entity.IsParalyzed) { return; } // Unable to attack when playing certain oneshot anims if (mobile && mobile.IsPlayingOneShot() && mobile.OneShotPauseActionsWhilePlaying()) { return; } // Countdown to next melee attack MeleeTimer -= Time.deltaTime; if (MeleeTimer < 0) { MeleeTimer = 0; } // Get entity speed and enforce a lower limit so Drain Speed does not prevent attack ever firing EnemyEntity entity = entityBehaviour.Entity as EnemyEntity; int speed = entity.Stats.LiveSpeed; if (speed < speedFloor) { speed = speedFloor; } // Slow down enemy frame rate based on floored speed value // If enemy is still at maximum speed then divisor is 1 and will experience no change to frame rate mobile.FrameSpeedDivisor = entity.Stats.PermanentSpeed / speed; // Note: Speed comparison here is reversed from classic. Classic's way makes fewer attack // attempts at higher speeds, so it seems backwards. if (GameManager.ClassicUpdate && (DFRandom.rand() % speed >= (speed >> 3) + 6 && MeleeTimer == 0)) { if (!MeleeAnimation()) { return; } ResetMeleeTimer(); } }
/// <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)); } }
// Gets random surname for Nord names that follow 0+1+"sen" pattern string GetRandomNordSurname(NameBank nameBank) { // Get set parts string[] partsA, partsB; partsA = nameBank.sets[0].parts; partsB = nameBank.sets[1].parts; // Generate strings uint index = DFRandom.rand() % (uint)partsA.Length; string stringA = partsA[index]; index = DFRandom.rand() % (uint)partsB.Length; string stringB = partsB[index]; return(stringA + stringB + "sen"); }
// 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); }
public override void StartQuest(bool isCureQuest) { base.StartQuest(isCureQuest); if (isCureQuest && DFRandom.random_range_inclusive(1, 100) < 30) { // Do nothing if a cure instance already running // This is a long-running quest that involves hunters if player not cured by end of time limit ulong[] quests = QuestMachine.Instance.FindQuests(cureQuestName); if (quests != null && quests.Length > 0) { return; } // Start the cure quest QuestMachine.Instance.InstantiateQuest(cureQuestName); } }
// // -= 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); }
public override void StartQuest(bool isCureQuest) { // More about vampire clan quests can found here: // https://en.uesp.net/wiki/Daggerfall:Quests#Vampire_Clans if (isCureQuest) { if (DFRandom.random_range_inclusive(10, 100) < 30) { QuestMachine.Instance.StartQuest("$CUREVAM"); } } else if (hasStartedInitialVampireQuest) { // Get an appropriate quest for player's level? if (DFRandom.random_range_inclusive(1, 100) < 50) { // Get the regional vampire clan faction id for affecting reputation on success/failure, and current rep int factionId = (int)vampireClan; int reputation = GameManager.Instance.PlayerEntity.FactionData.GetReputation(factionId); // Select a quest at random from appropriate pool Quest offeredQuest = GameManager.Instance.QuestListsManager.GetGuildQuest( FactionFile.GuildGroups.Vampires, MembershipStatus.Nonmember, factionId, reputation, GameManager.Instance.PlayerEntity.Level); if (offeredQuest != null) { QuestMachine.Instance.StartQuest(offeredQuest); } } } else if (DFRandom.random_range_inclusive(1, 100) < 50) { QuestMachine.Instance.StartQuest("P0A01L00"); hasStartedInitialVampireQuest = true; } }
// Gets random Redguard name which follows 0+1+2+3(75%) (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 uint index = DFRandom.rand() % (uint)partsA.Length; string stringA = partsA[index]; index = DFRandom.rand() % (uint)partsB.Length; string stringB = partsB[index]; index = DFRandom.rand() % (uint)partsC.Length; string stringC = partsC[index]; string stringD = string.Empty; if (gender == Genders.Female || (DFRandom.rand() % 100 < 75)) { index = DFRandom.rand() % (uint)partsD.Length; stringD = partsD[index]; } return(stringA + stringB + stringC + stringD); }
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); }
// 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); }
// 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 uint index = DFRandom.rand() % (uint)partsA.Length; string stringA = partsA[index]; index = DFRandom.rand() % (uint)partsB.Length; string stringB = partsB[index]; return(stringA + stringB); }