public static void Twoda_rando(KPaths paths) { BIF b = new BIF(Path.Combine(paths.data, "2da.bif")); KEY k = new KEY(paths.chitin_backup); b.AttachKey(k, "data\\2da.bif"); var filesInOverride = paths.FilesInOverride.ToList(); foreach (BIF.VariableResourceEntry VRE in b.VariableResourceTable.Where(x => Globals.Selected2DAs.Keys.Contains(x.ResRef))) { // Check to see if this table is already in the override directory. TwoDA t; if (filesInOverride.Any(fi => fi.Name == $"{VRE.ResRef}.2da")) { // Modify the existing table. t = new TwoDA(File.ReadAllBytes(filesInOverride.First(fi => fi.Name == $"{VRE.ResRef}.2da").FullName), VRE.ResRef); } else { // Fetch the table from the 2DA BIF file. t = new TwoDA(VRE.EntryData, VRE.ResRef); } if (!LookupTable.ContainsKey(VRE.ResRef)) { // Add 2DA to the table. LookupTable.Add(VRE.ResRef, new Dictionary <string, List <Tuple <string, string> > >()); } foreach (string col in Globals.Selected2DAs[VRE.ResRef]) { if (!LookupTable[VRE.ResRef].ContainsKey(col)) { // Add column to the table. LookupTable[VRE.ResRef].Add(col, new List <Tuple <string, string> >()); } var old = t.Data[col].ToList(); // Save list of old data. Randomize.FisherYatesShuffle(t.Data[col]); // Randomize 2DA column data. for (int i = 0; i < old.Count; i++) { // Add old and new data to the table. LookupTable[VRE.ResRef][col].Add(new Tuple <string, string>(old[i], t.Data[col][i])); } } t.WriteToDirectory(paths.Override); // Write new 2DA data to file. } }
public static void Twoda_rando(KPaths paths) { BIF b = new BIF(Path.Combine(paths.data, "2da.bif")); KEY k = new KEY(paths.chitin_backup); b.AttachKey(k, "data\\2da.bif"); foreach (BIF.VariableResourceEntry VRE in b.VariableResourceTable.Where(x => Globals.Selected2DAs.Keys.Contains(x.ResRef))) { TwoDA t = new TwoDA(VRE.EntryData, VRE.ResRef); foreach (string col in Globals.Selected2DAs[VRE.ResRef]) { Randomize.FisherYatesShuffle(t.Data[col]); } t.WriteToDirectory(paths.Override); } }
public static void CreateSpoilerLog(XLWorkbook workbook) { if (LookupTable.Count == 0) { return; } var ws = workbook.Worksheets.Add("Item"); var paths = new KPaths(Properties.Settings.Default.Kotor1Path); KEY k = new KEY(paths.chitin_backup); BIF b = new BIF(Path.Combine(paths.data, "templates.bif")); b.AttachKey(k, "data\\templates.bif"); var items = b.VariableResourceTable.Where(x => x.ResourceType == ResourceType.UTI); TLK t = new TLK(File.Exists(paths.dialog_backup) ? paths.dialog_backup : paths.dialog); int i = 1; ws.Cell(i, 1).Value = "Seed"; ws.Cell(i, 2).Value = Properties.Settings.Default.Seed; ws.Cell(i, 1).Style.Font.Bold = true; i++; Version version = typeof(StartForm).Assembly.GetName().Version; ws.Cell(i, 1).Value = "Version"; ws.Cell(i, 1).Style.Font.Bold = true; ws.Cell(i, 2).Value = $"v{version.Major}.{version.Minor}.{version.Build}"; ws.Cell(i, 2).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Right; i += 2; // Skip a row. // Item Randomization Settings ws.Cell(i, 1).Value = "Item Type"; ws.Cell(i, 2).Value = "Rando Level"; ws.Cell(i, 1).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 2).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 1).Style.Font.Bold = true; ws.Cell(i, 2).Style.Font.Bold = true; i++; var settings = new List <Tuple <string, string> >() { new Tuple <string, string>("Armbands", Properties.Settings.Default.RandomizeArmbands.ToString()), new Tuple <string, string>("Armor", Properties.Settings.Default.RandomizeArmor.ToString()), new Tuple <string, string>("Belts", Properties.Settings.Default.RandomizeBelts.ToString()), new Tuple <string, string>("Blasters", Properties.Settings.Default.RandomizeBlasters.ToString()), new Tuple <string, string>("Creature Hides", Properties.Settings.Default.RandomizeHides.ToString()), new Tuple <string, string>("Creature Weapons", Properties.Settings.Default.RandomizeCreature.ToString()), new Tuple <string, string>("Droid Equipment", Properties.Settings.Default.RandomizeDroid.ToString()), new Tuple <string, string>("Gauntlets", Properties.Settings.Default.RandomizeGloves.ToString()), new Tuple <string, string>("Grenades", Properties.Settings.Default.RandomizeGrenades.ToString()), new Tuple <string, string>("Implants", Properties.Settings.Default.RandomizeImplants.ToString()), new Tuple <string, string>("Lightsabers", Properties.Settings.Default.RandomizeLightsabers.ToString()), new Tuple <string, string>("Masks", Properties.Settings.Default.RandomizeMask.ToString()), new Tuple <string, string>("Melee Weapons", Properties.Settings.Default.RandomizeMelee.ToString()), new Tuple <string, string>("Mines", Properties.Settings.Default.RandomizeMines.ToString()), new Tuple <string, string>("Pazaak Cards", Properties.Settings.Default.RandomizePaz.ToString()), new Tuple <string, string>("Stims/Medpacs", Properties.Settings.Default.RandomizeStims.ToString()), new Tuple <string, string>("Upgrades/Crystals", Properties.Settings.Default.RandomizeUpgrade.ToString()), new Tuple <string, string>("Various", Properties.Settings.Default.RandomizeVarious.ToString()), }; foreach (var setting in settings) { ws.Cell(i, 1).Value = setting.Item1; ws.Cell(i, 2).Value = setting.Item2; ws.Cell(i, 1).Style.Font.Italic = true; i++; } i++; // Skip a row. // Omitted Items int iMax = i; i = 3; // Restart at the top of the settings list. ws.Cell(i, 4).Value = "Omitted Items"; ws.Cell(i, 4).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; ws.Cell(i, 4).Style.Font.Bold = true; ws.Range(i, 4, i, 5).Merge(); i++; ws.Cell(i, 4).Value = "ID"; ws.Cell(i, 5).Value = "Label"; ws.Cell(i, 4).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 5).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 4).Style.Font.Italic = true; ws.Cell(i, 5).Style.Font.Italic = true; i++; var sortedList = Globals.OmitItems.ToList(); sortedList.Sort(); foreach (var item in sortedList) { ws.Cell(i, 4).Value = item; var origItemName = ""; var origItemVre = items.FirstOrDefault(x => x.ResRef == item); if (origItemVre != null) { GFF origItem = new GFF(origItemVre.EntryData); if (origItem.Top_Level.Fields.FirstOrDefault(x => x.Label == "LocalizedName") is GFF.CExoLocString field) { origItemName = t.String_Data_Table[field.StringRef].StringText; } } ws.Cell(i, 5).Value = origItemName; i++; } // Handle variable length of omitted items list. if (iMax > i) { i = iMax; // Return to the bottom of the settings list. } else { i++; // Skip a row. } i++; // Skip an additional 2 rows. // Randomized Items ws.Cell(i, 1).Value = "Has Changed"; ws.Cell(i - 1, 2).Value = "Original (New Item)"; ws.Cell(i, 2).Value = "ID"; ws.Cell(i, 3).Value = "Label"; ws.Cell(i - 1, 4).Value = "Randomized (Old Item)"; ws.Cell(i, 4).Value = "ID"; ws.Cell(i, 5).Value = "Label"; ws.Cell(i, 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; ws.Cell(i - 1, 2).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; ws.Cell(i - 1, 4).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; ws.Cell(i, 1).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 2).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 3).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 4).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i, 5).Style.Border.BottomBorder = XLBorderStyleValues.Thin; ws.Cell(i - 1, 2).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i, 2).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i - 1, 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i, 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i - 1, 6).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i, 6).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i, 1).Style.Font.Bold = true; ws.Cell(i - 1, 2).Style.Font.Bold = true; ws.Cell(i, 2).Style.Font.Italic = true; ws.Cell(i, 3).Style.Font.Italic = true; ws.Cell(i - 1, 4).Style.Font.Bold = true; ws.Cell(i, 4).Style.Font.Italic = true; ws.Cell(i, 5).Style.Font.Italic = true; ws.Range(i - 1, 2, i - 1, 3).Merge(); ws.Range(i - 1, 4, i - 1, 5).Merge(); i++; var sortedLookup = LookupTable.OrderBy(tpl => tpl.Item1); foreach (var tpl in sortedLookup) { string origItemName = ""; string randItemName = ""; var omitted = Globals.OmitItems.Any(x => x == tpl.Item1); var changed = tpl.Item1 != tpl.Item2; // Has the shuffle changed this item? var origItemVre = items.FirstOrDefault(x => x.ResRef == tpl.Item1); if (origItemVre != null) { GFF origItem = new GFF(origItemVre.EntryData); if (origItem.Top_Level.Fields.FirstOrDefault(x => x.Label == "LocalizedName") is GFF.CExoLocString field) { origItemName = t.String_Data_Table[field.StringRef].StringText; } } if (changed) { var randItemVre = items.FirstOrDefault(x => x.ResRef == tpl.Item2); if (randItemVre != null) { GFF randItem = new GFF(randItemVre.EntryData); if (randItem.Top_Level.Fields.FirstOrDefault(x => x.Label == "LocalizedName") is GFF.CExoLocString field) { randItemName = t.String_Data_Table[field.StringRef].StringText; } } } else { randItemName = origItemName; } ws.Cell(i, 1).Value = omitted ? "OMITTED" : changed.ToString(); ws.Cell(i, 2).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i, 2).Value = tpl.Item1; ws.Cell(i, 3).Value = origItemName; ws.Cell(i, 4).Style.Border.LeftBorder = XLBorderStyleValues.Thin; ws.Cell(i, 4).Value = tpl.Item2; ws.Cell(i, 5).Value = randItemName; ws.Cell(i, 6).Style.Border.LeftBorder = XLBorderStyleValues.Thin; if (omitted) { // Center "OMITTED" text. ws.Cell(i, 1).Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; } else { // Set color of "Has Changed" column. Booleans are automatically centered. if (changed) { ws.Cell(i, 1).Style.Font.FontColor = XLColor.Green; } else { ws.Cell(i, 1).Style.Font.FontColor = XLColor.Red; } } i++; } // Resize Columns ws.Column(1).AdjustToContents(); ws.Column(2).AdjustToContents(); ws.Column(3).AdjustToContents(); ws.Column(4).AdjustToContents(); ws.Column(5).AdjustToContents(); }
public static void other_rando(KPaths paths) { // NameGen if (Properties.Settings.Default.RandomizeNameGen) { List <string> male_names = Properties.Settings.Default.FirstnamesM.Cast <string>().Select(x => x.Trim()).Where(x => x.Length > 2).ToList(); LTR ltr_male_names = new LTR(male_names); List <string> female_names = Properties.Settings.Default.FirstnamesF.Cast <string>().Select(x => x.Trim()).Where(x => x.Length > 2).ToList(); LTR ltr_female_names = new LTR(female_names); List <string> last_names = Properties.Settings.Default.Lastnames.Cast <string>().Select(x => x.Trim()).Where(x => x.Length > 2).ToList(); LTR ltr_last_names = new LTR(last_names); if (male_names.Any()) { ltr_male_names.WriteToFile(paths.Override + "humanm.ltr"); } if (female_names.Any()) { ltr_female_names.WriteToFile(paths.Override + "humanf.ltr"); } if (last_names.Any()) { ltr_last_names.WriteToFile(paths.Override + "humanl.ltr"); } } // Polymorph // Random NPC Pazaak Decks if (Properties.Settings.Default.RandomizePazaakDecks) { string ops = "+-*"; BIF b = new BIF(paths.data + "\\2da.bif"); KEY k = new KEY(paths.chitin_backup); b.AttachKey(k, "data\\2da.bif"); var resource = b.VariableResourceTable.Where(x => x.ResRef == PAZAAKDECKS_RESREF).FirstOrDefault(); if (resource == null) { throw new ArgumentOutOfRangeException($"The ResRef \"{PAZAAKDECKS_RESREF}\" could not be found."); } TwoDA t = new TwoDA(resource.EntryData, PAZAAKDECKS_RESREF); foreach (string c in t.Columns) { if (c == DECKNAME_COLUMN) { continue; } // [+-*][1-6] // "" + ops[Randomize.Rng.Next(0, 3)] + Convert.ToString(Randomize.Rng.Next(1, 7)); t.Data[c][0] = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; t.Data[c][1] = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; t.Data[c][2] = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; t.Data[c][3] = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; } t.WriteToDirectory(paths.Override); } }
public static void other_rando(KPaths paths) { // NameGen if (Properties.Settings.Default.RandomizeNameGen) { List <string> male_names = Properties.Settings.Default.FirstnamesM.Cast <string>().Select(x => x.Trim()).Where(x => x.Length > 2).ToList(); LTR ltr_male_names = new LTR(male_names); List <string> female_names = Properties.Settings.Default.FirstnamesF.Cast <string>().Select(x => x.Trim()).Where(x => x.Length > 2).ToList(); LTR ltr_female_names = new LTR(female_names); List <string> last_names = Properties.Settings.Default.Lastnames.Cast <string>().Select(x => x.Trim()).Where(x => x.Length > 2).ToList(); LTR ltr_last_names = new LTR(last_names); if (male_names.Any()) { NameGenLookup.Add(NAME_GEN_MALE, male_names); ltr_male_names.WriteToFile(paths.Override + "humanm.ltr"); } if (female_names.Any()) { NameGenLookup.Add(NAME_GEN_FEMALE, female_names); ltr_female_names.WriteToFile(paths.Override + "humanf.ltr"); } if (last_names.Any()) { NameGenLookup.Add(NAME_GEN_LAST, last_names); ltr_last_names.WriteToFile(paths.Override + "humanl.ltr"); } } // Polymorph if (Properties.Settings.Default.PolymorphMode) { BIF b = new BIF(paths.data + "templates.bif"); KEY k = new KEY(paths.chitin); b.AttachKey(k, "data\\templates.bif"); foreach (var res in b.VariableResourceTable.Where(x => x.ResourceType == ResourceType.UTI)) { GFF g = new GFF(res.EntryData); int item_basetype = (g.Top_Level.Fields.Where(x => x.Label == "BaseItem").FirstOrDefault() as GFF.INT).Value; //ignore items that can't be equipped in the chest slot if ((item_basetype < 35 || item_basetype > 43) && (item_basetype < 66 || item_basetype > 68) && item_basetype != 85 && item_basetype != 89) { continue; } ushort rando_appearance = 0; while (Globals.BROKEN_CHARS.Contains((int)rando_appearance) || Globals.LARGE_CHARS.Contains((int)rando_appearance)) { rando_appearance = (ushort)Randomize.Rng.Next(508); } //STRUCT that gives an item the "disguise" property GFF.STRUCT disguise_prop = new GFF.STRUCT("", 0, new List <GFF.FIELD>() { new GFF.BYTE("ChanceAppear", 100), new GFF.BYTE("CostTable", 0), new GFF.WORD("CostValue", 0), new GFF.BYTE("Param1", 255), new GFF.BYTE("Param1Value", 0), new GFF.WORD("PropertyName", 59), //Disguise property new GFF.WORD("Subtype", rando_appearance), //The random appearance value (same values used in model rando) } ); //Adds the disguise property to the UTI's property list (g.Top_Level.Fields.Where(x => x.Label == "PropertiesList").FirstOrDefault() as GFF.LIST).Structs.Add(disguise_prop); PolymorphLookupTable.Add(res.ResRef, rando_appearance); g.WriteToFile(paths.Override + res.ResRef + ".uti"); } } // Random NPC Pazaak Decks if (Properties.Settings.Default.RandomizePazaakDecks) { string ops = "+-*"; BIF b = new BIF(paths.data + "2da.bif"); KEY k = new KEY(paths.chitin_backup); b.AttachKey(k, "data\\2da.bif"); var resource = b.VariableResourceTable.Where(x => x.ResRef == PAZAAKDECKS_RESREF).FirstOrDefault(); if (resource == null) { throw new ArgumentOutOfRangeException($"The ResRef \"{PAZAAKDECKS_RESREF}\" could not be found."); } TwoDA t = new TwoDA(resource.EntryData, PAZAAKDECKS_RESREF); foreach (string c in t.Columns) { if (c == DECKNAME_COLUMN) { NpcPazaakLookupTable.Add(c, new List <Tuple <string, string> >() { new Tuple <string, string>(t.Data[c][0], t.Data[c][0]), new Tuple <string, string>(t.Data[c][1], t.Data[c][1]), new Tuple <string, string>(t.Data[c][2], t.Data[c][2]), new Tuple <string, string>(t.Data[c][3], t.Data[c][3]), }); continue; } NpcPazaakLookupTable.Add(c, new List <Tuple <string, string> >()); // [+-*][1-6] // "" + ops[Randomize.Rng.Next(0, 3)] + Convert.ToString(Randomize.Rng.Next(1, 7)); var card0 = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; var card1 = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; var card2 = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; var card3 = $"{ops[Randomize.Rng.Next(0, 3)]}{Convert.ToString(Randomize.Rng.Next(1, 7))}"; NpcPazaakLookupTable[c].Add(new Tuple <string, string>(t.Data[c][0], card0)); NpcPazaakLookupTable[c].Add(new Tuple <string, string>(t.Data[c][1], card1)); NpcPazaakLookupTable[c].Add(new Tuple <string, string>(t.Data[c][2], card2)); NpcPazaakLookupTable[c].Add(new Tuple <string, string>(t.Data[c][3], card3)); t.Data[c][0] = card0; t.Data[c][1] = card1; t.Data[c][2] = card2; t.Data[c][3] = card3; } t.WriteToDirectory(paths.Override); } // Party Rando if (Properties.Settings.Default.RandomizePartyMembers) { BIF b = new BIF(paths.data + "templates.bif"); KEY k = new KEY(paths.chitin_backup); b.AttachKey(k, "data\\templates.bif"); foreach (var ID in Party_IDs) { // Find a creature that isn't this party member var charsList = b.VariableResourceTable.Where(x => x.ResourceType == ResourceType.UTC).ToList(); var character = charsList.First(x => x.ResRef == ID.Item2); BIF.VariableResourceEntry resource; GFF g; do { int randoIndex = Randomize.Rng.Next(charsList.Count); resource = charsList[randoIndex]; if (resource.ResRef != character.ResRef && !InvalidPartyMembers.Contains(resource.ResRef)) { // Potentially valid party member. Check against broken and large characters. g = new GFF(resource.EntryData); var appearance = g.Top_Level.Fields.First(x => x.Label == ModelRando.LBL_APPEARANCE_TYPE) as GFF.WORD; if (!Globals.BROKEN_CHARS.Contains(appearance.Value) && !Globals.LARGE_CHARS.Contains(appearance.Value)) { break; // Character is valid. } } // Character is invalid, broken, or large. Skip it. Console.WriteLine($"Skipped invalid party member ({resource.ResRef}) when randomizing {ID.Item2}."); }while (true); PartyLookupTable.Add(ID.Item3, resource.ResRef); GFF gOld = new GFF(character.EntryData); ushort portraitId = (gOld.Top_Level.Fields.Where(x => x.Label == "PortraitId").FirstOrDefault() as GFF.WORD)?.Value ?? 0; // Turns creature file into a playable companion replacing the current party member. (g.Top_Level.Fields.Where(x => x.Label == "Conversation").FirstOrDefault() as GFF.ResRef).Reference = ID.Item1; (g.Top_Level.Fields.Where(x => x.Label == "Tag").FirstOrDefault() as GFF.CExoString).CEString = ID.Item3; (g.Top_Level.Fields.Where(x => x.Label == "TemplateResRef").FirstOrDefault() as GFF.ResRef).Reference = ID.Item2; (g.Top_Level.Fields.Where(x => x.Label == "NoPermDeath").FirstOrDefault() as GFF.BYTE).Value = 1; (g.Top_Level.Fields.Where(x => x.Label == "FactionID").FirstOrDefault() as GFF.WORD).Value = 2; // Give new companion the old companion's portrait. if (g.Top_Level.Fields.Where(x => x.Label == "PortraitId").FirstOrDefault() is GFF.WORD field) { field.Value = portraitId; } // Henchmen script suite. (g.Top_Level.Fields.Where(x => x.Label == "ScriptHeartbeat").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_heartbt01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptOnNotice").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_percept01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptSpellAt").FirstOrDefault() as GFF.ResRef).Reference = ""; (g.Top_Level.Fields.Where(x => x.Label == "ScriptAttacked").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_attacked01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptDamaged").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_damage01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptDisturbed").FirstOrDefault() as GFF.ResRef).Reference = ""; (g.Top_Level.Fields.Where(x => x.Label == "ScriptEndRound").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_combend01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptEndDialogu").FirstOrDefault() as GFF.ResRef).Reference = ""; (g.Top_Level.Fields.Where(x => x.Label == "ScriptDialogue").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_dialogue01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptSpawn").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_spawn01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptRested").FirstOrDefault() as GFF.ResRef).Reference = ""; (g.Top_Level.Fields.Where(x => x.Label == "ScriptDeath").FirstOrDefault() as GFF.ResRef).Reference = ""; (g.Top_Level.Fields.Where(x => x.Label == "ScriptOnBlocked").FirstOrDefault() as GFF.ResRef).Reference = "k_hen_blocked01"; (g.Top_Level.Fields.Where(x => x.Label == "ScriptUserDefine").FirstOrDefault() as GFF.ResRef).Reference = ""; // Add a Dummy Feat to prevent the feats menu from crashing. (g.Top_Level.Fields.Where(x => x.Label == "FeatList").FirstOrDefault() as GFF.LIST).Structs.Add(new GFF.STRUCT("", 1, new List <GFF.FIELD>() { new GFF.WORD("Feat", 27) })); // If they are a Jedi class, add a Power to prevent powers menu from crashing. var charClassList = g.Top_Level.Fields.First(x => x.Label == "ClassList") as GFF.LIST; foreach (var classStruct in charClassList.Structs) { var charClassValue = (classStruct.Fields.First(x => x.Label == "Class") as GFF.INT).Value; if (charClassValue == 3 || // Jedi Guardian charClassValue == 4 || // Jedi Consular charClassValue == 5) // Jedi Sentinel { // Build a power to add to the list. GFF.STRUCT affectMind = new GFF.STRUCT("", 3, new List <GFF.FIELD>() { new GFF.WORD("Spell", 6), new GFF.BYTE("SpellMetaMagic", 0), new GFF.BYTE("SpellFlags", 1), }); if (!(classStruct.Fields.FirstOrDefault(x => x.Label == "KnownList0") is GFF.LIST knownList)) { // KnownList0 doesn't exist. Create it and add Affect Mind. classStruct.Fields.Add(new GFF.LIST("KnownList0", new List <GFF.STRUCT>() { affectMind })); } else if (knownList.Structs.Count == 0) { // KnownList0 exists but is empty. Add affect Mind. knownList.Structs.Add(affectMind); } break; } } g.WriteToFile(paths.Override + ID.Item2 + ".utc"); } }
public static void model_rando(KPaths paths) { const int MAX_CHAR_INDEX = 509; const int MIN_DOOR_INDEX_BROKEN = 13; const int MAX_DOOR_INDEX = 65; const int MAX_PLAC_INDEX = 232; const string CHAR_2DA = "appearance"; const string DOOR_2DA = "genericdoors"; const string PLAC_2DA = "placeables"; const string COL_LABEL = "label"; LookupTable.Clear(); BIF bif = new BIF(Path.Combine(paths.data, "2da.bif")); KEY key = new KEY(paths.chitin); bif.AttachKey(key, "data\\2da.bif"); var charVRE = bif.VariableResourceTable.Where(x => x.ResRef == CHAR_2DA).FirstOrDefault(); var doorVRE = bif.VariableResourceTable.Where(x => x.ResRef == DOOR_2DA).FirstOrDefault(); var placVRE = bif.VariableResourceTable.Where(x => x.ResRef == PLAC_2DA).FirstOrDefault(); TwoDA char2DA = new TwoDA(charVRE.EntryData, charVRE.ResRef); TwoDA door2DA = new TwoDA(doorVRE.EntryData, doorVRE.ResRef); TwoDA plac2DA = new TwoDA(placVRE.EntryData, placVRE.ResRef); // Check if the floor panel fix is enabled. bool isFloorPanelActive = (Properties.Settings.Default.RandomizePlaceModels & 8) > 0; var catacombsFile = AREA_UNK_CATACOMBS; // Check if modules have been randomized. var moduleFiles = paths.FilesInModules.ToList(); if (ModuleRando.LookupTable.Any()) { // If randomized, ensure module files are processed in the same order every time. var sortedLookup = ModuleRando.LookupTable.OrderBy(kvp => kvp.Key); var newList = new List<FileInfo>(); foreach (var kvp in sortedLookup) { // Find the file that has replaced the catacombs for the floor panel fix. if (kvp.Key == AREA_UNK_CATACOMBS) catacombsFile = kvp.Value; // Add the files to modify to the new list in proper order. var filesToAdd = moduleFiles.Where(fi => fi.Name.Contains(kvp.Value)); newList.AddRange(filesToAdd); } moduleFiles = newList; } // Loop through each file and randomize the requested model types. foreach (FileInfo fi in moduleFiles) { RIM r = new RIM(fi.FullName); LookupTable.Add(fi.Name, new Dictionary<string, Dictionary<string, Tuple<int, string, int, string>>>()); // Doors if ((Properties.Settings.Default.RandomizeDoorModels & 1) > 0) { LookupTable[fi.Name].Add(DOOR, new Dictionary<string, Tuple<int, string, int, string>>()); foreach (RIM.rFile rf in r.File_Table.Where(x => x.TypeID == (int)ResourceType.UTD)) { GFF g = new GFF(rf.File_Data); int randAppear = 0; //The randomly generated Appearance ID //Generate the random appearacne values before ommitting airlock, to create more seed consistancy if ((Properties.Settings.Default.RandomizeDoorModels & 4) > 0) // Broken Doors { randAppear = Randomize.Rng.Next(MIN_DOOR_INDEX_BROKEN, MAX_DOOR_INDEX); // First 12 doors are open so this is easier } else { randAppear = Randomize.Rng.Next(0, MAX_DOOR_INDEX); } // Airlock if ((Properties.Settings.Default.RandomizeDoorModels & 2) > 0 && (g.Top_Level.Fields.Where(f => f.Label == LBL_LOC_NAME).FirstOrDefault() as GFF.CExoLocString).StringRef == 21080) { continue; } //Get Info from Door2DA for the Spoiler Log var field = g.Top_Level.Fields.Where(f => f.Label == LBL_GENERIC_TYPE).FirstOrDefault() as GFF.BYTE; int id = (int)field.Value; var label_old = door2DA.Data[COL_LABEL][id]; var label_new = door2DA.Data[COL_LABEL][randAppear]; LookupTable[fi.Name][DOOR].Add(rf.Label, new Tuple<int, string, int, string>(id, label_old, randAppear, label_new)); //Change the appearance value (g.Top_Level.Fields.Where(f => f.Label == LBL_GENERIC_TYPE).FirstOrDefault() as GFF.BYTE).Value = (byte)randAppear; rf.File_Data = g.ToRawData(); } } // Placeables if ((Properties.Settings.Default.RandomizePlaceModels & 1) > 0) { LookupTable[fi.Name].Add(PLACEABLE, new Dictionary<string, Tuple<int, string, int, string>>()); // Check if floor panels should be replaced with valid placeables. bool useValidFloorPanels = isFloorPanelActive && fi.Name.Contains(catacombsFile); foreach (RIM.rFile rf in r.File_Table.Where(k => k.TypeID == (int)ResourceType.UTP)) { GFF g = new GFF(rf.File_Data); // If this is a broken placeable, skip it. if (Globals.BROKEN_PLACE.Contains((int)(g.Top_Level.Fields.Where(f => f.Label == LBL_APPEARANCE).FirstOrDefault() as GFF.DWORD).Value)) { continue; } int randAppear = 0; // Randomly generate a valid replacement for the "Lights Out" panels. if (useValidFloorPanels && (rf.Label.StartsWith(LABEL_UNK_FLPNL) || rf.Label == LABEL_UNK_RESETPANEL)) { randAppear = Globals.PANEL_PLACE[Randomize.Rng.Next(0, Globals.PANEL_PLACE.Count)]; } else { // Generate a random appearance for this placeable. bool isBroken = false; bool isLarge = false; do { randAppear = Randomize.Rng.Next(0, MAX_PLAC_INDEX); isBroken = ((Properties.Settings.Default.RandomizePlaceModels & 4) > 0) && Globals.BROKEN_PLACE.Contains(randAppear); // Always Satisfied if Broken omission disbaled isLarge = ((Properties.Settings.Default.RandomizePlaceModels & 2) > 0) && Globals.LARGE_PLACE.Contains(randAppear); // Always satisifed if Large omission disabled } while (isBroken || isLarge); } var field = g.Top_Level.Fields.Where(f => f.Label == LBL_APPEARANCE).FirstOrDefault() as GFF.DWORD; int id = (int)field.Value; var label_old = plac2DA.Data[COL_LABEL][id]; var label_new = plac2DA.Data[COL_LABEL][randAppear]; LookupTable[fi.Name][PLACEABLE].Add(rf.Label, new Tuple<int, string, int, string>(id, label_old, randAppear, label_new)); // Change the appearance value. (g.Top_Level.Fields.Where(f => f.Label == LBL_APPEARANCE).FirstOrDefault() as GFF.DWORD).Value = (uint)randAppear; rf.File_Data = g.ToRawData(); } } // Characters if ((Properties.Settings.Default.RandomizeCharModels & 1) > 0) { LookupTable[fi.Name].Add(CHARACTER, new Dictionary<string, Tuple<int, string, int, string>>()); foreach (RIM.rFile rf in r.File_Table.Where(k => k.TypeID == (int)ResourceType.UTC)) { GFF g = new GFF(rf.File_Data); int randAppear = 0; bool isBroken = false; bool isLarge = false; do { randAppear = Randomize.Rng.Next(0, MAX_CHAR_INDEX); isBroken = ((Properties.Settings.Default.RandomizeCharModels & 4) > 0) && Globals.BROKEN_CHARS.Contains(randAppear); // Always Satisfied if Broken omission disabled isLarge = ((Properties.Settings.Default.RandomizeCharModels & 2) > 0) && Globals.LARGE_CHARS.Contains(randAppear); // Always satisifed if Large omission disabled } while (isBroken || isLarge); var field = g.Top_Level.Fields.Where(f => f.Label == LBL_APPEARANCE_TYPE).FirstOrDefault() as GFF.WORD; int id = (int)field.Value; var label_old = char2DA.Data[COL_LABEL][id]; var label_new = char2DA.Data[COL_LABEL][randAppear]; LookupTable[fi.Name][CHARACTER].Add(rf.Label, new Tuple<int, string, int, string>(id, label_old, randAppear, label_new)); (g.Top_Level.Fields.Where(f => f.Label == LBL_APPEARANCE_TYPE).FirstOrDefault() as GFF.WORD).Value = (ushort)randAppear; rf.File_Data = g.ToRawData(); } } r.WriteToFile(fi.FullName); } }